summaryrefslogtreecommitdiffstats
path: root/chart2
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /chart2
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'chart2')
-rw-r--r--chart2/AllLangMoTarget_chart.mk13
-rw-r--r--chart2/CppunitTest_chart2_common_functors.mk43
-rw-r--r--chart2/CppunitTest_chart2_dialogs_test.mk76
-rw-r--r--chart2/CppunitTest_chart2_dump.mk128
-rw-r--r--chart2/CppunitTest_chart2_export.mk15
-rw-r--r--chart2/CppunitTest_chart2_export2.mk14
-rw-r--r--chart2/CppunitTest_chart2_export3.mk14
-rw-r--r--chart2/CppunitTest_chart2_geometry.mk143
-rw-r--r--chart2/CppunitTest_chart2_import.mk15
-rw-r--r--chart2/CppunitTest_chart2_import2.mk14
-rw-r--r--chart2/CppunitTest_chart2_pivot_chart_test.mk135
-rw-r--r--chart2/CppunitTest_chart2_trendcalculators.mk131
-rw-r--r--chart2/CppunitTest_chart2_uichart.mk58
-rw-r--r--chart2/CppunitTest_chart2_xshape.mk135
-rw-r--r--chart2/IwyuFilter_chart2.yaml751
-rw-r--r--chart2/JunitTest_chart2_unoapi.mk14
-rw-r--r--chart2/Library_chartcontroller.mk218
-rw-r--r--chart2/Library_chartcore.mk240
-rw-r--r--chart2/Makefile14
-rw-r--r--chart2/Module_chart2.mk59
-rw-r--r--chart2/README.md9
-rw-r--r--chart2/UIConfig_chart2.mk83
-rw-r--r--chart2/export_setup.mk90
-rw-r--r--chart2/import_setup.mk145
-rw-r--r--chart2/inc/ChartModel.hxx491
-rw-r--r--chart2/inc/ChartTypeManager.hxx74
-rw-r--r--chart2/inc/ChartView.hxx256
-rw-r--r--chart2/inc/SpecialCharacters.hxx18
-rw-r--r--chart2/inc/bitmaps.hlst132
-rw-r--r--chart2/inc/chart.hrc24
-rw-r--r--chart2/inc/pch/precompiled_chartcontroller.cxx12
-rw-r--r--chart2/inc/pch/precompiled_chartcontroller.hxx515
-rw-r--r--chart2/inc/pch/precompiled_chartcore.cxx12
-rw-r--r--chart2/inc/pch/precompiled_chartcore.hxx303
-rw-r--r--chart2/inc/strings.hrc198
-rw-r--r--chart2/inc/unonames.hxx38
-rw-r--r--chart2/qa/TestCaseOldAPI.java957
-rw-r--r--chart2/qa/data.chd14
-rw-r--r--chart2/qa/extras/PivotChartTest.cxx967
-rw-r--r--chart2/qa/extras/chart2_trendcalculators.cxx217
-rw-r--r--chart2/qa/extras/chart2dump/chart2dump.cxx1122
-rw-r--r--chart2/qa/extras/chart2dump/data/axis_special_positioning.odpbin0 -> 25153 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_with_titles.odsbin0 -> 24943 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_without_titles.odsbin0 -> 25090 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/chartwall_custom_positioning.odsbin0 -> 29351 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/column_chart_small_spacing.odsbin0 -> 29333 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/custom_legend_position.odpbin0 -> 16422 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/date-categories.pptxbin0 -> 41931 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/default_formated_axis.odpbin0 -> 26218 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/donut_chart.odsbin0 -> 24630 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/exploded_pie_chart.odsbin0 -> 26180 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/formated_axis_labels.odpbin0 -> 15328 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/formated_axis_lines.odpbin0 -> 24305 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/formated_grid_line.odsbin0 -> 30275 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/horizontal_grid.odsbin0 -> 30942 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/legend_on_bottom.odpbin0 -> 16526 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/legend_on_left_side.odpbin0 -> 16235 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/legend_on_right_side.odpbin0 -> 14176 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/legend_on_top.odpbin0 -> 16410 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/many_legend_entries.odpbin0 -> 20961 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/minimal_legend_test.odpbin0 -> 18253 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/minor_grid.odsbin0 -> 30004 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/multiple_categories.odpbin0 -> 21476 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/multiple_categories.odsbin0 -> 35766 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/normal_area_chart.odsbin0 -> 29023 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/normal_bar_chart.odsbin0 -> 31385 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/normal_column_chart.odsbin0 -> 29326 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/normal_line_chart_lines_and_points.odsbin0 -> 29690 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/normal_line_chart_lines_only.odsbin0 -> 29596 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/normal_line_chart_points_only.odsbin0 -> 29686 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/normal_pie_chart.odsbin0 -> 26374 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/percent_stacked_area_chart.odsbin0 -> 31559 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/percent_stacked_bar_chart.odsbin0 -> 29672 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.odpbin0 -> 23155 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.odsbin0 -> 31177 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_and_points.odsbin0 -> 23971 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_only.odsbin0 -> 23869 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_points_only.odsbin0 -> 23751 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/pie_chart_many_slices.odsbin0 -> 16351 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/pivotchart_data_button.odsbin0 -> 18366 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/rotated_axis_labels.odpbin0 -> 24098 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/rotated_pie_chart.odsbin0 -> 26286 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/scatter_chart_lines_and_points.odsbin0 -> 23728 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/scatter_chart_lines_only.odsbin0 -> 23540 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/scatter_chart_points_only.odsbin0 -> 23520 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/simple_chart.odsbin0 -> 29601 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/stacked_area_chart.odsbin0 -> 30199 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/stacked_bar_chart.odsbin0 -> 29285 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/stacked_column_chart.odsbin0 -> 29893 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_and_points.odsbin0 -> 23638 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_only.odsbin0 -> 23312 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/stacked_line_chart_points_only.odsbin0 -> 23484 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/tdf118150.xlsxbin0 -> 14212 bytes
-rw-r--r--chart2/qa/extras/chart2dump/data/vertical_grid.odsbin0 -> 31470 bytes
-rw-r--r--chart2/qa/extras/chart2dump/reference/areacharttest/normal_area_chart.txt62
-rw-r--r--chart2/qa/extras/chart2dump/reference/areacharttest/percent_stacked_area_chart.txt62
-rw-r--r--chart2/qa/extras/chart2dump/reference/areacharttest/stacked_area_chart.txt62
-rw-r--r--chart2/qa/extras/chart2dump/reference/axisgeometrytest/axis_special_positioning.txt38
-rw-r--r--chart2/qa/extras/chart2dump/reference/axisgeometrytest/default_formated_axis.txt38
-rw-r--r--chart2/qa/extras/chart2dump/reference/axisgeometrytest/formated_axis_lines.txt38
-rw-r--r--chart2/qa/extras/chart2dump/reference/axisgeometrytest/rotated_axis_labels.txt38
-rw-r--r--chart2/qa/extras/chart2dump/reference/axislabeltest/date-categories.txt180
-rw-r--r--chart2/qa/extras/chart2dump/reference/axislabeltest/default_formated_axis.txt96
-rw-r--r--chart2/qa/extras/chart2dump/reference/axislabeltest/formated_axis_labels.txt96
-rw-r--r--chart2/qa/extras/chart2dump/reference/axislabeltest/percent_stacked_column_chart.txt96
-rw-r--r--chart2/qa/extras/chart2dump/reference/axislabeltest/rotated_axis_labels.txt60
-rw-r--r--chart2/qa/extras/chart2dump/reference/axislabeltest/tdf118150.txt216
-rw-r--r--chart2/qa/extras/chart2dump/reference/chartdatatest/multiple_categories.txt70
-rw-r--r--chart2/qa/extras/chart2dump/reference/chartdatatest/simple_chart.txt50
-rw-r--r--chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_with_titles.txt10
-rw-r--r--chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_without_titles.txt10
-rw-r--r--chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_custom_positioning.txt10
-rw-r--r--chart2/qa/extras/chart2dump/reference/chartwalltest/formated_chartwall.txt10
-rw-r--r--chart2/qa/extras/chart2dump/reference/columnbarcharttest/column_chart_small_spacing.txt162
-rw-r--r--chart2/qa/extras/chart2dump/reference/columnbarcharttest/normal_bar_chart.txt162
-rw-r--r--chart2/qa/extras/chart2dump/reference/columnbarcharttest/normal_column_chart.txt162
-rw-r--r--chart2/qa/extras/chart2dump/reference/columnbarcharttest/percent_stacked_bar_chart.txt162
-rw-r--r--chart2/qa/extras/chart2dump/reference/columnbarcharttest/percent_stacked_column_chart.txt162
-rw-r--r--chart2/qa/extras/chart2dump/reference/columnbarcharttest/stacked_bar_chart.txt162
-rw-r--r--chart2/qa/extras/chart2dump/reference/columnbarcharttest/stacked_column_chart.txt162
-rw-r--r--chart2/qa/extras/chart2dump/reference/gridtest/formated_grid_line.txt17
-rw-r--r--chart2/qa/extras/chart2dump/reference/gridtest/horizontal_grid.txt17
-rw-r--r--chart2/qa/extras/chart2dump/reference/gridtest/minor_grid.txt68
-rw-r--r--chart2/qa/extras/chart2dump/reference/gridtest/vertical_grid.txt17
-rw-r--r--chart2/qa/extras/chart2dump/reference/legendtest/custom_legend_position.txt50
-rw-r--r--chart2/qa/extras/chart2dump/reference/legendtest/legend_on_bottom.txt50
-rw-r--r--chart2/qa/extras/chart2dump/reference/legendtest/legend_on_left_side.txt50
-rw-r--r--chart2/qa/extras/chart2dump/reference/legendtest/legend_on_right_side.txt18
-rw-r--r--chart2/qa/extras/chart2dump/reference/legendtest/legend_on_top.txt50
-rw-r--r--chart2/qa/extras/chart2dump/reference/legendtest/many_legend_entries.txt182
-rw-r--r--chart2/qa/extras/chart2dump/reference/legendtest/minimal_legend_test.txt14
-rw-r--r--chart2/qa/extras/chart2dump/reference/legendtest/multiple_categories.txt66
-rw-r--r--chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt194
-rw-r--r--chart2/qa/extras/chart2dump/reference/piecharttest/exploded_pie_chart.txt50
-rw-r--r--chart2/qa/extras/chart2dump/reference/piecharttest/normal_pie_chart.txt50
-rw-r--r--chart2/qa/extras/chart2dump/reference/piecharttest/pie_chart_many_slices.txt275
-rw-r--r--chart2/qa/extras/chart2dump/reference/piecharttest/rotated_pie_chart.txt50
-rw-r--r--chart2/qa/extras/chart2dump/reference/pivotchartdatabuttontest/pivotchart_data_button.txt2
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_lines_and_points.txt250
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_lines_only.txt58
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_points_only.txt198
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_lines_and_points.txt310
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_lines_only.txt58
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_points_only.txt258
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_lines_and_points.txt310
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_lines_only.txt58
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_points_only.txt258
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_lines_and_points.txt310
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_lines_only.txt58
-rw-r--r--chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_points_only.txt258
-rw-r--r--chart2/qa/extras/chart2export.cxx1258
-rw-r--r--chart2/qa/extras/chart2export2.cxx1685
-rw-r--r--chart2/qa/extras/chart2export3.cxx767
-rw-r--r--chart2/qa/extras/chart2geometry.cxx493
-rw-r--r--chart2/qa/extras/chart2import.cxx2242
-rw-r--r--chart2/qa/extras/chart2import2.cxx892
-rw-r--r--chart2/qa/extras/charttest.hxx605
-rw-r--r--chart2/qa/extras/data/doc/chart.docbin0 -> 15872 bytes
-rw-r--r--chart2/qa/extras/data/docx/3d-bar-label.docxbin0 -> 24163 bytes
-rw-r--r--chart2/qa/extras/data/docx/Bar_horizontal_cone.docxbin0 -> 18237 bytes
-rw-r--r--chart2/qa/extras/data/docx/DisplayUnits.docxbin0 -> 18137 bytes
-rw-r--r--chart2/qa/extras/data/docx/FDO74430.docxbin0 -> 19199 bytes
-rw-r--r--chart2/qa/extras/data/docx/FDO75975.docxbin0 -> 18257 bytes
-rw-r--r--chart2/qa/extras/data/docx/MSO_Custom_Leader_Line.docxbin0 -> 25883 bytes
-rw-r--r--chart2/qa/extras/data/docx/MSO_axis_position.docxbin0 -> 41444 bytes
-rw-r--r--chart2/qa/extras/data/docx/PieChartDataLabels.docxbin0 -> 120403 bytes
-rw-r--r--chart2/qa/extras/data/docx/TableOnPage3.docxbin0 -> 35511 bytes
-rw-r--r--chart2/qa/extras/data/docx/UpDownBars.docxbin0 -> 24198 bytes
-rw-r--r--chart2/qa/extras/data/docx/area-chart-labels.docxbin0 -> 24123 bytes
-rw-r--r--chart2/qa/extras/data/docx/bar-chart-labels.docxbin0 -> 24357 bytes
-rw-r--r--chart2/qa/extras/data/docx/barChartRotation.docxbin0 -> 24220 bytes
-rw-r--r--chart2/qa/extras/data/docx/bubblechart.docxbin0 -> 17740 bytes
-rw-r--r--chart2/qa/extras/data/docx/chart.docxbin0 -> 17749 bytes
-rw-r--r--chart2/qa/extras/data/docx/clustered-bar-chart-labels.docxbin0 -> 22977 bytes
-rw-r--r--chart2/qa/extras/data/docx/data-label-borders.docxbin0 -> 34843 bytes
-rw-r--r--chart2/qa/extras/data/docx/data_point_inherited_color.docxbin0 -> 5426 bytes
-rw-r--r--chart2/qa/extras/data/docx/doughnut-chart-labels.docxbin0 -> 23902 bytes
-rw-r--r--chart2/qa/extras/data/docx/doughnutChart.docxbin0 -> 17486 bytes
-rw-r--r--chart2/qa/extras/data/docx/fdo74115_WallBitmapFill.docxbin0 -> 34418 bytes
-rw-r--r--chart2/qa/extras/data/docx/fdo74115_WallGradientFill.docxbin0 -> 17942 bytes
-rw-r--r--chart2/qa/extras/data/docx/fdo78290_Combination_Chart_Marker_x.docxbin0 -> 24245 bytes
-rw-r--r--chart2/qa/extras/data/docx/fdo78290_Line_Chart_Marker_x.docxbin0 -> 24041 bytes
-rw-r--r--chart2/qa/extras/data/docx/fdo78290_Scatter_Chart_Marker_x.docxbin0 -> 23747 bytes
-rw-r--r--chart2/qa/extras/data/docx/fdo83058_dlblPos.docxbin0 -> 35931 bytes
-rw-r--r--chart2/qa/extras/data/docx/line-chart-label-default-placement.docxbin0 -> 17824 bytes
-rw-r--r--chart2/qa/extras/data/docx/pieChartRotation.docxbin0 -> 23528 bytes
-rw-r--r--chart2/qa/extras/data/docx/piechart_deleted_legend_entry.docxbin0 -> 27165 bytes
-rw-r--r--chart2/qa/extras/data/docx/radar-chart-labels.docxbin0 -> 24223 bytes
-rw-r--r--chart2/qa/extras/data/docx/scatter-chart-text-x-values.docxbin0 -> 23974 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf121744.docxbin0 -> 25221 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf123206.docxbin0 -> 24223 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf124083.docxbin0 -> 25793 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf124243.docxbin0 -> 25872 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf125337.docxbin0 -> 25063 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf128794.docxbin0 -> 31616 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf132174.docxbin0 -> 13865 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf133632.docxbin0 -> 26280 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf134111.docxbin0 -> 22831 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf134255.docxbin0 -> 33169 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf136650.docxbin0 -> 25543 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf139658.docxbin0 -> 27488 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf143130.docxbin0 -> 26675 bytes
-rw-r--r--chart2/qa/extras/data/docx/tdf91250.docxbin0 -> 25895 bytes
-rw-r--r--chart2/qa/extras/data/docx/testAreaChartLoad.docxbin0 -> 23962 bytes
-rw-r--r--chart2/qa/extras/data/docx/testAxisTitlePosition.docxbin0 -> 26274 bytes
-rw-r--r--chart2/qa/extras/data/docx/testBarChart.docxbin0 -> 23955 bytes
-rw-r--r--chart2/qa/extras/data/docx/testBarChartDataPointPropDOCX.docxbin0 -> 25590 bytes
-rw-r--r--chart2/qa/extras/data/docx/testChartDataTable.docxbin0 -> 18084 bytes
-rw-r--r--chart2/qa/extras/data/docx/testChartTitlePropertiesBitmapFill.docxbin0 -> 47851 bytes
-rw-r--r--chart2/qa/extras/data/docx/testChartTitlePropertiesColorFill.docxbin0 -> 5549 bytes
-rw-r--r--chart2/qa/extras/data/docx/testChartTitlePropertiesGradientFill.docxbin0 -> 5595 bytes
-rw-r--r--chart2/qa/extras/data/docx/testColorGradientWithTransparency.docxbin0 -> 25872 bytes
-rw-r--r--chart2/qa/extras/data/docx/testCustomlabeltext.docxbin0 -> 26031 bytes
-rw-r--r--chart2/qa/extras/data/docx/testLabelSeparator.docxbin0 -> 25333 bytes
-rw-r--r--chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docxbin0 -> 5890 bytes
-rw-r--r--chart2/qa/extras/data/docx/testMultipleChart.docxbin0 -> 47534 bytes
-rw-r--r--chart2/qa/extras/data/docx/testMultiplechartembeddings.docxbin0 -> 47534 bytes
-rw-r--r--chart2/qa/extras/data/docx/testSeriesIdxOrder.docxbin0 -> 25941 bytes
-rw-r--r--chart2/qa/extras/data/docx/testSimpleCategoryAxis.docxbin0 -> 31629 bytes
-rw-r--r--chart2/qa/extras/data/docx/testStockChart.docxbin0 -> 19894 bytes
-rw-r--r--chart2/qa/extras/data/docx/testTdf108110.docxbin0 -> 25892 bytes
-rw-r--r--chart2/qa/extras/data/docx/testTdf114179.docxbin0 -> 5839 bytes
-rw-r--r--chart2/qa/extras/data/docx/testTdf122226.docxbin0 -> 19648 bytes
-rw-r--r--chart2/qa/extras/data/docx/testchartoleobjectembeddings.docxbin0 -> 2041727 bytes
-rw-r--r--chart2/qa/extras/data/docx/testcustomshapepos.docxbin0 -> 26359 bytes
-rw-r--r--chart2/qa/extras/data/fods/stacked-column-chart.fods861
-rw-r--r--chart2/qa/extras/data/odp/BarChartVeryLongLabel.odpbin0 -> 16390 bytes
-rw-r--r--chart2/qa/extras/data/odp/chart.odpbin0 -> 14747 bytes
-rw-r--r--chart2/qa/extras/data/odp/ellipticalGradientFill.odpbin0 -> 17071 bytes
-rw-r--r--chart2/qa/extras/data/odp/tdf119029.odpbin0 -> 13643 bytes
-rw-r--r--chart2/qa/extras/data/odp/tdf121189.odpbin0 -> 16945 bytes
-rw-r--r--chart2/qa/extras/data/odp/tdf123206.odpbin0 -> 19589 bytes
-rw-r--r--chart2/qa/extras/data/odp/tdf128345_ChartArea_CG_TS.odpbin0 -> 19486 bytes
-rw-r--r--chart2/qa/extras/data/odp/tdf128345_ChartWall_CS_TG.odpbin0 -> 16551 bytes
-rw-r--r--chart2/qa/extras/data/odp/tdf128345_Legend_CS_TG_axial.odpbin0 -> 15174 bytes
-rw-r--r--chart2/qa/extras/data/ods/ErrorBarRange.odsbin0 -> 17937 bytes
-rw-r--r--chart2/qa/extras/data/ods/PivotChartRoundTrip.odsbin0 -> 21988 bytes
-rw-r--r--chart2/qa/extras/data/ods/PivotTableExample.odsbin0 -> 17183 bytes
-rw-r--r--chart2/qa/extras/data/ods/axis-numformats-linked.odsbin0 -> 26944 bytes
-rw-r--r--chart2/qa/extras/data/ods/axis_number_format.odsbin0 -> 12662 bytes
-rw-r--r--chart2/qa/extras/data/ods/chart.odsbin0 -> 12599 bytes
-rw-r--r--chart2/qa/extras/data/ods/chartWithDotInSheetName.odsbin0 -> 15057 bytes
-rw-r--r--chart2/qa/extras/data/ods/combined_chart_secondary_axis.odsbin0 -> 16334 bytes
-rw-r--r--chart2/qa/extras/data/ods/error_bar.odsbin0 -> 13724 bytes
-rw-r--r--chart2/qa/extras/data/ods/error_bar_properties.odsbin0 -> 17387 bytes
-rw-r--r--chart2/qa/extras/data/ods/error_bar_range.odsbin0 -> 13490 bytes
-rw-r--r--chart2/qa/extras/data/ods/fdo60083.odsbin0 -> 14538 bytes
-rw-r--r--chart2/qa/extras/data/ods/labelString.odsbin0 -> 17401 bytes
-rw-r--r--chart2/qa/extras/data/ods/legend_overlay.odsbin0 -> 12314 bytes
-rw-r--r--chart2/qa/extras/data/ods/moving-type.odsbin0 -> 29749 bytes
-rw-r--r--chart2/qa/extras/data/ods/multilevelcat.odsbin0 -> 13559 bytes
-rw-r--r--chart2/qa/extras/data/ods/multiple_axis.odsbin0 -> 12864 bytes
-rw-r--r--chart2/qa/extras/data/ods/pie_chart_100_and_0.odsbin0 -> 11354 bytes
-rw-r--r--chart2/qa/extras/data/ods/secondary_axis.odsbin0 -> 16783 bytes
-rw-r--r--chart2/qa/extras/data/ods/ser_labels.odsbin0 -> 29539 bytes
-rw-r--r--chart2/qa/extras/data/ods/smoothedLines.odsbin0 -> 16115 bytes
-rw-r--r--chart2/qa/extras/data/ods/stepped_lines.odsbin0 -> 76168 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf101894.odsbin0 -> 18221 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf107097.odsbin0 -> 17945 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf108021.odsbin0 -> 16728 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf120348.odsbin0 -> 43612 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf123774.odsbin0 -> 16140 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf128432.odsbin0 -> 13755 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf131115.odsbin0 -> 13814 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf131979.odsbin0 -> 11510 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf132076.odsbin0 -> 16138 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf135366_data_label_series.odsbin0 -> 7661 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf136011.odsbin0 -> 23559 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf136024.odsbin0 -> 15430 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf146066.odsbin0 -> 15079 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf146463.odsbin0 -> 21780 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf148142.odsbin0 -> 15349 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf151091.odsbin0 -> 14140 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf158223.odsbin0 -> 27391 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf59857.odsbin0 -> 33209 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf62057.odsbin0 -> 16852 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf64224.odsbin0 -> 33209 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf72776.odsbin0 -> 14798 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf86624.odsbin0 -> 14461 bytes
-rw-r--r--chart2/qa/extras/data/ods/tdf96161.odsbin0 -> 17545 bytes
-rw-r--r--chart2/qa/extras/data/ods/testChartMainWithSubTitle.odsbin0 -> 12317 bytes
-rw-r--r--chart2/qa/extras/data/ods/testChartSubTitle.odsbin0 -> 12598 bytes
-rw-r--r--chart2/qa/extras/data/ods/testColorGradientWithTransparency.odsbin0 -> 17224 bytes
-rw-r--r--chart2/qa/extras/data/ods/test_CrossBetween.odsbin0 -> 12365 bytes
-rw-r--r--chart2/qa/extras/data/ods/trend_calculators.odsbin0 -> 45107 bytes
-rw-r--r--chart2/qa/extras/data/ods/trendline.odsbin0 -> 17563 bytes
-rw-r--r--chart2/qa/extras/data/odt/axis-position.odtbin0 -> 21224 bytes
-rw-r--r--chart2/qa/extras/data/odt/chart.odtbin0 -> 13470 bytes
-rw-r--r--chart2/qa/extras/data/odt/multilevelcat.odtbin0 -> 13942 bytes
-rw-r--r--chart2/qa/extras/data/odt/scatter-plot-labels.odtbin0 -> 13454 bytes
-rw-r--r--chart2/qa/extras/data/odt/stock_chart_LO_6_2.odtbin0 -> 16810 bytes
-rw-r--r--chart2/qa/extras/data/odt/tdf108022.odtbin0 -> 23191 bytes
-rw-r--r--chart2/qa/extras/data/odt/tdf114657.odtbin0 -> 12890 bytes
-rw-r--r--chart2/qa/extras/data/odt/tdf128733.odtbin0 -> 13708 bytes
-rw-r--r--chart2/qa/extras/data/odt/tdf131143.odtbin0 -> 13970 bytes
-rw-r--r--chart2/qa/extras/data/odt/tdf135366_data_label_export.odtbin0 -> 16069 bytes
-rw-r--r--chart2/qa/extras/data/odt/tdf135366_data_label_point.odtbin0 -> 8344 bytes
-rw-r--r--chart2/qa/extras/data/odt/testPieChartWallLineStyle.odtbin0 -> 16427 bytes
-rw-r--r--chart2/qa/extras/data/ppt/chart.pptbin0 -> 76800 bytes
-rw-r--r--chart2/qa/extras/data/pptx/PieChartWithAutomaticLayout_SizeAndPosition.pptxbin0 -> 165804 bytes
-rw-r--r--chart2/qa/extras/data/pptx/bnc864396.pptxbin0 -> 41580 bytes
-rw-r--r--chart2/qa/extras/data/pptx/bnc882383.pptxbin0 -> 43962 bytes
-rw-r--r--chart2/qa/extras/data/pptx/bnc889755.pptxbin0 -> 34771 bytes
-rw-r--r--chart2/qa/extras/data/pptx/chart.pptxbin0 -> 33393 bytes
-rw-r--r--chart2/qa/extras/data/pptx/percentage-number-formats.pptxbin0 -> 58872 bytes
-rw-r--r--chart2/qa/extras/data/pptx/sparse-chart.pptxbin0 -> 57398 bytes
-rw-r--r--chart2/qa/extras/data/pptx/stacked-bar-chart-hidden-series.pptxbin0 -> 54370 bytes
-rw-r--r--chart2/qa/extras/data/pptx/stacked-non-stacked-mix-y-axis.pptxbin0 -> 86216 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf105517.pptxbin0 -> 37194 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf106217.pptxbin0 -> 47976 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf115107-2.pptxbin0 -> 50519 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf115107.pptxbin0 -> 50726 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf115859.pptxbin0 -> 49120 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf116163.pptxbin0 -> 47591 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf121205.pptxbin0 -> 42922 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf122765.pptxbin0 -> 47625 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf125444.pptxbin0 -> 34078 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf127393.pptxbin0 -> 64536 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf127720.pptxbin0 -> 38935 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf127811.pptxbin0 -> 59647 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf128345_ChartArea_CG_TS.pptxbin0 -> 21913 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf128345_ChartWall_CS_TG.pptxbin0 -> 21921 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf128345_Legend_CS_TG_axial.pptxbin0 -> 21932 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf135366_CustomLabelText.pptxbin0 -> 36946 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf137691_dataTable.pptxbin0 -> 49901 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf150176.pptxbin0 -> 52342 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf48041.pptxbin0 -> 23937 bytes
-rw-r--r--chart2/qa/extras/data/pptx/tdf60316.pptxbin0 -> 46023 bytes
-rw-r--r--chart2/qa/extras/data/pptx/testChartTitlePropertiesBitmapFill.pptxbin0 -> 50865 bytes
-rw-r--r--chart2/qa/extras/data/pptx/testChartTitlePropertiesColorFill.pptxbin0 -> 47424 bytes
-rw-r--r--chart2/qa/extras/data/pptx/testChartTitlePropertiesGradientFill.pptxbin0 -> 47473 bytes
-rw-r--r--chart2/qa/extras/data/xls/axis_sourceformatting.xlsbin0 -> 7168 bytes
-rw-r--r--chart2/qa/extras/data/xls/chart.xlsbin0 -> 7168 bytes
-rw-r--r--chart2/qa/extras/data/xls/piechart_outside.xlsbin0 -> 60928 bytes
-rw-r--r--chart2/qa/extras/data/xls/source_number_format_axis.xlsbin0 -> 7168 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/ChartDataTable.xlsxbin0 -> 8142 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/DataTable-MultipleLegendEntriesForOneDataSeries.xlsxbin0 -> 15745 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/add_series_secondary_axis.xlsxbin0 -> 20217 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/auto_marker_excel10.xlsxbin0 -> 16250 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/autotitledel_2007.xlsxbin0 -> 10455 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/autotitledel_2013.xlsxbin0 -> 13222 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/axis-label-rotation.xlsxbin0 -> 13698 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/axis_character_properties.xlsxbin0 -> 10381 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/axis_title_default_rotation.xlsxbin0 -> 11868 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/axis_title_rotated.xlsxbin0 -> 11579 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/axis_title_rotation.xlsxbin0 -> 13057 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/bar_chart_simple.xlsxbin0 -> 12966 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/barchart_outend.xlsxbin0 -> 15277 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/barchart_totalsrow.xlsxbin0 -> 20117 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/bubble_chart_simple.xlsxbin0 -> 13010 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/chart-area-style-background.xlsxbin0 -> 13796 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/chart-area-style-border.xlsxbin0 -> 12006 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/chart-auto-background.xlsxbin0 -> 11310 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/chart-hatch-fill.xlsxbin0 -> 11579 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/chart-text-can-overlap.xlsxbin0 -> 13368 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/chart.xlsxbin0 -> 7055 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/chart_label_text_break.xlsxbin0 -> 13940 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/chart_pie2007.xlsxbin0 -> 9091 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/chart_title.xlsxbin0 -> 13085 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/chart_with_name_range.xlsxbin0 -> 14575 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/combined_chart_secondary_axis.xlsxbin0 -> 15304 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/custom_data_label.xlsxbin0 -> 13944 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/data_label.xlsxbin0 -> 13057 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/data_labels_fill_color.xlsxbin0 -> 11256 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/deleted_data_labels.xlsxbin0 -> 7536 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/deleted_legend_entry.xlsxbin0 -> 14346 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/deleted_legend_entry2.xlsxbin0 -> 20060 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/dispBlanksAs_2007.xlsxbin0 -> 10520 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/dispBlanksAs_2013.xlsxbin0 -> 13430 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/empty_chart.xlsxbin0 -> 13370 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/external_str_ref.xlsxbin0 -> 23847 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/fdo54361-1.xlsxbin0 -> 11106 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/fdo54361.xlsxbin0 -> 10273 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/fdo70609.xlsxbin0 -> 13654 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/fdo78080.xlsxbin0 -> 7020 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/gapWidth.xlsxbin0 -> 18668 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/hidden_cells.xlsxbin0 -> 11215 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/incorrect_label_position.xlsxbin0 -> 14112 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/legend_manual_layout.xlsxbin0 -> 13145 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/majorTickMark.xlsxbin0 -> 11223 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/markerColor.xlsxbin0 -> 12999 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/minorTickMark.xlsxbin0 -> 11256 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/no_marker.xlsxbin0 -> 13006 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/number-formats.xlsxbin0 -> 12638 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/pie_chart_datapoint_explosion.xlsxbin0 -> 19237 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/piechart_deleted_legendentry.xlsxbin0 -> 13447 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/piechart_legend.xlsxbin0 -> 13426 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/piechart_outside.xlsxbin0 -> 15473 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/plotVisOnly.xlsxbin0 -> 11206 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/plot_area_manual_layout.xlsxbin0 -> 13142 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/rAngAx.xlsxbin0 -> 11364 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/secondary_axis_title_default_rotation.xlsxbin0 -> 11529 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/ser_labels.xlsxbin0 -> 18412 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/smoothed_series.xlsxbin0 -> 12836 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/smoothed_series2007.xlsxbin0 -> 12351 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/strict_chart.xlsxbin0 -> 12779 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf100084.xlsxbin0 -> 10070 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf108107.xlsxbin0 -> 14277 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf111173.xlsxbin0 -> 16013 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf111824.xlsxbin0 -> 15235 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf114139.xlsxbin0 -> 18794 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf115012.xlsxbin0 -> 13729 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf119138-missing-autotitledeleted.xlsxbin0 -> 8424 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf122031.xlsxbin0 -> 13229 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf122915.xlsxbin0 -> 14310 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf124817.xlsxbin0 -> 20868 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf126033.xlsxbin0 -> 20012 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf126115.xlsxbin0 -> 20173 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf127777.xlsxbin0 -> 14421 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf128619.xlsxbin0 -> 13658 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf128621.xlsxbin0 -> 15011 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf128627.xlsxbin0 -> 14307 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf128633.xlsxbin0 -> 15018 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf128634.xlsxbin0 -> 14185 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf128732.xlsxbin0 -> 7511 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf130657.xlsxbin0 -> 7468 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf130986.xlsxbin0 -> 15393 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf132076.xlsxbin0 -> 14632 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf133190_tdf133191.xlsxbin0 -> 12142 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf133376.xlsxbin0 -> 12736 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf134118.xlsxbin0 -> 16014 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf134225.xlsxbin0 -> 13956 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf134978.xlsxbin0 -> 13746 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf135184RoundLineCap.xlsxbin0 -> 25538 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf135184RoundLineCap2.xlsxbin0 -> 21937 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf136105.xlsxbin0 -> 16753 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf136267.xlsxbin0 -> 31986 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf136752.xlsxbin0 -> 11909 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf137505.xlsxbin0 -> 14908 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf137734.xlsxbin0 -> 6504 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf137917.xlsxbin0 -> 13940 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf138204.xlsxbin0 -> 15138 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf140489.xlsxbin0 -> 32626 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf142351.xlsxbin0 -> 15077 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf143127.xlsxbin0 -> 18486 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf143942.xlsxbin0 -> 13697 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf150434.xlsxbin0 -> 14918 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf81396.xlsxbin0 -> 8224 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf90876.xlsxbin0 -> 12736 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdf98690.xlsxbin0 -> 17975 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/tdfPieNumFormat.xlsxbin0 -> 13917 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/test3DAreaChartZAxis.xlsxbin0 -> 15501 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testAutoTitleDeleted.xlsxbin0 -> 15097 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testBarChartDataPointPropXLSX.xlsxbin0 -> 14007 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testChartTitlePropertiesBitmapFill.xlsxbin0 -> 49790 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testChartTitlePropertiesColorFill.xlsxbin0 -> 11515 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testChartTitlePropertiesGradientFill.xlsxbin0 -> 7542 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testCombinedChartAxis.xlsxbin0 -> 20857 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testCustomPosDataLabels.xlsxbin0 -> 14332 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testDataPointLabelCustomPos.xlsxbin0 -> 15069 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testDataseriesOverlapStackedChart.xlsxbin0 -> 11007 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testErrorBarProp.xlsxbin0 -> 14559 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testSecondaryAxis.xlsxbin0 -> 14757 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testTdf130032.xlsxbin0 -> 14208 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/testTdf90749.xlsxbin0 -> 14505 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/title_character_properties.xlsxbin0 -> 10355 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/title_manual_layout.xlsxbin0 -> 13160 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/trendline.xlsxbin0 -> 13397 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/trendline2007.xlsxbin0 -> 12514 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/vary_color.xlsxbin0 -> 13935 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/vary_color2007.xlsxbin0 -> 13142 bytes
-rw-r--r--chart2/qa/extras/data/xlsx/xAxisLabelsRotation.xlsxbin0 -> 13601 bytes
-rw-r--r--chart2/qa/extras/uichart.cxx441
-rw-r--r--chart2/qa/extras/xshape/chart2xshape.cxx322
-rw-r--r--chart2/qa/extras/xshape/data/ods/fdo75075.odsbin0 -> 15763 bytes
-rw-r--r--chart2/qa/extras/xshape/data/ods/property-mapping-bar.odsbin0 -> 15481 bytes
-rw-r--r--chart2/qa/extras/xshape/data/ods/tdf151424.odsbin0 -> 17727 bytes
-rw-r--r--chart2/qa/extras/xshape/data/ods/tdf76649_TrendLineBug.odsbin0 -> 12060 bytes
-rw-r--r--chart2/qa/extras/xshape/data/ods/tdf90839-4.odsbin0 -> 19765 bytes
-rw-r--r--chart2/qa/extras/xshape/data/ods/testChart.odsbin0 -> 11156 bytes
-rw-r--r--chart2/qa/extras/xshape/data/pptx/tdf149204.pptxbin0 -> 33324 bytes
-rw-r--r--chart2/qa/extras/xshape/data/pptx/tdf88154_LabelRotatedLayout.pptxbin0 -> 34771 bytes
-rw-r--r--chart2/qa/extras/xshape/data/reference/fdo75075.xml1692
-rw-r--r--chart2/qa/extras/xshape/data/reference/property-mapping-bar.xml1164
-rw-r--r--chart2/qa/extras/xshape/data/reference/tdf149204.xml397
-rw-r--r--chart2/qa/extras/xshape/data/reference/tdf150832.xml974
-rw-r--r--chart2/qa/extras/xshape/data/reference/tdf151424.xml1160
-rw-r--r--chart2/qa/extras/xshape/data/reference/tdf90839-1.xml336
-rw-r--r--chart2/qa/extras/xshape/data/reference/tdf90839-2.xml336
-rw-r--r--chart2/qa/extras/xshape/data/reference/tdf90839-3.xml336
-rw-r--r--chart2/qa/extras/xshape/data/reference/tdf90839-4.xml336
-rw-r--r--chart2/qa/extras/xshape/data/reference/testChart.xml1218
-rw-r--r--chart2/qa/extras/xshape/data/reference/tolerance.xml15
-rw-r--r--chart2/qa/extras/xshape/data/xls/tdf150832.xlsbin0 -> 7168 bytes
-rw-r--r--chart2/qa/extras/xshape/data/xlsx/tdf90839-1.xlsxbin0 -> 13080 bytes
-rw-r--r--chart2/qa/extras/xshape/data/xlsx/tdf90839-2.xlsxbin0 -> 12498 bytes
-rw-r--r--chart2/qa/extras/xshape/data/xlsx/tdf90839-3.xlsxbin0 -> 13200 bytes
-rw-r--r--chart2/qa/unit/chart2-dialogs-test.cxx61
-rw-r--r--chart2/qa/unit/common_functor_test.cxx83
-rw-r--r--chart2/qa/unit/data/chart2-dialogs-test.txt69
-rw-r--r--chart2/qa/unit/data/tolerance.xml7
-rw-r--r--chart2/qa/unoapi/knownissues.xcl58
-rw-r--r--chart2/qa/unoapi/sch.sce42
-rw-r--r--chart2/qa/unoapi/testdocuments/TransparencyChart.sxsbin0 -> 10810 bytes
-rw-r--r--chart2/qa/unoapi/testdocuments/emptyChart.sdsbin0 -> 44544 bytes
-rw-r--r--chart2/qa/unoapi/testdocuments/space-metal.jpgbin0 -> 4313 bytes
-rw-r--r--chart2/source/chartcore.component266
-rw-r--r--chart2/source/controller/accessibility/AccessibleBase.cxx848
-rw-r--r--chart2/source/controller/accessibility/AccessibleChartElement.cxx229
-rw-r--r--chart2/source/controller/accessibility/AccessibleChartElement.hxx105
-rw-r--r--chart2/source/controller/accessibility/AccessibleChartShape.cxx250
-rw-r--r--chart2/source/controller/accessibility/AccessibleChartShape.hxx83
-rw-r--r--chart2/source/controller/accessibility/AccessibleChartView.cxx415
-rw-r--r--chart2/source/controller/accessibility/AccessibleTextHelper.cxx159
-rw-r--r--chart2/source/controller/accessibility/AccessibleViewForwarder.cxx79
-rw-r--r--chart2/source/controller/accessibility/AccessibleViewForwarder.hxx56
-rw-r--r--chart2/source/controller/accessibility/ChartElementFactory.cxx71
-rw-r--r--chart2/source/controller/accessibility/ChartElementFactory.hxx39
-rw-r--r--chart2/source/controller/chartapiwrapper/AreaWrapper.cxx157
-rw-r--r--chart2/source/controller/chartapiwrapper/AreaWrapper.hxx80
-rw-r--r--chart2/source/controller/chartapiwrapper/AxisWrapper.cxx665
-rw-r--r--chart2/source/controller/chartapiwrapper/AxisWrapper.hxx123
-rw-r--r--chart2/source/controller/chartapiwrapper/Chart2ModelContact.cxx303
-rw-r--r--chart2/source/controller/chartapiwrapper/Chart2ModelContact.hxx149
-rw-r--r--chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx703
-rw-r--r--chart2/source/controller/chartapiwrapper/ChartDataWrapper.hxx117
-rw-r--r--chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx1442
-rw-r--r--chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx890
-rw-r--r--chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.hxx124
-rw-r--r--chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx1898
-rw-r--r--chart2/source/controller/chartapiwrapper/DiagramWrapper.hxx217
-rw-r--r--chart2/source/controller/chartapiwrapper/GridWrapper.cxx173
-rw-r--r--chart2/source/controller/chartapiwrapper/GridWrapper.hxx81
-rw-r--r--chart2/source/controller/chartapiwrapper/LegendWrapper.cxx413
-rw-r--r--chart2/source/controller/chartapiwrapper/LegendWrapper.hxx87
-rw-r--r--chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.cxx352
-rw-r--r--chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.hxx103
-rw-r--r--chart2/source/controller/chartapiwrapper/ReferenceSizePropertyProvider.hxx38
-rw-r--r--chart2/source/controller/chartapiwrapper/TitleWrapper.cxx502
-rw-r--r--chart2/source/controller/chartapiwrapper/TitleWrapper.hxx110
-rw-r--r--chart2/source/controller/chartapiwrapper/UpDownBarWrapper.cxx317
-rw-r--r--chart2/source/controller/chartapiwrapper/UpDownBarWrapper.hxx105
-rw-r--r--chart2/source/controller/chartapiwrapper/WallFloorWrapper.cxx149
-rw-r--r--chart2/source/controller/chartapiwrapper/WallFloorWrapper.hxx69
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedAddInProperty.cxx121
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedAddInProperty.hxx87
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.cxx123
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.hxx46
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.cxx407
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.hxx54
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.cxx138
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.hxx77
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.cxx156
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.hxx44
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.cxx169
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.hxx73
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.cxx124
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.hxx64
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedScaleProperty.cxx589
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedScaleProperty.hxx83
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.cxx139
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.hxx43
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedSceneProperty.cxx102
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedSceneProperty.hxx55
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.cxx53
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.hxx45
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedSeriesOrDiagramProperty.hxx165
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx286
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedSplineProperties.hxx42
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx1071
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.hxx44
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedStockProperties.cxx284
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedStockProperties.hxx42
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx531
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.hxx44
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.cxx71
-rw-r--r--chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.hxx43
-rw-r--r--chart2/source/controller/chartcontroller.component53
-rw-r--r--chart2/source/controller/dialogs/ChangingResource.cxx38
-rw-r--r--chart2/source/controller/dialogs/ChartResourceGroupDlgs.cxx131
-rw-r--r--chart2/source/controller/dialogs/ChartResourceGroups.cxx383
-rw-r--r--chart2/source/controller/dialogs/ChartTypeDialogController.cxx1254
-rw-r--r--chart2/source/controller/dialogs/DataBrowser.cxx1376
-rw-r--r--chart2/source/controller/dialogs/DataBrowser.hxx187
-rw-r--r--chart2/source/controller/dialogs/DataBrowserModel.cxx935
-rw-r--r--chart2/source/controller/dialogs/DataBrowserModel.hxx170
-rw-r--r--chart2/source/controller/dialogs/DialogModel.cxx849
-rw-r--r--chart2/source/controller/dialogs/DialogModel.hxx176
-rw-r--r--chart2/source/controller/dialogs/ObjectNameProvider.cxx868
-rw-r--r--chart2/source/controller/dialogs/RangeSelectionHelper.cxx178
-rw-r--r--chart2/source/controller/dialogs/RangeSelectionListener.cxx61
-rw-r--r--chart2/source/controller/dialogs/TextDirectionListBox.cxx36
-rw-r--r--chart2/source/controller/dialogs/TimerTriggeredControllerLock.cxx52
-rw-r--r--chart2/source/controller/dialogs/TitleDialogData.cxx113
-rw-r--r--chart2/source/controller/dialogs/dlg_ChartType.cxx46
-rw-r--r--chart2/source/controller/dialogs/dlg_ChartType_UNO.cxx113
-rw-r--r--chart2/source/controller/dialogs/dlg_CreationWizard.cxx202
-rw-r--r--chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx362
-rw-r--r--chart2/source/controller/dialogs/dlg_DataEditor.cxx148
-rw-r--r--chart2/source/controller/dialogs/dlg_DataSource.cxx178
-rw-r--r--chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx88
-rw-r--r--chart2/source/controller/dialogs/dlg_InsertDataLabel.cxx43
-rw-r--r--chart2/source/controller/dialogs/dlg_InsertDataTable.cxx61
-rw-r--r--chart2/source/controller/dialogs/dlg_InsertErrorBars.cxx103
-rw-r--r--chart2/source/controller/dialogs/dlg_InsertLegend.cxx45
-rw-r--r--chart2/source/controller/dialogs/dlg_InsertTitle.cxx41
-rw-r--r--chart2/source/controller/dialogs/dlg_NumberFormat.cxx57
-rw-r--r--chart2/source/controller/dialogs/dlg_NumberFormat.hxx45
-rw-r--r--chart2/source/controller/dialogs/dlg_ObjectProperties.cxx638
-rw-r--r--chart2/source/controller/dialogs/dlg_ShapeFont.cxx61
-rw-r--r--chart2/source/controller/dialogs/dlg_ShapeParagraph.cxx64
-rw-r--r--chart2/source/controller/dialogs/dlg_View3D.cxx81
-rw-r--r--chart2/source/controller/dialogs/res_BarGeometry.cxx65
-rw-r--r--chart2/source/controller/dialogs/res_DataLabel.cxx388
-rw-r--r--chart2/source/controller/dialogs/res_DataLabel.hxx101
-rw-r--r--chart2/source/controller/dialogs/res_DataTableProperties.cxx111
-rw-r--r--chart2/source/controller/dialogs/res_ErrorBar.cxx716
-rw-r--r--chart2/source/controller/dialogs/res_LegendPosition.cxx244
-rw-r--r--chart2/source/controller/dialogs/res_Titles.cxx132
-rw-r--r--chart2/source/controller/dialogs/res_Trendline.cxx434
-rw-r--r--chart2/source/controller/dialogs/res_Trendline.hxx98
-rw-r--r--chart2/source/controller/dialogs/tp_3D_SceneAppearance.cxx318
-rw-r--r--chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx69
-rw-r--r--chart2/source/controller/dialogs/tp_3D_SceneGeometry.cxx258
-rw-r--r--chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx87
-rw-r--r--chart2/source/controller/dialogs/tp_3D_SceneIllumination.cxx533
-rw-r--r--chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx98
-rw-r--r--chart2/source/controller/dialogs/tp_AxisLabel.cxx300
-rw-r--r--chart2/source/controller/dialogs/tp_AxisLabel.hxx83
-rw-r--r--chart2/source/controller/dialogs/tp_AxisPositions.cxx320
-rw-r--r--chart2/source/controller/dialogs/tp_AxisPositions.hxx83
-rw-r--r--chart2/source/controller/dialogs/tp_ChartType.cxx385
-rw-r--r--chart2/source/controller/dialogs/tp_ChartType.hxx94
-rw-r--r--chart2/source/controller/dialogs/tp_DataLabel.cxx54
-rw-r--r--chart2/source/controller/dialogs/tp_DataLabel.hxx48
-rw-r--r--chart2/source/controller/dialogs/tp_DataPointOption.cxx66
-rw-r--r--chart2/source/controller/dialogs/tp_DataPointOption.hxx48
-rw-r--r--chart2/source/controller/dialogs/tp_DataSource.cxx924
-rw-r--r--chart2/source/controller/dialogs/tp_DataSource.hxx149
-rw-r--r--chart2/source/controller/dialogs/tp_DataTable.cxx43
-rw-r--r--chart2/source/controller/dialogs/tp_DataTable.hxx37
-rw-r--r--chart2/source/controller/dialogs/tp_ErrorBars.cxx67
-rw-r--r--chart2/source/controller/dialogs/tp_ErrorBars.hxx50
-rw-r--r--chart2/source/controller/dialogs/tp_LegendPosition.cxx76
-rw-r--r--chart2/source/controller/dialogs/tp_LegendPosition.hxx49
-rw-r--r--chart2/source/controller/dialogs/tp_PointGeometry.cxx78
-rw-r--r--chart2/source/controller/dialogs/tp_PointGeometry.hxx44
-rw-r--r--chart2/source/controller/dialogs/tp_PolarOptions.cxx106
-rw-r--r--chart2/source/controller/dialogs/tp_PolarOptions.hxx57
-rw-r--r--chart2/source/controller/dialogs/tp_RangeChooser.cxx380
-rw-r--r--chart2/source/controller/dialogs/tp_RangeChooser.hxx98
-rw-r--r--chart2/source/controller/dialogs/tp_Scale.cxx637
-rw-r--r--chart2/source/controller/dialogs/tp_Scale.hxx109
-rw-r--r--chart2/source/controller/dialogs/tp_SeriesToAxis.cxx248
-rw-r--r--chart2/source/controller/dialogs/tp_SeriesToAxis.hxx77
-rw-r--r--chart2/source/controller/dialogs/tp_TitleRotation.cxx121
-rw-r--r--chart2/source/controller/dialogs/tp_TitleRotation.hxx61
-rw-r--r--chart2/source/controller/dialogs/tp_Trendline.cxx59
-rw-r--r--chart2/source/controller/dialogs/tp_Trendline.hxx46
-rw-r--r--chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx160
-rw-r--r--chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx72
-rw-r--r--chart2/source/controller/drawinglayer/DrawViewWrapper.cxx366
-rw-r--r--chart2/source/controller/drawinglayer/ViewElementListProvider.cxx198
-rw-r--r--chart2/source/controller/inc/AccessibleBase.hxx322
-rw-r--r--chart2/source/controller/inc/AccessibleChartView.hxx122
-rw-r--r--chart2/source/controller/inc/AccessibleTextHelper.hxx87
-rw-r--r--chart2/source/controller/inc/AxisItemConverter.hxx74
-rw-r--r--chart2/source/controller/inc/CharacterPropertyItemConverter.hxx59
-rw-r--r--chart2/source/controller/inc/ChartController.hxx555
-rw-r--r--chart2/source/controller/inc/ChartDocumentWrapper.hxx176
-rw-r--r--chart2/source/controller/inc/ChartToolbarController.hxx79
-rw-r--r--chart2/source/controller/inc/ChartWindow.hxx84
-rw-r--r--chart2/source/controller/inc/CommandDispatchContainer.hxx136
-rw-r--r--chart2/source/controller/inc/DataPointItemConverter.hxx90
-rw-r--r--chart2/source/controller/inc/DataTableItemConverter.hxx56
-rw-r--r--chart2/source/controller/inc/DrawViewWrapper.hxx100
-rw-r--r--chart2/source/controller/inc/ErrorBarItemConverter.hxx60
-rw-r--r--chart2/source/controller/inc/GraphicPropertyItemConverter.hxx64
-rw-r--r--chart2/source/controller/inc/ItemConverter.hxx185
-rw-r--r--chart2/source/controller/inc/ItemPropertyMap.hxx34
-rw-r--r--chart2/source/controller/inc/LegendItemConverter.hxx61
-rw-r--r--chart2/source/controller/inc/MultipleChartConverters.hxx103
-rw-r--r--chart2/source/controller/inc/MultipleItemConverter.hxx49
-rw-r--r--chart2/source/controller/inc/ObjectHierarchy.hxx125
-rw-r--r--chart2/source/controller/inc/ObjectNameProvider.hxx69
-rw-r--r--chart2/source/controller/inc/PositionAndSizeHelper.hxx48
-rw-r--r--chart2/source/controller/inc/RangeSelectionHelper.hxx71
-rw-r--r--chart2/source/controller/inc/RangeSelectionListener.hxx70
-rw-r--r--chart2/source/controller/inc/RegressionCurveItemConverter.hxx60
-rw-r--r--chart2/source/controller/inc/RegressionEquationItemConverter.hxx61
-rw-r--r--chart2/source/controller/inc/SelectionHelper.hxx115
-rw-r--r--chart2/source/controller/inc/SeriesOptionsItemConverter.hxx84
-rw-r--r--chart2/source/controller/inc/StatisticsItemConverter.hxx52
-rw-r--r--chart2/source/controller/inc/TabPageNotifiable.hxx42
-rw-r--r--chart2/source/controller/inc/TextDirectionListBox.hxx34
-rw-r--r--chart2/source/controller/inc/TextLabelItemConverter.hxx74
-rw-r--r--chart2/source/controller/inc/TimerTriggeredControllerLock.hxx58
-rw-r--r--chart2/source/controller/inc/TitleDialogData.hxx53
-rw-r--r--chart2/source/controller/inc/TitleItemConverter.hxx59
-rw-r--r--chart2/source/controller/inc/ViewElementListProvider.hxx63
-rw-r--r--chart2/source/controller/inc/dlg_ChartType.hxx48
-rw-r--r--chart2/source/controller/inc/dlg_ChartType_UNO.hxx67
-rw-r--r--chart2/source/controller/inc/dlg_CreationWizard.hxx82
-rw-r--r--chart2/source/controller/inc/dlg_CreationWizard_UNO.hxx116
-rw-r--r--chart2/source/controller/inc/dlg_DataEditor.hxx73
-rw-r--r--chart2/source/controller/inc/dlg_DataSource.hxx75
-rw-r--r--chart2/source/controller/inc/dlg_InsertAxis_Grid.hxx67
-rw-r--r--chart2/source/controller/inc/dlg_InsertDataLabel.hxx46
-rw-r--r--chart2/source/controller/inc/dlg_InsertDataTable.hxx52
-rw-r--r--chart2/source/controller/inc/dlg_InsertErrorBars.hxx58
-rw-r--r--chart2/source/controller/inc/dlg_InsertLegend.hxx49
-rw-r--r--chart2/source/controller/inc/dlg_InsertTitle.hxx40
-rw-r--r--chart2/source/controller/inc/dlg_ObjectProperties.hxx145
-rw-r--r--chart2/source/controller/inc/dlg_ShapeFont.hxx43
-rw-r--r--chart2/source/controller/inc/dlg_ShapeParagraph.hxx38
-rw-r--r--chart2/source/controller/inc/dlg_View3D.hxx58
-rw-r--r--chart2/source/controller/inc/helpids.h32
-rw-r--r--chart2/source/controller/inc/res_DataTableProperties.hxx48
-rw-r--r--chart2/source/controller/inc/res_ErrorBar.hxx142
-rw-r--r--chart2/source/controller/inc/res_LegendPosition.hxx75
-rw-r--r--chart2/source/controller/inc/res_Titles.hxx73
-rw-r--r--chart2/source/controller/inc/uiobject.hxx68
-rw-r--r--chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx989
-rw-r--r--chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx557
-rw-r--r--chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx829
-rw-r--r--chart2/source/controller/itemsetwrapper/DataTableItemConverter.cxx109
-rw-r--r--chart2/source/controller/itemsetwrapper/ErrorBarItemConverter.cxx434
-rw-r--r--chart2/source/controller/itemsetwrapper/GraphicPropertyItemConverter.cxx752
-rw-r--r--chart2/source/controller/itemsetwrapper/ItemConverter.cxx223
-rw-r--r--chart2/source/controller/itemsetwrapper/LegendItemConverter.cxx205
-rw-r--r--chart2/source/controller/itemsetwrapper/MultipleChartConverters.cxx193
-rw-r--r--chart2/source/controller/itemsetwrapper/MultipleItemConverter.cxx72
-rw-r--r--chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx351
-rw-r--r--chart2/source/controller/itemsetwrapper/RegressionEquationItemConverter.cxx149
-rw-r--r--chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx181
-rw-r--r--chart2/source/controller/itemsetwrapper/SeriesOptionsItemConverter.cxx434
-rw-r--r--chart2/source/controller/itemsetwrapper/StatisticsItemConverter.cxx859
-rw-r--r--chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx723
-rw-r--r--chart2/source/controller/itemsetwrapper/TitleItemConverter.cxx210
-rw-r--r--chart2/source/controller/main/ChartController.cxx1655
-rw-r--r--chart2/source/controller/main/ChartController_EditData.cxx52
-rw-r--r--chart2/source/controller/main/ChartController_Insert.cxx987
-rw-r--r--chart2/source/controller/main/ChartController_Position.cxx202
-rw-r--r--chart2/source/controller/main/ChartController_Properties.cxx840
-rw-r--r--chart2/source/controller/main/ChartController_TextEdit.cxx230
-rw-r--r--chart2/source/controller/main/ChartController_Tools.cxx1127
-rw-r--r--chart2/source/controller/main/ChartController_Window.cxx2103
-rw-r--r--chart2/source/controller/main/ChartDropTargetHelper.cxx178
-rw-r--r--chart2/source/controller/main/ChartDropTargetHelper.hxx56
-rw-r--r--chart2/source/controller/main/ChartFrameloader.cxx185
-rw-r--r--chart2/source/controller/main/ChartFrameloader.hxx67
-rw-r--r--chart2/source/controller/main/ChartModelClone.cxx227
-rw-r--r--chart2/source/controller/main/ChartModelClone.hxx75
-rw-r--r--chart2/source/controller/main/ChartTransferable.cxx161
-rw-r--r--chart2/source/controller/main/ChartTransferable.hxx60
-rw-r--r--chart2/source/controller/main/ChartWindow.cxx376
-rw-r--r--chart2/source/controller/main/CommandDispatch.cxx141
-rw-r--r--chart2/source/controller/main/CommandDispatch.hxx130
-rw-r--r--chart2/source/controller/main/CommandDispatchContainer.cxx201
-rw-r--r--chart2/source/controller/main/ControllerCommandDispatch.cxx844
-rw-r--r--chart2/source/controller/main/ControllerCommandDispatch.hxx119
-rw-r--r--chart2/source/controller/main/DragMethod_Base.cxx75
-rw-r--r--chart2/source/controller/main/DragMethod_Base.hxx59
-rw-r--r--chart2/source/controller/main/DragMethod_PieSegment.cxx151
-rw-r--r--chart2/source/controller/main/DragMethod_PieSegment.hxx54
-rw-r--r--chart2/source/controller/main/DragMethod_RotateDiagram.cxx230
-rw-r--r--chart2/source/controller/main/DragMethod_RotateDiagram.hxx86
-rw-r--r--chart2/source/controller/main/DrawCommandDispatch.cxx613
-rw-r--r--chart2/source/controller/main/DrawCommandDispatch.hxx74
-rw-r--r--chart2/source/controller/main/ElementSelector.cxx319
-rw-r--r--chart2/source/controller/main/ElementSelector.hxx99
-rw-r--r--chart2/source/controller/main/FeatureCommandDispatchBase.cxx94
-rw-r--r--chart2/source/controller/main/FeatureCommandDispatchBase.hxx135
-rw-r--r--chart2/source/controller/main/ObjectHierarchy.cxx727
-rw-r--r--chart2/source/controller/main/PositionAndSizeHelper.cxx179
-rw-r--r--chart2/source/controller/main/SelectionHelper.cxx651
-rw-r--r--chart2/source/controller/main/ShapeController.cxx673
-rw-r--r--chart2/source/controller/main/ShapeController.hxx81
-rw-r--r--chart2/source/controller/main/StatusBarCommandDispatch.cxx127
-rw-r--r--chart2/source/controller/main/StatusBarCommandDispatch.hxx94
-rw-r--r--chart2/source/controller/main/ToolbarController.cxx121
-rw-r--r--chart2/source/controller/main/UndoActions.cxx115
-rw-r--r--chart2/source/controller/main/UndoActions.hxx101
-rw-r--r--chart2/source/controller/main/UndoCommandDispatch.cxx146
-rw-r--r--chart2/source/controller/main/UndoCommandDispatch.hxx69
-rw-r--r--chart2/source/controller/main/UndoGuard.cxx152
-rw-r--r--chart2/source/controller/main/UndoGuard.hxx115
-rw-r--r--chart2/source/controller/sidebar/Chart2PanelFactory.cxx147
-rw-r--r--chart2/source/controller/sidebar/Chart2PanelFactory.hxx56
-rw-r--r--chart2/source/controller/sidebar/ChartAreaPanel.cxx551
-rw-r--r--chart2/source/controller/sidebar/ChartAreaPanel.hxx86
-rw-r--r--chart2/source/controller/sidebar/ChartAxisPanel.cxx373
-rw-r--r--chart2/source/controller/sidebar/ChartAxisPanel.hxx93
-rw-r--r--chart2/source/controller/sidebar/ChartColorWrapper.cxx237
-rw-r--r--chart2/source/controller/sidebar/ChartColorWrapper.hxx68
-rw-r--r--chart2/source/controller/sidebar/ChartElementsPanel.cxx663
-rw-r--r--chart2/source/controller/sidebar/ChartElementsPanel.hxx116
-rw-r--r--chart2/source/controller/sidebar/ChartErrorBarPanel.cxx425
-rw-r--r--chart2/source/controller/sidebar/ChartErrorBarPanel.hxx91
-rw-r--r--chart2/source/controller/sidebar/ChartLinePanel.cxx290
-rw-r--r--chart2/source/controller/sidebar/ChartLinePanel.hxx87
-rw-r--r--chart2/source/controller/sidebar/ChartSeriesPanel.cxx474
-rw-r--r--chart2/source/controller/sidebar/ChartSeriesPanel.hxx110
-rw-r--r--chart2/source/controller/sidebar/ChartSidebarModifyListener.cxx39
-rw-r--r--chart2/source/controller/sidebar/ChartSidebarModifyListener.hxx42
-rw-r--r--chart2/source/controller/sidebar/ChartSidebarSelectionListener.cxx84
-rw-r--r--chart2/source/controller/sidebar/ChartSidebarSelectionListener.hxx52
-rw-r--r--chart2/source/controller/sidebar/ChartTypePanel.cxx438
-rw-r--r--chart2/source/controller/sidebar/ChartTypePanel.hxx121
-rw-r--r--chart2/source/controller/uitest/uiobject.cxx202
-rw-r--r--chart2/source/inc/Axis.hxx145
-rw-r--r--chart2/source/inc/AxisHelper.hxx211
-rw-r--r--chart2/source/inc/AxisIndexDefines.hxx30
-rw-r--r--chart2/source/inc/BaseCoordinateSystem.hxx129
-rw-r--r--chart2/source/inc/BaseGFXHelper.hxx86
-rw-r--r--chart2/source/inc/CachedDataSequence.hxx164
-rw-r--r--chart2/source/inc/ChangingResource.hxx46
-rw-r--r--chart2/source/inc/CharacterProperties.hxx136
-rw-r--r--chart2/source/inc/ChartModelHelper.hxx77
-rw-r--r--chart2/source/inc/ChartResourceGroupDlgs.hxx63
-rw-r--r--chart2/source/inc/ChartResourceGroups.hxx147
-rw-r--r--chart2/source/inc/ChartType.hxx161
-rw-r--r--chart2/source/inc/ChartTypeDialogController.hxx325
-rw-r--r--chart2/source/inc/ChartTypeHelper.hxx90
-rw-r--r--chart2/source/inc/ChartTypeTemplate.hxx283
-rw-r--r--chart2/source/inc/ChartTypeTemplateProvider.hxx37
-rw-r--r--chart2/source/inc/ChartViewHelper.hxx44
-rw-r--r--chart2/source/inc/CloneHelper.hxx80
-rw-r--r--chart2/source/inc/ColorPerPointHelper.hxx50
-rw-r--r--chart2/source/inc/CommonConverters.hxx219
-rw-r--r--chart2/source/inc/CommonFunctors.hxx126
-rw-r--r--chart2/source/inc/ConfigColorScheme.hxx76
-rw-r--r--chart2/source/inc/ControllerLockGuard.hxx95
-rw-r--r--chart2/source/inc/DataInterpreter.hxx154
-rw-r--r--chart2/source/inc/DataSeries.hxx190
-rw-r--r--chart2/source/inc/DataSeriesHelper.hxx170
-rw-r--r--chart2/source/inc/DataSeriesProperties.hxx48
-rw-r--r--chart2/source/inc/DataSource.hxx66
-rw-r--r--chart2/source/inc/DataSourceHelper.hxx126
-rw-r--r--chart2/source/inc/DataTable.hxx87
-rw-r--r--chart2/source/inc/Diagram.hxx381
-rw-r--r--chart2/source/inc/DiagramHelper.hxx116
-rw-r--r--chart2/source/inc/DisposeHelper.hxx49
-rw-r--r--chart2/source/inc/ErrorBar.hxx137
-rw-r--r--chart2/source/inc/EventListenerHelper.hxx121
-rw-r--r--chart2/source/inc/ExplicitCategoriesProvider.hxx115
-rw-r--r--chart2/source/inc/ExponentialRegressionCurveCalculator.hxx62
-rw-r--r--chart2/source/inc/FastPropertyIdRanges.hxx46
-rw-r--r--chart2/source/inc/FillProperties.hxx74
-rw-r--r--chart2/source/inc/FormattedString.hxx142
-rw-r--r--chart2/source/inc/FormattedStringHelper.hxx44
-rw-r--r--chart2/source/inc/GridProperties.hxx98
-rw-r--r--chart2/source/inc/InternalData.hxx96
-rw-r--r--chart2/source/inc/InternalDataProvider.hxx220
-rw-r--r--chart2/source/inc/LabeledDataSequence.hxx88
-rw-r--r--chart2/source/inc/Legend.hxx106
-rw-r--r--chart2/source/inc/LegendHelper.hxx58
-rw-r--r--chart2/source/inc/LifeTime.hxx198
-rw-r--r--chart2/source/inc/LinePropertiesHelper.hxx68
-rw-r--r--chart2/source/inc/LinearRegressionCurveCalculator.hxx51
-rw-r--r--chart2/source/inc/LogarithmicRegressionCurveCalculator.hxx60
-rw-r--r--chart2/source/inc/MeanValueRegressionCurveCalculator.hxx59
-rw-r--r--chart2/source/inc/MediaDescriptorHelper.hxx90
-rw-r--r--chart2/source/inc/ModifyListenerCallBack.hxx57
-rw-r--r--chart2/source/inc/ModifyListenerHelper.hxx254
-rw-r--r--chart2/source/inc/MovingAverageRegressionCurveCalculator.hxx63
-rw-r--r--chart2/source/inc/NameContainer.hxx82
-rw-r--r--chart2/source/inc/NumberFormatterWrapper.hxx68
-rw-r--r--chart2/source/inc/OPropertySet.hxx233
-rw-r--r--chart2/source/inc/ObjectIdentifier.hxx262
-rw-r--r--chart2/source/inc/PolynomialRegressionCurveCalculator.hxx61
-rw-r--r--chart2/source/inc/PopupRequest.hxx42
-rw-r--r--chart2/source/inc/PotentialRegressionCurveCalculator.hxx61
-rw-r--r--chart2/source/inc/PropertyHelper.hxx148
-rw-r--r--chart2/source/inc/RangeHighlighter.hxx107
-rw-r--r--chart2/source/inc/ReferenceSizeProvider.hxx130
-rw-r--r--chart2/source/inc/RegressionCalculationHelper.hxx134
-rw-r--r--chart2/source/inc/RegressionCurveCalculator.hxx103
-rw-r--r--chart2/source/inc/RegressionCurveHelper.hxx202
-rw-r--r--chart2/source/inc/RegressionCurveModel.hxx242
-rw-r--r--chart2/source/inc/RelativePositionHelper.hxx103
-rw-r--r--chart2/source/inc/RelativeSizeHelper.hxx56
-rw-r--r--chart2/source/inc/ResId.hxx31
-rw-r--r--chart2/source/inc/Scaling.hxx159
-rw-r--r--chart2/source/inc/SceneProperties.hxx82
-rw-r--r--chart2/source/inc/StackMode.hxx35
-rw-r--r--chart2/source/inc/StatisticsHelper.hxx102
-rw-r--r--chart2/source/inc/ThreeDHelper.hxx100
-rw-r--r--chart2/source/inc/Title.hxx109
-rw-r--r--chart2/source/inc/TitleHelper.hxx94
-rw-r--r--chart2/source/inc/UncachedDataSequence.hxx173
-rw-r--r--chart2/source/inc/UserDefinedProperties.hxx54
-rw-r--r--chart2/source/inc/WeakListenerAdapter.hxx86
-rw-r--r--chart2/source/inc/WrappedDefaultProperty.hxx51
-rw-r--r--chart2/source/inc/WrappedDirectStateProperty.hxx40
-rw-r--r--chart2/source/inc/WrappedIgnoreProperty.hxx62
-rw-r--r--chart2/source/inc/WrappedProperty.hxx86
-rw-r--r--chart2/source/inc/WrappedPropertySet.hxx123
-rw-r--r--chart2/source/inc/XMLRangeHelper.hxx60
-rw-r--r--chart2/source/inc/charttoolsdllapi.hxx32
-rw-r--r--chart2/source/inc/chartview/ChartSfxItemIds.hxx236
-rw-r--r--chart2/source/inc/chartview/DataPointSymbolSupplier.hxx42
-rw-r--r--chart2/source/inc/chartview/DrawModelWrapper.hxx92
-rw-r--r--chart2/source/inc/chartview/ExplicitScaleValues.hxx154
-rw-r--r--chart2/source/inc/chartview/ExplicitValueProvider.hxx100
-rw-r--r--chart2/source/inc/chartview/chartviewdllapi.hxx32
-rw-r--r--chart2/source/inc/defines.hxx24
-rw-r--r--chart2/source/inc/res_BarGeometry.hxx45
-rw-r--r--chart2/source/inc/servicenames.hxx53
-rw-r--r--chart2/source/inc/servicenames_charttypes.hxx44
-rw-r--r--chart2/source/inc/servicenames_coosystems.hxx26
-rw-r--r--chart2/source/model/filter/XMLFilter.cxx761
-rw-r--r--chart2/source/model/inc/CartesianCoordinateSystem.hxx71
-rw-r--r--chart2/source/model/inc/PolarCoordinateSystem.hxx71
-rw-r--r--chart2/source/model/inc/StockBar.hxx92
-rw-r--r--chart2/source/model/inc/XMLFilter.hxx164
-rw-r--r--chart2/source/model/main/Axis.cxx601
-rw-r--r--chart2/source/model/main/BaseCoordinateSystem.cxx387
-rw-r--r--chart2/source/model/main/CartesianCoordinateSystem.cxx160
-rw-r--r--chart2/source/model/main/ChartModel.cxx1339
-rw-r--r--chart2/source/model/main/ChartModel_Persistence.cxx802
-rw-r--r--chart2/source/model/main/DataPoint.cxx255
-rw-r--r--chart2/source/model/main/DataPoint.hxx109
-rw-r--r--chart2/source/model/main/DataPointProperties.cxx544
-rw-r--r--chart2/source/model/main/DataPointProperties.hxx103
-rw-r--r--chart2/source/model/main/DataSeries.cxx733
-rw-r--r--chart2/source/model/main/DataSeriesProperties.cxx99
-rw-r--r--chart2/source/model/main/DataTable.cxx209
-rw-r--r--chart2/source/model/main/Diagram.cxx2288
-rw-r--r--chart2/source/model/main/FormattedString.cxx276
-rw-r--r--chart2/source/model/main/GridProperties.cxx201
-rw-r--r--chart2/source/model/main/Legend.cxx275
-rw-r--r--chart2/source/model/main/PageBackground.cxx198
-rw-r--r--chart2/source/model/main/PageBackground.hxx100
-rw-r--r--chart2/source/model/main/PolarCoordinateSystem.cxx158
-rw-r--r--chart2/source/model/main/StockBar.cxx173
-rw-r--r--chart2/source/model/main/Title.cxx343
-rw-r--r--chart2/source/model/main/UndoManager.cxx350
-rw-r--r--chart2/source/model/main/UndoManager.hxx92
-rw-r--r--chart2/source/model/main/Wall.cxx155
-rw-r--r--chart2/source/model/main/Wall.hxx95
-rw-r--r--chart2/source/model/template/AreaChartType.cxx84
-rw-r--r--chart2/source/model/template/AreaChartType.hxx53
-rw-r--r--chart2/source/model/template/AreaChartTypeTemplate.cxx188
-rw-r--r--chart2/source/model/template/AreaChartTypeTemplate.hxx80
-rw-r--r--chart2/source/model/template/BarChartType.cxx90
-rw-r--r--chart2/source/model/template/BarChartType.hxx55
-rw-r--r--chart2/source/model/template/BarChartTypeTemplate.cxx254
-rw-r--r--chart2/source/model/template/BarChartTypeTemplate.hxx94
-rw-r--r--chart2/source/model/template/BubbleChartType.cxx182
-rw-r--r--chart2/source/model/template/BubbleChartType.hxx71
-rw-r--r--chart2/source/model/template/BubbleChartTypeTemplate.cxx156
-rw-r--r--chart2/source/model/template/BubbleChartTypeTemplate.hxx73
-rw-r--r--chart2/source/model/template/BubbleDataInterpreter.cxx277
-rw-r--r--chart2/source/model/template/BubbleDataInterpreter.hxx46
-rw-r--r--chart2/source/model/template/CandleStickChartType.cxx309
-rw-r--r--chart2/source/model/template/CandleStickChartType.hxx75
-rw-r--r--chart2/source/model/template/ChartType.cxx315
-rw-r--r--chart2/source/model/template/ChartTypeManager.cxx589
-rw-r--r--chart2/source/model/template/ChartTypeTemplate.cxx867
-rw-r--r--chart2/source/model/template/ColumnChartType.cxx168
-rw-r--r--chart2/source/model/template/ColumnChartType.hxx63
-rw-r--r--chart2/source/model/template/ColumnLineChartTypeTemplate.cxx355
-rw-r--r--chart2/source/model/template/ColumnLineChartTypeTemplate.hxx93
-rw-r--r--chart2/source/model/template/ColumnLineDataInterpreter.cxx79
-rw-r--r--chart2/source/model/template/ColumnLineDataInterpreter.hxx44
-rw-r--r--chart2/source/model/template/DataInterpreter.cxx444
-rw-r--r--chart2/source/model/template/FilledNetChartType.cxx89
-rw-r--r--chart2/source/model/template/FilledNetChartType.hxx49
-rw-r--r--chart2/source/model/template/LineChartType.cxx183
-rw-r--r--chart2/source/model/template/LineChartType.hxx61
-rw-r--r--chart2/source/model/template/LineChartTypeTemplate.cxx327
-rw-r--r--chart2/source/model/template/LineChartTypeTemplate.hxx83
-rw-r--r--chart2/source/model/template/NetChartType.cxx175
-rw-r--r--chart2/source/model/template/NetChartType.hxx75
-rw-r--r--chart2/source/model/template/NetChartTypeTemplate.cxx174
-rw-r--r--chart2/source/model/template/NetChartTypeTemplate.hxx68
-rw-r--r--chart2/source/model/template/PieChartType.cxx208
-rw-r--r--chart2/source/model/template/PieChartType.hxx68
-rw-r--r--chart2/source/model/template/PieChartTypeTemplate.cxx568
-rw-r--r--chart2/source/model/template/PieChartTypeTemplate.hxx104
-rw-r--r--chart2/source/model/template/ScatterChartType.cxx221
-rw-r--r--chart2/source/model/template/ScatterChartType.hxx68
-rw-r--r--chart2/source/model/template/ScatterChartTypeTemplate.cxx344
-rw-r--r--chart2/source/model/template/ScatterChartTypeTemplate.hxx84
-rw-r--r--chart2/source/model/template/StockChartTypeTemplate.cxx434
-rw-r--r--chart2/source/model/template/StockChartTypeTemplate.hxx111
-rw-r--r--chart2/source/model/template/StockDataInterpreter.cxx341
-rw-r--r--chart2/source/model/template/StockDataInterpreter.hxx56
-rw-r--r--chart2/source/model/template/XYDataInterpreter.cxx242
-rw-r--r--chart2/source/model/template/XYDataInterpreter.hxx46
-rw-r--r--chart2/source/tools/AxisHelper.cxx1109
-rw-r--r--chart2/source/tools/BaseGFXHelper.cxx236
-rw-r--r--chart2/source/tools/CachedDataSequence.cxx350
-rw-r--r--chart2/source/tools/CharacterProperties.cxx460
-rw-r--r--chart2/source/tools/ChartModelHelper.cxx223
-rw-r--r--chart2/source/tools/ChartTypeHelper.cxx724
-rw-r--r--chart2/source/tools/ChartViewHelper.cxx62
-rw-r--r--chart2/source/tools/ColorPerPointHelper.cxx80
-rw-r--r--chart2/source/tools/CommonConverters.cxx601
-rw-r--r--chart2/source/tools/ConfigColorScheme.cxx180
-rw-r--r--chart2/source/tools/ControllerLockGuard.cxx83
-rw-r--r--chart2/source/tools/DataSeriesHelper.cxx680
-rw-r--r--chart2/source/tools/DataSource.cxx88
-rw-r--r--chart2/source/tools/DataSourceHelper.cxx477
-rw-r--r--chart2/source/tools/DiagramHelper.cxx552
-rw-r--r--chart2/source/tools/ErrorBar.cxx469
-rw-r--r--chart2/source/tools/ExplicitCategoriesProvider.cxx564
-rw-r--r--chart2/source/tools/ExponentialRegressionCurveCalculator.cxx221
-rw-r--r--chart2/source/tools/FillProperties.cxx202
-rw-r--r--chart2/source/tools/FormattedStringHelper.cxx59
-rw-r--r--chart2/source/tools/InternalData.cxx550
-rw-r--r--chart2/source/tools/InternalDataProvider.cxx1552
-rw-r--r--chart2/source/tools/LabeledDataSequence.cxx177
-rw-r--r--chart2/source/tools/LegendHelper.cxx122
-rw-r--r--chart2/source/tools/LifeTime.cxx430
-rw-r--r--chart2/source/tools/LinePropertiesHelper.cxx193
-rw-r--r--chart2/source/tools/LinearRegressionCurveCalculator.cxx69
-rw-r--r--chart2/source/tools/LogarithmicRegressionCurveCalculator.cxx186
-rw-r--r--chart2/source/tools/MeanValueRegressionCurveCalculator.cxx126
-rw-r--r--chart2/source/tools/MediaDescriptorHelper.cxx225
-rw-r--r--chart2/source/tools/ModifyListenerCallBack.cxx111
-rw-r--r--chart2/source/tools/ModifyListenerHelper.cxx74
-rw-r--r--chart2/source/tools/MovingAverageRegressionCurveCalculator.cxx173
-rw-r--r--chart2/source/tools/NameContainer.cxx128
-rw-r--r--chart2/source/tools/NumberFormatterWrapper.cxx149
-rw-r--r--chart2/source/tools/OPropertySet.cxx465
-rw-r--r--chart2/source/tools/ObjectIdentifier.cxx1405
-rw-r--r--chart2/source/tools/PolynomialRegressionCurveCalculator.cxx392
-rw-r--r--chart2/source/tools/PopupRequest.cxx31
-rw-r--r--chart2/source/tools/PotentialRegressionCurveCalculator.cxx188
-rw-r--r--chart2/source/tools/PropertyHelper.cxx312
-rw-r--r--chart2/source/tools/RangeHighlighter.cxx394
-rw-r--r--chart2/source/tools/ReferenceSizeProvider.cxx340
-rw-r--r--chart2/source/tools/RegressionCurveCalculator.cxx219
-rw-r--r--chart2/source/tools/RegressionCurveHelper.cxx917
-rw-r--r--chart2/source/tools/RegressionCurveModel.cxx551
-rw-r--r--chart2/source/tools/RegressionEquation.cxx301
-rw-r--r--chart2/source/tools/RegressionEquation.hxx116
-rw-r--r--chart2/source/tools/RelativePositionHelper.cxx381
-rw-r--r--chart2/source/tools/RelativeSizeHelper.cxx120
-rw-r--r--chart2/source/tools/ResId.cxx30
-rw-r--r--chart2/source/tools/Scaling.cxx267
-rw-r--r--chart2/source/tools/SceneProperties.cxx333
-rw-r--r--chart2/source/tools/StatisticsHelper.cxx361
-rw-r--r--chart2/source/tools/ThreeDHelper.cxx826
-rw-r--r--chart2/source/tools/TitleHelper.cxx424
-rw-r--r--chart2/source/tools/UncachedDataSequence.cxx317
-rw-r--r--chart2/source/tools/UserDefinedProperties.cxx61
-rw-r--r--chart2/source/tools/WeakListenerAdapter.cxx46
-rw-r--r--chart2/source/tools/WrappedDefaultProperty.cxx78
-rw-r--r--chart2/source/tools/WrappedDirectStateProperty.cxx45
-rw-r--r--chart2/source/tools/WrappedIgnoreProperty.cxx113
-rw-r--r--chart2/source/tools/WrappedProperty.cxx126
-rw-r--r--chart2/source/tools/WrappedPropertySet.cxx445
-rw-r--r--chart2/source/tools/XMLRangeHelper.cxx393
-rw-r--r--chart2/source/view/axes/DateHelper.cxx93
-rw-r--r--chart2/source/view/axes/DateScaling.cxx205
-rw-r--r--chart2/source/view/axes/DateScaling.hxx95
-rw-r--r--chart2/source/view/axes/MinimumAndMaximumSupplier.cxx203
-rw-r--r--chart2/source/view/axes/ScaleAutomatism.cxx989
-rw-r--r--chart2/source/view/axes/TickmarkProperties.hxx37
-rw-r--r--chart2/source/view/axes/Tickmarks.cxx318
-rw-r--r--chart2/source/view/axes/Tickmarks.hxx162
-rw-r--r--chart2/source/view/axes/Tickmarks_Dates.cxx151
-rw-r--r--chart2/source/view/axes/Tickmarks_Dates.hxx49
-rw-r--r--chart2/source/view/axes/Tickmarks_Equidistant.cxx626
-rw-r--r--chart2/source/view/axes/Tickmarks_Equidistant.hxx146
-rw-r--r--chart2/source/view/axes/VAxisBase.cxx254
-rw-r--r--chart2/source/view/axes/VAxisBase.hxx118
-rw-r--r--chart2/source/view/axes/VAxisOrGridBase.cxx70
-rw-r--r--chart2/source/view/axes/VAxisOrGridBase.hxx63
-rw-r--r--chart2/source/view/axes/VAxisProperties.cxx413
-rw-r--r--chart2/source/view/axes/VAxisProperties.hxx172
-rw-r--r--chart2/source/view/axes/VCartesianAxis.cxx2028
-rw-r--r--chart2/source/view/axes/VCartesianAxis.hxx165
-rw-r--r--chart2/source/view/axes/VCartesianCoordinateSystem.cxx222
-rw-r--r--chart2/source/view/axes/VCartesianCoordinateSystem.hxx49
-rw-r--r--chart2/source/view/axes/VCartesianGrid.cxx298
-rw-r--r--chart2/source/view/axes/VCartesianGrid.hxx52
-rw-r--r--chart2/source/view/axes/VCoordinateSystem.cxx579
-rw-r--r--chart2/source/view/axes/VPolarAngleAxis.cxx205
-rw-r--r--chart2/source/view/axes/VPolarAngleAxis.hxx51
-rw-r--r--chart2/source/view/axes/VPolarAxis.cxx64
-rw-r--r--chart2/source/view/axes/VPolarAxis.hxx54
-rw-r--r--chart2/source/view/axes/VPolarCoordinateSystem.cxx196
-rw-r--r--chart2/source/view/axes/VPolarCoordinateSystem.hxx53
-rw-r--r--chart2/source/view/axes/VPolarGrid.cxx248
-rw-r--r--chart2/source/view/axes/VPolarGrid.hxx71
-rw-r--r--chart2/source/view/axes/VPolarRadiusAxis.cxx165
-rw-r--r--chart2/source/view/axes/VPolarRadiusAxis.hxx72
-rw-r--r--chart2/source/view/charttypes/AreaChart.cxx952
-rw-r--r--chart2/source/view/charttypes/AreaChart.hxx86
-rw-r--r--chart2/source/view/charttypes/BarChart.cxx973
-rw-r--r--chart2/source/view/charttypes/BarChart.hxx118
-rw-r--r--chart2/source/view/charttypes/BarPositionHelper.cxx73
-rw-r--r--chart2/source/view/charttypes/BarPositionHelper.hxx44
-rw-r--r--chart2/source/view/charttypes/BubbleChart.cxx362
-rw-r--r--chart2/source/view/charttypes/BubbleChart.hxx60
-rw-r--r--chart2/source/view/charttypes/CandleStickChart.cxx314
-rw-r--r--chart2/source/view/charttypes/CandleStickChart.hxx54
-rw-r--r--chart2/source/view/charttypes/CategoryPositionHelper.cxx82
-rw-r--r--chart2/source/view/charttypes/CategoryPositionHelper.hxx57
-rw-r--r--chart2/source/view/charttypes/NetChart.cxx642
-rw-r--r--chart2/source/view/charttypes/NetChart.hxx74
-rw-r--r--chart2/source/view/charttypes/PieChart.cxx1723
-rw-r--r--chart2/source/view/charttypes/PieChart.hxx145
-rw-r--r--chart2/source/view/charttypes/Splines.cxx872
-rw-r--r--chart2/source/view/charttypes/Splines.hxx48
-rw-r--r--chart2/source/view/charttypes/VSeriesPlotter.cxx2950
-rw-r--r--chart2/source/view/diagram/VDiagram.cxx703
-rw-r--r--chart2/source/view/inc/Clipping.hxx61
-rw-r--r--chart2/source/view/inc/DataTableView.hxx88
-rw-r--r--chart2/source/view/inc/DateHelper.hxx43
-rw-r--r--chart2/source/view/inc/LabelAlignment.hxx38
-rw-r--r--chart2/source/view/inc/LabelPositionHelper.hxx66
-rw-r--r--chart2/source/view/inc/LegendEntryProvider.hxx98
-rw-r--r--chart2/source/view/inc/Linear3DTransformation.hxx46
-rw-r--r--chart2/source/view/inc/MinimumAndMaximumSupplier.hxx92
-rw-r--r--chart2/source/view/inc/PlotterBase.hxx79
-rw-r--r--chart2/source/view/inc/PlottingPositionHelper.hxx463
-rw-r--r--chart2/source/view/inc/PolarLabelPositionHelper.hxx70
-rw-r--r--chart2/source/view/inc/PropertyMapper.hxx125
-rw-r--r--chart2/source/view/inc/ScaleAutomatism.hxx144
-rw-r--r--chart2/source/view/inc/ShapeFactory.hxx301
-rw-r--r--chart2/source/view/inc/Stripe.hxx71
-rw-r--r--chart2/source/view/inc/VCoordinateSystem.hxx209
-rw-r--r--chart2/source/view/inc/VDataSeries.hxx266
-rw-r--r--chart2/source/view/inc/VDiagram.hxx117
-rw-r--r--chart2/source/view/inc/VLegendSymbolFactory.hxx53
-rw-r--r--chart2/source/view/inc/VLineProperties.hxx49
-rw-r--r--chart2/source/view/inc/VPolarTransformation.hxx45
-rw-r--r--chart2/source/view/inc/VSeriesPlotter.hxx448
-rw-r--r--chart2/source/view/inc/ViewDefines.hxx35
-rw-r--r--chart2/source/view/main/AxisUsage.hxx143
-rw-r--r--chart2/source/view/main/ChartItemPool.cxx250
-rw-r--r--chart2/source/view/main/ChartItemPool.hxx48
-rw-r--r--chart2/source/view/main/ChartView.cxx2080
-rw-r--r--chart2/source/view/main/Clipping.cxx425
-rw-r--r--chart2/source/view/main/DataPointSymbolSupplier.cxx44
-rw-r--r--chart2/source/view/main/DataTableView.cxx558
-rw-r--r--chart2/source/view/main/DrawModelWrapper.cxx330
-rw-r--r--chart2/source/view/main/ExplicitValueProvider.cxx203
-rw-r--r--chart2/source/view/main/LabelPositionHelper.cxx468
-rw-r--r--chart2/source/view/main/Linear3DTransformation.cxx124
-rw-r--r--chart2/source/view/main/PlotterBase.cxx106
-rw-r--r--chart2/source/view/main/PlottingPositionHelper.cxx704
-rw-r--r--chart2/source/view/main/PolarLabelPositionHelper.cxx158
-rw-r--r--chart2/source/view/main/PropertyMapper.cxx561
-rw-r--r--chart2/source/view/main/SeriesPlotterContainer.cxx746
-rw-r--r--chart2/source/view/main/SeriesPlotterContainer.hxx160
-rw-r--r--chart2/source/view/main/ShapeFactory.cxx2554
-rw-r--r--chart2/source/view/main/Stripe.cxx347
-rw-r--r--chart2/source/view/main/VButton.cxx136
-rw-r--r--chart2/source/view/main/VButton.hxx86
-rw-r--r--chart2/source/view/main/VDataSeries.cxx1122
-rw-r--r--chart2/source/view/main/VLegend.cxx1110
-rw-r--r--chart2/source/view/main/VLegend.hxx91
-rw-r--r--chart2/source/view/main/VLegendSymbolFactory.cxx188
-rw-r--r--chart2/source/view/main/VLineProperties.cxx85
-rw-r--r--chart2/source/view/main/VPolarTransformation.cxx88
-rw-r--r--chart2/source/view/main/VTitle.cxx159
-rw-r--r--chart2/source/view/main/VTitle.hxx73
-rw-r--r--chart2/uiconfig/accelerator/en-US/default.xml46
-rw-r--r--chart2/uiconfig/menubar/menubar.xml177
-rw-r--r--chart2/uiconfig/popupmenu/draw.xml31
-rw-r--r--chart2/uiconfig/popupmenu/drawtext.xml29
-rw-r--r--chart2/uiconfig/statusbar/statusbar.xml23
-rw-r--r--chart2/uiconfig/toolbar/arrowshapes.xml51
-rw-r--r--chart2/uiconfig/toolbar/basicshapes.xml48
-rw-r--r--chart2/uiconfig/toolbar/calloutshapes.xml29
-rw-r--r--chart2/uiconfig/toolbar/drawbar.xml37
-rw-r--r--chart2/uiconfig/toolbar/flowchartshapes.xml53
-rw-r--r--chart2/uiconfig/toolbar/standardbar.xml37
-rw-r--r--chart2/uiconfig/toolbar/starshapes.xml34
-rw-r--r--chart2/uiconfig/toolbar/symbolshapes.xml41
-rw-r--r--chart2/uiconfig/toolbar/toolbar.xml47
-rw-r--r--chart2/uiconfig/ui/3dviewdialog.ui101
-rw-r--r--chart2/uiconfig/ui/attributedialog.ui115
-rw-r--r--chart2/uiconfig/ui/chardialog.ui253
-rw-r--r--chart2/uiconfig/ui/chartdatadialog.ui361
-rw-r--r--chart2/uiconfig/ui/charttypedialog.ui101
-rw-r--r--chart2/uiconfig/ui/columnfragment.ui35
-rw-r--r--chart2/uiconfig/ui/combobox.ui38
-rw-r--r--chart2/uiconfig/ui/datarangedialog.ui194
-rw-r--r--chart2/uiconfig/ui/dlg_DataLabel.ui676
-rw-r--r--chart2/uiconfig/ui/dlg_InsertDataTable.ui215
-rw-r--r--chart2/uiconfig/ui/dlg_InsertErrorBars.ui695
-rw-r--r--chart2/uiconfig/ui/dlg_InsertLegend.ui224
-rw-r--r--chart2/uiconfig/ui/imagefragment.ui22
-rw-r--r--chart2/uiconfig/ui/insertaxisdlg.ui294
-rw-r--r--chart2/uiconfig/ui/insertgriddlg.ui299
-rw-r--r--chart2/uiconfig/ui/inserttitledlg.ui410
-rw-r--r--chart2/uiconfig/ui/paradialog.ui302
-rw-r--r--chart2/uiconfig/ui/sidebaraxis.ui131
-rw-r--r--chart2/uiconfig/ui/sidebarelements.ui469
-rw-r--r--chart2/uiconfig/ui/sidebarerrorbar.ui210
-rw-r--r--chart2/uiconfig/ui/sidebarseries.ui242
-rw-r--r--chart2/uiconfig/ui/sidebartype.ui347
-rw-r--r--chart2/uiconfig/ui/smoothlinesdlg.ui253
-rw-r--r--chart2/uiconfig/ui/steppedlinesdlg.ui244
-rw-r--r--chart2/uiconfig/ui/titlerotationtabpage.ui185
-rw-r--r--chart2/uiconfig/ui/tp_3D_SceneAppearance.ui144
-rw-r--r--chart2/uiconfig/ui/tp_3D_SceneGeometry.ui196
-rw-r--r--chart2/uiconfig/ui/tp_3D_SceneIllumination.ui489
-rw-r--r--chart2/uiconfig/ui/tp_AxisPositions.ui681
-rw-r--r--chart2/uiconfig/ui/tp_ChartType.ui525
-rw-r--r--chart2/uiconfig/ui/tp_DataLabel.ui579
-rw-r--r--chart2/uiconfig/ui/tp_DataPointOption.ui75
-rw-r--r--chart2/uiconfig/ui/tp_DataSource.ui493
-rw-r--r--chart2/uiconfig/ui/tp_DataTable.ui115
-rw-r--r--chart2/uiconfig/ui/tp_ErrorBars.ui621
-rw-r--r--chart2/uiconfig/ui/tp_LegendPosition.ui242
-rw-r--r--chart2/uiconfig/ui/tp_PolarOptions.ui181
-rw-r--r--chart2/uiconfig/ui/tp_RangeChooser.ui289
-rw-r--r--chart2/uiconfig/ui/tp_Scale.ui661
-rw-r--r--chart2/uiconfig/ui/tp_SeriesToAxis.ui447
-rw-r--r--chart2/uiconfig/ui/tp_Trendline.ui699
-rw-r--r--chart2/uiconfig/ui/tp_axisLabel.ui430
-rw-r--r--chart2/uiconfig/ui/wizelementspage.ui496
-rw-r--r--chart2/workbench/addin/exports.dxp2
-rw-r--r--chart2/workbench/addin/makefile.mk76
-rw-r--r--chart2/workbench/addin/sampleaddin.cxx652
-rw-r--r--chart2/workbench/addin/sampleaddin.def6
-rw-r--r--chart2/workbench/addin/sampleaddin.hxx152
1215 files changed, 204016 insertions, 0 deletions
diff --git a/chart2/AllLangMoTarget_chart.mk b/chart2/AllLangMoTarget_chart.mk
new file mode 100644
index 0000000000..bf3b19b387
--- /dev/null
+++ b/chart2/AllLangMoTarget_chart.mk
@@ -0,0 +1,13 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+$(eval $(call gb_AllLangMoTarget_AllLangMoTarget,chart))
+
+$(eval $(call gb_AllLangMoTarget_set_polocation,chart,chart2))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_common_functors.mk b/chart2/CppunitTest_chart2_common_functors.mk
new file mode 100644
index 0000000000..947ae6b4e9
--- /dev/null
+++ b/chart2/CppunitTest_chart2_common_functors.mk
@@ -0,0 +1,43 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,chart2_common_functors))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,chart2_common_functors, \
+ chart2/qa/unit/common_functor_test \
+))
+
+$(eval $(call gb_CppunitTest_add_defs,chart2_common_functors,\
+ -DOOO_DLLIMPLEMENTATION_CHARTTOOLS \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,chart2_common_functors, \
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,chart2_common_functors, \
+ cppu \
+ cppuhelper \
+ sal \
+ salhelper \
+))
+
+$(eval $(call gb_CppunitTest_set_include,chart2_common_functors,\
+ -I$(SRCDIR)/chart2/inc \
+ -I$(SRCDIR)/chart2/source/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_common_functors))
+
+$(eval $(call gb_CppunitTest_use_ure,chart2_common_functors))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_dialogs_test.mk b/chart2/CppunitTest_chart2_dialogs_test.mk
new file mode 100644
index 0000000000..bfbd0d3d37
--- /dev/null
+++ b/chart2/CppunitTest_chart2_dialogs_test.mk
@@ -0,0 +1,76 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitScreenShot,chart2_dialogs_test))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,chart2_dialogs_test, \
+ chart2/qa/unit/chart2-dialogs-test \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_dialogs_test))
+
+$(eval $(call gb_CppunitTest_set_include,chart2_dialogs_test,\
+ -I$(SRCDIR)/chart2/source/inc \
+ -I$(SRCDIR)/chart2/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,chart2_dialogs_test, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ i18nlangtag \
+ i18nutil \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_external,chart2_dialogs_test,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_ure,chart2_dialogs_test))
+$(eval $(call gb_CppunitTest_use_vcl_non_headless_with_windows,chart2_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_rdb,chart2_dialogs_test,services))
+
+$(eval $(call gb_CppunitTest_use_configuration,chart2_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,chart2_dialogs_test,\
+ modules/schart \
+ svx \
+))
+
+$(eval $(call gb_CppunitTest_use_packages,chart2_dialogs_test,\
+ extras_palettes \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_dump.mk b/chart2/CppunitTest_chart2_dump.mk
new file mode 100644
index 0000000000..fa46774d76
--- /dev/null
+++ b/chart2/CppunitTest_chart2_dump.mk
@@ -0,0 +1,128 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,chart2_dump))
+
+$(eval $(call gb_CppunitTest_use_externals,chart2_dump, \
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,chart2_dump, \
+ chart2/qa/extras/chart2dump/chart2dump \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,chart2_dump, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ vcl \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sc \
+ sw \
+ sd \
+ sfx \
+ sot \
+ subsequenttest \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ xo \
+ sw \
+))
+
+$(eval $(call gb_CppunitTest_set_include,chart2_dump,\
+ -I$(SRCDIR)/chart2/qa/extras \
+ -I$(SRCDIR)/chart2/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_dump))
+
+$(eval $(call gb_CppunitTest_use_ure,chart2_dump))
+$(eval $(call gb_CppunitTest_use_vcl,chart2_dump))
+
+$(eval $(call gb_CppunitTest_use_components,chart2_dump,\
+ basic/util/sb \
+ animations/source/animcore/animcore \
+ chart2/source/controller/chartcontroller \
+ chart2/source/chartcore \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ embeddedobj/util/embobj \
+ eventattacher/source/evtatt \
+ filter/source/config/cache/filterconfig1 \
+ filter/source/storagefilterdetect/storagefd \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ sc/util/sc \
+ sc/util/scd \
+ sc/util/scfilt \
+ sw/util/sw \
+ sw/util/swd \
+ sw/util/msword \
+ sd/util/sd \
+ sd/util/sdd \
+ $(call gb_Helper_optional,SCRIPTING, \
+ sc/util/vbaobj) \
+ scaddins/source/analysis/analysis \
+ scaddins/source/datefunc/date \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ svtools/util/svt \
+ svx/util/svx \
+ svx/util/svxcore \
+ toolkit/util/tk \
+ vcl/vcl.common \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ uui/util/uui \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ writerfilter/util/writerfilter \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,chart2_dump))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_export.mk b/chart2/CppunitTest_chart2_export.mk
new file mode 100644
index 0000000000..df390d9b42
--- /dev/null
+++ b/chart2/CppunitTest_chart2_export.mk
@@ -0,0 +1,15 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+# empty second argument (i.e. no 1)
+$(eval $(call chart2_export_test,))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_export2.mk b/chart2/CppunitTest_chart2_export2.mk
new file mode 100644
index 0000000000..0584cbfc99
--- /dev/null
+++ b/chart2/CppunitTest_chart2_export2.mk
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call chart2_export_test,2))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_export3.mk b/chart2/CppunitTest_chart2_export3.mk
new file mode 100644
index 0000000000..3b3e2ed0b5
--- /dev/null
+++ b/chart2/CppunitTest_chart2_export3.mk
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call chart2_export_test,3))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_geometry.mk b/chart2/CppunitTest_chart2_geometry.mk
new file mode 100644
index 0000000000..1b31bf9d72
--- /dev/null
+++ b/chart2/CppunitTest_chart2_geometry.mk
@@ -0,0 +1,143 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,chart2_geometry))
+
+$(eval $(call gb_CppunitTest_use_externals,chart2_geometry, \
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,chart2_geometry, \
+ chart2/qa/extras/chart2geometry \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,chart2_geometry, \
+ $(call gb_Helper_optional,AVMEDIA,avmedia) \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sc \
+ sw \
+ sd \
+ sfx \
+ sot \
+ subsequenttest \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_set_include,chart2_geometry,\
+ -I$(SRCDIR)/chart2/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_geometry))
+
+$(eval $(call gb_CppunitTest_use_ure,chart2_geometry))
+$(eval $(call gb_CppunitTest_use_vcl,chart2_geometry))
+
+$(eval $(call gb_CppunitTest_use_components,chart2_geometry,\
+ basic/util/sb \
+ animations/source/animcore/animcore \
+ chart2/source/controller/chartcontroller \
+ chart2/source/chartcore \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ dbaccess/util/dba \
+ embeddedobj/util/embobj \
+ emfio/emfio \
+ eventattacher/source/evtatt \
+ filter/source/config/cache/filterconfig1 \
+ filter/source/odfflatxml/odfflatxml \
+ filter/source/storagefilterdetect/storagefd \
+ filter/source/xmlfilteradaptor/xmlfa \
+ filter/source/xmlfilterdetect/xmlfd \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ sc/util/sc \
+ sc/util/scd \
+ sc/util/scfilt \
+ sw/util/sw \
+ sw/util/swd \
+ sw/util/msword \
+ sd/util/sd \
+ sd/util/sdd \
+ $(call gb_Helper_optional,SCRIPTING, \
+ sc/util/vbaobj) \
+ scaddins/source/analysis/analysis \
+ scaddins/source/datefunc/date \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ svtools/util/svt \
+ svx/util/svx \
+ svx/util/svxcore \
+ toolkit/util/tk \
+ vcl/vcl.common \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ writerfilter/util/writerfilter \
+ xmloff/util/xo \
+ xmlscript/util/xmlscript \
+))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,chart2_geometry, \
+ modules/swriter \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,chart2_geometry))
+
+$(eval $(call gb_CppunitTest_add_arguments,chart2_geometry, \
+ -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \
+))
+
+$(call gb_CppunitTest_get_target,chart2_geometry): $(call gb_Package_get_target,postprocess_images)
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_import.mk b/chart2/CppunitTest_chart2_import.mk
new file mode 100644
index 0000000000..d568b88553
--- /dev/null
+++ b/chart2/CppunitTest_chart2_import.mk
@@ -0,0 +1,15 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+# empty second argument (i.e. no 1)
+$(eval $(call chart2_import_test,))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_import2.mk b/chart2/CppunitTest_chart2_import2.mk
new file mode 100644
index 0000000000..0e4a967de5
--- /dev/null
+++ b/chart2/CppunitTest_chart2_import2.mk
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call chart2_import_test,2))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_pivot_chart_test.mk b/chart2/CppunitTest_chart2_pivot_chart_test.mk
new file mode 100644
index 0000000000..cd8157a5ad
--- /dev/null
+++ b/chart2/CppunitTest_chart2_pivot_chart_test.mk
@@ -0,0 +1,135 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,chart2_pivot_chart_test))
+
+$(eval $(call gb_CppunitTest_use_externals,chart2_pivot_chart_test, \
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,chart2_pivot_chart_test, \
+ chart2/qa/extras/PivotChartTest \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,chart2_pivot_chart_test, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ vcl \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sc \
+ sw \
+ sd \
+ sfx \
+ sot \
+ subsequenttest \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ xo \
+ sw \
+))
+
+$(eval $(call gb_CppunitTest_set_include,chart2_pivot_chart_test,\
+ -I$(SRCDIR)/chart2/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_pivot_chart_test))
+$(eval $(call gb_CppunitTest_use_ure,chart2_pivot_chart_test))
+$(eval $(call gb_CppunitTest_use_vcl,chart2_pivot_chart_test))
+
+$(eval $(call gb_CppunitTest_use_components,chart2_pivot_chart_test,\
+ basic/util/sb \
+ animations/source/animcore/animcore \
+ chart2/source/controller/chartcontroller \
+ chart2/source/chartcore \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ dbaccess/util/dba \
+ embeddedobj/util/embobj \
+ eventattacher/source/evtatt \
+ filter/source/config/cache/filterconfig1 \
+ filter/source/odfflatxml/odfflatxml \
+ filter/source/storagefilterdetect/storagefd \
+ filter/source/xmlfilteradaptor/xmlfa \
+ filter/source/xmlfilterdetect/xmlfd \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ sc/util/sc \
+ sc/util/scd \
+ sc/util/scfilt \
+ sw/util/sw \
+ sw/util/swd \
+ sw/util/msword \
+ sd/util/sd \
+ sd/util/sdd \
+ $(call gb_Helper_optional,SCRIPTING, \
+ sc/util/vbaobj) \
+ scaddins/source/analysis/analysis \
+ scaddins/source/datefunc/date \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ svtools/util/svt \
+ svx/util/svx \
+ svx/util/svxcore \
+ toolkit/util/tk \
+ vcl/vcl.common \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ writerfilter/util/writerfilter \
+ xmloff/util/xo \
+ xmlscript/util/xmlscript \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,chart2_pivot_chart_test))
+
+$(eval $(call gb_CppunitTest_add_arguments,chart2_pivot_chart_test, \
+ -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_trendcalculators.mk b/chart2/CppunitTest_chart2_trendcalculators.mk
new file mode 100644
index 0000000000..87c76ab103
--- /dev/null
+++ b/chart2/CppunitTest_chart2_trendcalculators.mk
@@ -0,0 +1,131 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,chart2_trendcalculators))
+
+$(eval $(call gb_CppunitTest_use_externals,chart2_trendcalculators, \
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,chart2_trendcalculators, \
+ chart2/qa/extras/chart2_trendcalculators \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,chart2_trendcalculators, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ vcl \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sc \
+ sw \
+ sd \
+ sfx \
+ sot \
+ subsequenttest \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ xo \
+ sw \
+))
+
+$(eval $(call gb_CppunitTest_set_include,chart2_trendcalculators,\
+ -I$(SRCDIR)/chart2/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_trendcalculators))
+
+$(eval $(call gb_CppunitTest_use_ure,chart2_trendcalculators))
+$(eval $(call gb_CppunitTest_use_vcl,chart2_trendcalculators))
+
+$(eval $(call gb_CppunitTest_use_components,chart2_trendcalculators,\
+ basic/util/sb \
+ animations/source/animcore/animcore \
+ chart2/source/controller/chartcontroller \
+ chart2/source/chartcore \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ embeddedobj/util/embobj \
+ eventattacher/source/evtatt \
+ filter/source/config/cache/filterconfig1 \
+ filter/source/odfflatxml/odfflatxml \
+ filter/source/storagefilterdetect/storagefd \
+ filter/source/xmlfilteradaptor/xmlfa \
+ filter/source/xmlfilterdetect/xmlfd \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ sc/util/sc \
+ sc/util/scd \
+ sc/util/scfilt \
+ sw/util/sw \
+ sw/util/swd \
+ sw/util/msword \
+ sd/util/sd \
+ sd/util/sdd \
+ $(call gb_Helper_optional,SCRIPTING, \
+ sc/util/vbaobj) \
+ scaddins/source/analysis/analysis \
+ scaddins/source/datefunc/date \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ svtools/util/svt \
+ svx/util/svx \
+ svx/util/svxcore \
+ toolkit/util/tk \
+ vcl/vcl.common \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ writerfilter/util/writerfilter \
+ xmloff/util/xo \
+ xmlscript/util/xmlscript \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,chart2_trendcalculators))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_uichart.mk b/chart2/CppunitTest_chart2_uichart.mk
new file mode 100644
index 0000000000..9e464e0a7c
--- /dev/null
+++ b/chart2/CppunitTest_chart2_uichart.mk
@@ -0,0 +1,58 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,chart2_uichart))
+
+$(eval $(call gb_CppunitTest_use_externals,chart2_uichart, \
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,chart2_uichart, \
+ chart2/qa/extras/uichart \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,chart2_uichart, \
+ comphelper \
+ cppu \
+ cppuhelper \
+ i18nlangtag \
+ sal \
+ sc \
+ sfx \
+ subsequenttest \
+ svl \
+ svl \
+ svx \
+ svxcore \
+ test \
+ tl \
+ unotest \
+ utl \
+ vcl \
+))
+
+$(eval $(call gb_CppunitTest_set_include,chart2_uichart,\
+ -I$(SRCDIR)/chart2/qa/extras \
+ -I$(SRCDIR)/chart2/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_uichart))
+
+$(eval $(call gb_CppunitTest_use_ure,chart2_uichart))
+$(eval $(call gb_CppunitTest_use_vcl,chart2_uichart))
+
+$(eval $(call gb_CppunitTest_use_rdb,chart2_uichart,services))
+
+$(eval $(call gb_CppunitTest_use_configuration,chart2_uichart))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/CppunitTest_chart2_xshape.mk b/chart2/CppunitTest_chart2_xshape.mk
new file mode 100644
index 0000000000..e964891e88
--- /dev/null
+++ b/chart2/CppunitTest_chart2_xshape.mk
@@ -0,0 +1,135 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,chart2_xshape))
+
+$(eval $(call gb_CppunitTest_use_externals,chart2_xshape, \
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,chart2_xshape, \
+ chart2/qa/extras/xshape/chart2xshape \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,chart2_xshape, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ vcl \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sc \
+ sw \
+ sd \
+ sfx \
+ sot \
+ subsequenttest \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ xo \
+ sw \
+))
+
+$(eval $(call gb_CppunitTest_set_include,chart2_xshape,\
+ -I$(SRCDIR)/chart2/qa/extras \
+ -I$(SRCDIR)/chart2/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_xshape))
+
+$(eval $(call gb_CppunitTest_use_ure,chart2_xshape))
+$(eval $(call gb_CppunitTest_use_vcl,chart2_xshape))
+
+$(eval $(call gb_CppunitTest_use_components,chart2_xshape,\
+ basic/util/sb \
+ animations/source/animcore/animcore \
+ chart2/source/controller/chartcontroller \
+ chart2/source/chartcore \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ embeddedobj/util/embobj \
+ eventattacher/source/evtatt \
+ filter/source/config/cache/filterconfig1 \
+ filter/source/storagefilterdetect/storagefd \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ sc/util/sc \
+ sc/util/scd \
+ sc/util/scfilt \
+ sw/util/sw \
+ sw/util/swd \
+ sw/util/msword \
+ sd/util/sd \
+ sd/util/sdd \
+ $(call gb_Helper_optional,SCRIPTING, \
+ sc/util/vbaobj) \
+ scaddins/source/analysis/analysis \
+ scaddins/source/datefunc/date \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ svtools/util/svt \
+ svx/util/svx \
+ svx/util/svxcore \
+ toolkit/util/tk \
+ vcl/vcl.common \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ uui/util/uui \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ writerfilter/util/writerfilter \
+ xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,chart2_xshape))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,chart2_xshape, \
+ modules/scalc \
+ modules/simpress \
+ sfx \
+ svt \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/IwyuFilter_chart2.yaml b/chart2/IwyuFilter_chart2.yaml
new file mode 100644
index 0000000000..219c179a0d
--- /dev/null
+++ b/chart2/IwyuFilter_chart2.yaml
@@ -0,0 +1,751 @@
+---
+assumeFilename: chart2/source/controller/main/ChartWindow.cxx
+excludelist:
+ chart2/inc/ChartModel.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/X3DChartWindowProvider.hpp
+ - com/sun/star/chart2/XChartDocument.hpp
+ - com/sun/star/chart2/XTitled.hpp
+ - com/sun/star/chart2/data/XDataReceiver.hpp
+ - com/sun/star/chart2/data/XDataSource.hpp
+ - com/sun/star/container/XChild.hpp
+ - com/sun/star/datatransfer/XTransferable.hpp
+ - com/sun/star/document/XDocumentPropertiesSupplier.hpp
+ - com/sun/star/document/XStorageBasedDocument.hpp
+ - com/sun/star/document/XUndoManagerSupplier.hpp
+ - com/sun/star/embed/XVisualObject.hpp
+ - com/sun/star/frame/XLoadable.hpp
+ - com/sun/star/frame/XStorable2.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ - com/sun/star/lang/XMultiServiceFactory.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/lang/XUnoTunnel.hpp
+ - com/sun/star/qa/XDumper.hpp
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XCloseable.hpp
+ - com/sun/star/util/XModifiable.hpp
+ - com/sun/star/util/XNumberFormatsSupplier.hpp
+ - com/sun/star/util/XUpdatable.hpp
+ chart2/inc/ChartView.hxx:
+ # base class has to be a complete type
+ - com/sun/star/util/XModeChangeBroadcaster.hpp
+ - com/sun/star/util/XUpdatable2.hpp
+ - com/sun/star/beans/XPropertySet.hpp
+ - com/sun/star/datatransfer/XTransferable.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ - com/sun/star/lang/XMultiServiceFactory.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/lang/XUnoTunnel.hpp
+ - com/sun/star/qa/XDumper.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/inc/AxisHelper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/ScaleData.hpp
+ chart2/source/inc/CachedDataSequence.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/data/XDataSequence.hpp
+ - com/sun/star/chart2/data/XNumericalDataSequence.hpp
+ - com/sun/star/chart2/data/XTextualDataSequence.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ chart2/source/inc/ConfigColorScheme.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/XColorScheme.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/inc/chartview/ChartSfxItemIds.hxx:
+ # Needed for TypedWhichId macros
+ - class SvxSizeItem
+ - class SfxIntegerListItem
+ - class SfxBoolItem
+ - class SfxStringItem
+ - class SfxInt32Item
+ - class SfxUInt32Item
+ - class SvxChartIndicateItem
+ - class SvxDoubleItem
+ - class SvxBrushItem
+ chart2/source/inc/chartview/ExplicitScaleValues.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/XScaling.hpp
+ chart2/source/inc/DataSource.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/data/XDataSink.hpp
+ - com/sun/star/chart2/data/XDataSource.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/inc/ErrorBar.hxx:
+ # base class has to be a complete type
+ - com/sun/star/beans/XPropertySet.hpp
+ - com/sun/star/beans/XPropertyState.hpp
+ - com/sun/star/chart2/data/XDataSink.hpp
+ - com/sun/star/chart2/data/XDataSource.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/inc/InternalData.hxx:
+ # complete type is needed in the inline dtor
+ - com/sun/star/uno/Sequence.hxx
+ chart2/source/inc/InternalDataProvider.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/data/XRangeXMLConversion.hpp
+ - com/sun/star/chart2/XAnyDescriptionAccess.hpp
+ - com/sun/star/chart2/XInternalDataProvider.hpp
+ - com/sun/star/chart/XDateCategories.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ chart2/source/inc/LabeledDataSequence.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/data/XLabeledDataSequence2.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/inc/ModifyListenerHelper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/inc/NameContainer.hxx:
+ # base class has to be a complete type
+ - com/sun/star/container/XNameContainer.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ chart2/source/inc/NumberFormatterWrapper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/util/XNumberFormatsSupplier.hpp
+ chart2/source/inc/PropertyHelper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/uno/Any.hxx
+ chart2/source/inc/PopupRequest.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/XRequestCallback.hpp
+ chart2/source/inc/RangeHighlighter.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/data/XRangeHighlighter.hpp
+ - com/sun/star/view/XSelectionChangeListener.hpp
+ chart2/source/inc/RegressionCurveCalculator.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/XRegressionCurveCalculator.hpp
+ chart2/source/inc/Scaling.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/XScaling.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/lang/XServiceName.hpp
+ chart2/source/inc/UncachedDataSequence.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/data/XDataSequence.hpp
+ - com/sun/star/chart2/data/XNumericalDataSequence.hpp
+ - com/sun/star/chart2/data/XTextualDataSequence.hpp
+ - com/sun/star/container/XIndexReplace.hpp
+ - com/sun/star/container/XNamed.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifiable.hpp
+ chart2/source/inc/WeakListenerAdapter.hxx:
+ # base class has to be a complete type
+ - com/sun/star/view/XSelectionChangeListener.hpp
+ chart2/source/inc/WrappedProperty.hxx:
+ # Needed for implicit dtor
+ - com/sun/star/uno/Any.hxx
+ chart2/source/inc/WrappedPropertySet.hxx:
+ # base class has to be a complete type
+ - com/sun/star/beans/XMultiPropertySet.hpp
+ - com/sun/star/beans/XMultiPropertyStates.hpp
+ - com/sun/star/beans/XPropertySet.hpp
+ - com/sun/star/beans/XPropertyState.hpp
+ chart2/source/model/inc/StockBar.hxx:
+ # base class has to be a complete type
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/model/inc/XMLFilter.hxx:
+ # base class has to be a complete type
+ - com/sun/star/document/XExporter.hpp
+ - com/sun/star/document/XFilter.hpp
+ - com/sun/star/document/XImporter.hpp
+ - com/sun/star/lang/XMultiServiceFactory.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/model/filter/XMLFilter.cxx:
+ # Actually used
+ - com/sun/star/lang/XMultiComponentFactory.hpp
+ chart2/source/model/main/ChartModel_Persistence.cxx:
+ # Needed for implicit dtor
+ - BaseCoordinateSystem.hxx
+ chart2/source/model/main/DataPoint.hxx:
+ # base class has to be a complete type
+ - com/sun/star/container/XChild.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/model/main/Axis.cxx:
+ # Needed for template
+ - com/sun/star/awt/Size.hpp
+ chart2/source/model/main/DataPointProperties.cxx:
+ # Needed for template
+ - com/sun/star/chart2/XDataPointCustomLabelField.hpp
+ chart2/source/model/main/Diagram.cxx:
+ # Needed for template
+ - com/sun/star/chart2/RelativePosition.hpp
+ - com/sun/star/chart2/RelativeSize.hpp
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/inc/FormattedString.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/XDataPointCustomLabelField.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/model/main/GridProperties.hxx:
+ # base class has to be a complete type
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/model/main/Legend.cxx:
+ # Needed for template
+ - com/sun/star/awt/Size.hpp
+ - com/sun/star/chart2/RelativePosition.hpp
+ - com/sun/star/chart2/RelativeSize.hpp
+ chart2/source/model/main/PageBackground.hxx:
+ # base class has to be a complete type
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/model/main/Title.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/XTitle.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/model/main/Title.cxx:
+ # Needed for template
+ - com/sun/star/awt/Size.hpp
+ - com/sun/star/chart2/RelativePosition.hpp
+ chart2/source/model/main/UndoManager.hxx:
+ # base class has to be a complete type
+ - com/sun/star/document/XUndoManager.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ chart2/source/model/main/Wall.hxx:
+ # base class has to be a complete type
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/model/template/AreaChartTypeTemplate.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/BubbleChartTypeTemplate.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/BarChartTypeTemplate.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/ChartTypeTemplate.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/ChartTypeManager.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/ColumnLineChartTypeTemplate.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/NetChartTypeTemplate.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/LineChartTypeTemplate.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/ScatterChartTypeTemplate.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/StockChartTypeTemplate.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/PieChartTypeTemplate.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/model/template/XYDataInterpreter.cxx:
+ # Used after #ifdef
+ - sal/log.hxx
+ chart2/source/tools/AxisHelper.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/tools/BaseGFXHelper.cxx:
+ # Actually used
+ - com/sun/star/drawing/PolyPolygonShape3D.hpp
+ - com/sun/star/awt/Rectangle.hpp
+ chart2/source/tools/CommonConverters.cxx:
+ # Actually used
+ - com/sun/star/awt/Rectangle.hpp
+ - com/sun/star/drawing/PolyPolygonBezierCoords.hpp
+ - com/sun/star/chart2/data/XDataSequence.hpp
+ chart2/source/tools/ErrorBar.cxx:
+ # Actually used
+ - com/sun/star/drawing/LineStyle.hpp
+ - com/sun/star/util/Color.hpp
+ - com/sun/star/drawing/LineJoint.hpp
+ chart2/source/tools/ExplicitCategoriesProvider.cxx:
+ # Needed for implicit dtor
+ - ChartType.hxx
+ chart2/source/tools/CharacterProperties.cxx:
+ # Actually used
+ - com/sun/star/beans/XMultiPropertySet.hpp
+ chart2/source/tools/DataSourceHelper.cxx:
+ # Actually used
+ - com/sun/star/chart2/data/XLabeledDataSequence.hpp
+ chart2/source/tools/InternalDataProvider.cxx:
+ # Needed for implicit dtor
+ - BaseCoordinateSystem.hxx
+ chart2/source/tools/LegendHelper.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/tools/LinePropertiesHelper.cxx:
+ # Needed for template
+ - com/sun/star/drawing/LineDash.hpp
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ chart2/source/tools/LifeTime.cxx:
+ # Has to be complete type
+ - com/sun/star/util/CloseVetoException.hpp
+ chart2/source/tools/MediaDescriptorHelper.cxx:
+ # Needed for template
+ - com/sun/star/embed/XStorage.hpp
+ # Actually used
+ - com/sun/star/beans/PropertyValue.hpp
+ chart2/source/tools/ObjectIdentifier.cxx:
+ # Needed for template
+ - com/sun/star/drawing/XShape.hpp
+ chart2/source/tools/RangeHighlighter.cxx:
+ # Needed for template
+ - com/sun/star/drawing/XShape.hpp
+ # Actually used
+ - com/sun/star/view/XSelectionSupplier.hpp
+ chart2/source/tools/RegressionCurveHelper.cxx:
+ # Actually used
+ - com/sun/star/chart2/XRegressionCurveCalculator.hpp
+ # Needed for implicit dtor
+ - ChartType.hxx
+ chart2/source/tools/RegressionEquation.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/XTitle.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloneable.hpp
+ - com/sun/star/util/XModifyBroadcaster.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/tools/RegressionEquation.cxx:
+ # Needed for template
+ - com/sun/star/awt/Size.hpp
+ - com/sun/star/chart2/RelativePosition.hpp
+ chart2/source/tools/RelativePositionHelper.cxx:
+ # Actually used
+ - com/sun/star/awt/Size.hpp
+ - com/sun/star/chart2/RelativeSize.hpp
+ # Needed for rtl::math::round
+ - rtl/math.hxx
+ chart2/source/tools/RelativeSizeHelper.cxx:
+ # Actually used
+ - com/sun/star/awt/Size.hpp
+ - com/sun/star/beans/XPropertySet.hpp
+ chart2/source/tools/PropertyHelper.cxx:
+ # Actually used
+ - com/sun/star/lang/XMultiServiceFactory.hpp
+ chart2/source/tools/StatisticsHelper.cxx:
+ # Actually used
+ - com/sun/star/chart2/data/XDataProvider.hpp
+ chart2/source/tools/UserDefinedProperties.cxx:
+ # Needs a complete type
+ - com/sun/star/beans/Property.hpp
+ # Needed for template
+ - com/sun/star/container/XNameContainer.hpp
+ chart2/source/tools/WrappedProperty.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertyState.hpp
+ chart2/source/view/inc/VLineProperties.hxx:
+ # base class has to be a complete type
+ - com/sun/star/uno/Reference.h
+ chart2/source/view/axes/DateScaling.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/XScaling.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/lang/XServiceName.hpp
+ chart2/source/view/axes/VAxisProperties.cxx:
+ # Needed for rtl::math::round
+ - rtl/math.hxx
+ chart2/source/view/axes/VPolarAngleAxis.cxx:
+ # Needed for implicit dtor
+ - Axis.hxx
+ chart2/source/view/axes/VPolarRadiusAxis.cxx:
+ # Needed for implicit dtor
+ - Axis.hxx
+ chart2/source/view/axes/VCartesianGrid.hxx:
+ # base class has to be a complete type
+ - com/sun/star/beans/XPropertySet.hpp
+ chart2/source/view/charttypes/BarChart.cxx:
+ # comphelper::ScopeGuard being used
+ - comphelper/scopeguard.hxx
+ chart2/source/view/diagram/VDiagram.cxx:
+ # Needed for implicit dtor
+ - ChartType.hxx
+ chart2/source/view/main/LabelPositionHelper.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ # Actually used
+ - rtl/math.hxx
+ chart2/source/view/main/PropertyMapper.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ chart2/source/view/main/ShapeFactory.cxx:
+ # Needed for template
+ - com/sun/star/graphic/XGraphic.hpp
+ # Actually used
+ - com/sun/star/chart2/XFormattedString.hpp
+ chart2/source/view/main/ChartView.cxx:
+ # comphelper::ScopeGuard being used
+ - comphelper/scopeguard.hxx
+ chart2/source/view/main/VLineProperties.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ chart2/source/view/main/VTitle.cxx:
+ # Actually used
+ - com/sun/star/chart2/XTitle.hpp
+ chart2/source/controller/inc/AccessibleTextHelper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/accessibility/XAccessibleContext.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ chart2/source/controller/inc/AccessibleChartView.hxx:
+ # base class has to be a complete type
+ - com/sun/star/lang/XInitialization.hpp
+ - com/sun/star/view/XSelectionChangeListener.hpp
+ chart2/source/controller/inc/AccessibleBase.hxx:
+ # base class has to be a complete type
+ - com/sun/star/accessibility/XAccessible.hpp
+ - com/sun/star/accessibility/XAccessibleContext.hpp
+ - com/sun/star/accessibility/XAccessibleComponent.hpp
+ - com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/lang/XEventListener.hpp
+ chart2/source/controller/inc/CharacterPropertyItemConverter.hxx:
+ # has to be a complete type
+ - com/sun/star/awt/Size.hpp
+ chart2/source/controller/inc/ChartToolbarController.hxx:
+ # base class has to be a complete type
+ - com/sun/star/frame/XStatusListener.hpp
+ - com/sun/star/frame/XToolbarController.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XUpdatable.hpp
+ chart2/source/controller/inc/ChartController.hxx:
+ # base class has to be a complete type
+ - com/sun/star/frame/XController.hpp
+ - com/sun/star/frame/XDispatchProvider.hpp
+ - com/sun/star/frame/XLayoutManagerListener.hpp
+ - com/sun/star/ui/XContextMenuInterception.hpp
+ - com/sun/star/util/XModeChangeListener.hpp
+ - com/sun/star/lang/XMultiServiceFactory.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XCloseListener.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/controller/inc/ChartDocumentWrapper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart/XChartDocument.hpp
+ - com/sun/star/drawing/XDrawPageSupplier.hpp
+ - com/sun/star/lang/XMultiServiceFactory.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/uno/XAggregation.hpp
+ chart2/source/controller/inc/dlg_ChartType.hxx:
+ # Needed for vclptr type
+ - namespace chart { class ChartTypeTabPage; }
+ chart2/source/controller/inc/dlg_DataEditor.hxx:
+ # Needed for vclptr type
+ - namespace chart { class DataBrowser; }
+ chart2/source/controller/inc/dlg_View3D.hxx:
+ - namespace chart { class ThreeD_SceneAppearance_TabPage; }
+ - namespace chart { class ThreeD_SceneGeometry_TabPage; }
+ - namespace chart { class ThreeD_SceneIllumination_TabPage; }
+ chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx:
+ # Needed for vclptr type
+ - class ColorListBox
+ chart2/source/controller/inc/ItemPropertyMap.hxx:
+ # base class has to be a complete type
+ - map
+ chart2/source/controller/inc/RangeSelectionHelper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/uno/Sequence.h
+ chart2/source/controller/inc/RangeSelectionListener.hxx:
+ # base class has to be a complete type
+ - com/sun/star/sheet/XRangeSelectionListener.hpp
+ chart2/source/controller/accessibility/AccessibleChartShape.hxx:
+ # base class has to be a complete type
+ - AccessibleBase.hxx
+ - com/sun/star/accessibility/XAccessibleExtendedComponent.hpp
+ chart2/source/controller/accessibility/AccessibleChartElement.hxx:
+ # base class has to be a complete type
+ - AccessibleBase.hxx
+ - com/sun/star/accessibility/XAccessibleExtendedComponent.hpp
+ chart2/source/controller/accessibility/AccessibleChartView.cxx:
+ # Actually used
+ - com/sun/star/view/XSelectionSupplier.hpp
+ chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx:
+ # Needed for rtl::math::round
+ - rtl/math.hxx
+ chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx:
+ # Needed for complex variable type
+ - com/sun/star/util/XRefreshable.hpp
+ chart2/source/controller/chartapiwrapper/WrappedAddInProperty.cxx:
+ # Needed for complex variable type
+ - com/sun/star/util/XRefreshable.hpp
+ chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ - com/sun/star/beans/XPropertyState.hpp
+ chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx:
+ # Needed for implicit dtor
+ - BaseCoordinateSystem.hxx
+ chart2/source/controller/dialogs/ChartTypeDialogController.cxx:
+ # Needed for implicit dtor
+ - DataSeries.hxx
+ - BaseCoordinateSystem.hxx
+ chart2/source/controller/dialogs/DialogModel.cxx:
+ # Needed for implicit dtor
+ - LabeledDataSequence.hxx
+ chart2/source/controller/dialogs/dlg_CreationWizard.cxx:
+ # Needed for implicit dtor
+ - ChartTypeTemplate.hxx
+ chart2/source/controller/dialogs/dlg_DataEditor.cxx:
+ # Needed for direct member access
+ - com/sun/star/awt/XWindow.hpp
+ chart2/source/controller/dialogs/tp_3D_SceneGeometry.cxx:
+ # Needed for implicit dtor
+ - ChartType.hxx
+ chart2/source/controller/dialogs/tp_AxisPositions.cxx:
+ # Actually used
+ - rtl/math.hxx
+ chart2/source/controller/dialogs/tp_3D_SceneIllumination.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ chart2/source/controller/dialogs/tp_DataSource.cxx:
+ # Needed for implicit dtor
+ - ChartTypeTemplate.hxx
+ - LabeledDataSequence.hxx
+ chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx:
+ # Needed for rtl::math::round
+ - rtl/math.hxx
+ chart2/source/controller/itemsetwrapper/ItemConverter.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ chart2/source/controller/itemsetwrapper/LegendItemConverter.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ chart2/source/controller/itemsetwrapper/TitleItemConverter.cxx:
+ # Needed for rtl::math::round
+ - rtl/math.hxx
+ chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx:
+ # Needed for implicit dtor
+ - RegressionCurveModel.hxx
+ chart2/source/controller/itemsetwrapper/RegressionEquationItemConverter.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ chart2/source/controller/itemsetwrapper/GraphicPropertyItemConverter.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ - com/sun/star/lang/XMultiServiceFactory.hpp
+ chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySet.hpp
+ # Needed for rtl::math::round
+ - rtl/math.hxx
+ chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx:
+ # Needed for rtl::math::round
+ - rtl/math.hxx
+ # Needed for implicit dtor
+ - ChartType.hxx
+ - Diagram.hxx
+ chart2/source/controller/main/ChartModelClone.hxx:
+ # Needed for implicit dtor
+ - com/sun/star/uno/Any.hxx
+ chart2/source/controller/main/ChartController.cxx:
+ # Needed for implicit dtor
+ - com/sun/star/awt/XWindowPeer.hpp
+ chart2/source/controller/main/ChartFrameloader.hxx:
+ # base class has to be a complete type
+ - com/sun/star/frame/XSynchronousFrameLoader.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/controller/main/ChartFrameloader.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ chart2/source/controller/main/CommandDispatch.hxx:
+ # base class has to be a complete type
+ - com/sun/star/frame/XDispatch.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ - comphelper/interfacecontainer2.hxx
+ chart2/source/controller/main/ControllerCommandDispatch.hxx:
+ # base class has to be a complete type
+ - CommandDispatch.hxx
+ - com/sun/star/view/XSelectionChangeListener.hpp
+ chart2/source/controller/main/ElementSelector.hxx:
+ # base class has to be a complete type
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/controller/main/StatusBarCommandDispatch.hxx:
+ # base class has to be a complete type
+ - CommandDispatch.hxx
+ - com/sun/star/view/XSelectionChangeListener.hpp
+ chart2/source/controller/main/ChartController_Insert.cxx:
+ # Needed for implicit dtor
+ - Legend.hxx
+ chart2/source/controller/main/ChartController_Position.cxx:
+ # Needed for implicit dtor
+ - ChartModel.hxx
+ chart2/source/controller/main/ChartController_Properties.cxx:
+ # Needed for implicit dtor
+ - RegressionCurveModel.hxx
+ chart2/source/controller/main/ChartController_TextEdit.cxx:
+ # Needed for implicit dtor
+ - ChartModel.hxx
+ chart2/source/controller/main/ChartController_Tools.cxx:
+ # Needed for template
+ - com/sun/star/graphic/XGraphic.hpp
+ chart2/source/controller/main/ControllerCommandDispatch.cxx:
+ # Needed for implicit dtor
+ - Axis.hxx
+ chart2/source/controller/main/DragMethod_RotateDiagram.cxx:
+ # Needed for implicit dtor
+ - ChartType.hxx
+ chart2/source/controller/main/PositionAndSizeHelper.cxx:
+ # Actually used
+ - com/sun/star/awt/Rectangle.hpp
+ # Needed for implicit dtor
+ - Diagram.hxx
+ chart2/source/controller/main/SelectionHelper.cxx:
+ # Needed for implicit dtor
+ - Diagram.hxx
+ chart2/source/controller/main/StatusBarCommandDispatch.cxx:
+ # Actually used
+ - com/sun/star/view/XSelectionSupplier.hpp
+ chart2/source/controller/main/UndoGuard.cxx:
+ # Actually used
+ - com/sun/star/document/XUndoManager.hpp
+ chart2/source/controller/main/UndoActions.hxx:
+ # base class has to be a complete type
+ - com/sun/star/document/XUndoAction.hpp
+ chart2/source/controller/sidebar/Chart2PanelFactory.hxx:
+ # base class has to be a complete type
+ - com/sun/star/ui/XUIElementFactory.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/controller/sidebar/ChartSeriesPanel.cxx:
+ # Needed for implicit dtor
+ - RegressionCurveModel.hxx
+ chart2/source/controller/sidebar/ChartSidebarModifyListener.hxx:
+ # base class has to be a complete type
+ - com/sun/star/util/XModifyListener.hpp
+ chart2/source/controller/sidebar/ChartSidebarSelectionListener.hxx:
+ # base class has to be a complete type
+ - com/sun/star/view/XSelectionChangeListener.hpp
+ chart2/source/controller/chartapiwrapper/ChartDataWrapper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/XAnyDescriptionAccess.hpp
+ - com/sun/star/chart/XDateCategories.hpp
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/uno/XComponent.hpp
+ chart2/source/controller/chartapiwrapper/AxisWrapper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart/XAxis.hpp
+ - com/sun/star/drawing/XShape.hpp
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/util/XNumberFormatsSupplier.hpp
+ - WrappedPropertySet.hxx
+ chart2/source/controller/chartapiwrapper/AreaWrapper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/drawing/XShape.hpp
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - WrappedPropertySet.hxx
+ chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XEventListener.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - WrappedPropertySet.hxx
+ chart2/source/controller/chartapiwrapper/DiagramWrapper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/chart2/XDiagramProvider.hpp
+ - com/sun/star/chart/X3DDefaultSetter.hpp
+ - com/sun/star/chart/X3DDisplay.hpp
+ - com/sun/star/chart/XAxisSupplier.hpp
+ - com/sun/star/chart/XAxisZSupplier.hpp
+ - com/sun/star/chart/XDiagram.hpp
+ - com/sun/star/chart/XDiagramPositioning.hpp
+ - com/sun/star/chart/XSecondAxisTitleSupplier.hpp
+ - com/sun/star/chart/XStatisticDisplay.hpp
+ - com/sun/star/chart/XTwoAxisXSupplier.hpp
+ - com/sun/star/chart/XTwoAxisYSupplier.hpp
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - WrappedPropertySet.hxx
+ chart2/source/controller/chartapiwrapper/GridWrapper.hxx:
+ # base class has to be a complete type
+ - WrappedPropertySet.hxx
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/controller/chartapiwrapper/LegendWrapper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/drawing/XShape.hpp
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - WrappedPropertySet.hxx
+ chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/beans/XMultiPropertySet.hpp
+ - com/sun/star/beans/XMultiPropertyStates.hpp
+ - com/sun/star/beans/XPropertySet.hpp
+ - com/sun/star/beans/XPropertyState.hpp
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/controller/chartapiwrapper/UpDownBarWrapper.hxx:
+ # base class has to be a complete type
+ - com/sun/star/beans/XMultiPropertySet.hpp
+ - com/sun/star/beans/XMultiPropertyStates.hpp
+ - com/sun/star/beans/XPropertySet.hpp
+ - com/sun/star/beans/XPropertyState.hpp
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/controller/chartapiwrapper/TitleWrapper.hxx:
+ # base class has to be a complete type
+ - WrappedPropertySet.hxx
+ - com/sun/star/drawing/XShape.hpp
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/controller/chartapiwrapper/WallFloorWrapper.hxx:
+ # base class has to be a complete type
+ - WrappedPropertySet.hxx
+ - com/sun/star/lang/XComponent.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.hxx:
+ # Needed for css namespace shortcut
+ - sal/types.h
+ chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.hxx:
+ # Needed for css namespace shortcut
+ - sal/types.h
+ chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.hxx:
+ # Needed for css namespace shortcut
+ - sal/types.h
+ chart2/source/controller/chartapiwrapper/WrappedSplineProperties.hxx:
+ # Needed for css namespace shortcut
+ - sal/types.h
+ chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.hxx:
+ # Needed for css namespace shortcut
+ - sal/types.h
+ chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.hxx:
+ # Needed for css namespace shortcut
+ - sal/types.h
+ chart2/source/controller/chartapiwrapper/WrappedStockProperties.hxx:
+ # Needed for css namespace shortcut
+ - sal/types.h
+ chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx:
+ # Needed for implicit dtor
+ - RegressionCurveModel.hxx
diff --git a/chart2/JunitTest_chart2_unoapi.mk b/chart2/JunitTest_chart2_unoapi.mk
new file mode 100644
index 0000000000..7607c46482
--- /dev/null
+++ b/chart2/JunitTest_chart2_unoapi.mk
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_JunitTest_JunitTest,chart2_unoapi))
+
+$(eval $(call gb_JunitTest_set_unoapi_test_defaults,chart2_unoapi,,sch.sce))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/Library_chartcontroller.mk b/chart2/Library_chartcontroller.mk
new file mode 100644
index 0000000000..ca50d52a1f
--- /dev/null
+++ b/chart2/Library_chartcontroller.mk
@@ -0,0 +1,218 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,chartcontroller))
+
+$(eval $(call gb_Library_set_include,chartcontroller,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/chart2/source/controller/inc \
+ -I$(SRCDIR)/chart2/source/inc \
+ -I$(SRCDIR)/chart2/inc \
+))
+
+$(eval $(call gb_Library_set_precompiled_header,chartcontroller,chart2/inc/pch/precompiled_chartcontroller))
+
+$(eval $(call gb_Library_use_external,chartcontroller,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,chartcontroller))
+
+$(eval $(call gb_Library_use_custom_headers,chartcontroller,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_Library_use_libraries,chartcontroller,\
+ basegfx \
+ chartcore \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ docmodel \
+ editeng \
+ sal \
+ salhelper \
+ i18nlangtag \
+ sfx \
+ sot \
+ svl \
+ svt \
+ svxcore \
+ svx \
+ tk \
+ tl \
+ ucbhelper \
+ utl \
+ vcl \
+))
+
+$(eval $(call gb_Library_set_componentfile,chartcontroller,chart2/source/controller/chartcontroller,services))
+
+ifneq ($(ENABLE_WASM_STRIP_ACCESSIBILITY),TRUE)
+$(eval $(call gb_Library_add_exception_objects,chartcontroller,\
+ chart2/source/controller/accessibility/AccessibleBase \
+ chart2/source/controller/accessibility/AccessibleChartElement \
+ chart2/source/controller/accessibility/AccessibleChartShape \
+ chart2/source/controller/accessibility/AccessibleChartView \
+ chart2/source/controller/accessibility/AccessibleTextHelper \
+ chart2/source/controller/accessibility/AccessibleViewForwarder \
+ chart2/source/controller/accessibility/ChartElementFactory \
+))
+endif
+
+$(eval $(call gb_Library_add_exception_objects,chartcontroller,\
+ chart2/source/controller/chartapiwrapper/AreaWrapper \
+ chart2/source/controller/chartapiwrapper/AxisWrapper \
+ chart2/source/controller/chartapiwrapper/Chart2ModelContact \
+ chart2/source/controller/chartapiwrapper/ChartDataWrapper \
+ chart2/source/controller/chartapiwrapper/ChartDocumentWrapper \
+ chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper \
+ chart2/source/controller/chartapiwrapper/DiagramWrapper \
+ chart2/source/controller/chartapiwrapper/GridWrapper \
+ chart2/source/controller/chartapiwrapper/LegendWrapper \
+ chart2/source/controller/chartapiwrapper/MinMaxLineWrapper \
+ chart2/source/controller/chartapiwrapper/TitleWrapper \
+ chart2/source/controller/chartapiwrapper/UpDownBarWrapper \
+ chart2/source/controller/chartapiwrapper/WallFloorWrapper \
+ chart2/source/controller/chartapiwrapper/WrappedAddInProperty \
+ chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties \
+ chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties \
+ chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty \
+ chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties \
+ chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty \
+ chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty \
+ chart2/source/controller/chartapiwrapper/WrappedScaleProperty \
+ chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties \
+ chart2/source/controller/chartapiwrapper/WrappedSceneProperty \
+ chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty \
+ chart2/source/controller/chartapiwrapper/WrappedSplineProperties \
+ chart2/source/controller/chartapiwrapper/WrappedStatisticProperties \
+ chart2/source/controller/chartapiwrapper/WrappedStockProperties \
+ chart2/source/controller/chartapiwrapper/WrappedSymbolProperties \
+ chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty \
+ chart2/source/controller/dialogs/ChangingResource \
+ chart2/source/controller/dialogs/ChartResourceGroupDlgs \
+ chart2/source/controller/dialogs/ChartResourceGroups \
+ chart2/source/controller/dialogs/ChartTypeDialogController \
+ chart2/source/controller/dialogs/DataBrowser \
+ chart2/source/controller/dialogs/DataBrowserModel \
+ chart2/source/controller/dialogs/DialogModel \
+ chart2/source/controller/dialogs/dlg_ChartType \
+ chart2/source/controller/dialogs/dlg_ChartType_UNO \
+ chart2/source/controller/dialogs/dlg_CreationWizard \
+ chart2/source/controller/dialogs/dlg_CreationWizard_UNO \
+ chart2/source/controller/dialogs/dlg_DataEditor \
+ chart2/source/controller/dialogs/dlg_DataSource \
+ chart2/source/controller/dialogs/dlg_InsertAxis_Grid \
+ chart2/source/controller/dialogs/dlg_InsertDataLabel \
+ chart2/source/controller/dialogs/dlg_InsertDataTable \
+ chart2/source/controller/dialogs/dlg_InsertErrorBars \
+ chart2/source/controller/dialogs/dlg_InsertLegend \
+ chart2/source/controller/dialogs/dlg_InsertTitle \
+ chart2/source/controller/dialogs/dlg_NumberFormat \
+ chart2/source/controller/dialogs/dlg_ObjectProperties \
+ chart2/source/controller/dialogs/dlg_ShapeFont \
+ chart2/source/controller/dialogs/dlg_ShapeParagraph \
+ chart2/source/controller/dialogs/dlg_View3D \
+ chart2/source/controller/dialogs/ObjectNameProvider \
+ chart2/source/controller/dialogs/RangeSelectionHelper \
+ chart2/source/controller/dialogs/RangeSelectionListener \
+ chart2/source/controller/dialogs/res_BarGeometry \
+ chart2/source/controller/dialogs/res_DataLabel \
+ chart2/source/controller/dialogs/res_DataTableProperties \
+ chart2/source/controller/dialogs/res_ErrorBar \
+ chart2/source/controller/dialogs/res_LegendPosition \
+ chart2/source/controller/dialogs/res_Titles \
+ chart2/source/controller/dialogs/res_Trendline \
+ chart2/source/controller/dialogs/TextDirectionListBox \
+ chart2/source/controller/dialogs/TimerTriggeredControllerLock \
+ chart2/source/controller/dialogs/TitleDialogData \
+ chart2/source/controller/dialogs/tp_3D_SceneAppearance \
+ chart2/source/controller/dialogs/tp_3D_SceneGeometry \
+ chart2/source/controller/dialogs/tp_3D_SceneIllumination \
+ chart2/source/controller/dialogs/tp_AxisLabel \
+ chart2/source/controller/dialogs/tp_AxisPositions \
+ chart2/source/controller/dialogs/tp_ChartType \
+ chart2/source/controller/dialogs/tp_DataLabel \
+ chart2/source/controller/dialogs/tp_DataPointOption \
+ chart2/source/controller/dialogs/tp_DataSource \
+ chart2/source/controller/dialogs/tp_DataTable \
+ chart2/source/controller/dialogs/tp_ErrorBars \
+ chart2/source/controller/dialogs/tp_LegendPosition \
+ chart2/source/controller/dialogs/tp_PointGeometry \
+ chart2/source/controller/dialogs/tp_PolarOptions \
+ chart2/source/controller/dialogs/tp_RangeChooser \
+ chart2/source/controller/dialogs/tp_Scale \
+ chart2/source/controller/dialogs/tp_SeriesToAxis \
+ chart2/source/controller/dialogs/tp_TitleRotation \
+ chart2/source/controller/dialogs/tp_Trendline \
+ chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects \
+ chart2/source/controller/drawinglayer/DrawViewWrapper \
+ chart2/source/controller/drawinglayer/ViewElementListProvider \
+ chart2/source/controller/itemsetwrapper/AxisItemConverter \
+ chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter \
+ chart2/source/controller/itemsetwrapper/DataPointItemConverter \
+ chart2/source/controller/itemsetwrapper/DataTableItemConverter \
+ chart2/source/controller/itemsetwrapper/ErrorBarItemConverter \
+ chart2/source/controller/itemsetwrapper/GraphicPropertyItemConverter \
+ chart2/source/controller/itemsetwrapper/ItemConverter \
+ chart2/source/controller/itemsetwrapper/LegendItemConverter \
+ chart2/source/controller/itemsetwrapper/MultipleChartConverters \
+ chart2/source/controller/itemsetwrapper/MultipleItemConverter \
+ chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter \
+ chart2/source/controller/itemsetwrapper/RegressionEquationItemConverter \
+ chart2/source/controller/itemsetwrapper/SeriesOptionsItemConverter \
+ chart2/source/controller/itemsetwrapper/StatisticsItemConverter \
+ chart2/source/controller/itemsetwrapper/TextLabelItemConverter \
+ chart2/source/controller/itemsetwrapper/TitleItemConverter \
+ chart2/source/controller/main/ChartController \
+ chart2/source/controller/main/ChartController_EditData \
+ chart2/source/controller/main/ChartController_Insert \
+ chart2/source/controller/main/ChartController_Position \
+ chart2/source/controller/main/ChartController_Properties \
+ chart2/source/controller/main/ChartController_TextEdit \
+ chart2/source/controller/main/ChartController_Tools \
+ chart2/source/controller/main/ChartController_Window \
+ chart2/source/controller/main/ChartDropTargetHelper \
+ chart2/source/controller/main/ChartFrameloader \
+ chart2/source/controller/main/ChartModelClone \
+ chart2/source/controller/main/ChartTransferable \
+ chart2/source/controller/main/ChartWindow \
+ chart2/source/controller/main/CommandDispatchContainer \
+ chart2/source/controller/main/CommandDispatch \
+ chart2/source/controller/main/ControllerCommandDispatch \
+ chart2/source/controller/main/DragMethod_Base \
+ chart2/source/controller/main/DragMethod_PieSegment \
+ chart2/source/controller/main/DragMethod_RotateDiagram \
+ chart2/source/controller/main/DrawCommandDispatch \
+ chart2/source/controller/main/ElementSelector \
+ chart2/source/controller/main/FeatureCommandDispatchBase \
+ chart2/source/controller/main/ObjectHierarchy \
+ chart2/source/controller/main/PositionAndSizeHelper \
+ chart2/source/controller/main/SelectionHelper \
+ chart2/source/controller/main/ShapeController \
+ chart2/source/controller/main/StatusBarCommandDispatch \
+ chart2/source/controller/main/ToolbarController \
+ chart2/source/controller/main/UndoActions \
+ chart2/source/controller/main/UndoCommandDispatch \
+ chart2/source/controller/main/UndoGuard \
+ chart2/source/controller/sidebar/Chart2PanelFactory \
+ chart2/source/controller/sidebar/ChartAreaPanel \
+ chart2/source/controller/sidebar/ChartAxisPanel \
+ chart2/source/controller/sidebar/ChartColorWrapper \
+ chart2/source/controller/sidebar/ChartElementsPanel \
+ chart2/source/controller/sidebar/ChartErrorBarPanel \
+ chart2/source/controller/sidebar/ChartLinePanel \
+ chart2/source/controller/sidebar/ChartSeriesPanel \
+ chart2/source/controller/sidebar/ChartSidebarModifyListener \
+ chart2/source/controller/sidebar/ChartSidebarSelectionListener \
+ chart2/source/controller/sidebar/ChartTypePanel \
+ chart2/source/controller/uitest/uiobject \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/Library_chartcore.mk b/chart2/Library_chartcore.mk
new file mode 100644
index 0000000000..b61390ec42
--- /dev/null
+++ b/chart2/Library_chartcore.mk
@@ -0,0 +1,240 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,chartcore))
+
+$(eval $(call gb_Library_set_include,chartcore,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/chart2/source/model/inc \
+ -I$(SRCDIR)/chart2/source/view/inc \
+ -I$(SRCDIR)/chart2/source/inc \
+ -I$(SRCDIR)/chart2/inc \
+))
+
+# not ideal - we should use a single core define ideally
+$(eval $(call gb_Library_add_defs,chartcore,\
+ -DOOO_DLLIMPLEMENTATION_CHARTTOOLS \
+ -DOOO_DLLIMPLEMENTATION_CHARTVIEW \
+))
+
+$(eval $(call gb_Library_set_precompiled_header,chartcore,chart2/inc/pch/precompiled_chartcore))
+
+$(eval $(call gb_Library_use_externals,chartcore,\
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_Library_use_custom_headers,chartcore,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_Library_use_sdk_api,chartcore))
+
+$(eval $(call gb_Library_use_libraries,chartcore,\
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ fwk \
+ i18nlangtag \
+ sal \
+ salhelper \
+ sfx \
+ svl \
+ svt \
+ svxcore \
+ tl \
+ ucbhelper \
+ utl \
+ vcl \
+ docmodel \
+))
+
+$(eval $(call gb_Library_set_componentfile,chartcore,chart2/source/chartcore,services))
+
+# view pieces ...
+$(eval $(call gb_Library_add_exception_objects,chartcore,\
+ chart2/source/view/axes/DateHelper \
+ chart2/source/view/axes/DateScaling \
+ chart2/source/view/axes/MinimumAndMaximumSupplier \
+ chart2/source/view/axes/ScaleAutomatism \
+ chart2/source/view/axes/Tickmarks \
+ chart2/source/view/axes/Tickmarks_Dates \
+ chart2/source/view/axes/Tickmarks_Equidistant \
+ chart2/source/view/axes/VAxisBase \
+ chart2/source/view/axes/VAxisOrGridBase \
+ chart2/source/view/axes/VAxisProperties \
+ chart2/source/view/axes/VCartesianAxis \
+ chart2/source/view/axes/VCartesianCoordinateSystem \
+ chart2/source/view/axes/VCartesianGrid \
+ chart2/source/view/axes/VCoordinateSystem \
+ chart2/source/view/axes/VPolarAngleAxis \
+ chart2/source/view/axes/VPolarAxis \
+ chart2/source/view/axes/VPolarCoordinateSystem \
+ chart2/source/view/axes/VPolarGrid \
+ chart2/source/view/axes/VPolarRadiusAxis \
+ chart2/source/view/charttypes/AreaChart \
+ chart2/source/view/charttypes/BarChart \
+ chart2/source/view/charttypes/BarPositionHelper \
+ chart2/source/view/charttypes/BubbleChart \
+ chart2/source/view/charttypes/CandleStickChart \
+ chart2/source/view/charttypes/CategoryPositionHelper \
+ chart2/source/view/charttypes/NetChart \
+ chart2/source/view/charttypes/PieChart \
+ chart2/source/view/charttypes/Splines \
+ chart2/source/view/charttypes/VSeriesPlotter \
+ chart2/source/view/diagram/VDiagram \
+ chart2/source/view/main/ChartItemPool \
+ chart2/source/view/main/ChartView \
+ chart2/source/view/main/Clipping \
+ chart2/source/view/main/DataPointSymbolSupplier \
+ chart2/source/view/main/DataTableView \
+ chart2/source/view/main/DrawModelWrapper \
+ chart2/source/view/main/ExplicitValueProvider \
+ chart2/source/view/main/LabelPositionHelper \
+ chart2/source/view/main/Linear3DTransformation \
+ chart2/source/view/main/PlotterBase \
+ chart2/source/view/main/PlottingPositionHelper \
+ chart2/source/view/main/PolarLabelPositionHelper \
+ chart2/source/view/main/PropertyMapper \
+ chart2/source/view/main/SeriesPlotterContainer \
+ chart2/source/view/main/ShapeFactory \
+ chart2/source/view/main/Stripe \
+ chart2/source/view/main/VDataSeries \
+ chart2/source/view/main/VLegend \
+ chart2/source/view/main/VLegendSymbolFactory \
+ chart2/source/view/main/VLineProperties \
+ chart2/source/view/main/VPolarTransformation \
+ chart2/source/view/main/VTitle \
+ chart2/source/view/main/VButton \
+))
+
+# model pieces ...
+$(eval $(call gb_Library_add_exception_objects,chartcore,\
+ chart2/source/model/filter/XMLFilter \
+ chart2/source/model/main/Axis \
+ chart2/source/model/main/BaseCoordinateSystem \
+ chart2/source/model/main/CartesianCoordinateSystem \
+ chart2/source/model/main/ChartModel \
+ chart2/source/model/main/ChartModel_Persistence \
+ chart2/source/model/main/DataPoint \
+ chart2/source/model/main/DataPointProperties \
+ chart2/source/model/main/DataSeries \
+ chart2/source/model/main/DataSeriesProperties \
+ chart2/source/model/main/DataTable \
+ chart2/source/model/main/Diagram \
+ chart2/source/model/main/FormattedString \
+ chart2/source/model/main/GridProperties \
+ chart2/source/model/main/Legend \
+ chart2/source/model/main/PageBackground \
+ chart2/source/model/main/PolarCoordinateSystem \
+ chart2/source/model/main/StockBar \
+ chart2/source/model/main/Title \
+ chart2/source/model/main/UndoManager \
+ chart2/source/model/main/Wall \
+ chart2/source/model/template/AreaChartType \
+ chart2/source/model/template/AreaChartTypeTemplate \
+ chart2/source/model/template/BarChartType \
+ chart2/source/model/template/BarChartTypeTemplate \
+ chart2/source/model/template/BubbleChartType \
+ chart2/source/model/template/BubbleChartTypeTemplate \
+ chart2/source/model/template/BubbleDataInterpreter \
+ chart2/source/model/template/CandleStickChartType \
+ chart2/source/model/template/ChartType \
+ chart2/source/model/template/ChartTypeManager \
+ chart2/source/model/template/ChartTypeTemplate \
+ chart2/source/model/template/ColumnChartType \
+ chart2/source/model/template/ColumnLineChartTypeTemplate \
+ chart2/source/model/template/ColumnLineDataInterpreter \
+ chart2/source/model/template/DataInterpreter \
+ chart2/source/model/template/FilledNetChartType \
+ chart2/source/model/template/LineChartType \
+ chart2/source/model/template/LineChartTypeTemplate \
+ chart2/source/model/template/NetChartType \
+ chart2/source/model/template/NetChartTypeTemplate \
+ chart2/source/model/template/PieChartType \
+ chart2/source/model/template/PieChartTypeTemplate \
+ chart2/source/model/template/ScatterChartType \
+ chart2/source/model/template/ScatterChartTypeTemplate \
+ chart2/source/model/template/StockChartTypeTemplate \
+ chart2/source/model/template/StockDataInterpreter \
+ chart2/source/model/template/XYDataInterpreter \
+))
+
+# tools pieces
+$(eval $(call gb_Library_add_exception_objects,chartcore,\
+ chart2/source/tools/AxisHelper \
+ chart2/source/tools/BaseGFXHelper \
+ chart2/source/tools/CachedDataSequence \
+ chart2/source/tools/CharacterProperties \
+ chart2/source/tools/ChartModelHelper \
+ chart2/source/tools/ChartTypeHelper \
+ chart2/source/tools/ChartViewHelper \
+ chart2/source/tools/ColorPerPointHelper \
+ chart2/source/tools/CommonConverters \
+ chart2/source/tools/ConfigColorScheme \
+ chart2/source/tools/ControllerLockGuard \
+ chart2/source/tools/DataSeriesHelper \
+ chart2/source/tools/DataSource \
+ chart2/source/tools/DataSourceHelper \
+ chart2/source/tools/DiagramHelper \
+ chart2/source/tools/ErrorBar \
+ chart2/source/tools/ExplicitCategoriesProvider \
+ chart2/source/tools/ExponentialRegressionCurveCalculator \
+ chart2/source/tools/FillProperties \
+ chart2/source/tools/FormattedStringHelper \
+ chart2/source/tools/InternalData \
+ chart2/source/tools/InternalDataProvider \
+ chart2/source/tools/LabeledDataSequence \
+ chart2/source/tools/LegendHelper \
+ chart2/source/tools/LifeTime \
+ chart2/source/tools/LinearRegressionCurveCalculator \
+ chart2/source/tools/LinePropertiesHelper \
+ chart2/source/tools/LogarithmicRegressionCurveCalculator \
+ chart2/source/tools/MeanValueRegressionCurveCalculator \
+ chart2/source/tools/MediaDescriptorHelper \
+ chart2/source/tools/ModifyListenerCallBack \
+ chart2/source/tools/ModifyListenerHelper \
+ chart2/source/tools/MovingAverageRegressionCurveCalculator \
+ chart2/source/tools/NameContainer \
+ chart2/source/tools/NumberFormatterWrapper \
+ chart2/source/tools/ObjectIdentifier \
+ chart2/source/tools/OPropertySet \
+ chart2/source/tools/PolynomialRegressionCurveCalculator \
+ chart2/source/tools/PopupRequest \
+ chart2/source/tools/PotentialRegressionCurveCalculator \
+ chart2/source/tools/PropertyHelper \
+ chart2/source/tools/RangeHighlighter \
+ chart2/source/tools/ReferenceSizeProvider \
+ chart2/source/tools/RegressionCurveCalculator \
+ chart2/source/tools/RegressionCurveHelper \
+ chart2/source/tools/RegressionCurveModel \
+ chart2/source/tools/RegressionEquation \
+ chart2/source/tools/RelativePositionHelper \
+ chart2/source/tools/RelativeSizeHelper \
+ chart2/source/tools/ResId \
+ chart2/source/tools/Scaling \
+ chart2/source/tools/SceneProperties \
+ chart2/source/tools/StatisticsHelper \
+ chart2/source/tools/ThreeDHelper \
+ chart2/source/tools/TitleHelper \
+ chart2/source/tools/UncachedDataSequence \
+ chart2/source/tools/UserDefinedProperties \
+ chart2/source/tools/WeakListenerAdapter \
+ chart2/source/tools/WrappedDefaultProperty \
+ chart2/source/tools/WrappedDirectStateProperty \
+ chart2/source/tools/WrappedIgnoreProperty \
+ chart2/source/tools/WrappedProperty \
+ chart2/source/tools/WrappedPropertySet \
+ chart2/source/tools/XMLRangeHelper \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/Makefile b/chart2/Makefile
new file mode 100644
index 0000000000..0997e62848
--- /dev/null
+++ b/chart2/Makefile
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/Module_chart2.mk b/chart2/Module_chart2.mk
new file mode 100644
index 0000000000..5f7fd5aee9
--- /dev/null
+++ b/chart2/Module_chart2.mk
@@ -0,0 +1,59 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+include $(SRCDIR)/chart2/import_setup.mk
+include $(SRCDIR)/chart2/export_setup.mk
+
+$(eval $(call gb_Module_Module,chart2))
+
+$(eval $(call gb_Module_add_targets,chart2,\
+ Library_chartcontroller \
+ Library_chartcore \
+ UIConfig_chart2 \
+))
+
+$(eval $(call gb_Module_add_l10n_targets,chart2,\
+ AllLangMoTarget_chart \
+))
+
+ifneq ($(OS),iOS)
+$(eval $(call gb_Module_add_check_targets,chart2,\
+ CppunitTest_chart2_common_functors \
+))
+
+$(eval $(call gb_Module_add_slowcheck_targets,chart2,\
+ CppunitTest_chart2_export \
+ CppunitTest_chart2_export2 \
+ CppunitTest_chart2_export3 \
+ CppunitTest_chart2_import \
+ CppunitTest_chart2_import2 \
+ CppunitTest_chart2_trendcalculators \
+ CppunitTest_chart2_dump \
+ CppunitTest_chart2_pivot_chart_test \
+ CppunitTest_chart2_geometry \
+ CppunitTest_chart2_uichart \
+))
+
+ifeq ($(WITH_FONTS), TRUE)
+$(eval $(call gb_Module_add_slowcheck_targets,chart2,\
+ CppunitTest_chart2_xshape \
+))
+endif
+
+$(eval $(call gb_Module_add_subsequentcheck_targets,chart2,\
+ JunitTest_chart2_unoapi \
+))
+
+# screenshots
+$(eval $(call gb_Module_add_screenshot_targets,chart2,\
+ CppunitTest_chart2_dialogs_test \
+))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/README.md b/chart2/README.md
new file mode 100644
index 0000000000..fa63da9bcc
--- /dev/null
+++ b/chart2/README.md
@@ -0,0 +1,9 @@
+# Chart Implementation for LibreOffice Calc
+
+The `chart2` denotes a second generation re-write done to rid us of the
+foul and twisted legacy chart code.
+
+## Debugging
+
+### Shortcuts
+CTRL + F12 creates a layout dump based on the `XShapeDumper` based on `SAL_WARN("chart2", ...`
diff --git a/chart2/UIConfig_chart2.mk b/chart2/UIConfig_chart2.mk
new file mode 100644
index 0000000000..274efd0263
--- /dev/null
+++ b/chart2/UIConfig_chart2.mk
@@ -0,0 +1,83 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UIConfig_UIConfig,modules/schart))
+
+$(eval $(call gb_UIConfig_add_menubarfiles,modules/schart,\
+ chart2/uiconfig/menubar/menubar \
+))
+
+$(eval $(call gb_UIConfig_add_popupmenufiles,modules/schart,\
+ chart2/uiconfig/popupmenu/draw \
+ chart2/uiconfig/popupmenu/drawtext \
+))
+
+$(eval $(call gb_UIConfig_add_statusbarfiles,modules/schart,\
+ chart2/uiconfig/statusbar/statusbar \
+))
+
+$(eval $(call gb_UIConfig_add_toolbarfiles,modules/schart,\
+ chart2/uiconfig/toolbar/arrowshapes \
+ chart2/uiconfig/toolbar/basicshapes \
+ chart2/uiconfig/toolbar/calloutshapes \
+ chart2/uiconfig/toolbar/drawbar \
+ chart2/uiconfig/toolbar/flowchartshapes \
+ chart2/uiconfig/toolbar/standardbar \
+ chart2/uiconfig/toolbar/starshapes \
+ chart2/uiconfig/toolbar/symbolshapes \
+ chart2/uiconfig/toolbar/toolbar \
+))
+
+$(eval $(call gb_UIConfig_add_uifiles,modules/schart,\
+ chart2/uiconfig/ui/3dviewdialog \
+ chart2/uiconfig/ui/attributedialog \
+ chart2/uiconfig/ui/chardialog \
+ chart2/uiconfig/ui/chartdatadialog \
+ chart2/uiconfig/ui/charttypedialog \
+ chart2/uiconfig/ui/columnfragment \
+ chart2/uiconfig/ui/combobox \
+ chart2/uiconfig/ui/datarangedialog \
+ chart2/uiconfig/ui/dlg_DataLabel \
+ chart2/uiconfig/ui/dlg_InsertDataTable \
+ chart2/uiconfig/ui/dlg_InsertErrorBars \
+ chart2/uiconfig/ui/dlg_InsertLegend \
+ chart2/uiconfig/ui/imagefragment \
+ chart2/uiconfig/ui/insertaxisdlg \
+ chart2/uiconfig/ui/insertgriddlg \
+ chart2/uiconfig/ui/inserttitledlg \
+ chart2/uiconfig/ui/paradialog \
+ chart2/uiconfig/ui/sidebaraxis \
+ chart2/uiconfig/ui/sidebarelements \
+ chart2/uiconfig/ui/sidebarerrorbar \
+ chart2/uiconfig/ui/sidebarseries \
+ chart2/uiconfig/ui/sidebartype \
+ chart2/uiconfig/ui/smoothlinesdlg \
+ chart2/uiconfig/ui/steppedlinesdlg \
+ chart2/uiconfig/ui/titlerotationtabpage \
+ chart2/uiconfig/ui/tp_3D_SceneAppearance \
+ chart2/uiconfig/ui/tp_3D_SceneGeometry \
+ chart2/uiconfig/ui/tp_3D_SceneIllumination \
+ chart2/uiconfig/ui/tp_axisLabel \
+ chart2/uiconfig/ui/tp_AxisPositions \
+ chart2/uiconfig/ui/tp_ChartType \
+ chart2/uiconfig/ui/tp_DataLabel \
+ chart2/uiconfig/ui/tp_DataPointOption \
+ chart2/uiconfig/ui/tp_DataSource \
+ chart2/uiconfig/ui/tp_DataTable \
+ chart2/uiconfig/ui/tp_ErrorBars \
+ chart2/uiconfig/ui/tp_LegendPosition \
+ chart2/uiconfig/ui/tp_PolarOptions \
+ chart2/uiconfig/ui/tp_RangeChooser \
+ chart2/uiconfig/ui/tp_SeriesToAxis \
+ chart2/uiconfig/ui/tp_Scale \
+ chart2/uiconfig/ui/tp_Trendline \
+ chart2/uiconfig/ui/wizelementspage \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/export_setup.mk b/chart2/export_setup.mk
new file mode 100644
index 0000000000..723df9897c
--- /dev/null
+++ b/chart2/export_setup.mk
@@ -0,0 +1,90 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+# template for export tests
+define chart2_export$(1)_test
+
+$(eval $(call gb_CppunitTest_CppunitTest,chart2_export$(1)))
+
+$(eval $(call gb_CppunitTest_use_externals,chart2_export$(1), \
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,chart2_export$(1), \
+ chart2/qa/extras/chart2export$(1) \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,chart2_export$(1), \
+ $(call gb_Helper_optional,AVMEDIA,avmedia) \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sc \
+ sw \
+ sd \
+ sfx \
+ sot \
+ subsequenttest \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_set_include,chart2_export$(1),\
+ -I$(SRCDIR)/chart2/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_export$(1)))
+
+$(eval $(call gb_CppunitTest_use_ure,chart2_export$(1)))
+$(eval $(call gb_CppunitTest_use_vcl,chart2_export$(1)))
+$(eval $(call gb_CppunitTest_use_rdb,chart2_export$(1),services))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,chart2_export$(1), \
+ modules/swriter \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,chart2_export$(1)))
+
+$(call gb_CppunitTest_get_target,chart2_export$(1)): $(call gb_Package_get_target,postprocess_images)
+
+$(eval $(call gb_CppunitTest_add_arguments,chart2_export$(1), \
+ -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \
+))
+
+endef
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/import_setup.mk b/chart2/import_setup.mk
new file mode 100644
index 0000000000..a63d314bfc
--- /dev/null
+++ b/chart2/import_setup.mk
@@ -0,0 +1,145 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+# template for import tests
+define chart2_import$(1)_test
+
+$(eval $(call gb_CppunitTest_CppunitTest,chart2_import$(1)))
+
+$(eval $(call gb_CppunitTest_use_externals,chart2_import$(1), \
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,chart2_import$(1), \
+ chart2/qa/extras/chart2import$(1) \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,chart2_import$(1), \
+ $(call gb_Helper_optional,AVMEDIA,avmedia) \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ docmodel \
+ editeng \
+ for \
+ forui \
+ i18nlangtag \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sb \
+ sc \
+ sw \
+ sd \
+ sfx \
+ sot \
+ subsequenttest \
+ svl \
+ svt \
+ svx \
+ svxcore \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ $(call gb_Helper_optional,SCRIPTING, \
+ vbahelper) \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_set_include,chart2_import$(1),\
+ -I$(SRCDIR)/chart2/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,chart2_import$(1)))
+
+$(eval $(call gb_CppunitTest_use_ure,chart2_import$(1)))
+$(eval $(call gb_CppunitTest_use_vcl,chart2_import$(1)))
+
+$(eval $(call gb_CppunitTest_use_components,chart2_import$(1),\
+ basic/util/sb \
+ animations/source/animcore/animcore \
+ chart2/source/controller/chartcontroller \
+ chart2/source/chartcore \
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ dbaccess/util/dba \
+ embeddedobj/util/embobj \
+ emfio/emfio \
+ eventattacher/source/evtatt \
+ filter/source/config/cache/filterconfig1 \
+ filter/source/odfflatxml/odfflatxml \
+ filter/source/storagefilterdetect/storagefd \
+ filter/source/xmlfilteradaptor/xmlfa \
+ filter/source/xmlfilterdetect/xmlfd \
+ forms/util/frm \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ linguistic/source/lng \
+ oox/util/oox \
+ package/source/xstor/xstor \
+ package/util/package2 \
+ sax/source/expatwrap/expwrap \
+ sc/util/sc \
+ sc/util/scd \
+ sc/util/scfilt \
+ sw/util/sw \
+ sw/util/swd \
+ sw/util/msword \
+ sd/util/sd \
+ sd/util/sdd \
+ $(call gb_Helper_optional,SCRIPTING, \
+ sc/util/vbaobj) \
+ scaddins/source/analysis/analysis \
+ scaddins/source/datefunc/date \
+ scripting/source/basprov/basprov \
+ scripting/util/scriptframe \
+ sfx2/util/sfx \
+ sot/util/sot \
+ svl/source/fsstor/fsstorage \
+ svl/util/svl \
+ svtools/util/svt \
+ svx/util/svx \
+ svx/util/svxcore \
+ toolkit/util/tk \
+ vcl/vcl.common \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+ ucb/source/ucp/tdoc/ucptdoc1 \
+ unotools/util/utl \
+ unoxml/source/rdf/unordf \
+ unoxml/source/service/unoxml \
+ uui/util/uui \
+ writerfilter/util/writerfilter \
+ xmloff/util/xo \
+ xmlscript/util/xmlscript \
+))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,chart2_import$(1), \
+ modules/swriter \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,chart2_import$(1)))
+
+$(call gb_CppunitTest_get_target,chart2_import$(1)): $(call gb_Package_get_target,postprocess_images)
+
+endef
+
+# vim: set noet sw=4 ts=4:
diff --git a/chart2/inc/ChartModel.hxx b/chart2/inc/ChartModel.hxx
new file mode 100644
index 0000000000..1255c4982d
--- /dev/null
+++ b/chart2/inc/ChartModel.hxx
@@ -0,0 +1,491 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <LifeTime.hxx>
+
+#include <com/sun/star/frame/XStorable2.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XUndoManagerSupplier.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/embed/XVisualObject.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <com/sun/star/qa/XDumper.hpp>
+
+// public API
+#include <com/sun/star/chart2/data/XDataReceiver.hpp>
+
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart2/XTitled.hpp>
+
+#include <com/sun/star/frame/XLoadable.hpp>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+
+#include <osl/mutex.hxx>
+#include <rtl/ref.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer2.hxx>
+#include <vcl/GraphicObject.hxx>
+
+#include <memory>
+
+typedef struct _xmlTextWriter* xmlTextWriterPtr;
+
+namespace com::sun::star::awt { class XRequestCallback; }
+namespace com::sun::star::chart2::data { class XDataProvider; }
+namespace com::sun::star::document { class XFilter; }
+namespace com::sun::star::embed { class XStorage; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::uno { class XAggregation; }
+
+class SvNumberFormatter;
+class SvNumberFormatsSupplierObj;
+
+namespace chart
+{
+class Diagram;
+class ChartTypeManager;
+class ChartTypeTemplate;
+class InternalDataProvider;
+class NameContainer;
+class PageBackground;
+class RangeHighlighter;
+class Title;
+
+namespace impl
+{
+
+// Note: needed for queryInterface (if it calls the base-class implementation)
+typedef cppu::WeakImplHelper<
+// css::frame::XModel //comprehends XComponent (required interface), base of XChartDocument
+ css::util::XCloseable //comprehends XCloseBroadcaster
+ ,css::frame::XStorable2 //(extension of XStorable)
+ ,css::util::XModifiable //comprehends XModifyBroadcaster (required interface)
+ ,css::lang::XServiceInfo
+ ,css::lang::XInitialization
+ ,css::chart2::XChartDocument // derived from XModel
+ ,css::chart2::data::XDataReceiver // public API
+ ,css::chart2::XTitled
+ ,css::frame::XLoadable
+ ,css::util::XCloneable
+ ,css::embed::XVisualObject
+ ,css::lang::XMultiServiceFactory
+ ,css::document::XStorageBasedDocument
+ ,css::lang::XUnoTunnel
+ ,css::util::XNumberFormatsSupplier
+ ,css::container::XChild
+ ,css::util::XModifyListener
+ ,css::datatransfer::XTransferable
+ ,css::document::XDocumentPropertiesSupplier
+ ,css::chart2::data::XDataSource
+ ,css::document::XUndoManagerSupplier
+ ,css::util::XUpdatable
+ ,css::qa::XDumper
+ >
+ ChartModel_Base;
+}
+
+class UndoManager;
+class ChartView;
+
+class OOO_DLLPUBLIC_CHARTTOOLS SAL_LOPLUGIN_ANNOTATE("crosscast") ChartModel final :
+ public impl::ChartModel_Base
+{
+
+private:
+ mutable ::apphelper::CloseableLifeTimeManager m_aLifeTimeManager;
+
+ mutable ::osl::Mutex m_aModelMutex;
+ bool volatile m_bReadOnly;
+ bool volatile m_bModified;
+ sal_Int32 m_nInLoad;
+ bool volatile m_bUpdateNotificationsPending;
+
+ bool mbTimeBased;
+
+ mutable rtl::Reference<ChartView> mxChartView;
+
+ OUString m_aResource;
+ css::uno::Sequence< css::beans::PropertyValue > m_aMediaDescriptor;
+ css::uno::Reference< css::document::XDocumentProperties > m_xDocumentProperties;
+ ::rtl::Reference< UndoManager > m_pUndoManager;
+
+ ::comphelper::OInterfaceContainerHelper2 m_aControllers;
+ css::uno::Reference< css::frame::XController > m_xCurrentController;
+ sal_uInt16 m_nControllerLockCount;
+
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ css::uno::Reference< css::uno::XAggregation > m_xOldModelAgg;
+
+ css::uno::Reference< css::embed::XStorage > m_xStorage;
+ //the content of this should be always synchronized with the current m_xViewWindow size. The variable is necessary to hold the information as long as no view window exists.
+ css::awt::Size m_aVisualAreaSize;
+ css::uno::Reference< css::frame::XModel > m_xParent;
+ rtl::Reference< ::chart::RangeHighlighter > m_xRangeHighlighter;
+ css::uno::Reference<css::awt::XRequestCallback> m_xPopupRequest;
+ std::vector< GraphicObject > m_aGraphicObjectVector;
+
+ css::uno::Reference< css::chart2::data::XDataProvider > m_xDataProvider;
+ /** is only valid if m_xDataProvider is set. If m_xDataProvider is set to an
+ external data provider this reference must be set to 0
+ */
+ rtl::Reference< InternalDataProvider > m_xInternalDataProvider;
+
+ rtl::Reference< SvNumberFormatsSupplierObj > m_xOwnNumberFormatsSupplier;
+ css::uno::Reference< css::util::XNumberFormatsSupplier >
+ m_xNumberFormatsSupplier;
+ std::unique_ptr< SvNumberFormatter > m_apSvNumberFormatter; // #i113784# avoid memory leak
+
+ rtl::Reference< ::chart::ChartTypeManager >
+ m_xChartTypeManager;
+
+ // Diagram Access
+ rtl::Reference< ::chart::Diagram > m_xDiagram;
+
+ rtl::Reference< ::chart::Title > m_xTitle;
+
+ rtl::Reference< ::chart::PageBackground > m_xPageBackground;
+
+ rtl::Reference< ::chart::NameContainer > m_xXMLNamespaceMap;
+
+private:
+ //private methods
+
+ OUString impl_g_getLocation();
+
+ bool
+ impl_isControllerConnected( const css::uno::Reference< com::sun::star::frame::XController >& xController );
+
+ /// @throws css::uno::RuntimeException
+ css::uno::Reference< css::frame::XController >
+ impl_getCurrentController();
+
+ /// @throws css::uno::RuntimeException
+ void
+ impl_notifyModifiedListeners();
+ /// @throws css::uno::RuntimeException
+ void
+ impl_notifyCloseListeners();
+ /// @throws css::uno::RuntimeException
+ void
+ impl_notifyStorageChangeListeners();
+
+ void impl_store(
+ const css::uno::Sequence< css::beans::PropertyValue >& rMediaDescriptor,
+ const css::uno::Reference< css::embed::XStorage > & xStorage );
+ void impl_load(
+ const css::uno::Sequence< css::beans::PropertyValue >& rMediaDescriptor,
+ const css::uno::Reference< css::embed::XStorage >& xStorage );
+ void impl_loadGraphics(
+ const css::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage );
+ css::uno::Reference< css::document::XFilter >
+ impl_createFilter( const css::uno::Sequence< css::beans::PropertyValue > & rMediaDescriptor );
+
+ rtl::Reference< ::chart::ChartTypeTemplate > impl_createDefaultChartTypeTemplate();
+ css::uno::Reference< css::chart2::data::XDataSource > impl_createDefaultData();
+
+ void impl_adjustAdditionalShapesPositionAndSize(
+ const css::awt::Size& aVisualAreaSize );
+
+ void insertDefaultChart();
+
+public:
+ ChartModel() = delete;
+ ChartModel(css::uno::Reference< css::uno::XComponentContext > xContext);
+ explicit ChartModel( const ChartModel & rOther );
+ virtual ~ChartModel() override;
+
+ // css::lang::XServiceInfo
+
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // css::lang::XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ // css::frame::XModel (required interface)
+
+ virtual sal_Bool SAL_CALL
+ attachResource( const OUString& rURL,
+ const css::uno::Sequence< css::beans::PropertyValue >& rMediaDescriptor ) override;
+
+ virtual OUString SAL_CALL
+ getURL() override;
+
+ virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL
+ getArgs() override;
+
+ virtual void SAL_CALL
+ connectController( const css::uno::Reference< css::frame::XController >& xController ) override;
+
+ virtual void SAL_CALL
+ disconnectController( const css::uno::Reference< css::frame::XController >& xController ) override;
+
+ virtual void SAL_CALL
+ lockControllers() override;
+
+ virtual void SAL_CALL
+ unlockControllers() override;
+
+ virtual sal_Bool SAL_CALL
+ hasControllersLocked() override;
+
+ virtual css::uno::Reference< css::frame::XController > SAL_CALL
+ getCurrentController() override;
+
+ virtual void SAL_CALL
+ setCurrentController( const css::uno::Reference< css::frame::XController >& xController ) override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ getCurrentSelection() override;
+
+ // css::lang::XComponent (base of XModel)
+ virtual void SAL_CALL
+ dispose() override;
+
+ virtual void SAL_CALL
+ addEventListener( const css::uno::Reference< css::lang::XEventListener > & xListener ) override;
+
+ virtual void SAL_CALL
+ removeEventListener( const css::uno::Reference< css::lang::XEventListener > & xListener ) override;
+
+ // css::util::XCloseable
+ virtual void SAL_CALL
+ close( sal_Bool bDeliverOwnership ) override;
+
+ // css::util::XCloseBroadcaster (base of XCloseable)
+ virtual void SAL_CALL
+ addCloseListener( const css::uno::Reference< css::util::XCloseListener > & xListener ) override;
+
+ virtual void SAL_CALL
+ removeCloseListener( const css::uno::Reference< css::util::XCloseListener > & xListener ) override;
+
+ // css::frame::XStorable2 (extension of XStorable)
+ virtual void SAL_CALL storeSelf(
+ const css::uno::Sequence< css::beans::PropertyValue >& rMediaDescriptor ) override;
+
+ // css::frame::XStorable (required interface)
+ virtual sal_Bool SAL_CALL
+ hasLocation() override;
+
+ virtual OUString SAL_CALL
+ getLocation() override;
+
+ virtual sal_Bool SAL_CALL
+ isReadonly() override;
+
+ virtual void SAL_CALL
+ store() override;
+
+ virtual void SAL_CALL
+ storeAsURL( const OUString& rURL,
+ const css::uno::Sequence< css::beans::PropertyValue >& rMediaDescriptor ) override;
+
+ virtual void SAL_CALL
+ storeToURL( const OUString& rURL,
+ const css::uno::Sequence< css::beans::PropertyValue >& rMediaDescriptor ) override;
+
+ // css::util::XModifiable (required interface)
+ virtual sal_Bool SAL_CALL
+ isModified() override;
+
+ virtual void SAL_CALL
+ setModified( sal_Bool bModified ) override;
+
+ // css::util::XModifyBroadcaster (base of XModifiable)
+ virtual void SAL_CALL
+ addModifyListener( const css::uno::Reference< css::util::XModifyListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ removeModifyListener( const css::uno::Reference< css::util::XModifyListener >& xListener ) override;
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ datatransferable::XTransferable ____
+ virtual css::uno::Any SAL_CALL getTransferData(
+ const css::datatransfer::DataFlavor& aFlavor ) override;
+ virtual css::uno::Sequence< css::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors() override;
+ virtual sal_Bool SAL_CALL isDataFlavorSupported(
+ const css::datatransfer::DataFlavor& aFlavor ) override;
+
+ // lang::XTypeProvider (override method of WeakImplHelper)
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL
+ getTypes() override;
+
+ // ____ document::XDocumentPropertiesSupplier ____
+ virtual css::uno::Reference< css::document::XDocumentProperties > SAL_CALL
+ getDocumentProperties( ) override;
+
+ // ____ document::XUndoManagerSupplier ____
+ virtual css::uno::Reference< css::document::XUndoManager > SAL_CALL
+ getUndoManager( ) override;
+
+ // css::chart2::XChartDocument
+ virtual css::uno::Reference< css::chart2::XDiagram > SAL_CALL
+ getFirstDiagram() override;
+ virtual void SAL_CALL setFirstDiagram(
+ const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) override;
+ virtual void SAL_CALL
+ createInternalDataProvider( sal_Bool bCloneExistingData ) override;
+ virtual sal_Bool SAL_CALL hasInternalDataProvider() override;
+ virtual css::uno::Reference< css::chart2::data::XDataProvider > SAL_CALL
+ getDataProvider() override;
+ virtual void SAL_CALL
+ setChartTypeManager( const css::uno::Reference< css::chart2::XChartTypeManager >& xNewManager ) override;
+ virtual css::uno::Reference< css::chart2::XChartTypeManager > SAL_CALL
+ getChartTypeManager() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ getPageBackground() override;
+
+ virtual void SAL_CALL createDefaultChart() override;
+
+ // ____ XDataReceiver (public API) ____
+ virtual void SAL_CALL
+ attachDataProvider( const css::uno::Reference< css::chart2::data::XDataProvider >& xProvider ) override;
+ virtual void SAL_CALL setArguments(
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getUsedRangeRepresentations() override;
+ virtual css::uno::Reference< css::chart2::data::XDataSource > SAL_CALL getUsedData() override;
+ virtual void SAL_CALL attachNumberFormatsSupplier( const css::uno::Reference<
+ css::util::XNumberFormatsSupplier >& xSupplier ) override;
+ virtual css::uno::Reference< css::chart2::data::XRangeHighlighter > SAL_CALL getRangeHighlighter() override;
+ virtual css::uno::Reference<css::awt::XRequestCallback> SAL_CALL getPopupRequest() override;
+
+ // ____ XTitled ____
+ virtual css::uno::Reference< css::chart2::XTitle > SAL_CALL getTitleObject() override;
+ virtual void SAL_CALL setTitleObject( const css::uno::Reference< css::chart2::XTitle >& Title ) override;
+
+ // ____ XInterface (for old API wrapper) ____
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+
+ // ____ XLoadable ____
+ virtual void SAL_CALL initNew() override;
+ virtual void SAL_CALL load( const css::uno::Sequence< css::beans::PropertyValue >& rMediaDescriptor ) override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XVisualObject ____
+ virtual void SAL_CALL setVisualAreaSize(
+ ::sal_Int64 nAspect,
+ const css::awt::Size& aSize ) override;
+ virtual css::awt::Size SAL_CALL getVisualAreaSize(
+ ::sal_Int64 nAspect ) override;
+ virtual css::embed::VisualRepresentation SAL_CALL getPreferredVisualRepresentation(
+ ::sal_Int64 nAspect ) override;
+ virtual ::sal_Int32 SAL_CALL getMapUnit(
+ ::sal_Int64 nAspect ) override;
+
+ // ____ XMultiServiceFactory ____
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstance( const OUString& aServiceSpecifier ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArguments( const OUString& ServiceSpecifier
+ , const css::uno::Sequence< css::uno::Any >& Arguments ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getAvailableServiceNames() override;
+
+ // ____ XStorageBasedDocument ____
+ virtual void SAL_CALL loadFromStorage(
+ const css::uno::Reference< css::embed::XStorage >& xStorage,
+ const css::uno::Sequence< css::beans::PropertyValue >& rMediaDescriptor ) override;
+ virtual void SAL_CALL storeToStorage(
+ const css::uno::Reference< css::embed::XStorage >& xStorage,
+ const css::uno::Sequence< css::beans::PropertyValue >& rMediaDescriptor ) override;
+ virtual void SAL_CALL switchToStorage(
+ const css::uno::Reference< css::embed::XStorage >& xStorage ) override;
+ virtual css::uno::Reference< css::embed::XStorage > SAL_CALL getDocumentStorage() override;
+ virtual void SAL_CALL addStorageChangeListener(
+ const css::uno::Reference< css::document::XStorageChangeListener >& xListener ) override;
+ virtual void SAL_CALL removeStorageChangeListener(
+ const css::uno::Reference< css::document::XStorageChangeListener >& xListener ) override;
+
+ // for SvNumberFormatsSupplierObj
+ // ____ XUnoTunnel ___
+ virtual ::sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< ::sal_Int8 >& aIdentifier ) override;
+
+ // ____ XNumberFormatsSupplier ____
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getNumberFormatSettings() override;
+ virtual css::uno::Reference< css::util::XNumberFormats > SAL_CALL getNumberFormats() override;
+
+ // ____ XChild ____
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent() override;
+ virtual void SAL_CALL setParent(
+ const css::uno::Reference< css::uno::XInterface >& Parent ) override;
+
+ // ____ XDataSource ____ allows access to the currently used data and data ranges
+ virtual css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > SAL_CALL getDataSequences() override;
+
+ // XUpdatable
+ virtual void SAL_CALL update() override;
+
+ // XDumper
+ virtual OUString SAL_CALL dump(OUString const & kind) override;
+
+ // normal methods
+ css::uno::Reference< css::util::XNumberFormatsSupplier > const &
+ getNumberFormatsSupplier();
+
+ ChartView* getChartView() const;
+
+ const rtl::Reference< ::chart::Diagram > & getFirstChartDiagram() { return m_xDiagram; }
+
+ bool isTimeBased() const { return mbTimeBased;}
+
+ void setTimeBasedRange(sal_Int32 nStart, sal_Int32 nEnd);
+
+ bool isDataFromSpreadsheet();
+
+ bool isDataFromPivotTable() const;
+
+ void removeDataProviders();
+
+ const rtl::Reference< ::chart::ChartTypeManager > & getTypeManager() const { return m_xChartTypeManager; }
+
+ rtl::Reference< ::chart::Title > getTitleObject2() const;
+ void setTitleObject( const rtl::Reference< ::chart::Title >& Title );
+
+private:
+ void dumpAsXml(xmlTextWriterPtr pWriter) const;
+
+ sal_Int32 mnStart;
+ sal_Int32 mnEnd;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/inc/ChartTypeManager.hxx b/chart2/inc/ChartTypeManager.hxx
new file mode 100644
index 0000000000..71fbf471e6
--- /dev/null
+++ b/chart2/inc/ChartTypeManager.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/chart2/XChartTypeManager.hpp>
+#include <charttoolsdllapi.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+class ChartTypeTemplate;
+
+class OOO_DLLPUBLIC_CHARTTOOLS ChartTypeManager final :
+ public ::cppu::WeakImplHelper<
+ css::lang::XServiceInfo,
+ css::lang::XMultiServiceFactory,
+ css::chart2::XChartTypeManager >
+{
+public:
+ explicit ChartTypeManager(
+ css::uno::Reference< css::uno::XComponentContext > xContext );
+ virtual ~ChartTypeManager() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName()
+ override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName )
+ override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames()
+ override;
+
+ // ____ XMultiServiceFactory ____
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( const OUString& aServiceSpecifier ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(
+ const OUString& ServiceSpecifier,
+ const css::uno::Sequence< css::uno::Any >& Arguments ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
+
+ // ____ XChartTypeManager ____
+ // currently empty
+
+ rtl::Reference< ::chart::ChartTypeTemplate > createTemplate( const OUString& aServiceSpecifier );
+
+private:
+ css::uno::Reference< css::uno::XComponentContext >
+ m_xContext;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/inc/ChartView.hxx b/chart2/inc/ChartView.hxx
new file mode 100644
index 0000000000..cbee98d8cb
--- /dev/null
+++ b/chart2/inc/ChartView.hxx
@@ -0,0 +1,256 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <chartview/ExplicitValueProvider.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+
+#include <svl/lstner.hxx>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/qa/XDumper.hpp>
+#include <com/sun/star/util/XModeChangeBroadcaster.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/util/XUpdatable2.hpp>
+#include <rtl/ref.hxx>
+#include <svx/unopage.hxx>
+#include <svx/unoshape.hxx>
+
+#include <vector>
+#include <memory>
+#include <mutex>
+
+#include <vcl/timer.hxx>
+
+namespace com::sun::star::drawing { class XDrawPage; }
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::io { class XOutputStream; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::util { class XUpdatable2; }
+
+class SdrPage;
+
+namespace chart {
+
+class VCoordinateSystem;
+class DrawModelWrapper;
+class VDataSeries;
+struct CreateShapeParam2D;
+
+struct TimeBasedInfo
+{
+ TimeBasedInfo():
+ bTimeBased(false),
+ nFrame(0) {}
+
+ bool bTimeBased;
+ size_t nFrame;
+ Timer maTimer { "chart2 TimeBasedInfo" };
+
+ // only valid when we are in the time based mode
+ std::vector< std::vector< VDataSeries* > > m_aDataSeriesList;
+};
+
+/**
+ * The ChartView is responsible to manage the generation of Drawing Objects
+ * for visualization on a given OutputDevice. The ChartModel is responsible
+ * to notify changes to the view. The view than changes to state dirty. The
+ * view can be updated with call 'update'.
+ *
+ * The View is not responsible to handle single user events (that is instead
+ * done by the ChartWindow).
+ */
+class OOO_DLLPUBLIC_CHARTVIEW ChartView final : public ::cppu::WeakImplHelper<
+ css::lang::XInitialization
+ ,css::lang::XServiceInfo
+ ,css::datatransfer::XTransferable
+ ,css::util::XModifyListener
+ ,css::util::XModeChangeBroadcaster
+ ,css::util::XUpdatable2
+ ,css::beans::XPropertySet
+ ,css::lang::XMultiServiceFactory
+ ,css::qa::XDumper
+ >
+ , public ExplicitValueProvider
+ , private SfxListener
+{
+private:
+ void init();
+
+public:
+ ChartView() = delete;
+ ChartView(css::uno::Reference<css::uno::XComponentContext> xContext, ChartModel& rModel);
+
+ virtual ~ChartView() override;
+
+ // ___lang::XServiceInfo___
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ___lang::XInitialization___
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ // ___ExplicitValueProvider___
+ virtual bool getExplicitValuesForAxis(
+ rtl::Reference< Axis > xAxis
+ , ExplicitScaleData& rExplicitScale
+ , ExplicitIncrementData& rExplicitIncrement ) override;
+ virtual rtl::Reference< SvxShape >
+ getShapeForCID( const OUString& rObjectCID ) override;
+
+ virtual css::awt::Rectangle getRectangleOfObject( const OUString& rObjectCID, bool bSnapRect=false ) override;
+
+ virtual css::awt::Rectangle getDiagramRectangleExcludingAxes() override;
+
+ std::shared_ptr< DrawModelWrapper > getDrawModelWrapper() override;
+
+ // ___XTransferable___
+ virtual css::uno::Any SAL_CALL getTransferData( const css::datatransfer::DataFlavor& aFlavor ) override;
+ virtual css::uno::Sequence< css::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors( ) override;
+ virtual sal_Bool SAL_CALL isDataFlavorSupported( const css::datatransfer::DataFlavor& aFlavor ) override;
+
+ // css::util::XEventListener (base of XCloseListener and XModifyListener)
+ virtual void SAL_CALL
+ disposing( const css::lang::EventObject& Source ) override;
+
+ // css::util::XModifyListener
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ //SfxListener
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
+
+ // css::util::XModeChangeBroadcaster
+
+ virtual void SAL_CALL addModeChangeListener( const css::uno::Reference< css::util::XModeChangeListener >& _rxListener ) override;
+ virtual void SAL_CALL removeModeChangeListener( const css::uno::Reference< css::util::XModeChangeListener >& _rxListener ) override;
+ virtual void SAL_CALL addModeChangeApproveListener( const css::uno::Reference< css::util::XModeChangeApproveListener >& _rxListener ) override;
+ virtual void SAL_CALL removeModeChangeApproveListener( const css::uno::Reference< css::util::XModeChangeApproveListener >& _rxListener ) override;
+
+ // css::util::XUpdatable
+ virtual void SAL_CALL update() override;
+
+ // util::XUpdatable2
+ virtual void SAL_CALL updateSoft() override;
+ virtual void SAL_CALL updateHard() override;
+
+ // css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+
+ // css::lang::XMultiServiceFactory
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( const OUString& aServiceSpecifier ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(
+ const OUString& ServiceSpecifier, const css::uno::Sequence< css::uno::Any >& Arguments ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
+
+ // XDumper
+ virtual OUString SAL_CALL dump(OUString const & kind) override;
+
+ void setViewDirty();
+
+ css::uno::Reference<css::uno::XComponentContext> const& getComponentContext() { return m_xCC;}
+
+ void dumpAsXml(xmlTextWriterPtr pWriter) const;
+
+private: //methods
+ void createShapes();
+ void createShapes2D( const css::awt::Size& rPageSize );
+ bool createAxisTitleShapes2D( CreateShapeParam2D& rParam, const css::awt::Size& rPageSize, bool bHasRelativeSize );
+ void getMetaFile( const css::uno::Reference< css::io::XOutputStream >& xOutStream
+ , bool bUseHighContrast );
+ SdrPage* getSdrPage();
+
+ void impl_deleteCoordinateSystems();
+ void impl_notifyModeChangeListener( const OUString& rNewMode );
+
+ void impl_refreshAddIn();
+
+ void impl_updateView( bool bCheckLockedCtrler = true );
+
+ css::awt::Rectangle impl_createDiagramAndContent( const CreateShapeParam2D& rParam, const css::awt::Size& rPageSize );
+
+ DECL_LINK( UpdateTimeBased, Timer*, void );
+
+private: //member
+ std::mutex m_aMutex;
+
+ css::uno::Reference< css::uno::XComponentContext> m_xCC;
+
+ ChartModel& mrChartModel;
+
+ css::uno::Reference< css::lang::XMultiServiceFactory>
+ m_xShapeFactory;
+ rtl::Reference<SvxDrawPage>
+ m_xDrawPage;
+ rtl::Reference<SvxShapeGroupAnyD>
+ mxRootShape;
+
+ css::uno::Reference< css::uno::XInterface > m_xDashTable;
+ css::uno::Reference< css::uno::XInterface > m_xGradientTable;
+ css::uno::Reference< css::uno::XInterface > m_xHatchTable;
+ css::uno::Reference< css::uno::XInterface > m_xBitmapTable;
+ css::uno::Reference< css::uno::XInterface > m_xTransGradientTable;
+ css::uno::Reference< css::uno::XInterface > m_xMarkerTable;
+
+ std::shared_ptr< DrawModelWrapper > m_pDrawModelWrapper;
+
+ std::vector< std::unique_ptr<VCoordinateSystem> > m_aVCooSysList;
+
+ comphelper::OInterfaceContainerHelper4<css::util::XModeChangeListener>
+ m_aModeChangeListeners;
+
+ bool m_bViewDirty; //states whether the view needs to be rebuild
+ bool m_bInViewUpdate;
+ bool m_bViewUpdatePending;
+ bool m_bRefreshAddIn;
+
+ //better performance for big data
+ css::awt::Size m_aPageResolution;
+ bool m_bPointsWereSkipped;
+
+ //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
+ sal_Int32 m_nScaleXNumerator;
+ sal_Int32 m_nScaleXDenominator;
+ sal_Int32 m_nScaleYNumerator;
+ sal_Int32 m_nScaleYDenominator;
+
+ bool m_bSdrViewIsInEditMode;
+
+ css::awt::Rectangle m_aResultingDiagramRectangleExcludingAxes;
+
+ TimeBasedInfo maTimeBased;
+ std::mutex maTimeMutex;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/inc/SpecialCharacters.hxx b/chart2/inc/SpecialCharacters.hxx
new file mode 100644
index 0000000000..26d2b11873
--- /dev/null
+++ b/chart2/inc/SpecialCharacters.hxx
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/types.h>
+
+const sal_Unicode aMinusSign = 0x2212;
+const sal_Unicode aSuperscriptFigures[10]
+ = { 0x2070, 0x00B9, 0x00B2, 0x00B3, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079 };
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/inc/bitmaps.hlst b/chart2/inc/bitmaps.hlst
new file mode 100644
index 0000000000..5ef14f869f
--- /dev/null
+++ b/chart2/inc/bitmaps.hlst
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+inline constexpr OUString BMP_TYPE_COLUMN = u"chart2/res/typecolumn_16.png"_ustr;
+inline constexpr OUString BMP_TYPE_BAR = u"chart2/res/typebar_16.png"_ustr;
+inline constexpr OUString BMP_TYPE_PIE = u"chart2/res/typepie_16.png"_ustr;
+inline constexpr OUString BMP_TYPE_LINE = u"chart2/res/typepointline_16.png"_ustr;
+inline constexpr OUString BMP_TYPE_XY = u"chart2/res/typexy_16.png"_ustr;
+inline constexpr OUString BMP_TYPE_AREA = u"chart2/res/typearea_16.png"_ustr;
+inline constexpr OUString BMP_TYPE_NET = u"chart2/res/typenet_16.png"_ustr;
+inline constexpr OUString BMP_TYPE_STOCK = u"chart2/res/typestock_16.png"_ustr;
+inline constexpr OUString BMP_TYPE_COLUMN_LINE = u"chart2/res/typecolumnline_16.png"_ustr;
+inline constexpr OUString BMP_TYPE_BUBBLE = u"chart2/res/typebubble_16.png"_ustr;
+inline constexpr OUString BMP_BUBBLE_1 = u"chart2/res/bubble_52x60.png"_ustr;
+inline constexpr OUString BMP_AREAS_2D = u"chart2/res/areas_52x60.png"_ustr;
+inline constexpr OUString BMP_AREAS_2D_1 = u"chart2/res/areaspiled_52x60.png"_ustr;
+inline constexpr OUString BMP_AREAS_2D_3 = u"chart2/res/areasfull_52x60.png"_ustr;
+inline constexpr OUString BMP_AREAS_3D = u"chart2/res/areaspiled3d_52x60.png"_ustr;
+inline constexpr OUString BMP_AREAS_3D_1 = u"chart2/res/areas3d_52x60.png"_ustr;
+inline constexpr OUString BMP_AREAS_3D_2 = u"chart2/res/areasfull3d_52x60.png"_ustr;
+inline constexpr OUString BMP_BARS_2D_1 = u"chart2/res/bar_52x60.png"_ustr;
+inline constexpr OUString BMP_BARS_2D_2 = u"chart2/res/barstack_52x60.png"_ustr;
+inline constexpr OUString BMP_BARS_2D_3 = u"chart2/res/barpercent_52x60.png"_ustr;
+inline constexpr OUString BMP_BARS_3D = u"chart2/res/bar3ddeep_52x60.png"_ustr;
+inline constexpr OUString BMP_BARS_3D_1 = u"chart2/res/bar3d_52x60.png"_ustr;
+inline constexpr OUString BMP_BARS_3D_2 = u"chart2/res/barstack3d_52x60.png"_ustr;
+inline constexpr OUString BMP_BARS_3D_3 = u"chart2/res/barpercent3d_52x60.png"_ustr;
+inline constexpr OUString BMP_CIRCLES_2D = u"chart2/res/pie_52x60.png"_ustr;
+inline constexpr OUString BMP_CIRCLES_2D_EXPLODED = u"chart2/res/pieexploded_52x60.png"_ustr;
+inline constexpr OUString BMP_CIRCLES_3D = u"chart2/res/pie3d_52x60.png"_ustr;
+inline constexpr OUString BMP_CIRCLES_3D_EXPLODED = u"chart2/res/pie3dexploded_52x60.png"_ustr;
+inline constexpr OUString BMP_DONUT_2D = u"chart2/res/donut_52x60.png"_ustr;
+inline constexpr OUString BMP_DONUT_2D_EXPLODED = u"chart2/res/donutexploded_52x60.png"_ustr;
+inline constexpr OUString BMP_DONUT_3D = u"chart2/res/donut3d_52x60.png"_ustr;
+inline constexpr OUString BMP_DONUT_3D_EXPLODED = u"chart2/res/donut3dexploded_52x60.png"_ustr;
+inline constexpr OUString BMP_COLUMNS_2D_1 = u"chart2/res/columns_52x60.png"_ustr;
+inline constexpr OUString BMP_COLUMNS_2D_2 = u"chart2/res/columnstack_52x60.png"_ustr;
+inline constexpr OUString BMP_COLUMNS_2D_3 = u"chart2/res/columnpercent_52x60.png"_ustr;
+inline constexpr OUString BMP_COLUMN_LINE = u"chart2/res/columnline_52x60.png"_ustr;
+inline constexpr OUString BMP_COLUMN_LINE_STACKED = u"chart2/res/columnstackline_52x60.png"_ustr;
+inline constexpr OUString BMP_COLUMNS_3D = u"chart2/res/columns3ddeep_52x60.png"_ustr;
+inline constexpr OUString BMP_COLUMNS_3D_1 = u"chart2/res/columns3d_52x60.png"_ustr;
+inline constexpr OUString BMP_COLUMNS_3D_2 = u"chart2/res/columnstack3d_52x60.png"_ustr;
+inline constexpr OUString BMP_COLUMNS_3D_3 = u"chart2/res/columnpercent3d_52x60.png"_ustr;
+inline constexpr OUString BMP_KEGELQ_3D_1 = u"chart2/res/conehori_52x60.png"_ustr;
+inline constexpr OUString BMP_KEGELQ_3D_2 = u"chart2/res/conehoristack_52x60.png"_ustr;
+inline constexpr OUString BMP_KEGELQ_3D_3 = u"chart2/res/conehoripercent_52x60.png"_ustr;
+inline constexpr OUString BMP_KEGELQ_3D_4 = u"chart2/res/conehorideep_52x60.png"_ustr;
+inline constexpr OUString BMP_KEGEL_3D_1 = u"chart2/res/cone_52x60.png"_ustr;
+inline constexpr OUString BMP_KEGEL_3D_2 = u"chart2/res/conestack_52x60.png"_ustr;
+inline constexpr OUString BMP_KEGEL_3D_3 = u"chart2/res/conepercent_52x60.png"_ustr;
+inline constexpr OUString BMP_KEGEL_3D_4 = u"chart2/res/conedeep_52x60.png"_ustr;
+inline constexpr OUString BMP_POINTS_XVALUES = u"chart2/res/valueaxisdirectpoints_52x60.png"_ustr;
+inline constexpr OUString BMP_POINTS_XCATEGORY = u"chart2/res/nostackdirectpoints_52x60.png"_ustr;
+inline constexpr OUString BMP_POINTS_STACKED = u"chart2/res/stackdirectpoints_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_P_XVALUES = u"chart2/res/valueaxisdirectboth_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_O_XVALUES = u"chart2/res/valueaxisdirectlines_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE3D_XVALUES = u"chart2/res/valueaxisdirect3d_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_P_XCATEGORY = u"chart2/res/nostackdirectboth_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_O_XCATEGORY = u"chart2/res/nostackdirectlines_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE3D_XCATEGORY = u"chart2/res/nostackdirect3d_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_P_STACKED = u"chart2/res/stackdirectboth_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_O_STACKED = u"chart2/res/stackdirectlines_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE3D_STACKED = u"chart2/res/stackdirect3d_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_P_XVALUES_SMOOTH = u"chart2/res/valueaxissmoothboth_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_O_XVALUES_SMOOTH = u"chart2/res/valueaxissmoothlines_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE3D_XVALUES_SMOOTH = u"chart2/res/valueaxissmooth3d_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_P_XCATEGORY_SMOOTH = u"chart2/res/nostacksmoothboth_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_O_XCATEGORY_SMOOTH = u"chart2/res/nostacksmoothlines_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE3D_XCATEGORY_SMOOTH = u"chart2/res/nostacksmooth3d_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_P_STACKED_SMOOTH = u"chart2/res/stacksmoothboth_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_O_STACKED_SMOOTH = u"chart2/res/stacksmoothlines_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE3D_STACKED_SMOOTH = u"chart2/res/stacksmooth3d_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_P_XVALUES_STEPPED = u"chart2/res/valueaxissteppedboth_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_O_XVALUES_STEPPED = u"chart2/res/valueaxissteppedlines_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE3D_XVALUES_STEPPED = u"chart2/res/valueaxisstepped3d_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_P_XCATEGORY_STEPPED = u"chart2/res/nostacksteppedboth_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_O_XCATEGORY_STEPPED = u"chart2/res/nostacksteppedlines_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE3D_XCATEGORY_STEPPED = u"chart2/res/nostackstepped3d_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_P_STACKED_STEPPED = u"chart2/res/stacksteppedboth_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE_O_STACKED_STEPPED = u"chart2/res/stacksteppedlines_52x60.png"_ustr;
+inline constexpr OUString BMP_LINE3D_STACKED_STEPPED = u"chart2/res/stackstepped3d_52x60.png"_ustr;
+inline constexpr OUString BMP_NET = u"chart2/res/net_52x60.png"_ustr;
+inline constexpr OUString BMP_NET_STACK = u"chart2/res/netstack_52x60.png"_ustr;
+inline constexpr OUString BMP_NET_SYMB = u"chart2/res/netpoint_52x60.png"_ustr;
+inline constexpr OUString BMP_NET_SYMB_STACK = u"chart2/res/netpointstack_52x60.png"_ustr;
+inline constexpr OUString BMP_NET_LINESYMB = u"chart2/res/netlinepoint_52x60.png"_ustr;
+inline constexpr OUString BMP_NET_LINESYMB_STACK = u"chart2/res/netlinepointstack_52x60.png"_ustr;
+inline constexpr OUString BMP_NET_FILL = u"chart2/res/netfill_52x60.png"_ustr;
+inline constexpr OUString BMP_NET_FILL_STACK = u"chart2/res/netstackfill_52x60.png"_ustr;
+inline constexpr OUString BMP_PYRAMIDQ_3D_1 = u"chart2/res/pyramindhori_52x60.png"_ustr;
+inline constexpr OUString BMP_PYRAMIDQ_3D_2 = u"chart2/res/pyramindhoristack_52x60.png"_ustr;
+inline constexpr OUString BMP_PYRAMIDQ_3D_3 = u"chart2/res/pyramindhoripercent_52x60.png"_ustr;
+inline constexpr OUString BMP_PYRAMIDQ_3D_4 = u"chart2/res/pyramindhorideep_52x60.png"_ustr;
+inline constexpr OUString BMP_PYRAMID_3D_1 = u"chart2/res/pyramind_52x60.png"_ustr;
+inline constexpr OUString BMP_PYRAMID_3D_2 = u"chart2/res/pyramindstack_52x60.png"_ustr;
+inline constexpr OUString BMP_PYRAMID_3D_3 = u"chart2/res/pyramindpercent_52x60.png"_ustr;
+inline constexpr OUString BMP_PYRAMID_3D_4 = u"chart2/res/pyraminddeep_52x60.png"_ustr;
+inline constexpr OUString BMP_ROEHRE_3D_1 = u"chart2/res/cylinderhori_52x60.png"_ustr;
+inline constexpr OUString BMP_ROEHRE_3D_2 = u"chart2/res/cylinderhoristack_52x60.png"_ustr;
+inline constexpr OUString BMP_ROEHRE_3D_3 = u"chart2/res/cylinderhoriprocent_52x60.png"_ustr;
+inline constexpr OUString BMP_ROEHRE_3D_4 = u"chart2/res/cylinderhorideep_52x60.png"_ustr;
+inline constexpr OUString BMP_SAEULE_3D_1 = u"chart2/res/cylinder_52x60.png"_ustr;
+inline constexpr OUString BMP_SAEULE_3D_2 = u"chart2/res/cylinderstack_52x60.png"_ustr;
+inline constexpr OUString BMP_SAEULE_3D_3 = u"chart2/res/cylinderpercent_52x60.png"_ustr;
+inline constexpr OUString BMP_SAEULE_3D_4 = u"chart2/res/cylinderdeep_52x60.png"_ustr;
+inline constexpr OUString BMP_STOCK_1 = u"chart2/res/stock_52x60.png"_ustr;
+inline constexpr OUString BMP_STOCK_2 = u"chart2/res/stockblock_52x60.png"_ustr;
+inline constexpr OUString BMP_STOCK_3 = u"chart2/res/stockcolumns_52x60.png"_ustr;
+inline constexpr OUString BMP_STOCK_4 = u"chart2/res/stockcolumnsattach_52x60.png"_ustr;
+inline constexpr OUString BMP_INDICATE_BOTH_VERTI = u"chart2/res/errorbothverti_30.png"_ustr;
+inline constexpr OUString BMP_INDICATE_DOWN = u"chart2/res/errordown_30.png"_ustr;
+inline constexpr OUString BMP_INDICATE_UP = u"chart2/res/errorup_30.png"_ustr;
+inline constexpr OUString BMP_INDICATE_BOTH_HORI = u"chart2/res/errorbothhori_30.png"_ustr;
+inline constexpr OUString BMP_INDICATE_RIGHT = u"chart2/res/errorright_30.png"_ustr;
+inline constexpr OUString BMP_INDICATE_LEFT = u"chart2/res/errorleft_30.png"_ustr;
+inline constexpr OUString BMP_REGRESSION_LINEAR = u"chart2/res/reglin.png"_ustr;
+inline constexpr OUString BMP_REGRESSION_LOG = u"chart2/res/reglog.png"_ustr;
+inline constexpr OUString BMP_REGRESSION_EXP = u"chart2/res/regexp.png"_ustr;
+inline constexpr OUString BMP_REGRESSION_POWER = u"chart2/res/regpow.png"_ustr;
+inline constexpr OUString BMP_REGRESSION_POLYNOMIAL = u"chart2/res/regpoly.png"_ustr;
+inline constexpr OUString BMP_REGRESSION_MOVING_AVERAGE = u"chart2/res/regavg.png"_ustr;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/chart2/inc/chart.hrc b/chart2/inc/chart.hrc
new file mode 100644
index 0000000000..b8b6a7e8b2
--- /dev/null
+++ b/chart2/inc/chart.hrc
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <unotools/resmgr.hxx>
+
+#define NC_(Context, String) TranslateId(Context, u8##String)
+
+const TranslateId CHART_TYPE[] =
+{
+ NC_("tp_ChartType|liststore1", "Bar"),
+ NC_("tp_ChartType|liststore1", "Cylinder"),
+ NC_("tp_ChartType|liststore1", "Cone"),
+ NC_("tp_ChartType|liststore1", "Pyramid")
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/chart2/inc/pch/precompiled_chartcontroller.cxx b/chart2/inc/pch/precompiled_chartcontroller.cxx
new file mode 100644
index 0000000000..44d47c4a42
--- /dev/null
+++ b/chart2/inc/pch/precompiled_chartcontroller.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "precompiled_chartcontroller.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/inc/pch/precompiled_chartcontroller.hxx b/chart2/inc/pch/precompiled_chartcontroller.hxx
new file mode 100644
index 0000000000..77745b0537
--- /dev/null
+++ b/chart2/inc/pch/precompiled_chartcontroller.hxx
@@ -0,0 +1,515 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ This file has been autogenerated by update_pch.sh. It is possible to edit it
+ manually (such as when an include file has been moved/renamed/removed). All such
+ manual changes will be rewritten by the next run of update_pch.sh (which presumably
+ also fixes all possible problems, so it's usually better to use it).
+
+ Generated on 2023-07-19 09:20:36 using:
+ ./bin/update_pch chart2 chartcontroller --cutoff=6 --exclude:system --include:module --include:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./chart2/inc/pch/precompiled_chartcontroller.hxx "make chart2.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <deque>
+#include <float.h>
+#include <functional>
+#include <initializer_list>
+#include <iomanip>
+#include <iterator>
+#include <limits.h>
+#include <limits>
+#include <map>
+#include <math.h>
+#include <memory>
+#include <mutex>
+#include <new>
+#include <numeric>
+#include <optional>
+#include <ostream>
+#include <set>
+#include <span>
+#include <stddef.h>
+#include <stdexcept>
+#include <string.h>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <typeinfo>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+#include <boost/property_tree/json_parser.hpp>
+#include <boost/property_tree/ptree_fwd.hpp>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <osl/diagnose.h>
+#include <osl/diagnose.hxx>
+#include <osl/doublecheckedlocking.h>
+#include <osl/endian.h>
+#include <osl/getglobalmutex.hxx>
+#include <osl/interlck.h>
+#include <osl/mutex.h>
+#include <osl/mutex.hxx>
+#include <rtl/alloc.h>
+#include <rtl/character.hxx>
+#include <rtl/instance.hxx>
+#include <rtl/locale.h>
+#include <rtl/math.h>
+#include <rtl/math.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/strbuf.h>
+#include <rtl/strbuf.hxx>
+#include <rtl/string.h>
+#include <rtl/string.hxx>
+#include <rtl/stringconcat.hxx>
+#include <rtl/stringutils.hxx>
+#include <rtl/textcvt.h>
+#include <rtl/textenc.h>
+#include <rtl/ustrbuf.h>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+#include <sal/backtrace.hxx>
+#include <sal/detail/log.h>
+#include <sal/log.hxx>
+#include <sal/macros.h>
+#include <sal/saldllapi.h>
+#include <sal/types.h>
+#include <sal/typesizes.h>
+#include <vcl/BinaryDataContainer.hxx>
+#include <vcl/GraphicAttributes.hxx>
+#include <vcl/GraphicExternalLink.hxx>
+#include <vcl/GraphicObject.hxx>
+#include <vcl/IDialogRenderable.hxx>
+#include <vcl/Scanline.hxx>
+#include <vcl/WindowPosSize.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/animate/Animation.hxx>
+#include <vcl/animate/AnimationFrame.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmap/BitmapTypes.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/builderpage.hxx>
+#include <vcl/cairo.hxx>
+#include <vcl/checksum.hxx>
+#include <vcl/customweld.hxx>
+#include <vcl/dllapi.h>
+#include <vcl/dockwin.hxx>
+#include <vcl/event.hxx>
+#include <vcl/fntstyle.hxx>
+#include <vcl/font.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/gfxlink.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/idle.hxx>
+#include <vcl/image.hxx>
+#include <vcl/kernarray.hxx>
+#include <vcl/keycod.hxx>
+#include <vcl/keycodes.hxx>
+#include <vcl/mapmod.hxx>
+#include <vcl/metaactiontypes.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/region.hxx>
+#include <vcl/rendercontext/AddFontSubstituteFlags.hxx>
+#include <vcl/rendercontext/AntialiasingFlags.hxx>
+#include <vcl/rendercontext/DrawGridFlags.hxx>
+#include <vcl/rendercontext/DrawImageFlags.hxx>
+#include <vcl/rendercontext/DrawModeFlags.hxx>
+#include <vcl/rendercontext/DrawTextFlags.hxx>
+#include <vcl/rendercontext/GetDefaultFontFlags.hxx>
+#include <vcl/rendercontext/ImplMapRes.hxx>
+#include <vcl/rendercontext/InvertFlags.hxx>
+#include <vcl/rendercontext/RasterOp.hxx>
+#include <vcl/rendercontext/SalLayoutFlags.hxx>
+#include <vcl/rendercontext/State.hxx>
+#include <vcl/rendercontext/SystemTextColorFlags.hxx>
+#include <vcl/salnativewidgets.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/task.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/toolboxid.hxx>
+#include <vcl/uitest/factory.hxx>
+#include <vcl/vclenum.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/vclreferencebase.hxx>
+#include <vcl/vectorgraphicdata.hxx>
+#include <vcl/wall.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/window.hxx>
+#include <vcl/windowstate.hxx>
+#include <vcl/wintypes.hxx>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <basegfx/basegfxdllapi.h>
+#include <basegfx/color/bcolor.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <basegfx/matrix/hommatrixtemplate.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/point/b3dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/range/Range2D.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/range/b3drange.hxx>
+#include <basegfx/range/basicrange.hxx>
+#include <basegfx/tuple/Size2D.hxx>
+#include <basegfx/tuple/Tuple2D.hxx>
+#include <basegfx/tuple/Tuple3D.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
+#include <basegfx/tuple/b2ituple.hxx>
+#include <basegfx/tuple/b3dtuple.hxx>
+#include <basegfx/utils/bgradient.hxx>
+#include <basegfx/utils/common.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/vector/b2enums.hxx>
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+#include <basegfx/vector/b3dvector.hxx>
+#include <chartview/ChartSfxItemIds.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <com/sun/star/awt/DeviceInfo.hpp>
+#include <com/sun/star/awt/Gradient2.hpp>
+#include <com/sun/star/awt/GradientStyle.hpp>
+#include <com/sun/star/awt/Key.hpp>
+#include <com/sun/star/awt/KeyGroup.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertyStates.hpp>
+#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XPropertySetOption.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XVetoableChangeListener.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/drawing/DashStyle.hpp>
+#include <com/sun/star/drawing/HatchStyle.hpp>
+#include <com/sun/star/drawing/LineCap.hpp>
+#include <com/sun/star/drawing/TextFitToSizeType.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/form/FormComponentType.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XModel3.hpp>
+#include <com/sun/star/frame/XStatusListener.hpp>
+#include <com/sun/star/frame/XToolbarController.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/graphic/XPrimitive2D.hpp>
+#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
+#include <com/sun/star/i18n/ForbiddenCharacters.hpp>
+#include <com/sun/star/i18n/LanguageCountryInfo.hpp>
+#include <com/sun/star/i18n/LocaleDataItem2.hpp>
+#include <com/sun/star/i18n/LocaleItem.hpp>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/i18n/reservedWords.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/io/XStream.hpp>
+#include <com/sun/star/io/XTruncate.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/text/textfield/Type.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.h>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/TypeClass.hdl>
+#include <com/sun/star/uno/XAggregation.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/uno/XWeak.hpp>
+#include <com/sun/star/uno/genfunc.h>
+#include <com/sun/star/uno/genfunc.hxx>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <com/sun/star/util/XAccounting.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/compbase.hxx>
+#include <comphelper/comphelperdllapi.h>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/errcode.hxx>
+#include <comphelper/interfacecontainer2.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <comphelper/lok.hxx>
+#include <comphelper/multicontainer2.hxx>
+#include <comphelper/propagg.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <comphelper/propertycontainerhelper.hxx>
+#include <comphelper/propstate.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/uno3.hxx>
+#include <comphelper/unoimplbase.hxx>
+#include <cppu/cppudllapi.h>
+#include <cppu/unotype.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/cppuhelperdllapi.h>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/implbase_ex.hxx>
+#include <cppuhelper/implbase_ex_post.hxx>
+#include <cppuhelper/implbase_ex_pre.hxx>
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/weakagg.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <docmodel/color/ComplexColor.hxx>
+#include <docmodel/color/Transformation.hxx>
+#include <docmodel/dllapi.h>
+#include <docmodel/theme/ThemeColorType.hxx>
+#include <drawinglayer/drawinglayerdllapi.h>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/primitive2d/CommonTypes.hxx>
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
+#include <drawinglayer/primitive2d/Primitive2DVisitor.hxx>
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/editdata.hxx>
+#include <editeng/editengdllapi.h>
+#include <editeng/editobj.hxx>
+#include <editeng/editstat.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/eedata.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/forbiddencharacterstable.hxx>
+#include <editeng/macros.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/outlobj.hxx>
+#include <editeng/overflowingtxt.hxx>
+#include <editeng/paragraphdata.hxx>
+#include <editeng/svxenum.hxx>
+#include <editeng/svxfont.hxx>
+#include <i18nlangtag/i18nlangtagdllapi.h>
+#include <i18nlangtag/lang.h>
+#include <i18nlangtag/languagetag.hxx>
+#include <o3tl/cow_wrapper.hxx>
+#include <o3tl/deleter.hxx>
+#include <o3tl/enumarray.hxx>
+#include <o3tl/hash_combine.hxx>
+#include <o3tl/safeint.hxx>
+#include <o3tl/sorted_vector.hxx>
+#include <o3tl/strong_int.hxx>
+#include <o3tl/typed_flags_set.hxx>
+#include <o3tl/underlyingenumvalue.hxx>
+#include <o3tl/unit_conversion.hxx>
+#include <salhelper/salhelperdllapi.h>
+#include <salhelper/simplereferenceobject.hxx>
+#include <sfx2/basedlgs.hxx>
+#include <sfx2/dllapi.h>
+#include <sfx2/shell.hxx>
+#include <sfx2/tabdlg.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sot/formats.hxx>
+#include <sot/sotdllapi.h>
+#include <svl/SfxBroadcaster.hxx>
+#include <svl/eitem.hxx>
+#include <svl/hint.hxx>
+#include <svl/intitem.hxx>
+#include <svl/itempool.hxx>
+#include <svl/itemset.hxx>
+#include <svl/languageoptions.hxx>
+#include <svl/lstner.hxx>
+#include <svl/poolitem.hxx>
+#include <svl/setitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/style.hxx>
+#include <svl/stylesheetuser.hxx>
+#include <svl/svldllapi.h>
+#include <svl/typedwhich.hxx>
+#include <svl/undo.hxx>
+#include <svl/whichranges.hxx>
+#include <svtools/colorcfg.hxx>
+#include <svtools/svtdllapi.h>
+#include <svx/ActionDescriptionProvider.hxx>
+#include <svx/XPropertyEntry.hxx>
+#include <svx/chrtitem.hxx>
+#include <svx/ipolypolygoneditorcontroller.hxx>
+#include <svx/itextprovider.hxx>
+#include <svx/sdangitm.hxx>
+#include <svx/sdr/animation/scheduler.hxx>
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <svx/sdr/overlay/overlayobjectlist.hxx>
+#include <svx/sdr/properties/defaultproperties.hxx>
+#include <svx/sdr/properties/properties.hxx>
+#include <svx/sdrobjectuser.hxx>
+#include <svx/sdtaditm.hxx>
+#include <svx/sdtaitm.hxx>
+#include <svx/sdtakitm.hxx>
+#include <svx/selectioncontroller.hxx>
+#include <svx/svddef.hxx>
+#include <svx/svddrag.hxx>
+#include <svx/svdedtv.hxx>
+#include <svx/svdedxv.hxx>
+#include <svx/svdglev.hxx>
+#include <svx/svdglue.hxx>
+#include <svx/svdhdl.hxx>
+#include <svx/svdhlpln.hxx>
+#include <svx/svdlayer.hxx>
+#include <svx/svdmark.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdmrkv.hxx>
+#include <svx/svdoattr.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdobjkind.hxx>
+#include <svx/svdoedge.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/svdpntv.hxx>
+#include <svx/svdpoev.hxx>
+#include <svx/svdsnpv.hxx>
+#include <svx/svdsob.hxx>
+#include <svx/svdtext.hxx>
+#include <svx/svdtrans.hxx>
+#include <svx/svdtypes.hxx>
+#include <svx/svdundo.hxx>
+#include <svx/svxdllapi.h>
+#include <svx/xdash.hxx>
+#include <svx/xdef.hxx>
+#include <svx/xhatch.hxx>
+#include <svx/xit.hxx>
+#include <svx/xpoly.hxx>
+#include <svx/xtable.hxx>
+#include <tools/color.hxx>
+#include <tools/date.hxx>
+#include <tools/datetime.hxx>
+#include <tools/degree.hxx>
+#include <tools/fldunit.hxx>
+#include <tools/fontenum.hxx>
+#include <tools/fract.hxx>
+#include <tools/gen.hxx>
+#include <tools/helpers.hxx>
+#include <tools/lineend.hxx>
+#include <tools/link.hxx>
+#include <tools/long.hxx>
+#include <tools/mapunit.hxx>
+#include <tools/poly.hxx>
+#include <tools/ref.hxx>
+#include <tools/solar.h>
+#include <tools/stream.hxx>
+#include <tools/time.hxx>
+#include <tools/toolsdllapi.h>
+#include <tools/weakbase.h>
+#include <typelib/typeclass.h>
+#include <typelib/typedescription.h>
+#include <typelib/uik.h>
+#include <uno/any2.h>
+#include <uno/data.h>
+#include <uno/sequence2.h>
+#include <unotools/eventlisteneradapter.hxx>
+#include <unotools/fontdefs.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/options.hxx>
+#include <unotools/resmgr.hxx>
+#include <unotools/syslocale.hxx>
+#include <unotools/tempfile.hxx>
+#include <unotools/unotoolsdllapi.h>
+#include <unotools/weakref.hxx>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <CharacterPropertyItemConverter.hxx>
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <ChartView.hxx>
+#include <ChartWindow.hxx>
+#include <CommonConverters.hxx>
+#include <ControllerLockGuard.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DataSourceHelper.hxx>
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <DrawViewWrapper.hxx>
+#include <FastPropertyIdRanges.hxx>
+#include <FillProperties.hxx>
+#include <GraphicPropertyItemConverter.hxx>
+#include <ItemConverter.hxx>
+#include <ItemPropertyMap.hxx>
+#include <Legend.hxx>
+#include <LegendHelper.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <ObjectIdentifier.hxx>
+#include <ObjectNameProvider.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <ResId.hxx>
+#include <StatisticsHelper.hxx>
+#include <ThreeDHelper.hxx>
+#include <TitleHelper.hxx>
+#include <UserDefinedProperties.hxx>
+#include <ViewElementListProvider.hxx>
+#include <WrappedProperty.hxx>
+#include <charttoolsdllapi.hxx>
+#include <servicenames.hxx>
+#include <unonames.hxx>
+#endif // PCH_LEVEL >= 4
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/inc/pch/precompiled_chartcore.cxx b/chart2/inc/pch/precompiled_chartcore.cxx
new file mode 100644
index 0000000000..10d8b365b8
--- /dev/null
+++ b/chart2/inc/pch/precompiled_chartcore.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "precompiled_chartcore.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/inc/pch/precompiled_chartcore.hxx b/chart2/inc/pch/precompiled_chartcore.hxx
new file mode 100644
index 0000000000..9e7d56b2f7
--- /dev/null
+++ b/chart2/inc/pch/precompiled_chartcore.hxx
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ This file has been autogenerated by update_pch.sh. It is possible to edit it
+ manually (such as when an include file has been moved/renamed/removed). All such
+ manual changes will be rewritten by the next run of update_pch.sh (which presumably
+ also fixes all possible problems, so it's usually better to use it).
+
+ Generated on 2023-07-19 09:21:03 using:
+ ./bin/update_pch chart2 chartcore --cutoff=3 --exclude:system --exclude:module --include:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./chart2/inc/pch/precompiled_chartcore.hxx "make chart2.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <functional>
+#include <iterator>
+#include <limits>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <new>
+#include <optional>
+#include <ostream>
+#include <set>
+#include <span>
+#include <string_view>
+#include <type_traits>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+#include <boost/property_tree/ptree_fwd.hpp>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <osl/conditn.hxx>
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <rtl/alloc.h>
+#include <rtl/character.hxx>
+#include <rtl/instance.hxx>
+#include <rtl/locale.h>
+#include <rtl/math.h>
+#include <rtl/math.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/string.hxx>
+#include <rtl/stringconcat.hxx>
+#include <rtl/stringutils.hxx>
+#include <rtl/textenc.h>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+#include <rtl/uuid.h>
+#include <sal/log.hxx>
+#include <sal/macros.h>
+#include <sal/types.h>
+#include <vcl/dllapi.h>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <basegfx/basegfxdllapi.h>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
+#include <basegfx/tuple/b2ituple.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/vector/b2enums.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertyStates.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetOption.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart/ChartLegendExpansion.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/chart/TimeUnit.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/CurveStyle.hpp>
+#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart2/MovingAverageType.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart2/SymbolStyle.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/chart2/XFormattedString2.hpp>
+#include <com/sun/star/chart2/data/XDataSequence.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
+#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/drawing/LineCap.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/RectanglePoint.hpp>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.h>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <comphelper/comphelperdllapi.h>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/errcode.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/property.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/uno3.hxx>
+#include <cppu/cppudllapi.h>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/cppuhelperdllapi.h>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/implbase_ex.hxx>
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <editeng/editengdllapi.h>
+#include <editeng/unoprnms.hxx>
+#include <i18nlangtag/i18nlangtagdllapi.h>
+#include <i18nlangtag/lang.h>
+#include <i18nlangtag/languagetag.hxx>
+#include <libxml/xmlwriter.h>
+#include <o3tl/cow_wrapper.hxx>
+#include <o3tl/safeint.hxx>
+#include <o3tl/string_view.hxx>
+#include <o3tl/typed_flags_set.hxx>
+#include <officecfg/Office/Compatibility.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+#include <svl/cintitem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/numformat.hxx>
+#include <svl/poolitem.hxx>
+#include <svl/svldllapi.h>
+#include <svl/typedwhich.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svxdllapi.h>
+#include <svx/unoshape.hxx>
+#include <tools/UnitConversion.hxx>
+#include <tools/color.hxx>
+#include <tools/gen.hxx>
+#include <tools/helpers.hxx>
+#include <tools/lineend.hxx>
+#include <tools/link.hxx>
+#include <tools/long.hxx>
+#include <tools/ref.hxx>
+#include <tools/stream.hxx>
+#include <tools/toolsdllapi.h>
+#include <unotools/options.hxx>
+#include <unotools/unotoolsdllapi.h>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <AxisIndexDefines.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <BaseGFXHelper.hxx>
+#include <CartesianCoordinateSystem.hxx>
+#include <CharacterProperties.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <ChartView.hxx>
+#include <ChartViewHelper.hxx>
+#include <Clipping.hxx>
+#include <CloneHelper.hxx>
+#include <CommonConverters.hxx>
+#include <CommonFunctors.hxx>
+#include <ControllerLockGuard.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DataSeriesProperties.hxx>
+#include <DataSource.hxx>
+#include <DataSourceHelper.hxx>
+#include <DataTable.hxx>
+#include <DateHelper.hxx>
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <FillProperties.hxx>
+#include <FormattedString.hxx>
+#include <GridProperties.hxx>
+#include <InternalDataProvider.hxx>
+#include <LabelPositionHelper.hxx>
+#include <LabeledDataSequence.hxx>
+#include <Legend.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <MediaDescriptorHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <ObjectIdentifier.hxx>
+#include <PlottingPositionHelper.hxx>
+#include <PolarCoordinateSystem.hxx>
+#include <PolarLabelPositionHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <PropertyMapper.hxx>
+#include <RangeHighlighter.hxx>
+#include <ReferenceSizeProvider.hxx>
+#include <RegressionCalculationHelper.hxx>
+#include <RegressionCurveCalculator.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <RelativePositionHelper.hxx>
+#include <RelativeSizeHelper.hxx>
+#include <ResId.hxx>
+#include <ScaleAutomatism.hxx>
+#include <ShapeFactory.hxx>
+#include <SpecialCharacters.hxx>
+#include <Stripe.hxx>
+#include <ThreeDHelper.hxx>
+#include <Title.hxx>
+#include <TitleHelper.hxx>
+#include <UserDefinedProperties.hxx>
+#include <VLineProperties.hxx>
+#include <VSeriesPlotter.hxx>
+#include <ViewDefines.hxx>
+#include <WrappedProperty.hxx>
+#include <charttoolsdllapi.hxx>
+#include <defines.hxx>
+#include <servicenames.hxx>
+#include <servicenames_charttypes.hxx>
+#include <servicenames_coosystems.hxx>
+#include <unonames.hxx>
+#endif // PCH_LEVEL >= 4
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/inc/strings.hrc b/chart2/inc/strings.hrc
new file mode 100644
index 0000000000..8c22e850b9
--- /dev/null
+++ b/chart2/inc/strings.hrc
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef CHART_STRINGS_HRC
+#define CHART_STRINGS_HRC
+
+#define NC_(Context, String) TranslateId(Context, u8##String)
+
+#define STR_DLG_CHART_WIZARD NC_("STR_DLG_CHART_WIZARD", "Chart Wizard")
+#define STR_DLG_SMOOTH_LINE_PROPERTIES NC_("STR_DLG_SMOOTH_LINE_PROPERTIES", "Smooth Lines")
+#define STR_DLG_STEPPED_LINE_PROPERTIES NC_("STR_DLG_STEPPED_LINE_PROPERTIES", "Stepped Lines")
+#define STR_DLG_REMOVE_DATA_TABLE NC_("STR_DLG_REMOVE_DATA_TABLE", "This chart currently contains an internal data table. Do you want to proceed, deleting the internal data table, and set a new data range?")
+#define STR_PAGE_CHARTTYPE NC_("STR_PAGE_CHARTTYPE", "Chart Type")
+#define STR_PAGE_DATA_RANGE NC_("STR_PAGE_DATA_RANGE", "Data Range")
+#define STR_PAGE_CHART_ELEMENTS NC_("STR_PAGE_CHART_ELEMENTS", "Chart Elements")
+#define STR_PAGE_LINE NC_("STR_PAGE_LINE", "Line")
+#define STR_PAGE_BORDER NC_("STR_PAGE_BORDER", "Borders")
+#define STR_PAGE_AREA NC_("STR_PAGE_AREA", "Area")
+#define STR_PAGE_TRANSPARENCY NC_("STR_PAGE_TRANSPARENCY", "Transparency")
+#define STR_PAGE_FONT NC_("STR_PAGE_FONT", "Font")
+#define STR_PAGE_FONT_EFFECTS NC_("STR_PAGE_FONT_EFFECTS", "Font Effects")
+#define STR_PAGE_NUMBERS NC_("STR_PAGE_NUMBERS", "Numbers")
+#define STR_PAGE_POSITION NC_("STR_PAGE_POSITION", "Position")
+#define STR_PAGE_LAYOUT NC_("STR_PAGE_LAYOUT", "Layout")
+#define STR_PAGE_OPTIONS NC_("STR_PAGE_OPTIONS", "Options")
+#define STR_PAGE_SCALE NC_("STR_PAGE_SCALE", "Scale")
+#define STR_PAGE_POSITIONING NC_("STR_PAGE_POSITIONING", "Positioning")
+#define STR_PAGE_TRENDLINE_TYPE NC_("STR_PAGE_TRENDLINE_TYPE", "Type")
+#define STR_PAGE_XERROR_BARS NC_("STR_PAGE_XERROR_BARS", "X Error Bars")
+#define STR_PAGE_YERROR_BARS NC_("STR_PAGE_YERROR_BARS", "Y Error Bars")
+#define STR_PAGE_ALIGNMENT NC_("STR_PAGE_ALIGNMENT", "Alignment")
+#define STR_PAGE_PERSPECTIVE NC_("STR_PAGE_PERSPECTIVE", "Perspective")
+#define STR_PAGE_APPEARANCE NC_("STR_PAGE_APPEARANCE", "Appearance")
+#define STR_PAGE_ILLUMINATION NC_("STR_PAGE_ILLUMINATION", "Illumination")
+#define STR_PAGE_ASIAN NC_("STR_PAGE_ASIAN", "Asian Typography")
+#define STR_OBJECT_AVERAGE_LINE_WITH_PARAMETERS NC_("STR_OBJECT_AVERAGE_LINE_WITH_PARAMETERS", "Mean value line with value %AVERAGE_VALUE and standard deviation %STD_DEVIATION")
+#define STR_OBJECT_AXIS NC_("STR_OBJECT_AXIS", "Axis")
+#define STR_OBJECT_AXIS_X NC_("STR_OBJECT_AXIS_X", "X Axis")
+#define STR_OBJECT_AXIS_Y NC_("STR_OBJECT_AXIS_Y", "Y Axis")
+#define STR_OBJECT_AXIS_Z NC_("STR_OBJECT_AXIS_Z", "Z Axis")
+#define STR_OBJECT_SECONDARY_X_AXIS NC_("STR_OBJECT_SECONDARY_X_AXIS", "Secondary X Axis")
+#define STR_OBJECT_SECONDARY_Y_AXIS NC_("STR_OBJECT_SECONDARY_Y_AXIS", "Secondary Y Axis")
+#define STR_OBJECT_AXES NC_("STR_OBJECT_AXES", "Axes")
+#define STR_OBJECT_GRIDS NC_("STR_OBJECT_GRIDS", "Grids")
+#define STR_OBJECT_GRID NC_("STR_OBJECT_GRID", "Grid")
+#define STR_OBJECT_GRID_MAJOR_X NC_("STR_OBJECT_GRID_MAJOR_X", "X Axis Major Grid")
+#define STR_OBJECT_GRID_MAJOR_Y NC_("STR_OBJECT_GRID_MAJOR_Y", "Y Axis Major Grid")
+#define STR_OBJECT_GRID_MAJOR_Z NC_("STR_OBJECT_GRID_MAJOR_Z", "Z Axis Major Grid")
+#define STR_OBJECT_GRID_MINOR_X NC_("STR_OBJECT_GRID_MINOR_X", "X Axis Minor Grid")
+#define STR_OBJECT_GRID_MINOR_Y NC_("STR_OBJECT_GRID_MINOR_Y", "Y Axis Minor Grid")
+#define STR_OBJECT_GRID_MINOR_Z NC_("STR_OBJECT_GRID_MINOR_Z", "Z Axis Minor Grid")
+#define STR_OBJECT_LEGEND NC_("STR_OBJECT_LEGEND", "Legend")
+#define STR_OBJECT_TITLE NC_("STR_OBJECT_TITLE", "Title")
+#define STR_OBJECT_TITLES NC_("STR_OBJECT_TITLES", "Titles")
+#define STR_OBJECT_TITLE_MAIN NC_("STR_OBJECT_TITLE_MAIN", "Main Title")
+#define STR_OBJECT_TITLE_SUB NC_("STR_OBJECT_TITLE_SUB", "Subtitle")
+#define STR_OBJECT_TITLE_X_AXIS NC_("STR_OBJECT_TITLE_X_AXIS", "X Axis Title")
+#define STR_OBJECT_TITLE_Y_AXIS NC_("STR_OBJECT_TITLE_Y_AXIS", "Y Axis Title")
+#define STR_OBJECT_TITLE_Z_AXIS NC_("STR_OBJECT_TITLE_Z_AXIS", "Z Axis Title")
+#define STR_OBJECT_TITLE_SECONDARY_X_AXIS NC_("STR_OBJECT_TITLE_SECONDARY_X_AXIS", "Secondary X Axis Title")
+#define STR_OBJECT_TITLE_SECONDARY_Y_AXIS NC_("STR_OBJECT_TITLE_SECONDARY_Y_AXIS", "Secondary Y Axis Title")
+#define STR_OBJECT_LABEL NC_("STR_OBJECT_LABEL", "Label")
+#define STR_OBJECT_DATALABELS NC_("STR_OBJECT_DATALABELS", "Data Labels")
+#define STR_OBJECT_DATAPOINT NC_("STR_OBJECT_DATAPOINT", "Data Point")
+#define STR_OBJECT_DATAPOINTS NC_("STR_OBJECT_DATAPOINTS", "Data Points")
+#define STR_OBJECT_LEGEND_SYMBOL NC_("STR_OBJECT_LEGEND_SYMBOL", "Legend Key")
+#define STR_OBJECT_DATASERIES NC_("STR_OBJECT_DATASERIES", "Data Series")
+#define STR_OBJECT_DATASERIES_PLURAL NC_("STR_OBJECT_DATASERIES_PLURAL", "Data Series")
+#define STR_OBJECT_CURVE NC_("STR_OBJECT_CURVE", "Trend Line")
+#define STR_OBJECT_CURVES NC_("STR_OBJECT_CURVES", "Trend Lines")
+#define STR_OBJECT_CURVE_WITH_PARAMETERS NC_("STR_OBJECT_CURVE_WITH_PARAMETERS", "Trend line %FORMULA with accuracy R² = %RSQUARED")
+#define STR_OBJECT_MOVING_AVERAGE_WITH_PARAMETERS NC_("STR_OBJECT_MOVING_AVERAGE_WITH_PARAMETERS", "Moving average trend line with period = %PERIOD")
+#define STR_OBJECT_AVERAGE_LINE NC_("STR_OBJECT_AVERAGE_LINE", "Mean Value Line")
+#define STR_OBJECT_CURVE_EQUATION NC_("STR_OBJECT_CURVE_EQUATION", "Equation")
+#define STR_OBJECT_ERROR_BARS_X NC_("STR_OBJECT_ERROR_BARS_X", "X Error Bars")
+#define STR_OBJECT_ERROR_BARS_Y NC_("STR_OBJECT_ERROR_BARS_Y", "Y Error Bars")
+#define STR_OBJECT_ERROR_BARS_Z NC_("STR_OBJECT_ERROR_BARS_Z", "Z Error Bars")
+#define STR_OBJECT_STOCK_LOSS NC_("STR_OBJECT_STOCK_LOSS", "Stock Loss")
+#define STR_OBJECT_STOCK_GAIN NC_("STR_OBJECT_STOCK_GAIN", "Stock Gain")
+#define STR_OBJECT_PAGE NC_("STR_OBJECT_PAGE", "Chart Area")
+#define STR_OBJECT_DIAGRAM NC_("STR_OBJECT_DIAGRAM", "Chart")
+#define STR_OBJECT_DIAGRAM_WALL NC_("STR_OBJECT_DIAGRAM_WALL", "Chart Wall")
+#define STR_OBJECT_DIAGRAM_FLOOR NC_("STR_OBJECT_DIAGRAM_FLOOR", "Chart Floor")
+#define STR_OBJECT_SHAPE NC_("STR_OBJECT_SHAPE", "Drawing Object")
+#define STR_TIP_DATASERIES NC_("STR_TIP_DATASERIES", "Data Series '%SERIESNAME'")
+#define STR_TIP_DATAPOINT_INDEX NC_("STR_TIP_DATAPOINT_INDEX", "Data Point %POINTNUMBER")
+#define STR_TIP_DATAPOINT_VALUES NC_("STR_TIP_DATAPOINT_VALUES", "Values: %POINTVALUES")
+#define STR_TIP_DATAPOINT NC_("STR_TIP_DATAPOINT", "Data Point %POINTNUMBER, data series %SERIESNUMBER, values: %POINTVALUES")
+#define STR_STATUS_DATAPOINT_MARKED NC_("STR_STATUS_DATAPOINT_MARKED", "Data point %POINTNUMBER in data series %SERIESNUMBER selected, values: %POINTVALUES")
+#define STR_STATUS_OBJECT_MARKED NC_("STR_STATUS_OBJECT_MARKED", "%OBJECTNAME selected")
+#define STR_STATUS_PIE_SEGMENT_EXPLODED NC_("STR_STATUS_PIE_SEGMENT_EXPLODED", "Pie exploded by %PERCENTVALUE percent")
+#define STR_OBJECT_FOR_SERIES NC_("STR_OBJECT_FOR_SERIES", "%OBJECTNAME for Data Series '%SERIESNAME'")
+#define STR_OBJECT_FOR_ALL_SERIES NC_("STR_OBJECT_FOR_ALL_SERIES", "%OBJECTNAME for all Data Series")
+#define STR_ACTION_EDIT_CHARTTYPE NC_("STR_ACTION_EDIT_CHARTTYPE", "Edit chart type")
+#define STR_ACTION_EDIT_DATA_RANGES NC_("STR_ACTION_EDIT_DATA_RANGES", "Edit data ranges")
+#define STR_ACTION_EDIT_3D_VIEW NC_("STR_ACTION_EDIT_3D_VIEW", "Edit 3D view")
+#define STR_ACTION_EDIT_CHART_DATA NC_("STR_ACTION_EDIT_CHART_DATA", "Edit chart data")
+#define STR_ACTION_TOGGLE_LEGEND NC_("STR_ACTION_TOGGLE_LEGEND", "Legend on/off")
+#define STR_ACTION_TOGGLE_GRID_HORZ NC_("STR_ACTION_TOGGLE_GRID_HORZ", "Horizontal grid major/major&minor/off")
+#define STR_ACTION_TOGGLE_GRID_VERTICAL NC_("STR_ACTION_TOGGLE_GRID_VERTICAL", "Vertical grid major/major&minor/off")
+#define STR_ACTION_SCALE_TEXT NC_("STR_ACTION_SCALE_TEXT", "Scale Text")
+#define STR_ACTION_REARRANGE_CHART NC_("STR_ACTION_REARRANGE_CHART", "Automatic Layout")
+#define STR_ACTION_NOTPOSSIBLE NC_("STR_ACTION_NOTPOSSIBLE", "This function cannot be completed with the selected objects.")
+#define STR_ACTION_EDIT_TEXT NC_("STR_ACTION_EDIT_TEXT", "Edit text")
+#define STR_COLUMN_LABEL NC_("STR_COLUMN_LABEL", "Column %COLUMNNUMBER")
+#define STR_ROW_LABEL NC_("STR_ROW_LABEL", "Row %ROWNUMBER")
+#define STR_DATA_ROLE_LABEL NC_("STR_DATA_ROLE_LABEL", "Name")
+#define STR_DATA_ROLE_X NC_("STR_DATA_ROLE_X", "X-Values")
+#define STR_DATA_ROLE_Y NC_("STR_DATA_ROLE_Y", "Y-Values")
+#define STR_DATA_ROLE_SIZE NC_("STR_DATA_ROLE_SIZE", "Bubble Sizes")
+#define STR_DATA_ROLE_X_ERROR NC_("STR_DATA_ROLE_X_ERROR", "X-Error-Bars")
+#define STR_DATA_ROLE_X_ERROR_POSITIVE NC_("STR_DATA_ROLE_X_ERROR_POSITIVE", "Positive X-Error-Bars")
+#define STR_DATA_ROLE_X_ERROR_NEGATIVE NC_("STR_DATA_ROLE_X_ERROR_NEGATIVE", "Negative X-Error-Bars")
+#define STR_DATA_ROLE_Y_ERROR NC_("STR_DATA_ROLE_Y_ERROR", "Y-Error-Bars")
+#define STR_DATA_ROLE_Y_ERROR_POSITIVE NC_("STR_DATA_ROLE_Y_ERROR_POSITIVE", "Positive Y-Error-Bars")
+#define STR_DATA_ROLE_Y_ERROR_NEGATIVE NC_("STR_DATA_ROLE_Y_ERROR_NEGATIVE", "Negative Y-Error-Bars")
+#define STR_DATA_ROLE_FIRST NC_("STR_DATA_ROLE_FIRST", "Open Values")
+#define STR_DATA_ROLE_LAST NC_("STR_DATA_ROLE_LAST", "Close Values")
+#define STR_DATA_ROLE_MIN NC_("STR_DATA_ROLE_MIN", "Low Values")
+#define STR_DATA_ROLE_MAX NC_("STR_DATA_ROLE_MAX", "High Values")
+#define STR_DATA_ROLE_CATEGORIES NC_("STR_DATA_ROLE_CATEGORIES", "Categories")
+#define STR_DATA_UNNAMED_SERIES NC_("STR_DATA_UNNAMED_SERIES", "Series")
+#define STR_DATA_UNNAMED_SERIES_WITH_INDEX NC_("STR_DATA_UNNAMED_SERIES_WITH_INDEX", "Series%NUMBER")
+#define STR_DATA_SELECT_RANGE_FOR_SERIES NC_("STR_DATA_SELECT_RANGE_FOR_SERIES", "Select Range for %VALUETYPE of %SERIESNAME")
+#define STR_DATA_SELECT_RANGE_FOR_CATEGORIES NC_("STR_DATA_SELECT_RANGE_FOR_CATEGORIES", "Select Range for Categories")
+#define STR_DATA_SELECT_RANGE_FOR_DATALABELS NC_("STR_DATA_SELECT_RANGE_FOR_DATALABELS", "Select Range for data labels")
+#define STR_DATA_EDITOR_INCORRECT_INPUT NC_("STR_DATA_EDITOR_INCORRECT_INPUT", "Your last input is incorrect.\nIgnore this change and close the dialog?")
+#define STR_TEXT_DIRECTION_LTR NC_("STR_TEXT_DIRECTION_LTR", "Left-to-right")
+#define STR_TEXT_DIRECTION_RTL NC_("STR_TEXT_DIRECTION_RTL", "Right-to-left")
+#define STR_TEXT_DIRECTION_SUPER NC_("STR_TEXT_DIRECTION_SUPER", "Use superordinate object settings")
+#define STR_PROPERTY_ROLE_FILLCOLOR NC_("STR_PROPERTY_ROLE_FILLCOLOR", "Fill Color")
+#define STR_PROPERTY_ROLE_BORDERCOLOR NC_("STR_PROPERTY_ROLE_BORDERCOLOR", "Border Color")
+#define STR_DATA_TABLE NC_("STR_DATA_TABLE", "Data Table")
+
+#define STR_CONTROLTEXT_ERROR_BARS_FROM_DATA NC_("STR_CONTROLTEXT_ERROR_BARS_FROM_DATA", "From Data Table")
+#define STR_REGRESSION_LINEAR NC_("STR_REGRESSION_LINEAR", "Linear")
+#define STR_REGRESSION_LOG NC_("STR_REGRESSION_LOG", "Logarithmic")
+#define STR_REGRESSION_EXP NC_("STR_REGRESSION_EXP", "Exponential")
+#define STR_REGRESSION_POWER NC_("STR_REGRESSION_POWER", "Power")
+#define STR_REGRESSION_POLYNOMIAL NC_("STR_REGRESSION_POLYNOMIAL", "Polynomial")
+#define STR_REGRESSION_MOVING_AVERAGE NC_("STR_REGRESSION_MOVING_AVERAGE", "Moving average")
+#define STR_REGRESSION_MEAN NC_("STR_REGRESSION_MEAN", "Mean")
+
+#define STR_TYPE_COLUMN NC_("STR_TYPE_COLUMN", "Column")
+#define STR_TYPE_BAR NC_("STR_TYPE_BAR", "Bar")
+#define STR_TYPE_AREA NC_("STR_TYPE_AREA", "Area")
+#define STR_TYPE_PIE NC_("STR_TYPE_PIE", "Pie")
+#define STR_PIE_EXPLODED NC_("STR_PIE_EXPLODED", "Exploded Pie Chart")
+#define STR_DONUT_EXPLODED NC_("STR_DONUT_EXPLODED", "Exploded Donut Chart")
+#define STR_DONUT NC_("STR_DONUT", "Donut")
+#define STR_TYPE_LINE NC_("STR_TYPE_LINE", "Line")
+#define STR_TYPE_XY NC_("STR_TYPE_XY", "XY (Scatter)")
+#define STR_POINTS_AND_LINES NC_("STR_POINTS_AND_LINES", "Points and Lines")
+#define STR_POINTS_ONLY NC_("STR_POINTS_ONLY", "Points Only")
+#define STR_LINES_ONLY NC_("STR_LINES_ONLY", "Lines Only")
+#define STR_LINES_3D NC_("STR_LINES_3D", "3D Lines")
+#define STR_TYPE_COMBI_COLUMN_LINE NC_("STR_TYPE_COMBI_COLUMN_LINE", "Column and Line")
+#define STR_LINE_COLUMN NC_("STR_LINE_COLUMN", "Columns and Lines")
+#define STR_LINE_STACKEDCOLUMN NC_("STR_LINE_STACKEDCOLUMN", "Stacked Columns and Lines")
+#define STR_TYPE_NET NC_("STR_TYPE_NET", "Net")
+#define STR_TYPE_STOCK NC_("STR_TYPE_STOCK", "Stock")
+#define STR_STOCK_1 NC_("STR_STOCK_1", "Stock Chart 1")
+#define STR_STOCK_2 NC_("STR_STOCK_2", "Stock Chart 2")
+#define STR_STOCK_3 NC_("STR_STOCK_3", "Stock Chart 3")
+#define STR_STOCK_4 NC_("STR_STOCK_4", "Stock Chart 4")
+#define STR_NORMAL NC_("STR_NORMAL", "Normal")
+#define STR_STACKED NC_("STR_STACKED", "Stacked")
+#define STR_PERCENT NC_("STR_PERCENT", "Percent Stacked")
+#define STR_DEEP NC_("STR_DEEP", "Deep")
+#define STR_FILLED NC_("STR_FILLED", "Filled")
+#define STR_TYPE_BUBBLE NC_("STR_TYPE_BUBBLE", "Bubble")
+#define STR_BUBBLE_1 NC_("STR_BUBBLE_1", "Bubble Chart")
+
+#define STR_INVALID_NUMBER NC_("STR_INVALID_NUMBER", "Numbers are required. Check your input.")
+#define STR_STEP_GT_ZERO NC_("STR_STEP_GT_ZERO", "The major interval requires a positive number. Check your input.")
+#define STR_BAD_LOGARITHM NC_("STR_BAD_LOGARITHM", "The logarithmic scale requires positive numbers. Check your input.")
+#define STR_MIN_GREATER_MAX NC_("STR_MIN_GREATER_MAX", "The minimum must be lower than the maximum. Check your input.")
+#define STR_INVALID_INTERVALS NC_("STR_INVALID_INTERVALS", "The major interval needs to be greater than the minor interval. Check your input.")
+#define STR_INVALID_TIME_UNIT NC_("STR_INVALID_TIME_UNIT", "The major and minor interval need to be greater or equal to the resolution. Check your input.")
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/inc/unonames.hxx b/chart2/inc/unonames.hxx
new file mode 100644
index 0000000000..abe1908449
--- /dev/null
+++ b/chart2/inc/unonames.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+inline constexpr OUString CHART_UNONAME_SORT_BY_XVALUES = u"SortByXValues"_ustr;
+inline constexpr OUString CHART_UNONAME_SPLINE_TYPE = u"SplineType"_ustr;
+inline constexpr OUString CHART_UNONAME_SPLINE_ORDER = u"SplineOrder"_ustr;
+inline constexpr OUString CHART_UNONAME_SPLINE_RESOLUTION = u"SplineResolution"_ustr;
+inline constexpr OUString CHART_UNONAME_CURVE_STYLE = u"CurveStyle"_ustr;
+inline constexpr OUString CHART_UNONAME_CURVE_RESOLUTION = u"CurveResolution"_ustr;
+inline constexpr OUString CHART_UNONAME_NUMFMT = u"NumberFormat"_ustr;
+inline constexpr OUString CHART_UNONAME_LINK_TO_SRC_NUMFMT = u"LinkNumberFormatToSource"_ustr;
+inline constexpr OUString CHART_UNONAME_ERRORBAR_X = u"ErrorBarX"_ustr;
+inline constexpr OUString CHART_UNONAME_ERRORBAR_Y = u"ErrorBarY"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL = u"Label"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_SEP = u"LabelSeparator"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_BORDER_STYLE = u"LabelBorderStyle"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_BORDER_WIDTH = u"LabelBorderWidth"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_BORDER_COLOR = u"LabelBorderColor"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_BORDER_DASH = u"LabelBorderDash"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_BORDER_DASHNAME = u"LabelBorderDashName"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_BORDER_TRANS = u"LabelBorderTransparency"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_FILL_STYLE = u"LabelFillStyle"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_FILL_BACKGROUND = u"LabelFillBackground"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_FILL_HATCH_NAME = u"LabelFillHatchName"_ustr;
+inline constexpr OUString CHART_UNONAME_LABEL_FILL_COLOR = u"LabelFillColor"_ustr;
+inline constexpr OUString CHART_UNONAME_CUSTOM_LABEL_FIELDS = u"CustomLabelFields"_ustr;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/TestCaseOldAPI.java b/chart2/qa/TestCaseOldAPI.java
new file mode 100644
index 0000000000..f5bc4f571c
--- /dev/null
+++ b/chart2/qa/TestCaseOldAPI.java
@@ -0,0 +1,957 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+// package name: as default, start with complex
+package qa;
+
+import complexlib.ComplexTestCase;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.Type;
+import java.io.PrintWriter;
+import com.sun.star.lang.*;
+import com.sun.star.beans.*;
+import com.sun.star.frame.*;
+import com.sun.star.chart.*;
+import com.sun.star.drawing.*;
+import com.sun.star.awt.*;
+import com.sun.star.container.*;
+import com.sun.star.util.XCloseable;
+import com.sun.star.util.CloseVetoException;
+import com.sun.star.uno.AnyConverter;
+import util.utils;
+
+/**
+ * The following Complex Test will test the
+ * com.sun.star.document.IndexedPropertyValues
+ * service
+ */
+
+public class TestCaseOldAPI extends ComplexTestCase {
+
+ // The name of the tested service
+ private static final String testedServiceName =
+ "com.sun.star.chart.ChartDocument";
+
+ // The first of the mandatory functions:
+ /**
+ * Return the name of the test.
+ * In this case it is the actual name of the service.
+ * @return The tested service.
+ */
+ @Override
+ public String getTestObjectName() {
+ return testedServiceName;
+ }
+
+ // The second of the mandatory functions: return all test methods as an
+ // array. There is only one test function in this example.
+ /**
+ * Return all test methods.
+ * @return The test methods.
+ */
+ @Override
+ public String[] getTestMethodNames() {
+ // For some tests a view needs to be created. Accessing the model via
+ // this program and the view may lead to problems
+ boolean bAvoidViewCreation = false;
+
+ if( bAvoidViewCreation )
+ return new String[] {
+ "testData",
+ "testChartType",
+ "testArea",
+ "testAggregation",
+ "testFactory",
+ "testDataSeriesAndPoints",
+ "testStatistics",
+ "testStockProperties"
+ };
+
+ return new String[] {
+ "testData",
+ "testChartType",
+ "testTitle",
+ "testSubTitle",
+ "testDiagram",
+ "testAxis",
+ "testLegend",
+ "testArea",
+ "testAggregation",
+ "testFactory",
+ "testDataSeriesAndPoints",
+ "testStatistics",
+ "testStockProperties"
+ };
+ }
+
+
+
+ public void before()
+ {
+ // set to "true" to get a view
+ mbCreateView = true;
+
+ if( mbCreateView )
+ mxChartModel = createDocument( "schart" );
+ else
+ mxChartModel = createChartModel();
+
+ mxOldDoc = UnoRuntime.queryInterface(
+ XChartDocument.class, mxChartModel );
+ }
+
+
+
+ public void after()
+ {
+ XCloseable xCloseable = UnoRuntime.queryInterface(
+ XCloseable.class, mxChartModel );
+ assure( "document is no XCloseable", xCloseable != null );
+
+ // do not close document if there exists a view
+ if( ! mbCreateView )
+ {
+ try
+ {
+ xCloseable.close( true );
+ }
+ catch( CloseVetoException ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+ }
+
+
+
+ public void testTitle()
+ {
+ try
+ {
+ XPropertySet xDocProp = UnoRuntime.queryInterface(
+ XPropertySet.class, mxOldDoc );
+ assure( "Chart Document is no XPropertySet", xDocProp != null );
+ xDocProp.setPropertyValue( "HasMainTitle", Boolean.TRUE);
+ assure( "Property HasMainTitle", AnyConverter.toBoolean(
+ xDocProp.getPropertyValue( "HasMainTitle" )));
+
+ XShape xTitleShape = mxOldDoc.getTitle();
+ XPropertySet xTitleProp = UnoRuntime.queryInterface(
+ XPropertySet.class, xTitleShape );
+
+ // set property via old API
+ if( xTitleProp != null )
+ {
+ String aTitle = " Overwritten by Old API ";
+ float fHeight = (float)17.0;
+
+ xTitleProp.setPropertyValue( "String", aTitle );
+ xTitleProp.setPropertyValue( "CharHeight", Float.valueOf( fHeight ) );
+
+ float fNewHeight = AnyConverter.toFloat( xTitleProp.getPropertyValue( "CharHeight" ) );
+ assure( "Changing CharHeight via old API failed", fNewHeight == fHeight );
+
+ String aNewTitle = AnyConverter.toString( xTitleProp.getPropertyValue( "String" ) );
+ assure( "Property \"String\" failed", aNewTitle.equals( aTitle ));
+ }
+
+ // move title
+ Point aSetPos = new Point();
+ aSetPos.X = 1000;
+ aSetPos.Y = 200;
+ xTitleShape.setPosition( aSetPos );
+
+ Point aNewPos = xTitleShape.getPosition();
+ assure( "Title Position X", approxEqual( aNewPos.X, aSetPos.X, 1 ));
+ assure( "Title Position Y", approxEqual( aNewPos.Y, aSetPos.Y, 1 ));
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testSubTitle()
+ {
+ try
+ {
+ XPropertySet xDocProp = UnoRuntime.queryInterface(
+ XPropertySet.class, mxOldDoc );
+ assure( "Chart Document is no XPropertySet", xDocProp != null );
+ xDocProp.setPropertyValue( "HasSubTitle", Boolean.TRUE);
+ assure( "Property HasSubTitle", AnyConverter.toBoolean(
+ xDocProp.getPropertyValue( "HasSubTitle" )));
+
+ XShape xTitleShape = mxOldDoc.getSubTitle();
+ XPropertySet xTitleProp = UnoRuntime.queryInterface(
+ XPropertySet.class, xTitleShape );
+
+ // set Property via old API
+ if( xTitleProp != null )
+ {
+ int nColor = 0x009acd; // DeepSkyBlue3
+ float fWeight = FontWeight.BOLD;
+ float fHeight = (float)14.0;
+
+ xTitleProp.setPropertyValue( "CharColor", Integer.valueOf( nColor ) );
+ xTitleProp.setPropertyValue( "CharWeight", Float.valueOf( fWeight ));
+ xTitleProp.setPropertyValue( "CharHeight", Float.valueOf( fHeight ) );
+
+ int nNewColor = AnyConverter.toInt( xTitleProp.getPropertyValue( "CharColor" ) );
+ assure( "Changing CharColor via old API failed", nNewColor == nColor );
+
+ float fNewWeight = AnyConverter.toFloat( xTitleProp.getPropertyValue( "CharWeight" ) );
+ assure( "Changing CharWeight via old API failed", fNewWeight == fWeight );
+
+ float fNewHeight = AnyConverter.toFloat( xTitleProp.getPropertyValue( "CharHeight" ) );
+ assure( "Changing CharHeight via old API failed", fNewHeight == fHeight );
+ }
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testDiagram()
+ {
+ try
+ {
+ // testing wall
+ XDiagram xDia = mxOldDoc.getDiagram();
+ if( xDia != null )
+ {
+ X3DDisplay xDisp = UnoRuntime.queryInterface(
+ X3DDisplay.class, xDia );
+ assure( "X3DDisplay not supported", xDisp != null );
+
+ // Wall
+ XPropertySet xProp = xDisp.getWall();
+ if( xProp != null )
+ {
+ int nColor = 0xffe1ff; // thistle1
+ xProp.setPropertyValue( "FillColor", Integer.valueOf( nColor ) );
+ int nNewColor = AnyConverter.toInt( xProp.getPropertyValue( "FillColor" ) );
+ assure( "Changing FillColor via old API failed", nNewColor == nColor );
+ }
+
+ assure( "Wrong Diagram Type", xDia.getDiagramType().equals(
+ "com.sun.star.chart.BarDiagram" ));
+
+ // Diagram properties
+ xProp = UnoRuntime.queryInterface( XPropertySet.class, xDia );
+ assure( "Diagram is no property set", xProp != null );
+
+ // y-axis
+ boolean bFirstYAxisText = false;
+ xProp.setPropertyValue( "HasYAxisDescription", Boolean.valueOf( bFirstYAxisText ));
+ boolean bNewFirstYAxisText = AnyConverter.toBoolean(
+ xProp.getPropertyValue( "HasYAxisDescription" ));
+ assure( "Removing description of first y-axis", bNewFirstYAxisText == bFirstYAxisText );
+
+ // second y-axis
+ boolean bSecondaryYAxis = true;
+ xProp.setPropertyValue( "HasSecondaryYAxis", Boolean.valueOf( bSecondaryYAxis ));
+ boolean bNewSecYAxisValue = AnyConverter.toBoolean(
+ xProp.getPropertyValue( "HasSecondaryYAxis" ));
+ assure( "Adding a second y-axis does not work", bNewSecYAxisValue == bSecondaryYAxis );
+
+ XTwoAxisYSupplier xSecYAxisSuppl = UnoRuntime.queryInterface(
+ XTwoAxisYSupplier.class, xDia );
+ assure( "XTwoAxisYSupplier not implemented", xSecYAxisSuppl != null );
+ assure( "No second y-axis found", xSecYAxisSuppl.getSecondaryYAxis() != null );
+ }
+
+ // move diagram
+ {
+ XShape xDiagramShape = UnoRuntime.queryInterface(
+ XShape.class, xDia );
+
+ Point aOldPos = xDiagramShape.getPosition();
+ int xDiff = 20;
+ int yDiff = 20;
+ Point aSetPos = new Point();
+ aSetPos.X = aOldPos.X + xDiff;
+ aSetPos.Y = aOldPos.Y + yDiff;
+ xDiagramShape.setPosition( aSetPos );
+
+ Point aNewPos = xDiagramShape.getPosition();
+ assure( "Diagram Position X", approxEqual( aNewPos.X, aSetPos.X, 1 ));
+ assure( "Diagram Position Y", approxEqual( aNewPos.Y, aSetPos.Y, 1 ));
+ }
+
+ // size diagram
+ {
+ XShape xDiagramShape = UnoRuntime.queryInterface(
+ XShape.class, xDia );
+
+ Size aOldSize = xDiagramShape.getSize();
+ int xDiff = aOldSize.Width/2+2;
+ int yDiff = aOldSize.Height/2+2;
+ Size aSetSize = new Size();
+ aSetSize.Width = aOldSize.Width - xDiff;
+ aSetSize.Height = aOldSize.Height - yDiff;
+ xDiagramShape.setSize( aSetSize );
+
+ Size aNewSize = xDiagramShape.getSize();
+ assure( "Diagram Width", approxEqual( aNewSize.Width, aSetSize.Width, 2 ));
+ assure( "Diagram Height", approxEqual( aNewSize.Height, aSetSize.Height, 2 ));
+ }
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testAxis()
+ {
+ try
+ {
+ XAxisYSupplier xYAxisSuppl = UnoRuntime.queryInterface(
+ XAxisYSupplier.class, mxOldDoc.getDiagram() );
+ assure( "Diagram is no y-axis supplier", xYAxisSuppl != null );
+
+ XPropertySet xProp = xYAxisSuppl.getYAxis();
+ assure( "No y-axis found", xProp != null );
+
+ double fMax1, fMax2;
+ Object oMax = xProp.getPropertyValue( "Max" );
+ assure( "No Maximum set", AnyConverter.isDouble( oMax ));
+ fMax1 = AnyConverter.toDouble( oMax );
+ log.println( "Maximum retrieved: " + fMax1 );
+ //todo: the view has to be built before there is an explicit value
+ xProp.setPropertyValue( "AutoMax", Boolean.FALSE);
+ oMax = xProp.getPropertyValue( "Max" );
+ assure( "No Maximum set", AnyConverter.isDouble( oMax ));
+ fMax2 = AnyConverter.toDouble( oMax );
+ log.println( "Maximum with AutoMax off: " + fMax2 );
+ assure( "maxima differ", fMax1 == fMax2 );
+
+ double nNewMax = 12.3;
+ double nNewOrigin = 2.7;
+
+ xProp.setPropertyValue( "Max", Double.valueOf( nNewMax ));
+ assure( "AutoMax is on", ! AnyConverter.toBoolean( xProp.getPropertyValue( "AutoMax" )) );
+
+ assure( "Maximum value invalid",
+ utils.approxEqual(
+ AnyConverter.toDouble( xProp.getPropertyValue( "Max" )),
+ nNewMax ));
+
+ xProp.setPropertyValue( "AutoMin", Boolean.TRUE);
+ assure( "AutoMin is off", AnyConverter.toBoolean( xProp.getPropertyValue( "AutoMin" )) );
+
+ xProp.setPropertyValue( "Origin", Double.valueOf( nNewOrigin ));
+ assure( "Origin invalid",
+ utils.approxEqual(
+ AnyConverter.toDouble( xProp.getPropertyValue( "Origin" )),
+ nNewOrigin ));
+ xProp.setPropertyValue( "AutoOrigin", Boolean.TRUE);
+ assure( "AutoOrigin is off", AnyConverter.toBoolean( xProp.getPropertyValue( "AutoOrigin" )) );
+ Object oOrigin = xProp.getPropertyValue( "Origin" );
+ assure( "No Origin set", AnyConverter.isDouble( oOrigin ));
+ log.println( "Origin retrieved: " + AnyConverter.toDouble( oOrigin ));
+
+ xProp.setPropertyValue( "Logarithmic", Boolean.TRUE);
+ assure( "Scaling is not logarithmic",
+ AnyConverter.toBoolean( xProp.getPropertyValue( "Logarithmic" )) );
+ xProp.setPropertyValue( "Logarithmic", Boolean.FALSE);
+ assure( "Scaling is not logarithmic",
+ ! AnyConverter.toBoolean( xProp.getPropertyValue( "Logarithmic" )) );
+
+ int nNewColor = 0xcd853f; // peru
+ xProp.setPropertyValue( "LineColor", Integer.valueOf( nNewColor ));
+ assure( "Property LineColor",
+ AnyConverter.toInt( xProp.getPropertyValue( "LineColor" )) == nNewColor );
+ float fNewCharHeight = (float)(16.0);
+ xProp.setPropertyValue( "CharHeight", Float.valueOf( fNewCharHeight ));
+ assure( "Property CharHeight",
+ AnyConverter.toFloat( xProp.getPropertyValue( "CharHeight" )) == fNewCharHeight );
+
+ int nNewTextRotation = 700; // in 1/100 degrees
+ xProp.setPropertyValue( "TextRotation", Integer.valueOf( nNewTextRotation ));
+ assure( "Property TextRotation",
+ AnyConverter.toInt( xProp.getPropertyValue( "TextRotation" )) == nNewTextRotation );
+
+ double fStepMain = 10.0;
+ xProp.setPropertyValue( "StepMain", Double.valueOf( fStepMain ));
+ assure( "Property StepMain",
+ AnyConverter.toDouble( xProp.getPropertyValue( "StepMain" )) == fStepMain );
+
+ // note: fStepHelp must be a divider of fStepMain, because
+ // internally, the help-step is stored as an integer number of
+ // substeps
+ double fStepHelp = 5.0;
+ xProp.setPropertyValue( "StepHelp", Double.valueOf( fStepHelp ));
+ assure( "Property StepHelp",
+ AnyConverter.toDouble( xProp.getPropertyValue( "StepHelp" )) == fStepHelp );
+
+ xProp.setPropertyValue( "DisplayLabels", Boolean.FALSE);
+ assure( "Property DisplayLabels", ! AnyConverter.toBoolean(
+ xProp.getPropertyValue( "DisplayLabels" )));
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testLegend()
+ {
+ XShape xLegend = mxOldDoc.getLegend();
+ assure( "No Legend returned", xLegend != null );
+
+ XPropertySet xLegendProp = UnoRuntime.queryInterface(
+ XPropertySet.class, xLegend );
+ assure( "Legend is no property set", xLegendProp != null );
+
+ try
+ {
+ ChartLegendPosition eNewPos = ChartLegendPosition.BOTTOM;
+ xLegendProp.setPropertyValue( "Alignment", eNewPos );
+ assure( "Property Alignment",
+ AnyConverter.toObject(
+ new Type( ChartLegendPosition.class ),
+ xLegendProp.getPropertyValue( "Alignment" )) == eNewPos );
+
+ float fNewCharHeight = (float)(11.0);
+ xLegendProp.setPropertyValue( "CharHeight", Float.valueOf( fNewCharHeight ));
+ assure( "Property CharHeight",
+ AnyConverter.toFloat( xLegendProp.getPropertyValue( "CharHeight" )) == fNewCharHeight );
+
+ // move legend
+ {
+ Point aOldPos = xLegend.getPosition();
+ int xDiff = 20;
+ int yDiff = 20;
+ Point aSetPos = new Point();
+ aSetPos.X = aOldPos.X + xDiff;
+ aSetPos.Y = aOldPos.Y + yDiff;
+ xLegend.setPosition( aSetPos );
+
+ Point aNewPos = xLegend.getPosition();
+ assure( "Legend Position X", approxEqual( aNewPos.X, aSetPos.X, 1 ));
+ assure( "Legend Position Y", approxEqual( aNewPos.Y, aSetPos.Y, 1 ));
+ }
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testArea()
+ {
+ XPropertySet xArea = mxOldDoc.getArea();
+ assure( "No Area", xArea != null );
+
+ try
+ {
+ int nColor = 0xf5fffa; // mint cream
+ xArea.setPropertyValue( "FillColor", Integer.valueOf( nColor ) );
+ xArea.setPropertyValue( "FillStyle", FillStyle.SOLID );
+
+ int nNewColor = AnyConverter.toInt( xArea.getPropertyValue( "FillColor" ) );
+ assure( "Changing FillColor of Area failed", nNewColor == nColor );
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testChartType()
+ {
+ XMultiServiceFactory xFact = UnoRuntime.queryInterface(
+ XMultiServiceFactory.class, mxOldDoc );
+ assure( "document is no factory", xFact != null );
+
+ try
+ {
+ String aMyServiceName = "com.sun.star.chart.BarDiagram";
+ String aServices[] = xFact.getAvailableServiceNames();
+ boolean bServiceFound = false;
+ for( int i = 0; i < aServices.length; ++i )
+ {
+ if( aServices[ i ].equals( aMyServiceName ))
+ {
+ bServiceFound = true;
+ break;
+ }
+ }
+ assure( "getAvailableServiceNames did not return " + aMyServiceName, bServiceFound );
+
+ if( bServiceFound )
+ {
+ XDiagram xDia = UnoRuntime.queryInterface(
+ XDiagram.class, xFact.createInstance( aMyServiceName ));
+ assure( aMyServiceName + " could not be created", xDia != null );
+
+ mxOldDoc.setDiagram( xDia );
+
+ XPropertySet xDiaProp = UnoRuntime.queryInterface(
+ XPropertySet.class, xDia );
+ assure( "Diagram is no XPropertySet", xDiaProp != null );
+
+ xDiaProp.setPropertyValue( "Stacked", Boolean.TRUE);
+ assure( "StackMode could not be set correctly",
+ AnyConverter.toBoolean(
+ xDiaProp.getPropertyValue( "Stacked" )));
+
+ xDiaProp.setPropertyValue( "Dim3D", Boolean.FALSE);
+ assure( "Dim3D could not be set correctly",
+ ! AnyConverter.toBoolean(
+ xDiaProp.getPropertyValue( "Dim3D" )));
+
+ xDiaProp.setPropertyValue( "Vertical", Boolean.TRUE);
+ assure( "Vertical could not be set correctly",
+ AnyConverter.toBoolean(
+ xDiaProp.getPropertyValue( "Vertical" )));
+ }
+
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testAggregation()
+ {
+ // query to new type
+ XChartDocument xDiaProv = UnoRuntime.queryInterface(
+ XChartDocument.class, mxOldDoc );
+ assure( "query to new interface failed", xDiaProv != null );
+
+ com.sun.star.chart.XChartDocument xDoc = UnoRuntime.queryInterface(
+ com.sun.star.chart.XChartDocument.class, xDiaProv );
+ assure( "querying back to old interface failed", xDoc != null );
+ }
+
+
+
+ public void testDataSeriesAndPoints()
+ {
+ try
+ {
+ XDiagram xDia = mxOldDoc.getDiagram();
+ assure( "Invalid Diagram", xDia != null );
+ XMultiServiceFactory xFact = UnoRuntime.queryInterface(
+ XMultiServiceFactory.class, mxOldDoc );
+ assure( "document is no factory", xFact != null );
+
+ // FillColor
+ XPropertySet xProp = xDia.getDataRowProperties( 0 );
+ int nColor = 0xffd700; // gold
+ xProp.setPropertyValue( "FillColor", Integer.valueOf( nColor ));
+ int nNewColor = AnyConverter.toInt( xProp.getPropertyValue( "FillColor" ) );
+ assure( "Changing FillColor of Data Series failed", nNewColor == nColor );
+
+ // Gradient
+
+ // note: the FillGradient property is optional, however it was
+ // supported in the old chart's API
+ XNameContainer xGradientTable = UnoRuntime.queryInterface(
+ XNameContainer.class,
+ xFact.createInstance( "com.sun.star.drawing.GradientTable" ));
+ assure( "no gradient table", xGradientTable != null );
+ String aGradientName = "NewAPITestGradient";
+ Gradient aGradient = new Gradient();
+ aGradient.Style = GradientStyle.LINEAR;
+ aGradient.StartColor = 0xe0ffff; // light cyan
+ aGradient.EndColor = 0xff8c00; // dark orange
+ aGradient.Angle = 300; // 30 degrees
+ aGradient.Border = 15;
+ aGradient.XOffset = 0;
+ aGradient.YOffset = 0;
+ aGradient.StartIntensity = 100;
+ aGradient.EndIntensity = 80;
+ aGradient.StepCount = 23;
+
+ xGradientTable.insertByName( aGradientName, aGradient );
+ xProp.setPropertyValue( "FillStyle", FillStyle.GRADIENT );
+ xProp.setPropertyValue( "FillGradientName", aGradientName );
+ String aNewGradientName = AnyConverter.toString( xProp.getPropertyValue( "FillGradientName" ));
+ assure( "GradientName", aNewGradientName.equals( aGradientName ));
+ Gradient aNewGradient = (Gradient) AnyConverter.toObject(
+ new Type( Gradient.class ),
+ xGradientTable.getByName( aNewGradientName ));
+ assure( "Gradient Style", aNewGradient.Style == aGradient.Style );
+ assure( "Gradient StartColor", aNewGradient.StartColor == aGradient.StartColor );
+ assure( "Gradient EndColor", aNewGradient.EndColor == aGradient.EndColor );
+ assure( "Gradient Angle", aNewGradient.Angle == aGradient.Angle );
+ assure( "Gradient Border", aNewGradient.Border == aGradient.Border );
+ assure( "Gradient XOffset", aNewGradient.XOffset == aGradient.XOffset );
+ assure( "Gradient YOffset", aNewGradient.YOffset == aGradient.YOffset );
+ assure( "Gradient StartIntensity", aNewGradient.StartIntensity == aGradient.StartIntensity );
+ assure( "Gradient EndIntensity", aNewGradient.EndIntensity == aGradient.EndIntensity );
+ assure( "Gradient StepCount", aNewGradient.StepCount == aGradient.StepCount );
+
+ // Hatch
+ xProp = xDia.getDataPointProperties( 1, 0 );
+ assure( "No DataPointProperties for (1,0)", xProp != null );
+
+ // note: the FillHatch property is optional, however it was
+ // supported in the old chart's API
+ XNameContainer xHatchTable = UnoRuntime.queryInterface(
+ XNameContainer.class,
+ xFact.createInstance( "com.sun.star.drawing.HatchTable" ));
+ assure( "no hatch table", xHatchTable != null );
+ String aHatchName = "NewAPITestHatch";
+ Hatch aHatch = new Hatch();
+ aHatch.Style = HatchStyle.DOUBLE;
+ aHatch.Color = 0xd2691e; // chocolate
+ aHatch.Distance = 200; // 2 mm (?)
+ aHatch.Angle = 230; // 23 degrees
+
+ xHatchTable.insertByName( aHatchName, aHatch );
+ xProp.setPropertyValue( "FillHatchName", aHatchName );
+ xProp.setPropertyValue( "FillStyle", FillStyle.HATCH );
+ xProp.setPropertyValue( "FillBackground", Boolean.TRUE);
+ String aNewHatchName = AnyConverter.toString( xProp.getPropertyValue( "FillHatchName" ));
+ assure( "HatchName", aNewHatchName.equals( aHatchName ));
+ Hatch aNewHatch = (Hatch) AnyConverter.toObject(
+ new Type( Hatch.class ),
+ xHatchTable.getByName( aNewHatchName ));
+ assure( "Hatch Style", aNewHatch.Style == aHatch.Style );
+ assure( "Hatch Color", aNewHatch.Color == aHatch.Color );
+ assure( "Hatch Distance", aNewHatch.Distance == aHatch.Distance );
+ assure( "Hatch Angle", aNewHatch.Angle == aHatch.Angle );
+ assure( "FillBackground", AnyConverter.toBoolean( xProp.getPropertyValue( "FillBackground" )) );
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testStatistics()
+ {
+ try
+ {
+ XDiagram xDia = mxOldDoc.getDiagram();
+ assure( "Invalid Diagram", xDia != null );
+
+ XPropertySet xProp = xDia.getDataRowProperties( 0 );
+ assure( "No DataRowProperties for first series", xProp != null );
+
+ xProp.setPropertyValue( "MeanValue", Boolean.TRUE);
+ assure( "No MeanValue", AnyConverter.toBoolean( xProp.getPropertyValue( "MeanValue" )) );
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void setStockData_Type4()
+ {
+ try
+ {
+ XPropertySet xDiaProp = UnoRuntime.queryInterface(
+ XPropertySet.class, mxOldDoc.getDiagram() );
+
+ ChartDataRowSource eNewSource = ChartDataRowSource.ROWS;
+ xDiaProp.setPropertyValue( "DataRowSource", eNewSource );
+ assure( "Couldn't set \"DataRowSource\" property at Diagram",
+ AnyConverter.toObject(
+ new Type( ChartDataRowSource.class ),
+ xDiaProp.getPropertyValue( "DataRowSource" )) == eNewSource );
+
+ double aData[][] =
+ {
+ { 100.0, 200.0, 300.0, 250.0, 300.0 },
+ { 6.5, 4.5, 6.0, 5.5, 3.5 },
+ { 1.0, 1.5, 2.0, 2.5, 3.0 },
+ { 6.0, 6.5, 7.0, 6.5, 5.0 },
+ { 6.0, 5.5, 4.0, 4.5, 4.0 }
+ };
+
+ String[] aRowDescriptions =
+ {
+ "Volume", "Open", "Min", "Max", "Close"
+ };
+
+ String[] aColumnDescriptions =
+ {
+ "First Row", "Second Row", "Third Row", "Fourth Row", "Fifth Row"
+ };
+
+
+ XChartData xData = mxOldDoc.getData();
+ XChartDataArray xDataArray = UnoRuntime.queryInterface(
+ XChartDataArray.class, xData );
+ assure( "document has no XChartDataArray", xDataArray != null );
+
+ xDataArray.setData( aData );
+ xDataArray.setRowDescriptions( aRowDescriptions );
+ xDataArray.setColumnDescriptions( aColumnDescriptions );
+
+ mxOldDoc.attachData( xData );
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testStockProperties()
+ {
+ try
+ {
+ setStockData_Type4();
+
+ XMultiServiceFactory xFact = UnoRuntime.queryInterface(
+ XMultiServiceFactory.class, mxOldDoc );
+ assure( "document is no factory", xFact != null );
+
+ String aMyServiceName = "com.sun.star.chart.StockDiagram";
+ XDiagram xDia = UnoRuntime.queryInterface(
+ XDiagram.class, xFact.createInstance( aMyServiceName ));
+ assure( aMyServiceName + " could not be created", xDia != null );
+
+ mxOldDoc.setDiagram( xDia );
+
+ XPropertySet xDiaProp = UnoRuntime.queryInterface(
+ XPropertySet.class, xDia );
+ assure( "Diagram is no XPropertySet", xDiaProp != null );
+
+ xDiaProp.setPropertyValue( "Volume", Boolean.TRUE);
+ assure( "Has Volume", AnyConverter.toBoolean( xDiaProp.getPropertyValue( "Volume" )));
+
+ xDiaProp.setPropertyValue( "UpDown", Boolean.TRUE);
+ assure( "Has UpDown", AnyConverter.toBoolean( xDiaProp.getPropertyValue( "UpDown" )));
+
+ // MinMaxLine
+ XStatisticDisplay xMinMaxProvider = UnoRuntime.queryInterface(
+ XStatisticDisplay.class, xDia );
+ assure( "Diagram is no XStatisticDisplay", xMinMaxProvider != null );
+ XPropertySet xMinMaxProp = xMinMaxProvider.getMinMaxLine();
+ assure( "No MinMaxLine", xMinMaxProp != null );
+
+ int nLineColor = 0x458b00; // chartreuse4
+ xMinMaxProp.setPropertyValue( "LineColor", Integer.valueOf( nLineColor ));
+ int nNewColor = AnyConverter.toInt( xMinMaxProp.getPropertyValue( "LineColor" ) );
+ assure( "Changing LineColor of MinMax Line", nNewColor == nLineColor );
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testFactory()
+ {
+ try
+ {
+ XMultiServiceFactory xFact = UnoRuntime.queryInterface(
+ XMultiServiceFactory.class, mxOldDoc );
+ assure( "document is no factory", xFact != null );
+
+ Object aTestTable = xFact.createInstance( "com.sun.star.drawing.GradientTable" );
+ assure( "Couldn't create gradient table via factory", aTestTable != null );
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ public void testData()
+ {
+ try
+ {
+ // set data
+ double aData[][] = {
+ { 1.0, 1.5, 2.0, 2.5, 3.0 },
+ { 2.0, 2.5, 3.0, 3.5, 4.0 },
+ { 3.0, 3.5, 4.0, 4.5, 5.0 }
+ };
+
+ String[] aColumnDescriptions = {
+ "First Column", "Second Column", "Third Column",
+ "Fourth Column", "Fifth Column"
+ };
+
+ String[] aRowDescriptions = {
+ "First Row", "Second Row", "Third Row"
+ };
+
+ XPropertySet xDiaProp = UnoRuntime.queryInterface(
+ XPropertySet.class, mxOldDoc.getDiagram() );
+ ChartDataRowSource eNewSource = ChartDataRowSource.ROWS;
+ xDiaProp.setPropertyValue( "DataRowSource", eNewSource );
+ assure( "Couldn't set \"DataRowSource\" property at Diagram",
+ AnyConverter.toObject(
+ new Type( ChartDataRowSource.class ),
+ xDiaProp.getPropertyValue( "DataRowSource" )) == eNewSource );
+
+ XChartData xData = mxOldDoc.getData();
+ XChartDataArray xDataArray = UnoRuntime.queryInterface(
+ XChartDataArray.class, xData );
+ assure( "document has no XChartDataArray", xDataArray != null );
+
+ xDataArray.setData( aData );
+ xDataArray.setRowDescriptions( aRowDescriptions );
+ xDataArray.setColumnDescriptions( aColumnDescriptions );
+
+ mxOldDoc.attachData( xData );
+
+ // get data
+ double aReadData[][];
+ String[] aReadColumnDescriptions;
+ String[] aReadRowDescriptions;
+
+ // refetch data
+ xData = mxOldDoc.getData();
+ xDataArray = UnoRuntime.queryInterface(
+ XChartDataArray.class, xData );
+ assure( "document has no XChartDataArray", xDataArray != null );
+
+ aReadData = xDataArray.getData();
+ aReadRowDescriptions = xDataArray.getRowDescriptions();
+ aReadColumnDescriptions = xDataArray.getColumnDescriptions();
+
+ // compare to values set before
+ assure( "Data size differs", aData.length == aReadData.length );
+ for( int i=0; i<aReadData.length; ++i )
+ {
+ assure( "Data size differs", aData[i].length == aReadData[i].length );
+ for( int j=0; j<aReadData[i].length; ++j )
+ assure( "Data differs", aData[i][j] == aReadData[i][j] );
+ }
+
+ assure( "Column Description size differs", aColumnDescriptions.length == aReadColumnDescriptions.length );
+ for( int i=0; i<aReadColumnDescriptions.length; ++i )
+ assure( "Column Descriptions differ", aColumnDescriptions[i].equals( aReadColumnDescriptions[i] ));
+
+ assure( "Row Description size differs", aRowDescriptions.length == aReadRowDescriptions.length );
+ for( int i=0; i<aReadRowDescriptions.length; ++i )
+ assure( "Row Descriptions differ", aRowDescriptions[i].equals( aReadRowDescriptions[i] ));
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+ }
+
+
+
+ private XModel mxChartModel;
+ private XChartDocument mxOldDoc;
+ private boolean mbCreateView;
+
+
+
+ private XModel createDocument( String sDocType )
+ {
+ XModel aResult = null;
+ try
+ {
+ XComponentLoader aLoader = UnoRuntime.queryInterface(
+ XComponentLoader.class,
+ param.getMSF().createInstance( "com.sun.star.frame.Desktop" ) );
+
+ aResult = UnoRuntime.queryInterface(
+ XModel.class,
+ aLoader.loadComponentFromURL( "private:factory/" + sDocType,
+ "_blank",
+ 0,
+ new PropertyValue[ 0 ] ) );
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+
+ return aResult;
+ }
+
+
+
+ public XModel createChartModel()
+ {
+ XModel aResult = null;
+ try
+ {
+ aResult = UnoRuntime.queryInterface(
+ XModel.class,
+ param.getMSF().createInstance( "com.sun.star.comp.chart2.ChartModel" ) );
+ }
+ catch( Exception ex )
+ {
+ failed( ex.getMessage() );
+ ex.printStackTrace( (PrintWriter)log );
+ }
+
+ return aResult;
+ }
+
+ /** returns true if a and b differ no more than tolerance.
+
+ @param tolerance
+ must be non-negative
+ */
+ private boolean approxEqual( int a, int b, int tolerance )
+ {
+ if( a != b )
+ log.println( "Integer values differ by " + Math.abs( a-b ));
+ return ( ( a - tolerance <= b ) ||
+ ( a + tolerance >= b ));
+ }
+}
diff --git a/chart2/qa/data.chd b/chart2/qa/data.chd
new file mode 100644
index 0000000000..01888e4c19
--- /dev/null
+++ b/chart2/qa/data.chd
@@ -0,0 +1,14 @@
+# Series Labels
+Column_1 Column_2 Column_3
+
+# Categories
+Row_1 Row_2 Row_3 Row_4
+
+# Column 1
+9.1 2.4 3.1 4.3
+
+# Column 2
+3.2 8.8 1.5 9.02
+
+# Column 3
+4.54 9.65 3.7 6.2
diff --git a/chart2/qa/extras/PivotChartTest.cxx b/chart2/qa/extras/PivotChartTest.cxx
new file mode 100644
index 0000000000..d6a87ec057
--- /dev/null
+++ b/chart2/qa/extras/PivotChartTest.cxx
@@ -0,0 +1,967 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "charttest.hxx"
+
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+#include <com/sun/star/sheet/DataPilotFieldLayoutMode.hpp>
+#include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
+#include <com/sun/star/sheet/XDataPilotTable.hpp>
+#include <com/sun/star/sheet/XDataPilotDescriptor.hpp>
+#include <com/sun/star/sheet/XDataPilotTables.hpp>
+#include <com/sun/star/sheet/XDataPilotTablesSupplier.hpp>
+#include <com/sun/star/sheet/XSpreadsheet.hpp>
+#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
+#include <com/sun/star/sheet/XSpreadsheets.hpp>
+#include <com/sun/star/table/XTablePivotCharts.hpp>
+#include <com/sun/star/sheet/GeneralFunction.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+
+#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+
+namespace com::sun::star::table { class XCellRange; }
+namespace com::sun::star::util { class XNumberFormats; }
+
+class PivotChartTest : public ChartTest
+{
+public:
+ PivotChartTest()
+ : ChartTest("/chart2/qa/extras/data/")
+ {}
+
+ void testRoundtrip();
+ void testChangePivotTable();
+ void testPivotChartWithOneColumnField();
+ void testPivotChartWithOneRowField();
+ void testPivotTableDataProvider_PivotTableFields();
+ void testPivotChartRowFieldInOutlineMode();
+ void testPivotChartWithDateRowField();
+
+ CPPUNIT_TEST_SUITE(PivotChartTest);
+ CPPUNIT_TEST(testRoundtrip);
+ CPPUNIT_TEST(testChangePivotTable);
+ CPPUNIT_TEST(testPivotChartWithOneColumnField);
+ CPPUNIT_TEST(testPivotChartWithOneRowField);
+ CPPUNIT_TEST(testPivotTableDataProvider_PivotTableFields);
+ CPPUNIT_TEST(testPivotChartRowFieldInOutlineMode);
+ CPPUNIT_TEST(testPivotChartWithDateRowField);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+namespace
+{
+
+void lclModifyOrientation(uno::Reference<sheet::XDataPilotDescriptor> const & xDescriptor,
+ std::u16string_view sFieldName,
+ sheet::DataPilotFieldOrientation eOrientation)
+{
+ uno::Reference<container::XIndexAccess> xIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW);
+ sal_Int32 nCount = xIndexAccess->getCount();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ uno::Reference<container::XNamed> xNamed(xIndexAccess->getByIndex(i), UNO_QUERY_THROW);
+ OUString aName = xNamed->getName();
+ uno::Reference<beans::XPropertySet> xPropSet(xNamed, UNO_QUERY_THROW);
+ if (aName == sFieldName)
+ xPropSet->setPropertyValue("Orientation", uno::Any(eOrientation));
+ }
+}
+
+void lclModifyFunction(uno::Reference<sheet::XDataPilotDescriptor> const & xDescriptor,
+ std::u16string_view sFieldName,
+ sheet::GeneralFunction eFunction)
+{
+ uno::Reference<container::XIndexAccess> xPilotIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW);
+ sal_Int32 nCount = xPilotIndexAccess->getCount();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ uno::Reference<container::XNamed> xNamed(xPilotIndexAccess->getByIndex(i), UNO_QUERY_THROW);
+ OUString aName = xNamed->getName();
+ uno::Reference<beans::XPropertySet> xPropSet(xNamed, UNO_QUERY_THROW);
+ if (aName == sFieldName)
+ xPropSet->setPropertyValue("Function", uno::Any(eFunction));
+ }
+}
+
+void lclModifyLayoutInfo(uno::Reference<sheet::XDataPilotDescriptor> const & xDescriptor,
+ std::u16string_view sFieldName,
+ sheet::DataPilotFieldLayoutInfo aLayoutInfo)
+{
+ uno::Reference<container::XIndexAccess> xIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW);
+ sal_Int32 nCount = xIndexAccess->getCount();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ uno::Reference<container::XNamed> xNamed(xIndexAccess->getByIndex(i), UNO_QUERY_THROW);
+ OUString aName = xNamed->getName();
+ uno::Reference<beans::XPropertySet> xPropSet(xNamed, UNO_QUERY_THROW);
+ if (aName == sFieldName)
+ {
+ uno::Any aValue;
+ aValue <<= aLayoutInfo;
+ xPropSet->setPropertyValue("LayoutInfo", aValue);
+ }
+ }
+}
+
+void lclModifySubtotals(uno::Reference<sheet::XDataPilotDescriptor> const & xDescriptor,
+ std::u16string_view sFieldName,
+ uno::Sequence<sheet::GeneralFunction> const & rSubtotalFunctions)
+{
+ uno::Reference<container::XIndexAccess> xIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW);
+ sal_Int32 nCount = xIndexAccess->getCount();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ uno::Reference<container::XNamed> xNamed(xIndexAccess->getByIndex(i), UNO_QUERY_THROW);
+ OUString aName = xNamed->getName();
+ uno::Reference<beans::XPropertySet> xPropSet(xNamed, UNO_QUERY_THROW);
+ if (aName == sFieldName)
+ {
+ uno::Any aValue;
+ aValue <<= rSubtotalFunctions;
+ xPropSet->setPropertyValue("Subtotals", aValue);
+ }
+ }
+}
+
+void lclModifyColumnGrandTotal(uno::Reference<sheet::XDataPilotDescriptor> const & xDataPilotDescriptor, bool bTotal)
+{
+ uno::Reference<beans::XPropertySet> xProperties(xDataPilotDescriptor, uno::UNO_QUERY_THROW);
+ xProperties->setPropertyValue("ColumnGrand", uno::Any(bTotal));
+}
+
+void lclModifyRowGrandTotal(uno::Reference<sheet::XDataPilotDescriptor> const & xDataPilotDescriptor, bool bTotal)
+{
+ uno::Reference<beans::XPropertySet> xProperties(xDataPilotDescriptor, uno::UNO_QUERY_THROW);
+ xProperties->setPropertyValue("RowGrand", uno::Any(bTotal));
+}
+
+void lclCheckSequence(std::vector<double> const & reference,
+ uno::Sequence<uno::Any> const & values,
+ double delta)
+{
+ CPPUNIT_ASSERT_EQUAL(reference.size(), size_t(values.getLength()));
+ for (size_t i = 0; i < reference.size(); ++i)
+ {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(
+ reference[i], values[i].get<double>(), delta);
+ }
+}
+
+void lclCheckCategories(std::vector<OUString> const & reference,
+ uno::Reference<chart2::data::XDataSequence> const & xSequence)
+{
+ uno::Reference<chart2::data::XTextualDataSequence> xTextualDataSequence(xSequence, uno::UNO_QUERY_THROW);
+ uno::Sequence<OUString> aText = xTextualDataSequence->getTextualData();
+
+ CPPUNIT_ASSERT_EQUAL(reference.size(), size_t(aText.getLength()));
+ for (size_t i = 0; i < reference.size(); ++i)
+ {
+ CPPUNIT_ASSERT_EQUAL(reference[i], aText[i]);
+ }
+}
+
+OUString lclGetLabel(Reference<chart2::XChartDocument> const & xChartDoc, sal_Int32 nSeriesIndex)
+{
+ Reference<chart2::data::XDataSequence> xLabelDataSequence = getLabelDataSequenceFromDoc(xChartDoc, nSeriesIndex);
+ return xLabelDataSequence->getData()[0].get<OUString>();
+}
+
+uno::Reference<sheet::XDataPilotTable> lclGetPivotTableByName(sal_Int32 nIndex, OUString const & sPivotTableName,
+ uno::Reference<lang::XComponent> const & xComponent)
+{
+ uno::Reference<sheet::XSpreadsheetDocument> xDoc(xComponent, UNO_QUERY_THROW);
+ uno::Reference<container::XIndexAccess> xSheetIndexAccess(xDoc->getSheets(), UNO_QUERY_THROW);
+ uno::Any aAny = xSheetIndexAccess->getByIndex(nIndex);
+ uno::Reference<sheet::XSpreadsheet> xSheet;
+ CPPUNIT_ASSERT(aAny >>= xSheet);
+ uno::Reference<sheet::XDataPilotTablesSupplier> xDataPilotTablesSupplier(xSheet, uno::UNO_QUERY_THROW);
+ uno::Reference<sheet::XDataPilotTables> xDataPilotTables = xDataPilotTablesSupplier->getDataPilotTables();
+ return uno::Reference<sheet::XDataPilotTable>(xDataPilotTables->getByName(sPivotTableName), UNO_QUERY_THROW);
+}
+
+uno::Sequence<uno::Reference<chart2::data::XLabeledDataSequence>>
+ lclGetCategories(Reference<chart2::XChartDocument> const & xChartDoc)
+{
+ uno::Sequence<beans::PropertyValue> aArguments( comphelper::InitPropertySequence(
+ {{"CellRangeRepresentation", uno::Any(OUString("PT@categories"))}} ));
+
+ uno::Reference<chart2::data::XDataProvider> xDataProvider(xChartDoc->getDataProvider(), uno::UNO_SET_THROW);
+ return xDataProvider->createDataSource(aArguments)->getDataSequences();
+}
+
+struct Value
+{
+ OUString maString;
+ double mfValue;
+ bool mbIsValue;
+
+ Value(OUString const & rString)
+ : maString(rString)
+ , mfValue(0.0)
+ , mbIsValue(false)
+ {}
+
+ Value(double fValue)
+ : mfValue(fValue)
+ , mbIsValue(true)
+ {}
+};
+
+uno::Reference< sheet::XDataPilotTables>
+lclGetDataPilotTables(sal_Int32 nIndex, uno::Reference<sheet::XSpreadsheetDocument> const & xSheetDoc)
+{
+ uno::Reference<sheet::XSpreadsheets> xSpreadsheets = xSheetDoc->getSheets();
+ uno::Reference<container::XIndexAccess> oIndexAccess(xSpreadsheets, uno::UNO_QUERY_THROW);
+ uno::Reference<sheet::XSpreadsheet> xSheet;
+ CPPUNIT_ASSERT(oIndexAccess->getByIndex(nIndex) >>= xSheet);
+
+ // create the test objects
+ uno::Reference< sheet::XDataPilotTablesSupplier> xDataPilotTablesSupplier(xSheet, uno::UNO_QUERY_THROW);
+ return xDataPilotTablesSupplier->getDataPilotTables();
+}
+
+table::CellRangeAddress lclCreateTestData(uno::Reference<sheet::XSpreadsheetDocument> const & xSheetDoc)
+{
+ CPPUNIT_ASSERT_MESSAGE("no calc document!", xSheetDoc.is());
+
+ std::vector<OUString> aHeaders {
+ "Country", "City", "Type", "Sales T1", "Sales T2", "Sales T3", "Sales T4", "Date"
+ };
+
+ std::vector<std::vector<Value>> aData {
+ { {"FR"}, {"Paris"}, {"A"}, {123.0}, {223.0}, {323.0}, {423.0}, {"12/14/15"} },
+ { {"EN"}, {"London"}, {"A"}, {456.0}, {556.0}, {656.0}, {756.0}, {"12/11/15"} },
+ { {"DE"}, {"Berlin"}, {"A"}, {468.0}, {568.0}, {668.0}, {768.0}, {"12/11/15"} },
+ { {"FR"}, {"Nantes"}, {"A"}, {694.0}, {794.0}, {894.0}, {994.0}, {"12/11/15"} },
+ { {"EN"}, {"Glasgow"}, {"A"}, {298.0}, {398.0}, {498.0}, {598.0}, {"12/11/15"} },
+ { {"DE"}, {"Munich"}, {"A"}, {369.0}, {469.0}, {569.0}, {669.0}, {"12/11/15"} },
+ { {"FR"}, {"Paris"}, {"B"}, {645.0}, {745.0}, {845.0}, {945.0}, {"12/11/15"} },
+ { {"EN"}, {"London"}, {"B"}, {687.0}, {787.0}, {887.0}, {987.0}, {"03/21/17"} },
+ { {"DE"}, {"Munich"}, {"B"}, {253.0}, {353.0}, {453.0}, {553.0}, {"12/17/15"} },
+ { {"FR"}, {"Nantes"}, {"B"}, {474.0}, {574.0}, {674.0}, {774.0}, {"01/20/16"} },
+ { {"EN"}, {"Liverpool"}, {"B"}, {562.0}, {662.0}, {762.0}, {862.0}, {"01/20/16"} },
+ { {"DE"}, {"Berlin"}, {"B"}, {648.0}, {748.0}, {848.0}, {948.0}, {"01/20/16"} }
+ };
+
+ // Getting spreadsheet
+ uno::Reference<sheet::XSpreadsheets> xSpreadsheets = xSheetDoc->getSheets();
+ uno::Reference<container::XIndexAccess> oIndexAccess(xSpreadsheets, uno::UNO_QUERY_THROW);
+ uno::Reference<sheet::XSpreadsheet> xSheet;
+ CPPUNIT_ASSERT(oIndexAccess->getByIndex(0) >>= xSheet);
+
+ uno::Reference<sheet::XSpreadsheet> oPivotTableSheet;
+ xSpreadsheets->insertNewByName("Pivot Table", 1);
+ CPPUNIT_ASSERT(oIndexAccess->getByIndex(1) >>= oPivotTableSheet);
+
+ sal_Int32 currentRow = 0;
+ for (size_t column = 0; column < aHeaders.size(); ++column)
+ {
+ xSheet->getCellByPosition(column, currentRow)->setFormula(aHeaders[column]);
+ }
+ currentRow++;
+
+ for (std::vector<Value> const & rRowOfData : aData)
+ {
+ for (size_t column = 0; column < rRowOfData.size(); ++column)
+ {
+ Value const & rValue = rRowOfData[column];
+ uno::Reference<table::XCell> xCell(xSheet->getCellByPosition(column, currentRow));
+ if (rValue.mbIsValue)
+ xCell->setValue(rValue.mfValue);
+ else
+ xCell->setFormula(rValue.maString);
+ }
+ currentRow++;
+ }
+
+ sal_Int32 nEndCol = sal_Int32(aHeaders.size() - 1);
+ sal_Int32 nEndRow = sal_Int32(1/*HEADER*/ + aData.size() - 1);
+
+ // Apply date format to the last column
+ uno::Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(xSheetDoc, UNO_QUERY_THROW);
+ uno::Reference<util::XNumberFormats> xNumberFormats = xNumberFormatsSupplier->getNumberFormats();
+ uno::Reference<util::XNumberFormatTypes> xNumberFormatTypes(xNumberFormats, UNO_QUERY_THROW);
+ lang::Locale aLocale;
+ sal_Int32 nDateKey = xNumberFormatTypes->getStandardFormat(util::NumberFormat::DATE, aLocale);
+ uno::Reference<table::XCellRange> xCellRange = xSheet->getCellRangeByPosition(nEndCol, 1, nEndCol, nEndRow);
+ uno::Reference<beans::XPropertySet> xCellProp(xCellRange, UNO_QUERY_THROW);
+ xCellProp->setPropertyValue("NumberFormat", uno::Any(nDateKey));
+
+ table::CellRangeAddress sCellRangeAddress;
+ sCellRangeAddress.Sheet = 0;
+ sCellRangeAddress.StartColumn = 0;
+ sCellRangeAddress.StartRow = 0;
+ sCellRangeAddress.EndColumn = nEndCol;
+ sCellRangeAddress.EndRow = nEndRow;
+
+ return sCellRangeAddress;
+}
+
+} // end anonymous namespace
+
+void PivotChartTest::testRoundtrip()
+{
+ uno::Sequence<uno::Any> xSequence;
+ Reference<chart2::XChartDocument> xChartDoc;
+
+ std::vector<double> aReference1 { 10162.033139, 16614.523063, 27944.146101 };
+
+ std::vector<double> aReference2 { 101879.458079, 178636.929704, 314626.484864 };
+
+ loadFromFile(u"ods/PivotChartRoundTrip.ods");
+
+ xChartDoc = getPivotChartDocFromSheet(1, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getNumberOfDataSeries(xChartDoc));
+
+ // Check the data series
+ {
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference1, xSequence, 1E-4);
+ CPPUNIT_ASSERT_EQUAL(OUString("Exp."), lclGetLabel(xChartDoc, 0));
+ }
+ {
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData();
+ lclCheckSequence(aReference2, xSequence, 1E-4);
+ CPPUNIT_ASSERT_EQUAL(OUString("Rev."), lclGetLabel(xChartDoc, 1));
+ }
+
+ // Modify the pivot table
+ {
+ uno::Reference<sheet::XDataPilotTable> xDataPilotTable = lclGetPivotTableByName(1, "DataPilot1", mxComponent);
+ uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor(xDataPilotTable, UNO_QUERY_THROW);
+ lclModifyOrientation(xDataPilotDescriptor, u"Exp.", sheet::DataPilotFieldOrientation_HIDDEN);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc));
+
+ // Check again the data series
+ {
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference2, xSequence, 1E-4);
+ CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0));
+ }
+
+ saveAndReload("calc8");
+
+ xChartDoc = getPivotChartDocFromSheet(1, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc));
+
+ // Check again the data series
+ {
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference2, xSequence, 1E-4);
+ CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0));
+ }
+}
+
+void PivotChartTest::testChangePivotTable()
+{
+ uno::Sequence<uno::Any> xSequence;
+ Reference<chart2::XChartDocument> xChartDoc;
+
+ loadFromFile(u"ods/PivotTableExample.ods");
+
+ // Check we have the Pivot Table
+ OUString sPivotTableName("DataPilot1");
+ uno::Reference<sheet::XDataPilotTable> xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent);
+ CPPUNIT_ASSERT(xDataPilotTable.is());
+
+ // Check that we don't have any pivot chart in the document
+ uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent);
+ uno::Reference<container::XIndexAccess> xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount());
+
+ // Create a new pivot chart
+ xTablePivotCharts->addNewByName("Chart", awt::Rectangle{0, 0, 9000, 9000}, sPivotTableName);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
+
+ // Get the pivot chart document so we can access its data
+ xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0));
+
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getNumberOfDataSeries(xChartDoc));
+
+ // Check first data series
+ {
+ std::vector<double> aReference { 10162.033139, 16614.523063, 27944.146101 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-4);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Exp."), lclGetLabel(xChartDoc, 0));
+ }
+
+ // Check second data series
+ {
+ std::vector<double> aReference { 101879.458079, 178636.929704, 314626.484864 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-4);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Rev."), lclGetLabel(xChartDoc, 1));
+ }
+
+ // Modify the pivot table, move "Group Segment" to Column fields,
+ // add "Service Month" to Row fields, remove "Rev." Data field
+ {
+ uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor(xDataPilotTable, UNO_QUERY_THROW);
+
+ lclModifyOrientation(xDataPilotDescriptor, u"Service Month", sheet::DataPilotFieldOrientation_ROW);
+ lclModifyOrientation(xDataPilotDescriptor, u"Group Segment", sheet::DataPilotFieldOrientation_COLUMN);
+ lclModifyOrientation(xDataPilotDescriptor, u"Rev.", sheet::DataPilotFieldOrientation_HIDDEN);
+ }
+
+ // Check the pivot chart again as we expect it has been updated when we updated the pivot table
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getNumberOfDataSeries(xChartDoc));
+
+ // Check the first data series
+ {
+ std::vector<double> aReference { 2855.559, 1780.326, 2208.713, 2130.064, 1187.371 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-3);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Big"), lclGetLabel(xChartDoc, 0));
+ }
+
+ // Check the second data series
+ {
+ std::vector<double> aReference { 4098.908, 2527.286, 4299.716, 2362.225, 3326.389 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-3);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Medium"), lclGetLabel(xChartDoc, 1));
+ }
+
+ // Check the third data series
+ {
+ std::vector<double> aReference { 4926.303, 5684.060, 4201.398, 7290.795, 5841.591 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 2)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-3);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Small"), lclGetLabel(xChartDoc, 2));
+ }
+
+ // Remove "Service Month" so row fields are empty - check we handle empty rows
+ {
+ uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor(xDataPilotTable, uno::UNO_QUERY_THROW);
+ lclModifyOrientation(xDataPilotDescriptor, u"Service Month", sheet::DataPilotFieldOrientation_HIDDEN);
+ }
+
+ // Check the pivot chart again as we expect it has been updated when we updated the pivot table
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getNumberOfDataSeries(xChartDoc));
+
+ // Check the first data series
+ {
+ std::vector<double> aReference { 10162.033139 };
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-3);
+ CPPUNIT_ASSERT_EQUAL(OUString("Big"), lclGetLabel(xChartDoc, 0));
+ }
+ // Check the second data series
+ {
+ std::vector<double> aReference { 16614.523063 };
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-3);
+ CPPUNIT_ASSERT_EQUAL(OUString("Medium"), lclGetLabel(xChartDoc, 1));
+ }
+ // Check the third data series
+ {
+ std::vector<double> aReference { 27944.146101 };
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 2)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-3);
+ CPPUNIT_ASSERT_EQUAL(OUString("Small"), lclGetLabel(xChartDoc, 2));
+ }
+
+ // Enable column totals and check the data is still unchanged
+ {
+ uno::Reference<beans::XPropertySet> xProperties(xDataPilotTable, uno::UNO_QUERY_THROW);
+ xProperties->setPropertyValue("ColumnGrand", uno::Any(true));
+ }
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getNumberOfDataSeries(xChartDoc));
+
+ // Check the first data series
+ {
+ std::vector<double> aReference { 10162.033139 };
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-3);
+ CPPUNIT_ASSERT_EQUAL(OUString("Big"), lclGetLabel(xChartDoc, 0));
+ }
+ // Check the second data series
+ {
+ std::vector<double> aReference { 16614.523063 };
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-3);
+ CPPUNIT_ASSERT_EQUAL(OUString("Medium"), lclGetLabel(xChartDoc, 1));
+ }
+ // Check the third data series
+ {
+ std::vector<double> aReference { 27944.146101 };
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 2)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-3);
+ CPPUNIT_ASSERT_EQUAL(OUString("Small"), lclGetLabel(xChartDoc, 2));
+ }
+}
+
+void PivotChartTest::testPivotChartWithOneColumnField()
+{
+ // We put one field as COLUMN field only and one DATA field. We expect we will get as many data series
+ // in the pivot table as many distinct column values we have (with this example data 3: DE, EN, FR).
+
+ // SETUP DATA and PIVOT TABLE
+
+ mxComponent = loadFromDesktop("private:factory/scalc");
+
+ uno::Reference<sheet::XSpreadsheetDocument> xSheetDoc(mxComponent, uno::UNO_QUERY_THROW);
+
+ OUString sPivotTableName("DataPilotTable");
+
+ table::CellRangeAddress sCellRangeAddress = lclCreateTestData(xSheetDoc);
+
+ uno::Reference<sheet::XDataPilotTables> xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc);
+
+ uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor();
+ xDataPilotDescriptor->setSourceRange(sCellRangeAddress);
+
+ lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_COLUMN);
+ lclModifyOrientation(xDataPilotDescriptor, u"Sales T1", sheet::DataPilotFieldOrientation_DATA);
+ lclModifyFunction(xDataPilotDescriptor, u"Sales T1", sheet::GeneralFunction_SUM);
+
+ xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor);
+
+ // TEST
+
+ uno::Sequence<uno::Any> xSequence;
+ Reference<chart2::XChartDocument> xChartDoc;
+
+ // Check we have the Pivot Table
+
+ uno::Reference<sheet::XDataPilotTable> xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent);
+ CPPUNIT_ASSERT(xDataPilotTable.is());
+
+ // Check that we don't have any pivot chart in the document
+ uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent);
+ uno::Reference<container::XIndexAccess> xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount());
+
+ // Create a new pivot chart
+ xTablePivotCharts->addNewByName("PivotChart", awt::Rectangle{ 9000, 9000, 21000, 18000 }, sPivotTableName);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
+
+ // Get the pivot chart document so we can access its data
+ xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0));
+
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getNumberOfDataSeries(xChartDoc));
+ // Check data series 1
+ {
+ std::vector<double> aReference { 1738.0 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-4);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("DE"), lclGetLabel(xChartDoc, 0));
+ }
+
+ // Check data series 2
+ {
+ std::vector<double> aReference { 2003.0 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-4);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("EN"), lclGetLabel(xChartDoc, 1));
+ }
+ // Check data series 3
+ {
+ std::vector<double> aReference { 1936.0 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 2)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-4);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("FR"), lclGetLabel(xChartDoc, 2));
+ }
+}
+
+void PivotChartTest::testPivotChartWithOneRowField()
+{
+ // We put one field as ROW field only and one DATA field. We expect we will get one data series
+ // in the pivot table.
+
+ // SETUP DATA and PIVOT TABLE
+
+ mxComponent = loadFromDesktop("private:factory/scalc");
+
+ uno::Reference<sheet::XSpreadsheetDocument> xSheetDoc(mxComponent, uno::UNO_QUERY_THROW);
+
+ OUString sPivotTableName("DataPilotTable");
+
+ table::CellRangeAddress sCellRangeAddress = lclCreateTestData(xSheetDoc);
+
+ uno::Reference<sheet::XDataPilotTables> xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc);
+
+ uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor();
+ xDataPilotDescriptor->setSourceRange(sCellRangeAddress);
+
+ lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_ROW);
+ lclModifyOrientation(xDataPilotDescriptor, u"Sales T1", sheet::DataPilotFieldOrientation_DATA);
+ lclModifyFunction(xDataPilotDescriptor, u"Sales T1", sheet::GeneralFunction_SUM);
+
+ xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor);
+
+ // TEST
+
+ uno::Sequence<uno::Any> xSequence;
+ Reference<chart2::XChartDocument> xChartDoc;
+
+ // Check we have the Pivot Table
+
+ uno::Reference<sheet::XDataPilotTable> xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent);
+ CPPUNIT_ASSERT(xDataPilotTable.is());
+
+ // Check that we don't have any pivot chart in the document
+ uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent);
+ uno::Reference<container::XIndexAccess> xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount());
+
+ // Create a new pivot chart
+ xTablePivotCharts->addNewByName("PivotChart", awt::Rectangle{ 9000, 9000, 21000, 18000 }, sPivotTableName);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
+
+ // Get the pivot chart document so we can access its data
+ xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0));
+
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc));
+ // Check data series 1
+ {
+ std::vector<double> aReference { 1738.0, 2003.0, 1936.0 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-4);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0));
+ }
+}
+
+void PivotChartTest::testPivotTableDataProvider_PivotTableFields()
+{
+ // SETUP DATA and PIVOT TABLE
+
+ mxComponent = loadFromDesktop("private:factory/scalc");
+
+ uno::Reference<sheet::XSpreadsheetDocument> xSheetDoc(mxComponent, uno::UNO_QUERY_THROW);
+
+ OUString sPivotTableName("DataPilotTable");
+
+ table::CellRangeAddress sCellRangeAddress = lclCreateTestData(xSheetDoc);
+
+ uno::Reference<sheet::XDataPilotTables> xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc);
+
+ uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor();
+ xDataPilotDescriptor->setSourceRange(sCellRangeAddress);
+
+ lclModifyOrientation(xDataPilotDescriptor, u"City", sheet::DataPilotFieldOrientation_ROW);
+ lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_COLUMN);
+ lclModifyOrientation(xDataPilotDescriptor, u"Type", sheet::DataPilotFieldOrientation_COLUMN);
+ lclModifyOrientation(xDataPilotDescriptor, u"Sales T1", sheet::DataPilotFieldOrientation_DATA);
+ lclModifyFunction(xDataPilotDescriptor, u"Sales T1", sheet::GeneralFunction_SUM);
+ lclModifyOrientation(xDataPilotDescriptor, u"Sales T2", sheet::DataPilotFieldOrientation_DATA);
+ lclModifyFunction(xDataPilotDescriptor, u"Sales T2", sheet::GeneralFunction_SUM);
+
+ lclModifyColumnGrandTotal(xDataPilotDescriptor, true);
+ lclModifyRowGrandTotal(xDataPilotDescriptor, true);
+
+ xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor);
+
+ // TEST
+ Reference<chart2::XChartDocument> xChartDoc;
+
+ // Check we have the Pivot Table
+ uno::Reference<sheet::XDataPilotTable> xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent);
+ CPPUNIT_ASSERT(xDataPilotTable.is());
+
+ // refetch the XDataPilotDescriptor
+ xDataPilotDescriptor.set(xDataPilotTable, uno::UNO_QUERY_THROW);
+
+ // Check that we don't have any pivot chart in the document
+ uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent);
+ uno::Reference<container::XIndexAccess> xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount());
+
+ // Create a new pivot chart
+ xTablePivotCharts->addNewByName("PivotChart", awt::Rectangle{ 9000, 9000, 21000, 18000 }, sPivotTableName);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
+
+ // Get the pivot chart document so we can access its data
+ xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0));
+
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(xChartDoc->getDataProvider(), UNO_QUERY_THROW);
+ uno::Sequence<chart2::data::PivotTableFieldEntry> aFieldEntries;
+
+ aFieldEntries = xPivotTableDataProvider->getColumnFields();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aFieldEntries.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("Country"), aFieldEntries[0].Name);
+ CPPUNIT_ASSERT_EQUAL(OUString("Type"), aFieldEntries[1].Name);
+
+ aFieldEntries = xPivotTableDataProvider->getRowFields();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aFieldEntries.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("City"), aFieldEntries[0].Name);
+ CPPUNIT_ASSERT_EQUAL(OUString("Data"), aFieldEntries[1].Name);
+
+ aFieldEntries = xPivotTableDataProvider->getDataFields();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aFieldEntries.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("Sum - Sales T1"), aFieldEntries[0].Name);
+ CPPUNIT_ASSERT_EQUAL(OUString("Sum - Sales T2"), aFieldEntries[1].Name);
+
+ // Data to column fields
+ lclModifyOrientation(xDataPilotDescriptor, u"Data", sheet::DataPilotFieldOrientation_COLUMN);
+
+ // Change the order of column fields: expected data, type, country
+ lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_HIDDEN);
+ lclModifyOrientation(xDataPilotDescriptor, u"Type", sheet::DataPilotFieldOrientation_HIDDEN);
+
+ lclModifyOrientation(xDataPilotDescriptor, u"Type", sheet::DataPilotFieldOrientation_COLUMN);
+ lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_COLUMN);
+
+ // set the XPivotTableDataProvider again as the old one was exchanged
+ xPivotTableDataProvider.set(xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW);
+
+ aFieldEntries = xPivotTableDataProvider->getColumnFields();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aFieldEntries.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("Data"), aFieldEntries[0].Name);
+ CPPUNIT_ASSERT_EQUAL(OUString("Type"), aFieldEntries[1].Name);
+ CPPUNIT_ASSERT_EQUAL(OUString("Country"), aFieldEntries[2].Name);
+
+ aFieldEntries = xPivotTableDataProvider->getRowFields();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aFieldEntries.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("City"), aFieldEntries[0].Name);
+
+ aFieldEntries = xPivotTableDataProvider->getDataFields();
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aFieldEntries.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("Sum - Sales T1"), aFieldEntries[0].Name);
+ CPPUNIT_ASSERT_EQUAL(OUString("Sum - Sales T2"), aFieldEntries[1].Name);
+}
+
+void PivotChartTest::testPivotChartRowFieldInOutlineMode()
+{
+ // SETUP DATA and PIVOT TABLE
+
+ mxComponent = loadFromDesktop("private:factory/scalc");
+
+ uno::Reference<sheet::XSpreadsheetDocument> xSheetDoc(mxComponent, uno::UNO_QUERY_THROW);
+
+ OUString sPivotTableName("DataPilotTable");
+
+ table::CellRangeAddress sCellRangeAddress = lclCreateTestData(xSheetDoc);
+
+ uno::Reference<sheet::XDataPilotTables> xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc);
+
+ uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor();
+ xDataPilotDescriptor->setSourceRange(sCellRangeAddress);
+
+ lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_ROW);
+ lclModifyOrientation(xDataPilotDescriptor, u"City", sheet::DataPilotFieldOrientation_ROW);
+ lclModifyOrientation(xDataPilotDescriptor, u"Sales T1", sheet::DataPilotFieldOrientation_DATA);
+ lclModifyFunction(xDataPilotDescriptor, u"Sales T1", sheet::GeneralFunction_SUM);
+ xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor);
+
+ // TEST
+ uno::Sequence<uno::Any> xSequence;
+ Reference<chart2::XChartDocument> xChartDoc;
+
+ // Check we have the Pivot Table
+ uno::Reference<sheet::XDataPilotTable> xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent);
+ CPPUNIT_ASSERT(xDataPilotTable.is());
+
+ // refetch the XDataPilotDescriptor
+ xDataPilotDescriptor.set(xDataPilotTable, uno::UNO_QUERY_THROW);
+
+ // Check that we don't have any pivot chart in the document
+ uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent);
+ uno::Reference<container::XIndexAccess> xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount());
+
+ // Create a new pivot chart
+ xTablePivotCharts->addNewByName("PivotChart", awt::Rectangle{ 9000, 9000, 21000, 18000 }, sPivotTableName);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
+
+ // Get the pivot chart document so we can access its data
+ xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0));
+
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // Test case with defaults
+
+ // Check when using defaults the data is as expected
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc));
+ {
+ std::vector<double> aReference { 1116.0, 622.0, 298.0, 562.0, 1143.0, 1168.0, 768.0 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-4);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0));
+ }
+ // Check the categories
+ {
+ lclCheckCategories({ "DE", "", "EN", "", "", "FR", ""},
+ lclGetCategories(xChartDoc)[0]->getValues());
+ lclCheckCategories({ "Berlin", "Munich", "Glasgow", "Liverpool", "London", "Nantes", "Paris"},
+ lclGetCategories(xChartDoc)[1]->getValues());
+ }
+
+ sheet::DataPilotFieldLayoutInfo aLayoutInfoValue;
+
+ // Test case where we enable subtotals (auto) and set the outline subtotals at the bottom
+ // We don't expect any change in data as every extra subtotal row should be ignored
+
+ // Enable subtotals - set to auto
+ uno::Sequence<sheet::GeneralFunction> aGeneralFunctionSequence{ sheet::GeneralFunction_AUTO };
+ lclModifySubtotals(xDataPilotDescriptor, u"Country", aGeneralFunctionSequence);
+ // Set Subtotals layout to bottom + add empty lines
+ aLayoutInfoValue.AddEmptyLines = true;
+ aLayoutInfoValue.LayoutMode = sheet::DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM;
+ lclModifyLayoutInfo(xDataPilotDescriptor, u"Country", aLayoutInfoValue);
+
+ // Check data is unchanged
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc));
+ {
+ std::vector<double> aReference { 1116.0, 622.0, 298.0, 562.0, 1143.0, 1168.0, 768.0 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-4);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0));
+ }
+ // Check categories
+ {
+ lclCheckCategories({ "DE", "", "EN", "", "", "FR", ""},
+ lclGetCategories(xChartDoc)[0]->getValues());
+ lclCheckCategories({ "Berlin", "Munich", "Glasgow", "Liverpool", "London", "Nantes", "Paris"},
+ lclGetCategories(xChartDoc)[1]->getValues());
+ }
+
+ // Test case where we enable subtotals (auto) and set the outline subtotals at the top
+ // We don't expect any change in data as every extra subtotal row should be ignored
+
+ // Enable subtotals - set to auto
+ aGeneralFunctionSequence.getArray()[0] = sheet::GeneralFunction_AUTO;
+ lclModifySubtotals(xDataPilotDescriptor, u"Country", aGeneralFunctionSequence);
+ // Set Subtotals layout to top + add empty lines
+ aLayoutInfoValue.AddEmptyLines = true;
+ aLayoutInfoValue.LayoutMode = sheet::DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP;
+ lclModifyLayoutInfo(xDataPilotDescriptor, u"Country", aLayoutInfoValue);
+
+ // Check data is unchanged
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc));
+ {
+ std::vector<double> aReference { 1116.0, 622.0, 298.0, 562.0, 1143.0, 1168.0, 768.0 };
+
+ xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData();
+ lclCheckSequence(aReference, xSequence, 1E-4);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0));
+ }
+ // Check categories
+ {
+ lclCheckCategories({ "DE", "", "EN", "", "", "FR", ""},
+ lclGetCategories(xChartDoc)[0]->getValues());
+ lclCheckCategories({ "Berlin", "Munich", "Glasgow", "Liverpool", "London", "Nantes", "Paris"},
+ lclGetCategories(xChartDoc)[1]->getValues());
+ }
+}
+
+void PivotChartTest::testPivotChartWithDateRowField()
+{
+ // SETUP DATA and PIVOT TABLE
+
+ mxComponent = loadFromDesktop("private:factory/scalc");
+
+ uno::Reference<sheet::XSpreadsheetDocument> xSheetDoc(mxComponent, uno::UNO_QUERY_THROW);
+
+ OUString sPivotTableName("DataPilotTable");
+
+ table::CellRangeAddress sCellRangeAddress = lclCreateTestData(xSheetDoc);
+
+ uno::Reference<sheet::XDataPilotTables> xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc);
+
+ uno::Reference<sheet::XDataPilotDescriptor> xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor();
+ xDataPilotDescriptor->setSourceRange(sCellRangeAddress);
+
+ lclModifyOrientation(xDataPilotDescriptor, u"Date", sheet::DataPilotFieldOrientation_ROW);
+ lclModifyOrientation(xDataPilotDescriptor, u"City", sheet::DataPilotFieldOrientation_ROW);
+ lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_ROW);
+ lclModifyOrientation(xDataPilotDescriptor, u"Type", sheet::DataPilotFieldOrientation_COLUMN);
+ lclModifyOrientation(xDataPilotDescriptor, u"Sales T1", sheet::DataPilotFieldOrientation_DATA);
+ lclModifyFunction(xDataPilotDescriptor, u"Sales T1", sheet::GeneralFunction_SUM);
+
+ lclModifyColumnGrandTotal(xDataPilotDescriptor, true);
+ lclModifyRowGrandTotal(xDataPilotDescriptor, true);
+
+ xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor);
+
+ // TEST
+ Reference<chart2::XChartDocument> xChartDoc;
+
+ // Check we have the Pivot Table
+ uno::Reference<sheet::XDataPilotTable> xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent);
+ CPPUNIT_ASSERT(xDataPilotTable.is());
+
+ // refetch the XDataPilotDescriptor
+ xDataPilotDescriptor.set(xDataPilotTable, uno::UNO_QUERY_THROW);
+
+ // Check that we don't have any pivot chart in the document
+ uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent);
+ uno::Reference<container::XIndexAccess> xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount());
+
+ // Create a new pivot chart
+ xTablePivotCharts->addNewByName("PivotChart", awt::Rectangle{ 9000, 9000, 21000, 18000 }, sPivotTableName);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
+
+ // Get the pivot chart document so we can access its data
+ xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0));
+
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // Check if Date category is date formatted.
+ lclCheckCategories( { "12/11/15", "", "", "", "", "", "12/14/15", "12/17/15", "01/20/16", "", "", "03/21/17" },
+ lclGetCategories( xChartDoc )[0]->getValues() );
+}
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PivotChartTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/chart2_trendcalculators.cxx b/chart2/qa/extras/chart2_trendcalculators.cxx
new file mode 100644
index 0000000000..8639015d62
--- /dev/null
+++ b/chart2/qa/extras/chart2_trendcalculators.cxx
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "charttest.hxx"
+#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+#include <com/sun/star/chart2/XRegressionCurveCalculator.hpp>
+#include <SpecialCharacters.hxx>
+
+
+// Define the index of sheets in the test document
+constexpr sal_Int32 SHEET_POTENTIAL1 = 0;
+constexpr sal_Int32 SHEET_POTENTIAL2 = 1;
+constexpr sal_Int32 SHEET_LINEAR1 = 2;
+constexpr sal_Int32 SHEET_POLYNOMIAL1 = 3;
+constexpr sal_Int32 SHEET_EXPONENTIAL1 = 4;
+constexpr sal_Int32 SHEET_EXPONENTIAL2 = 5;
+
+class Chart2TrendCalculators : public ChartTest
+{
+public:
+ Chart2TrendCalculators()
+ : ChartTest("/chart2/qa/extras/data/")
+ {}
+
+ void setUp() override;
+ void tearDown() override;
+
+ void testPotentialRegression1();
+ void testPotentialRegression2();
+ void testLinearRegression1();
+ void testPolynomialRegression1();
+ void testExponentialRegression1();
+ void testExponentialRegression2();
+
+ CPPUNIT_TEST_SUITE(Chart2TrendCalculators);
+ CPPUNIT_TEST(testPotentialRegression1);
+ CPPUNIT_TEST(testPotentialRegression2);
+ CPPUNIT_TEST(testLinearRegression1);
+ CPPUNIT_TEST(testPolynomialRegression1);
+ CPPUNIT_TEST(testExponentialRegression1);
+ CPPUNIT_TEST(testExponentialRegression2);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ Reference<chart2::XRegressionCurve> m_xCurve;
+ Reference< chart2::XRegressionCurveCalculator > m_xRegressionCurveCalculator;
+
+ void loadCalculatorFromSheet(sal_Int32 nSheet);
+ void checkCalculator(
+ const Sequence< double >& xValues, const Sequence< double >& yValues,
+ const OUString& sExpectedFormula );
+};
+
+void Chart2TrendCalculators::setUp()
+{
+ ChartTest::setUp();
+ loadFromFile(u"ods/trend_calculators.ods");
+}
+
+void Chart2TrendCalculators::tearDown()
+{
+ m_xRegressionCurveCalculator.clear();
+ m_xCurve.clear();
+ ChartTest::tearDown();
+}
+
+void Chart2TrendCalculators::loadCalculatorFromSheet(sal_Int32 nSheet)
+{
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(nSheet, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ Reference<chart2::XRegressionCurveContainer> xRegressionCurveContainer(xDataSeries, UNO_QUERY_THROW);
+
+ Sequence< Reference< chart2::XRegressionCurve > > xRegressionCurveSequence = xRegressionCurveContainer->getRegressionCurves();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xRegressionCurveSequence.getLength());
+
+ m_xCurve = xRegressionCurveSequence[0];
+ CPPUNIT_ASSERT(m_xCurve.is());
+
+ m_xRegressionCurveCalculator = m_xCurve->getCalculator();
+ CPPUNIT_ASSERT(m_xRegressionCurveCalculator.is());
+}
+
+void Chart2TrendCalculators::checkCalculator(
+ const Sequence< double >& xValues, const Sequence< double >& yValues,
+ const OUString& sExpectedFormula )
+{
+ m_xRegressionCurveCalculator->recalculateRegression( xValues, yValues );
+ OUString aRepresentation = m_xRegressionCurveCalculator->getRepresentation ();
+ CPPUNIT_ASSERT_EQUAL( sExpectedFormula, aRepresentation );
+ double r2 = m_xRegressionCurveCalculator->getCorrelationCoefficient();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, r2, 1e-8 );
+}
+
+// test y = A x ^ B
+void Chart2TrendCalculators::testPotentialRegression1()
+{
+ loadCalculatorFromSheet( SHEET_POTENTIAL1 );
+ m_xRegressionCurveCalculator->setRegressionProperties( 0, false, 0, 0, 0 );
+ Sequence< double > xValues( 7 );
+ auto pxValues = xValues.getArray();
+ Sequence< double > yValues( 7 );
+ auto pyValues = yValues.getArray();
+ for (int i=0; i<7; i++)
+ {
+ const double d = static_cast<double>(i);
+ pxValues[i] = d;
+ pyValues[i] = 2.0 * pow ( d, 3 );
+ }
+ checkCalculator( xValues, yValues, "f(x) = 2 x^3");
+}
+
+// test y = A x ^ B
+void Chart2TrendCalculators::testPotentialRegression2()
+{
+ loadCalculatorFromSheet( SHEET_POTENTIAL2 );
+ m_xRegressionCurveCalculator->setRegressionProperties( 0, false, 0, 0, 0 );
+ Sequence< double > xValues( 7 );
+ auto pxValues = xValues.getArray();
+ Sequence< double > yValues( 7 );
+ auto pyValues = yValues.getArray();
+ for (int i=0; i<7; i++)
+ {
+ const double d = static_cast<double>(i);
+ pxValues[i] = d;
+ pyValues[i] = -2.0 * pow ( d, 3 );
+ }
+ checkCalculator( xValues, yValues, "f(x) = "+ OUStringChar(aMinusSign) +" 2 x^3");
+}
+
+// test y = - 2 X - 5
+void Chart2TrendCalculators::testLinearRegression1()
+{
+ loadCalculatorFromSheet( SHEET_LINEAR1 );
+ m_xRegressionCurveCalculator->setRegressionProperties( 1, false, 0, 0, 0 );
+ Sequence< double > xValues( 7 );
+ auto pxValues = xValues.getArray();
+ Sequence< double > yValues( 7 );
+ auto pyValues = yValues.getArray();
+ for (int i=0; i<7; i++)
+ {
+ const double d = static_cast<double>(i);
+ pxValues[i] = d;
+ pyValues[i] = - 2.0 * d - 5.0 ;
+ }
+ checkCalculator( xValues, yValues, "f(x) = "+ OUStringChar(aMinusSign) +" 2 x "+ OUStringChar(aMinusSign) +" 5");
+}
+
+// test y = A x ^ B
+void Chart2TrendCalculators::testPolynomialRegression1()
+{
+ loadCalculatorFromSheet( SHEET_POLYNOMIAL1 );
+ m_xRegressionCurveCalculator->setRegressionProperties( 2, false, 0, 0, 0 );
+ Sequence< double > xValues( 7 );
+ auto pxValues = xValues.getArray();
+ Sequence< double > yValues( 7 );
+ auto pyValues = yValues.getArray();
+ for (int i=0; i<7; i++)
+ {
+ const double d = static_cast<double>(i);
+ pxValues[i] = d;
+ pyValues[i] = - 2.0 * d * d + 4 * d - 5;
+ }
+ OUString sExpectedFormula( "f(x) = "+ OUStringChar(aMinusSign) +" 2 x" + OUStringChar( aSuperscriptFigures[2] ) + " + 4 x "+ OUStringChar(aMinusSign) +" 5" );
+ checkCalculator( xValues, yValues, sExpectedFormula );
+}
+
+void Chart2TrendCalculators::testExponentialRegression1()
+{
+ loadCalculatorFromSheet( SHEET_EXPONENTIAL1 );
+ m_xRegressionCurveCalculator->setRegressionProperties( 0, false, 0, 0, 0 );
+ Sequence< double > xValues( 7 );
+ auto pxValues = xValues.getArray();
+ Sequence< double > yValues( 7 );
+ auto pyValues = yValues.getArray();
+ for (int i=0; i<7; i++)
+ {
+ const double d = static_cast<double>(i);
+ pxValues[i] = d;
+ pyValues[i] = 2.0 * exp ( 0.3 * d );
+ }
+ checkCalculator( xValues, yValues, "f(x) = 2 exp( 0.3 x )");
+}
+
+void Chart2TrendCalculators::testExponentialRegression2()
+{
+ loadCalculatorFromSheet( SHEET_EXPONENTIAL2 );
+ m_xRegressionCurveCalculator->setRegressionProperties( 0, false, 0, 0, 0 );
+ Sequence< double > xValues( 7 );
+ auto pxValues = xValues.getArray();
+ Sequence< double > yValues( 7 );
+ auto pyValues = yValues.getArray();
+ for (int i=0; i<7; i++)
+ {
+ const double d = static_cast<double>(i);
+ pxValues[i] = d;
+ pyValues[i] = -2.0 * exp ( 0.3 * d );
+ }
+ checkCalculator( xValues, yValues, "f(x) = "+ OUStringChar(aMinusSign) + " 2 exp( 0.3 x )");
+}
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Chart2TrendCalculators);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/chart2dump/chart2dump.cxx b/chart2/qa/extras/chart2dump/chart2dump.cxx
new file mode 100644
index 0000000000..d13d768c03
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/chart2dump.cxx
@@ -0,0 +1,1122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <charttest.hxx>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/drawing/HomogenMatrix3.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+
+#include <editeng/unoprnms.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <fstream>
+#include <string_view>
+
+#if defined(X86)
+#define INT_EPS 2.1
+#else
+#define INT_EPS 0.1
+#endif
+
+#define DECLARE_DUMP_TEST(TestName, BaseClass, DumpMode) \
+ class TestName : public BaseClass { \
+ protected:\
+ virtual OUString getTestName() override { return #TestName; } \
+ public:\
+ TestName() : BaseClass(DumpMode) {}; \
+ CPPUNIT_TEST_SUITE(TestName); \
+ CPPUNIT_TEST(verify); \
+ CPPUNIT_TEST_SUITE_END(); \
+ virtual void verify() override;\
+ };\
+ CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \
+ void TestName::verify()
+
+
+#define CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aActual) \
+ if(isInDumpMode()) \
+ writeActual(OUString::number(aActual), #aActual); \
+ else \
+ { \
+ OString sTestFileName = OUStringToOString(getTestFileName(), RTL_TEXTENCODING_UTF8); \
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), readExpected(u ## #aActual), OUString(OUString::number(aActual))); \
+ }
+
+#define CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aActual, EPS_) \
+ if(isInDumpMode()) \
+ writeActual(OUString::number(aActual), #aActual); \
+ else \
+ { \
+ OString sTestFileName = OUStringToOString(getTestFileName(), RTL_TEXTENCODING_UTF8); \
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), readExpectedDouble(u ## #aActual), aActual, EPS_); \
+ }
+
+#define CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aActual) \
+ if(isInDumpMode()) \
+ writeActual(aActual, #aActual); \
+ else \
+ { \
+ OString sTestFileName = OUStringToOString(getTestFileName(), RTL_TEXTENCODING_UTF8); \
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), readExpected(u ## #aActual), aActual.trim()); \
+ }
+
+#define CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aActual, EPS_) \
+ if(isInDumpMode()) \
+ writeActualTransformation(aActual, #aActual); \
+ else \
+ { \
+ OUString expectedTransform; \
+ if (!readAndCheckTransformation (aActual, u ## #aActual, EPS_, expectedTransform)) \
+ { \
+ OString sTestFileName = OUStringToOString(getTestFileName(), RTL_TEXTENCODING_UTF8); \
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), expectedTransform, transformationToOneLineString(aActual)); \
+ } \
+ }
+
+class Chart2DumpTest : public ChartTest
+{
+protected:
+ Chart2DumpTest(bool bDumpMode)
+ : ChartTest("/chart2/qa/extras/chart2dump/data/")
+ {
+ m_bDumpMode = bDumpMode;
+ }
+
+ virtual ~Chart2DumpTest() override
+ {
+ }
+
+ void CPPUNIT_DUMP_ASSERT_NOTE(OUString const & Note) {
+ if(isInDumpMode())
+ writeNote(Note);
+ else
+ readNote(Note);
+ }
+
+ bool isInDumpMode () const {return m_bDumpMode;}
+
+ virtual OUString getTestName() { return OUString(); }
+ OUString const & getTestFileName() const { return m_sTestFileName; }
+ OUString getReferenceDirName()
+ {
+ return "/chart2/qa/extras/chart2dump/reference/" + getTestName().toAsciiLowerCase() + "/";
+ }
+
+ void setTestFileName (const OUString& sName)
+ {
+ m_sTestFileName = sName;
+
+ OUString sFileName = m_sTestFileName;
+ assert(sFileName.lastIndexOf('.') < sFileName.getLength());
+ sFileName = OUString::Concat(sFileName.subView(0, sFileName.lastIndexOf('.'))) + ".txt";
+ if (!m_bDumpMode)
+ {
+ if (m_aReferenceFile.is_open())
+ m_aReferenceFile.close();
+ OString sReferenceFile = OUStringToOString(Concat2View(m_directories.getPathFromSrc(getReferenceDirName()) + sFileName), RTL_TEXTENCODING_UTF8);
+ m_aReferenceFile.open(sReferenceFile.getStr(), std::ios_base::in);
+ CPPUNIT_ASSERT_MESSAGE(OString("Can't open reference file: " + sReferenceFile).getStr(), m_aReferenceFile.is_open());
+ }
+ else
+ {
+ if (m_aDumpFile.is_open())
+ m_aDumpFile.close();
+ OString sDumpFile = OUStringToOString(Concat2View(m_directories.getPathFromSrc(getReferenceDirName()) + sFileName), RTL_TEXTENCODING_UTF8);
+ m_aDumpFile.open(sDumpFile.getStr(), std::ios_base::out | std::ofstream::binary | std::ofstream::trunc);
+ CPPUNIT_ASSERT_MESSAGE(OString("Can't open dump file: " + sDumpFile).getStr(), m_aDumpFile.is_open());
+ }
+ }
+
+ virtual void verify()
+ {
+ CPPUNIT_FAIL("verify method must be overridden");
+ }
+
+ OUString readExpected(std::u16string_view sCheck)
+ {
+ assert(!m_bDumpMode);
+ assert(m_aReferenceFile.is_open());
+ std::string sTemp;
+ getline(m_aReferenceFile, sTemp);
+ OString sAssertMessage =
+ "The reference file does not contain the right content. Maybe it needs an update:"
+ + OUStringToOString(m_sTestFileName, RTL_TEXTENCODING_UTF8);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sAssertMessage.getStr(), OUString(OUString::Concat("// ") + sCheck), OUString(sTemp.data(), sTemp.length(), RTL_TEXTENCODING_UTF8));
+ getline(m_aReferenceFile, sTemp);
+ return OUString(sTemp.data(), sTemp.length(), RTL_TEXTENCODING_UTF8);
+ }
+
+ void writeActual(std::u16string_view sActualValue, const OUString& sCheck)
+ {
+ assert(m_bDumpMode);
+ assert(m_aDumpFile.is_open());
+ m_aDumpFile << "// " << sCheck << "\n"; // Add check string to make dump file readable
+ m_aDumpFile << OUString(sActualValue) << "\n"; // Write out the checked value, will be used as reference later
+ }
+
+ void readNote(std::u16string_view sNote)
+ {
+ assert(!m_bDumpMode);
+ assert(m_aReferenceFile.is_open());
+ std::string sTemp;
+ getline(m_aReferenceFile, sTemp);
+ OString sAssertMessage =
+ "The reference file does not contain the right content. Maybe it needs an update:"
+ + OUStringToOString(m_sTestFileName, RTL_TEXTENCODING_UTF8);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sAssertMessage.getStr(), OUString(OUString::Concat("/// ") + sNote), OUString(sTemp.data(), sTemp.length(), RTL_TEXTENCODING_UTF8));
+ }
+
+ void writeNote(const OUString& sNote)
+ {
+ assert(m_bDumpMode);
+ assert(m_aDumpFile.is_open());
+ m_aDumpFile << "/// " << sNote << "\n";
+ }
+
+ double readExpectedDouble(std::u16string_view sCheck)
+ {
+ OUString sExpected = readExpected(sCheck);
+ return sExpected.toDouble();
+ }
+
+ void writeActualTransformation(const drawing::HomogenMatrix3& rTransform, const OUString& sCheck)
+ {
+ writeActual(transformationToOneLineString(rTransform), sCheck);
+ }
+
+ bool readAndCheckTransformation(const drawing::HomogenMatrix3& rTransform, std::u16string_view sCheck, const double fEPS, OUString& rExpectedTransform)
+ {
+ rExpectedTransform = readExpected(sCheck); // Reference transformation string
+
+ // Convert string back to a transformation;
+ drawing::HomogenMatrix3 aExpectedTransform;
+ sal_Int32 nIdx {0};
+ aExpectedTransform.Line1.Column1 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx));
+ aExpectedTransform.Line1.Column2 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx));
+ aExpectedTransform.Line1.Column3 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx));
+ aExpectedTransform.Line2.Column1 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx));
+ aExpectedTransform.Line2.Column2 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx));
+ aExpectedTransform.Line2.Column3 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx));
+ aExpectedTransform.Line3.Column1 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx));
+ aExpectedTransform.Line3.Column2 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx));
+ aExpectedTransform.Line3.Column3 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx));
+
+ // Check the equality of the two transformation
+ return (std::abs(aExpectedTransform.Line1.Column1 - rTransform.Line1.Column1) < fEPS &&
+ std::abs(aExpectedTransform.Line1.Column2 - rTransform.Line1.Column2) < fEPS &&
+ std::abs(aExpectedTransform.Line1.Column3 - rTransform.Line1.Column3) < fEPS &&
+ std::abs(aExpectedTransform.Line2.Column1 - rTransform.Line2.Column1) < fEPS &&
+ std::abs(aExpectedTransform.Line2.Column2 - rTransform.Line2.Column2) < fEPS &&
+ std::abs(aExpectedTransform.Line2.Column3 - rTransform.Line2.Column3) < fEPS &&
+ std::abs(aExpectedTransform.Line3.Column1 - rTransform.Line3.Column1) < fEPS &&
+ std::abs(aExpectedTransform.Line3.Column2 - rTransform.Line3.Column2) < fEPS &&
+ std::abs(aExpectedTransform.Line3.Column3 - rTransform.Line3.Column3) < fEPS);
+ }
+
+ OUString sequenceToOneLineString(const uno::Sequence<OUString>& rSeq)
+ {
+ OUStringBuffer aBuffer;
+ for (const OUString& seqItem : rSeq)
+ {
+ aBuffer.append(seqItem + ";");
+ }
+ return aBuffer.makeStringAndClear();
+ }
+
+ OUString doubleVectorToOneLineString(const std::vector<double>& rVector)
+ {
+ OUStringBuffer aBuffer;
+ for (const double& vectorItem : rVector)
+ {
+ aBuffer.append(OUString::number(vectorItem) + ";");
+ }
+ return aBuffer.makeStringAndClear();
+ }
+
+ OUString transformationToOneLineString(const drawing::HomogenMatrix3& rTransform)
+ {
+ return OUString::number(rTransform.Line1.Column1) + ";" + OUString::number(rTransform.Line1.Column2) + ";" + OUString::number(rTransform.Line1.Column3) + ";" +
+ OUString::number(rTransform.Line2.Column1) + ";" + OUString::number(rTransform.Line2.Column2) + ";" + OUString::number(rTransform.Line2.Column3) + ";" +
+ OUString::number(rTransform.Line3.Column1) + ";" + OUString::number(rTransform.Line3.Column2) + ";" + OUString::number(rTransform.Line3.Column3);
+ }
+
+private:
+ OUString m_sTestFileName;
+ bool m_bDumpMode;
+ std::ifstream m_aReferenceFile;
+ std::ofstream m_aDumpFile;
+};
+
+DECLARE_DUMP_TEST(ChartDataTest, Chart2DumpTest, false)
+{
+ const std::vector<OUString> aTestFiles =
+ {
+ "simple_chart.ods",
+ "multiple_categories.ods"
+ };
+
+ for (const OUString& aTestFile : aTestFiles)
+ {
+ setTestFileName(aTestFile);
+ loadFromFile(getTestFileName());
+ uno::Reference< chart::XChartDocument > xChartDoc (getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW);
+
+ // Check title
+ uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW);
+ Reference<chart2::XTitled> xTitled(xChartDoc, uno::UNO_QUERY_THROW);
+ uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+ if(xTitle.is())
+ {
+ OUString sChartTitle = getTitleString(xTitled);
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sChartTitle);
+ }
+
+ // Check chart type
+ Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0);
+ CPPUNIT_ASSERT(xChartType.is());
+ OUString sChartType = xChartType->getChartType();
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sChartType);
+
+ // Check axis titles and number format
+ // x Axis
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc2, 0, 0, 0);
+ Reference<chart2::XTitled> xAxisTitled(xAxis, UNO_QUERY_THROW);
+ uno::Reference<chart2::XTitle> xAxisTitle = xAxisTitled->getTitleObject();
+ if (xAxisTitle.is())
+ {
+ OUString sXAxisTitle = getTitleString(xAxisTitled);
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sXAxisTitle);
+ }
+ sal_Int32 nXAxisNumberFormat = getNumberFormatFromAxis(xAxis);
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nXAxisNumberFormat);
+ sal_Int16 nXAxisNumberType = getNumberFormatType(xChartDoc2, nXAxisNumberFormat);
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nXAxisNumberType);
+
+ // y Axis
+ xAxis.set(getAxisFromDoc(xChartDoc2, 0, 1, 0));
+ xAxisTitled.set(xAxis, UNO_QUERY_THROW);
+ xAxisTitle.set(xAxisTitled->getTitleObject());
+ if (xAxisTitle.is())
+ {
+ OUString sYAxisTitle = getTitleString(xAxisTitled);
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sYAxisTitle);
+ }
+ sal_Int32 nYAxisNumberFormat = getNumberFormatFromAxis(xAxis);
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nYAxisNumberFormat);
+ sal_Int16 nYAxisNumberType = getNumberFormatType(xChartDoc2, nYAxisNumberFormat);
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nYAxisNumberType);
+
+ // Check column labels
+ uno::Reference< chart::XChartDataArray > xChartData(xChartDoc->getData(), UNO_QUERY_THROW);
+ uno::Sequence < OUString > aColumnLabels = xChartData->getColumnDescriptions();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aColumnLabels.getLength());
+ OUString sColumnLabels = sequenceToOneLineString(aColumnLabels);
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sColumnLabels);
+
+ // Check row labels
+ uno::Sequence< OUString > aRowLabels = xChartData->getRowDescriptions();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aRowLabels.getLength());
+ OUString sRowLabels = sequenceToOneLineString(aRowLabels);
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sRowLabels);
+
+ // Check Y values
+ std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType);
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aDataSeriesYValues.size());
+ for (const std::vector<double>& aYValuesOfSeries : aDataSeriesYValues)
+ {
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aYValuesOfSeries.size());
+ OUString sYValuesOfSeries = doubleVectorToOneLineString(aYValuesOfSeries);
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sYValuesOfSeries);
+ }
+
+ // Check source ranges
+ for (size_t nIndex = 0; nIndex < aDataSeriesYValues.size(); ++nIndex)
+ {
+ Reference< chart2::data::XDataSequence > xDataSeq = getDataSequenceFromDocByRole(xChartDoc2, u"values-x", nIndex);
+ if (xDataSeq.is())
+ {
+ OUString aXValuesSourceRange = xDataSeq->getSourceRangeRepresentation();
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aXValuesSourceRange);
+ }
+ xDataSeq.set(getDataSequenceFromDocByRole(xChartDoc2, u"values-y", nIndex));
+ if (xDataSeq.is())
+ {
+ OUString aYValuesSourceRange = xDataSeq->getSourceRangeRepresentation();
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aYValuesSourceRange);
+ }
+ xDataSeq.set(getDataSequenceFromDocByRole(xChartDoc2, u"categories", nIndex));
+ if (xDataSeq.is())
+ {
+ OUString aCategoriesSourceRange = xDataSeq->getSourceRangeRepresentation();
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aCategoriesSourceRange);
+ }
+ }
+ }
+}
+
+DECLARE_DUMP_TEST(LegendTest, Chart2DumpTest, false)
+{
+ const std::vector<OUString> aTestFiles =
+ {
+ "legend_on_right_side.odp",
+ "legend_on_bottom.odp",
+ "legend_on_left_side.odp",
+ "legend_on_top.odp",
+ "many_legend_entries.odp",
+ "custom_legend_position.odp",
+ "multiple_categories.odp",
+ "minimal_legend_test.odp"
+ };
+
+ for (const OUString& aTestFile : aTestFiles)
+ {
+ setTestFileName(aTestFile);
+ loadFromFile(getTestFileName());
+ uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ // Get legend shape
+ uno::Reference<drawing::XShape> xLegend = getShapeByName(xShapes, "CID/D=0:Legend=");
+ CPPUNIT_ASSERT(xLegend.is());
+
+ /* Check legend position and size
+ awt::Point aLegendPosition = xLegend->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendPosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendPosition.Y, INT_EPS);
+ awt::Size aLegendSize = xLegend->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendSize.Width, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendSize.Height, INT_EPS);*/
+
+ // Check legend entries
+ uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW);
+ Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0);
+ CPPUNIT_ASSERT(xChartType.is());
+ std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType);
+ size_t nLegendEntryCount = aDataSeriesYValues.size();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nLegendEntryCount);
+ // Check legend entries geometry
+ for (size_t nSeriesIndex = 0; nSeriesIndex < nLegendEntryCount; ++nSeriesIndex)
+ {
+ uno::Reference<drawing::XShape> xLegendEntry = getShapeByName(xShapes, "CID/MultiClick/D=0:CS=0:CT=0:Series=" + OUString::number(nSeriesIndex) + ":LegendEntry=0");
+ CPPUNIT_ASSERT(xLegendEntry.is());
+
+ /* Check position and size
+ awt::Point aLegendEntryPosition = xLegendEntry->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendEntryPosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendEntryPosition.Y, INT_EPS);
+ awt::Size aLegendEntrySize = xLegendEntry->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendEntrySize.Height, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendEntrySize.Width, INT_EPS);
+
+ // Check transformation
+ Reference< beans::XPropertySet > xLegendEntryPropSet(xLegendEntry, UNO_QUERY_THROW);
+ drawing::HomogenMatrix3 aLegendEntryTransformation;
+ xLegendEntryPropSet->getPropertyValue("Transformation") >>= aLegendEntryTransformation;
+ CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aLegendEntryTransformation, INT_EPS);*/
+
+ uno::Reference<container::XIndexAccess> xLegendEntryContainer(xLegendEntry, UNO_QUERY_THROW);
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(xLegendEntryContainer->getCount());
+ for (sal_Int32 nEntryGeometryElement = 1; nEntryGeometryElement < xLegendEntryContainer->getCount(); ++nEntryGeometryElement)
+ {
+ uno::Reference<drawing::XShape> xLegendEntryGeom(xLegendEntryContainer->getByIndex(nEntryGeometryElement), UNO_QUERY_THROW);
+
+ // Check geometry
+ uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xLegendEntryGeom, uno::UNO_QUERY_THROW);
+ OUString sEntryGeomShapeType = xShapeDescriptor->getShapeType();
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sEntryGeomShapeType);
+
+ // Check display color
+ Reference< beans::XPropertySet > xPropSet(xLegendEntryGeom, UNO_QUERY_THROW);
+ util::Color aEntryGeomColor = 0;
+ xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aEntryGeomColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aEntryGeomColor));
+ }
+ }
+ // Check legend entries' text
+ uno::Reference<container::XIndexAccess> xLegendContainer(xLegend, UNO_QUERY_THROW);
+ for (sal_Int32 i = 0; i < xLegendContainer->getCount(); ++i)
+ {
+ uno::Reference<drawing::XShape> xShape(xLegendContainer->getByIndex(i), uno::UNO_QUERY);
+ uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xShape, uno::UNO_QUERY_THROW);
+ OUString sShapeType = xShapeDescriptor->getShapeType();
+
+ if (sShapeType == "com.sun.star.drawing.TextShape")
+ {
+ uno::Reference<text::XText> xLegendEntryText = uno::Reference<text::XTextRange>(xShape, uno::UNO_QUERY_THROW)->getText();
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(xLegendEntryText->getString());
+ }
+ }
+ }
+}
+
+DECLARE_DUMP_TEST(GridTest, Chart2DumpTest, false)
+{
+ const std::vector<OUString> aTestFiles =
+ {
+ "vertical_grid.ods",
+ "horizontal_grid.ods",
+ "minor_grid.ods",
+ "formated_grid_line.ods"
+ };
+
+ for (const OUString& sTestFile : aTestFiles)
+ {
+ setTestFileName(sTestFile);
+ loadFromFile(getTestFileName());
+ uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ const std::vector<OUString> aGridShapeNames =
+ {
+ "CID/D=0:CS=0:Axis=1,0:Grid=0", // Major vertical grid
+ "CID/D=0:CS=0:Axis=0,0:Grid=0", // Major horizontal grid
+ "CID/D=0:CS=0:Axis=1,0:Grid=0:SubGrid=0", // Minor vertical grid
+ "CID/D=0:CS=0:Axis=0,0:Grid=0:SubGrid=0" // Minor horizontal grid
+ };
+
+ for (const OUString& sGridShapeName : aGridShapeNames)
+ {
+ uno::Reference<drawing::XShape> xGrid = getShapeByName(xShapes, sGridShapeName);
+ if (xGrid.is())
+ {
+ CPPUNIT_DUMP_ASSERT_NOTE(sGridShapeName);
+ // Check position and size
+ awt::Point aGridPosition = xGrid->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aGridPosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aGridPosition.Y, INT_EPS);
+ awt::Size aGridSize = xGrid->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aGridSize.Height, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aGridSize.Width, INT_EPS);
+
+ // Check transformation
+ Reference< beans::XPropertySet > xPropSet(xGrid, UNO_QUERY_THROW);
+ drawing::HomogenMatrix3 aGridTransformation;
+ xPropSet->getPropertyValue("Transformation") >>= aGridTransformation;
+ CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aGridTransformation, INT_EPS);
+
+ // Check line properties
+ uno::Reference<container::XIndexAccess> xIndexAccess(xGrid, UNO_QUERY_THROW);
+ uno::Reference<drawing::XShape> xGridLine(xIndexAccess->getByIndex(0), UNO_QUERY_THROW);
+ Reference< beans::XPropertySet > xGridLinePropSet(xGridLine, UNO_QUERY_THROW);
+ // Line type
+ drawing::LineDash aLineDash;
+ xGridLinePropSet->getPropertyValue("LineDash") >>= aLineDash;
+ OUString sGridLineDash =
+ OUString::number(static_cast<sal_Int32>(aLineDash.Style)) + ";" + OUString::number(aLineDash.Dots) + ";" + OUString::number(aLineDash.DotLen) +
+ OUString::number(aLineDash.Dashes) + ";" + OUString::number(aLineDash.DashLen) + ";" + OUString::number(aLineDash.Distance);
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sGridLineDash);
+ // Line color
+ util::Color aLineColor = 0;
+ xGridLinePropSet->getPropertyValue("LineColor") >>= aLineColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aLineColor));
+ // Line width
+ sal_Int32 nLineWidth = 0;
+ xGridLinePropSet->getPropertyValue("LineWidth") >>= nLineWidth;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nLineWidth);
+ }
+ }
+ }
+}
+
+DECLARE_DUMP_TEST(AxisGeometryTest, Chart2DumpTest, false)
+{
+ const std::vector<OUString> aTestFiles =
+ {
+ "default_formated_axis.odp",
+ "axis_special_positioning.odp",
+ "formated_axis_lines.odp",
+ "rotated_axis_labels.odp"
+ };
+
+ for (const OUString& sTestFile : aTestFiles)
+ {
+ setTestFileName(sTestFile);
+ loadFromFile(getTestFileName());
+ uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ const std::vector<OUString> aAxisShapeNames =
+ {
+ "CID/D=0:CS=0:Axis=0,0", // X Axis
+ "CID/D=0:CS=0:Axis=1,0", // Y Axis
+ };
+
+ for (const OUString& sAxisShapeName : aAxisShapeNames)
+ {
+ uno::Reference<drawing::XShape> xXAxis = getShapeByName(xShapes, sAxisShapeName);
+ CPPUNIT_ASSERT(xXAxis.is());
+
+ CPPUNIT_DUMP_ASSERT_NOTE(sAxisShapeName);
+ // Check position and size
+ awt::Point aAxisPosition = xXAxis->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAxisPosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAxisPosition.Y, INT_EPS);
+ awt::Size aAxisSize = xXAxis->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAxisSize.Height, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAxisSize.Width, INT_EPS);
+
+ // Check transformation
+ Reference< beans::XPropertySet > xPropSet(xXAxis, UNO_QUERY_THROW);
+ drawing::HomogenMatrix3 aAxisTransformation;
+ xPropSet->getPropertyValue("Transformation") >>= aAxisTransformation;
+ CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aAxisTransformation, INT_EPS);
+
+ // Check line properties
+ uno::Reference<container::XIndexAccess> xIndexAccess(xXAxis, UNO_QUERY_THROW);
+ sal_Int32 nAxisGeometriesCount = xIndexAccess->getCount();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nAxisGeometriesCount);
+ uno::Reference<drawing::XShape> xAxisLine(xIndexAccess->getByIndex(0), UNO_QUERY_THROW);
+ Reference< beans::XPropertySet > xAxisLinePropSet(xAxisLine, UNO_QUERY_THROW);
+ // Line type
+ drawing::LineDash aLineDash;
+ xAxisLinePropSet->getPropertyValue("LineDash") >>= aLineDash;
+ OUString sAxisLineDash =
+ OUString::number(static_cast<sal_Int32>(aLineDash.Style)) + ";" + OUString::number(aLineDash.Dots) + ";" + OUString::number(aLineDash.DotLen) +
+ OUString::number(aLineDash.Dashes) + ";" + OUString::number(aLineDash.DashLen) + ";" + OUString::number(aLineDash.Distance);
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sAxisLineDash);
+ // Line color
+ util::Color aAxisLineColor = 0;
+ xAxisLinePropSet->getPropertyValue("LineColor") >>= aAxisLineColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aAxisLineColor));
+ // Line width
+ sal_Int32 nAxisLineWidth = 0;
+ xAxisLinePropSet->getPropertyValue("LineWidth") >>= nAxisLineWidth;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nAxisLineWidth);
+ }
+ }
+}
+
+DECLARE_DUMP_TEST(AxisLabelTest, Chart2DumpTest, false)
+{
+ const std::vector<OUString> aTestFiles =
+ {
+ "default_formated_axis.odp",
+ "rotated_axis_labels.odp",
+ "formated_axis_labels.odp",
+ "percent_stacked_column_chart.odp",
+ "tdf118150.xlsx",
+ "date-categories.pptx",
+ };
+
+ for (const OUString& sTestFile : aTestFiles)
+ {
+ setTestFileName(sTestFile);
+ loadFromFile(getTestFileName());
+ uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ const std::vector<OUString> aAxisShapeNames =
+ {
+ "CID/D=0:CS=0:Axis=0,0", // X Axis
+ "CID/D=0:CS=0:Axis=1,0", // Y Axis
+ };
+
+ for (const OUString& sAxisShapeName : aAxisShapeNames)
+ {
+ uno::Reference<drawing::XShape> xXAxis = getShapeByName(xShapes, sAxisShapeName,
+ // Axis occurs twice in chart xshape representation so need to get the one related to labels
+ [](const uno::Reference<drawing::XShape>& rXShape) -> bool
+ {
+ uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xAxisShapes.is());
+ uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xChildShape, uno::UNO_QUERY_THROW);
+ return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape");
+ });
+ CPPUNIT_ASSERT(xXAxis.is());
+ CPPUNIT_DUMP_ASSERT_NOTE(sAxisShapeName);
+
+ // Check label count
+ uno::Reference<container::XIndexAccess> xIndexAccess(xXAxis, UNO_QUERY_THROW);
+ sal_Int32 nAxisLabelsCount = xIndexAccess->getCount();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nAxisLabelsCount);
+
+ // Check labels's text, positioning and font properties
+ for (sal_Int32 nLabelIndex = 0; nLabelIndex < nAxisLabelsCount; ++nLabelIndex)
+ {
+ // Check text
+ uno::Reference<text::XTextRange> xLabel(xIndexAccess->getByIndex(nLabelIndex), uno::UNO_QUERY);
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(xLabel->getString());
+
+ // Check size and position
+ uno::Reference<drawing::XShape> xLabelShape(xLabel, uno::UNO_QUERY);
+ /*awt::Point aLabelPosition = xLabelShape->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLabelPosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLabelPosition.Y, INT_EPS);
+ awt::Size aLabelSize = xLabelShape->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLabelSize.Height, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLabelSize.Width, INT_EPS);*/
+
+ // Check transformation
+ Reference< beans::XPropertySet > xPropSet(xLabelShape, UNO_QUERY_THROW);
+ /*drawing::HomogenMatrix3 aLabelTransformation;
+ xPropSet->getPropertyValue("Transformation") >>= aLabelTransformation;
+ CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aLabelTransformation, INT_EPS);*/
+
+ // Check font color and height
+ util::Color aLabelFontColor = 0;
+ xPropSet->getPropertyValue("CharColor") >>= aLabelFontColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aLabelFontColor));
+ float fLabelFontHeight = 0.0f;
+ xPropSet->getPropertyValue("CharHeight") >>= fLabelFontHeight;
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(fLabelFontHeight, 1E-12);
+ }
+ }
+ }
+}
+
+DECLARE_DUMP_TEST(ColumnBarChartTest, Chart2DumpTest, false)
+{
+ const std::vector<OUString> aTestFiles =
+ {
+ "normal_column_chart.ods",
+ "stacked_column_chart.ods",
+ "percent_stacked_column_chart.ods",
+ "column_chart_small_spacing.ods",
+ "normal_bar_chart.ods",
+ "stacked_bar_chart.ods",
+ "percent_stacked_bar_chart.ods",
+ };
+
+ for (const OUString& sTestFile : aTestFiles)
+ {
+ setTestFileName(sTestFile);
+ loadFromFile(getTestFileName());
+ uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW);
+ Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0);
+ CPPUNIT_ASSERT(xChartType.is());
+ std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType);
+ size_t nSeriesCount = aDataSeriesYValues.size();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount);
+
+ for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries)
+ {
+ uno::Reference<drawing::XShape> xSeriesColumnsOrBars = getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries));
+ CPPUNIT_ASSERT(xSeriesColumnsOrBars.is());
+ CPPUNIT_DUMP_ASSERT_NOTE("Series " + OUString::number(nSeries) + " ColumnsOrBars");
+
+ // Check column/bar count in the series
+ uno::Reference<container::XIndexAccess> xIndexAccess(xSeriesColumnsOrBars, UNO_QUERY_THROW);
+ sal_Int32 nColumnOrBarCountInSeries = xIndexAccess->getCount();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nColumnOrBarCountInSeries);
+
+ // Check column/bar fill style and color
+ Reference< beans::XPropertySet > xColumnOrBarPropSet(xIndexAccess->getByIndex(0), UNO_QUERY_THROW);
+ drawing::FillStyle aSeriesColumnOrBarFillStyle;
+ xColumnOrBarPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= aSeriesColumnOrBarFillStyle;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle));
+ util::Color aSeriesColumnOrBarFillColor = 0;
+ xColumnOrBarPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aSeriesColumnOrBarFillColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aSeriesColumnOrBarFillColor));
+
+ for (sal_Int32 nColumnOrBar = 0; nColumnOrBar < nColumnOrBarCountInSeries; ++nColumnOrBar)
+ {
+ uno::Reference<drawing::XShape> xColumnOrBar(xIndexAccess->getByIndex(nColumnOrBar), UNO_QUERY_THROW);
+ uno::Reference<container::XNamed> xNamedShape(xIndexAccess->getByIndex(nColumnOrBar), uno::UNO_QUERY);
+ CPPUNIT_DUMP_ASSERT_NOTE(xNamedShape->getName());
+
+ // Check size and position
+ awt::Point aColumnOrBarPosition = xColumnOrBar->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aColumnOrBarPosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aColumnOrBarPosition.Y, INT_EPS);
+ awt::Size aColumnOrBarSize = xColumnOrBar->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aColumnOrBarSize.Height, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aColumnOrBarSize.Width, INT_EPS);
+
+ // Check transformation
+ Reference< beans::XPropertySet > xPropSet(xColumnOrBar, UNO_QUERY_THROW);
+ drawing::HomogenMatrix3 aColumnOrBarTransformation;
+ xPropSet->getPropertyValue("Transformation") >>= aColumnOrBarTransformation;
+ CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aColumnOrBarTransformation, INT_EPS);
+ }
+ }
+ }
+}
+
+DECLARE_DUMP_TEST(ChartWallTest, Chart2DumpTest, false)
+{
+ const std::vector<OUString> aTestFiles =
+ {
+ "chartwall_auto_adjust_with_titles.ods",
+ "chartwall_auto_adjust_without_titles.ods",
+ "chartwall_custom_positioning.ods"
+ };
+
+ for (const OUString& sTestFile : aTestFiles)
+ {
+ setTestFileName(sTestFile);
+ loadFromFile(getTestFileName());
+ uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference<drawing::XShape> xChartWall = getShapeByName(xShapes, "CID/DiagramWall=");
+ CPPUNIT_ASSERT(xChartWall.is());
+
+ // Check position and size
+ /*awt::Point aChartWallPosition = xChartWall->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aChartWallPosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aChartWallPosition.Y, INT_EPS);
+ awt::Size aChartWallSize = xChartWall->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aChartWallSize.Height, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aChartWallSize.Width, INT_EPS);*/
+
+ // Check transformation
+ Reference< beans::XPropertySet > xPropSet(xChartWall, UNO_QUERY_THROW);
+ /*drawing::HomogenMatrix3 aChartWallTransformation;
+ xPropSet->getPropertyValue("Transformation") >>= aChartWallTransformation;
+ CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aChartWallTransformation, INT_EPS);*/
+
+ // Check fill properties
+ drawing::FillStyle aChartWallFillStyle;
+ xPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= aChartWallFillStyle;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aChartWallFillStyle));
+ util::Color aChartWallFillColor = 0;
+ xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aChartWallFillColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aChartWallFillColor));
+
+ // Check line properties
+ // Line type
+ drawing::LineDash aLineDash;
+ xPropSet->getPropertyValue("LineDash") >>= aLineDash;
+ OUString sChartWallLineDash =
+ OUString::number(static_cast<sal_Int32>(aLineDash.Style)) + ";" + OUString::number(aLineDash.Dots) + ";" + OUString::number(aLineDash.DotLen) +
+ OUString::number(aLineDash.Dashes) + ";" + OUString::number(aLineDash.DashLen) + ";" + OUString::number(aLineDash.Distance);
+ CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sChartWallLineDash);
+ // Line color
+ util::Color aChartWallLineColor = 0;
+ xPropSet->getPropertyValue("LineColor") >>= aChartWallLineColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aChartWallLineColor));
+ // Line width
+ sal_Int32 nChartWallLineWidth = 0;
+ xPropSet->getPropertyValue("LineWidth") >>= nChartWallLineWidth;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nChartWallLineWidth);
+ }
+}
+
+DECLARE_DUMP_TEST(PieChartTest, Chart2DumpTest, false)
+{
+ const std::vector<OUString> aTestFiles =
+ {
+ "normal_pie_chart.ods",
+ "rotated_pie_chart.ods",
+ "exploded_pie_chart.ods",
+ "donut_chart.ods",
+ "pie_chart_many_slices.ods",
+ };
+
+ for (const OUString& sTestFile : aTestFiles)
+ {
+ setTestFileName(sTestFile);
+ loadFromFile(getTestFileName());
+ uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW);
+ Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0);
+ CPPUNIT_ASSERT(xChartType.is());
+
+ std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType);
+ size_t nSeriesCount = aDataSeriesYValues.size();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount);
+
+ for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries)
+ {
+ uno::Reference<drawing::XShape> xSeriesSlices = getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries));
+ if (!xSeriesSlices.is())
+ break; // Normal pie chart displays only one series
+ CPPUNIT_DUMP_ASSERT_NOTE("Series " + OUString::number(nSeries) + " slices");
+
+ // Check slice count in the series
+ uno::Reference<container::XIndexAccess> xIndexAccess(xSeriesSlices, UNO_QUERY_THROW);
+ sal_Int32 nSlicesCountInSeries = xIndexAccess->getCount();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSlicesCountInSeries);
+
+ // Check slices properties
+ for (sal_Int32 nSlice = 0; nSlice < nSlicesCountInSeries; ++nSlice)
+ {
+ uno::Reference<drawing::XShape> xSlice(xIndexAccess->getByIndex(nSlice), UNO_QUERY_THROW);
+ uno::Reference<container::XNamed> xNamedShape(xIndexAccess->getByIndex(nSlice), uno::UNO_QUERY);
+ OUString sName = xNamedShape->getName();
+ CPPUNIT_DUMP_ASSERT_NOTE(sName.copy(sName.lastIndexOf("/D=0")));
+
+ // Check size and position
+ awt::Point aSlicePosition = xSlice->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aSlicePosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aSlicePosition.Y, INT_EPS);
+ awt::Size aSliceSize = xSlice->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aSliceSize.Height, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aSliceSize.Width, INT_EPS);
+
+ // Check transformation
+ Reference< beans::XPropertySet > xPropSet(xSlice, UNO_QUERY_THROW);
+ drawing::HomogenMatrix3 aSliceTransformation;
+ xPropSet->getPropertyValue("Transformation") >>= aSliceTransformation;
+ CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aSliceTransformation, INT_EPS);
+
+ // Check slice fill style and color
+ drawing::FillStyle aSliceFillStyle;
+ xPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= aSliceFillStyle;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aSliceFillStyle));
+ util::Color aSliceFillColor = 0;
+ xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aSliceFillColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aSliceFillColor));
+ }
+ }
+ }
+}
+
+DECLARE_DUMP_TEST(AreaChartTest, Chart2DumpTest, false)
+{
+ const std::vector<OUString> aTestFiles =
+ {
+ "normal_area_chart.ods",
+ "stacked_area_chart.ods",
+ "percent_stacked_area_chart.ods"
+ };
+
+ for (const OUString& sTestFile : aTestFiles)
+ {
+ setTestFileName(sTestFile);
+ loadFromFile(getTestFileName());
+ uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW);
+ Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0);
+ CPPUNIT_ASSERT(xChartType.is());
+
+ std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType);
+ size_t nSeriesCount = aDataSeriesYValues.size();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount);
+
+ for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries)
+ {
+ uno::Reference<drawing::XShape> xSeries = getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries));
+ CPPUNIT_ASSERT(xSeries.is());
+ CPPUNIT_DUMP_ASSERT_NOTE("Series " + OUString::number(nSeries));
+
+ // One area for one series
+ uno::Reference<container::XIndexAccess> xIndexAccess(xSeries, UNO_QUERY_THROW);
+ uno::Reference<container::XIndexAccess> xIndexAccess2(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); // Why this second group shape is here?
+ uno::Reference<drawing::XShape> xArea(xIndexAccess2->getByIndex(0), UNO_QUERY_THROW);
+
+ // Check size and position
+ awt::Point aAreaPosition = xArea->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAreaPosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAreaPosition.Y, INT_EPS);
+ awt::Size aAreaSize = xArea->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAreaSize.Height, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAreaSize.Width, INT_EPS);
+
+ // Check transformation
+ Reference< beans::XPropertySet > xPropSet(xArea, UNO_QUERY_THROW);
+ drawing::HomogenMatrix3 aAreaTransformation;
+ xPropSet->getPropertyValue("Transformation") >>= aAreaTransformation;
+ CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aAreaTransformation, INT_EPS);
+
+ // Check area fill style and color
+ drawing::FillStyle aAreaFillStyle;
+ xPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= aAreaFillStyle;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aAreaFillStyle));
+ util::Color aAreaFillColor = 0;
+ xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aAreaFillColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aAreaFillColor));
+ }
+ }
+}
+
+
+DECLARE_DUMP_TEST(PointLineChartTest, Chart2DumpTest, false)
+{
+ const std::vector<OUString> aTestFiles =
+ {
+ "normal_line_chart_lines_only.ods",
+ "normal_line_chart_points_only.ods",
+ "normal_line_chart_lines_and_points.ods",
+ "stacked_line_chart_lines_only.ods",
+ "stacked_line_chart_points_only.ods",
+ "stacked_line_chart_lines_and_points.ods",
+ "percent_stacked_line_chart_lines_only.ods",
+ "percent_stacked_line_chart_points_only.ods",
+ "percent_stacked_line_chart_lines_and_points.ods",
+ "scatter_chart_points_only.ods",
+ "scatter_chart_lines_only.ods",
+ "scatter_chart_lines_and_points.ods",
+ };
+
+ for (const OUString& sTestFile : aTestFiles)
+ {
+ setTestFileName(sTestFile);
+ loadFromFile(getTestFileName());
+ uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW);
+ Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0);
+ CPPUNIT_ASSERT(xChartType.is());
+
+ std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType);
+ size_t nSeriesCount = aDataSeriesYValues.size();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount);
+
+ for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries)
+ {
+ uno::Reference<drawing::XShape> xSeries = getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries));
+ CPPUNIT_ASSERT(xSeries.is());
+ CPPUNIT_DUMP_ASSERT_NOTE("Series " + OUString::number(nSeries));
+
+ uno::Reference<container::XIndexAccess> xIndexAccess(xSeries, UNO_QUERY_THROW);
+ uno::Reference<container::XIndexAccess> xIndexAccess2(xIndexAccess->getByIndex(0), UNO_QUERY_THROW);
+ uno::Reference<drawing::XShape> xLine(xIndexAccess2->getByIndex(0), UNO_QUERY_THROW);
+ Reference< beans::XPropertySet > xPropSet(xLine, UNO_QUERY_THROW);
+
+ // Check whether we have line
+ drawing::LineStyle aSeriesLineStyle;
+ xPropSet->getPropertyValue(UNO_NAME_LINESTYLE) >>= aSeriesLineStyle;
+ if (aSeriesLineStyle != drawing::LineStyle_NONE)
+ {
+ CPPUNIT_DUMP_ASSERT_NOTE("Lines are displayed");
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aSeriesLineStyle));
+
+ // Check line shape geometry
+ awt::Point aLinePosition = xLine->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLinePosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLinePosition.Y, INT_EPS);
+ awt::Size aLineSize = xLine->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLineSize.Height, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLineSize.Width, INT_EPS);
+ CPPUNIT_ASSERT(xPropSet.is());
+ drawing::HomogenMatrix3 aLineTransformation;
+ xPropSet->getPropertyValue("Transformation") >>= aLineTransformation;
+ CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aLineTransformation, INT_EPS);
+ }
+
+ // Check points of series
+ if (xIndexAccess->getCount() >= 2)
+ {
+ CPPUNIT_DUMP_ASSERT_NOTE("Points are displayed");
+ uno::Reference<container::XIndexAccess> xPointsOfSeries(xIndexAccess->getByIndex(1), UNO_QUERY_THROW);
+ sal_Int32 nPointCountInSeries = xPointsOfSeries->getCount();
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nPointCountInSeries);
+ for (sal_Int32 nPoint = 0; nPoint < nPointCountInSeries; ++nPoint)
+ {
+ uno::Reference<container::XIndexAccess> XPointContainer (
+ getShapeByName(xShapes, "CID/MultiClick/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries) + ":Point=" + OUString::number(nPoint)), UNO_QUERY_THROW);
+ uno::Reference<drawing::XShape> XPoint(XPointContainer->getByIndex(0), UNO_QUERY_THROW);
+ uno::Reference<container::XNamed> xNamedShape(XPointContainer, uno::UNO_QUERY);
+ CPPUNIT_DUMP_ASSERT_NOTE(xNamedShape->getName());
+
+ // Check size and position
+ awt::Point aPointPosition = XPoint->getPosition();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aPointPosition.X, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aPointPosition.Y, INT_EPS);
+ awt::Size aPointSize = XPoint->getSize();
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aPointSize.Height, INT_EPS);
+ CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aPointSize.Width, INT_EPS);
+
+ // Check transformation
+ Reference< beans::XPropertySet > xPointPropSet(XPoint, UNO_QUERY_THROW);
+ drawing::HomogenMatrix3 aPointTransformation;
+ xPointPropSet->getPropertyValue("Transformation") >>= aPointTransformation;
+ CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aPointTransformation, INT_EPS);
+
+ // Check fill style and color
+ drawing::FillStyle aPointFillStyle;
+ xPointPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= aPointFillStyle;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aPointFillStyle));
+ util::Color aPointFillColor = 0;
+ xPointPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aPointFillColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aPointFillColor));
+ }
+ }
+ }
+ }
+}
+
+DECLARE_DUMP_TEST( PivotChartDataButtonTest, Chart2DumpTest, false )
+{
+ setTestFileName( "pivotchart_data_button.ods" );
+ loadFromFile(getTestFileName());
+
+ // Check that we have pivot chart in the document
+ uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet( 1, mxComponent );
+ uno::Reference<container::XIndexAccess> xIndexAccess( xTablePivotCharts, UNO_QUERY_THROW );
+ CPPUNIT_ASSERT_EQUAL( sal_Int32(1), xIndexAccess->getCount() );
+
+ // Get the pivot chart document so we ca access its data
+ uno::Reference<chart2::XChartDocument> xChartDoc;
+ xChartDoc.set( getPivotChartDocFromSheet( xTablePivotCharts, 0 ) );
+ CPPUNIT_ASSERT( xChartDoc.is() );
+
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier( xChartDoc, uno::UNO_QUERY );
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes( xDrawPage->getByIndex(0), uno::UNO_QUERY );
+ CPPUNIT_ASSERT( xShapes.is() );
+
+ // Get the shape that represents the "Data" button.
+ uno::Reference<drawing::XShape> xButton = getShapeByName( xShapes, "FieldButton.Row.8",
+ []( const uno::Reference<drawing::XShape>& xShapeNode )
+ {
+ return xShapeNode->getShapeType() == "com.sun.star.drawing.TextShape";
+ } );
+ CPPUNIT_ASSERT_MESSAGE( "Cannot find Data button shape", xButton.is() );
+
+ // Make sure that there is no arrow shape with the Data button
+ uno::Reference<drawing::XShape> xArrow = getShapeByName( xShapes, "FieldButton.Row.8",
+ []( const uno::Reference<drawing::XShape>& xShapeNode )
+ {
+ return xShapeNode->getShapeType() == "com.sun.star.drawing.PolyPolygonShape";
+ } );
+ CPPUNIT_ASSERT_MESSAGE( "Arrow shape should not be present for the Data button", !xArrow.is() );
+
+ // Assert the background color of the Data button
+ util::Color aButtonFillColor = 0;
+ uno::Reference<beans::XPropertySet> xPropSet( xButton, UNO_QUERY_THROW );
+ xPropSet->getPropertyValue( UNO_NAME_FILLCOLOR ) >>= aButtonFillColor;
+ CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL( static_cast<sal_Int32>( aButtonFillColor ) );
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/chart2dump/data/axis_special_positioning.odp b/chart2/qa/extras/chart2dump/data/axis_special_positioning.odp
new file mode 100644
index 0000000000..a09ddb893d
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/axis_special_positioning.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_with_titles.ods b/chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_with_titles.ods
new file mode 100644
index 0000000000..1b41db316e
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_with_titles.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_without_titles.ods b/chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_without_titles.ods
new file mode 100644
index 0000000000..be5b118048
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/chartwall_auto_adjust_without_titles.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/chartwall_custom_positioning.ods b/chart2/qa/extras/chart2dump/data/chartwall_custom_positioning.ods
new file mode 100644
index 0000000000..b6ba872212
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/chartwall_custom_positioning.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/column_chart_small_spacing.ods b/chart2/qa/extras/chart2dump/data/column_chart_small_spacing.ods
new file mode 100644
index 0000000000..1206a4e198
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/column_chart_small_spacing.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/custom_legend_position.odp b/chart2/qa/extras/chart2dump/data/custom_legend_position.odp
new file mode 100644
index 0000000000..d36677ab49
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/custom_legend_position.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/date-categories.pptx b/chart2/qa/extras/chart2dump/data/date-categories.pptx
new file mode 100644
index 0000000000..b9e0c69f32
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/date-categories.pptx
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/default_formated_axis.odp b/chart2/qa/extras/chart2dump/data/default_formated_axis.odp
new file mode 100644
index 0000000000..a5cdd0522b
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/default_formated_axis.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/donut_chart.ods b/chart2/qa/extras/chart2dump/data/donut_chart.ods
new file mode 100644
index 0000000000..4490f76954
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/donut_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/exploded_pie_chart.ods b/chart2/qa/extras/chart2dump/data/exploded_pie_chart.ods
new file mode 100644
index 0000000000..68a9c98429
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/exploded_pie_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/formated_axis_labels.odp b/chart2/qa/extras/chart2dump/data/formated_axis_labels.odp
new file mode 100644
index 0000000000..a94c8c4d05
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/formated_axis_labels.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/formated_axis_lines.odp b/chart2/qa/extras/chart2dump/data/formated_axis_lines.odp
new file mode 100644
index 0000000000..7a421497b4
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/formated_axis_lines.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/formated_grid_line.ods b/chart2/qa/extras/chart2dump/data/formated_grid_line.ods
new file mode 100644
index 0000000000..1d0ef5389f
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/formated_grid_line.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/horizontal_grid.ods b/chart2/qa/extras/chart2dump/data/horizontal_grid.ods
new file mode 100644
index 0000000000..c9f913067b
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/horizontal_grid.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/legend_on_bottom.odp b/chart2/qa/extras/chart2dump/data/legend_on_bottom.odp
new file mode 100644
index 0000000000..b080d33116
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/legend_on_bottom.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/legend_on_left_side.odp b/chart2/qa/extras/chart2dump/data/legend_on_left_side.odp
new file mode 100644
index 0000000000..71e2947c6a
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/legend_on_left_side.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/legend_on_right_side.odp b/chart2/qa/extras/chart2dump/data/legend_on_right_side.odp
new file mode 100644
index 0000000000..7aac4d3f33
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/legend_on_right_side.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/legend_on_top.odp b/chart2/qa/extras/chart2dump/data/legend_on_top.odp
new file mode 100644
index 0000000000..318901f2e4
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/legend_on_top.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/many_legend_entries.odp b/chart2/qa/extras/chart2dump/data/many_legend_entries.odp
new file mode 100644
index 0000000000..8f02a99f66
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/many_legend_entries.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/minimal_legend_test.odp b/chart2/qa/extras/chart2dump/data/minimal_legend_test.odp
new file mode 100644
index 0000000000..63911f119c
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/minimal_legend_test.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/minor_grid.ods b/chart2/qa/extras/chart2dump/data/minor_grid.ods
new file mode 100644
index 0000000000..f8f30198b0
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/minor_grid.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/multiple_categories.odp b/chart2/qa/extras/chart2dump/data/multiple_categories.odp
new file mode 100644
index 0000000000..95e51f3f69
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/multiple_categories.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/multiple_categories.ods b/chart2/qa/extras/chart2dump/data/multiple_categories.ods
new file mode 100644
index 0000000000..67e00525b9
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/multiple_categories.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/normal_area_chart.ods b/chart2/qa/extras/chart2dump/data/normal_area_chart.ods
new file mode 100644
index 0000000000..84b9ec2247
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/normal_area_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/normal_bar_chart.ods b/chart2/qa/extras/chart2dump/data/normal_bar_chart.ods
new file mode 100644
index 0000000000..531f406f93
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/normal_bar_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/normal_column_chart.ods b/chart2/qa/extras/chart2dump/data/normal_column_chart.ods
new file mode 100644
index 0000000000..a8c6404001
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/normal_column_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/normal_line_chart_lines_and_points.ods b/chart2/qa/extras/chart2dump/data/normal_line_chart_lines_and_points.ods
new file mode 100644
index 0000000000..4dd613b6f4
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/normal_line_chart_lines_and_points.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/normal_line_chart_lines_only.ods b/chart2/qa/extras/chart2dump/data/normal_line_chart_lines_only.ods
new file mode 100644
index 0000000000..c4f57a6f3c
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/normal_line_chart_lines_only.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/normal_line_chart_points_only.ods b/chart2/qa/extras/chart2dump/data/normal_line_chart_points_only.ods
new file mode 100644
index 0000000000..e55b41115e
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/normal_line_chart_points_only.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/normal_pie_chart.ods b/chart2/qa/extras/chart2dump/data/normal_pie_chart.ods
new file mode 100644
index 0000000000..3c3a6a327f
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/normal_pie_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/percent_stacked_area_chart.ods b/chart2/qa/extras/chart2dump/data/percent_stacked_area_chart.ods
new file mode 100644
index 0000000000..0cc5d1728a
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/percent_stacked_area_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/percent_stacked_bar_chart.ods b/chart2/qa/extras/chart2dump/data/percent_stacked_bar_chart.ods
new file mode 100644
index 0000000000..2d337a5b3d
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/percent_stacked_bar_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.odp b/chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.odp
new file mode 100644
index 0000000000..e8180cfc73
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.ods b/chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.ods
new file mode 100644
index 0000000000..ce7440aa77
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/percent_stacked_column_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_and_points.ods b/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_and_points.ods
new file mode 100644
index 0000000000..ade9ea8f13
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_and_points.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_only.ods b/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_only.ods
new file mode 100644
index 0000000000..3228f51a3f
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_lines_only.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_points_only.ods b/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_points_only.ods
new file mode 100644
index 0000000000..b2483b6da5
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/percent_stacked_line_chart_points_only.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/pie_chart_many_slices.ods b/chart2/qa/extras/chart2dump/data/pie_chart_many_slices.ods
new file mode 100644
index 0000000000..2cc2e8b7bb
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/pie_chart_many_slices.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/pivotchart_data_button.ods b/chart2/qa/extras/chart2dump/data/pivotchart_data_button.ods
new file mode 100644
index 0000000000..d57edf66d2
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/pivotchart_data_button.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/rotated_axis_labels.odp b/chart2/qa/extras/chart2dump/data/rotated_axis_labels.odp
new file mode 100644
index 0000000000..24e9cf05b2
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/rotated_axis_labels.odp
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/rotated_pie_chart.ods b/chart2/qa/extras/chart2dump/data/rotated_pie_chart.ods
new file mode 100644
index 0000000000..ee8b3a7d96
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/rotated_pie_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/scatter_chart_lines_and_points.ods b/chart2/qa/extras/chart2dump/data/scatter_chart_lines_and_points.ods
new file mode 100644
index 0000000000..de7b1c67c5
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/scatter_chart_lines_and_points.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/scatter_chart_lines_only.ods b/chart2/qa/extras/chart2dump/data/scatter_chart_lines_only.ods
new file mode 100644
index 0000000000..fed5789927
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/scatter_chart_lines_only.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/scatter_chart_points_only.ods b/chart2/qa/extras/chart2dump/data/scatter_chart_points_only.ods
new file mode 100644
index 0000000000..dd1626d7a2
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/scatter_chart_points_only.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/simple_chart.ods b/chart2/qa/extras/chart2dump/data/simple_chart.ods
new file mode 100644
index 0000000000..f65584d12a
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/simple_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/stacked_area_chart.ods b/chart2/qa/extras/chart2dump/data/stacked_area_chart.ods
new file mode 100644
index 0000000000..56bc4e4992
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/stacked_area_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/stacked_bar_chart.ods b/chart2/qa/extras/chart2dump/data/stacked_bar_chart.ods
new file mode 100644
index 0000000000..2e8ca327e4
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/stacked_bar_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/stacked_column_chart.ods b/chart2/qa/extras/chart2dump/data/stacked_column_chart.ods
new file mode 100644
index 0000000000..159df229a4
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/stacked_column_chart.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_and_points.ods b/chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_and_points.ods
new file mode 100644
index 0000000000..d11ecb7058
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_and_points.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_only.ods b/chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_only.ods
new file mode 100644
index 0000000000..1652c3a589
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/stacked_line_chart_lines_only.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/stacked_line_chart_points_only.ods b/chart2/qa/extras/chart2dump/data/stacked_line_chart_points_only.ods
new file mode 100644
index 0000000000..a85a2abe86
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/stacked_line_chart_points_only.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/tdf118150.xlsx b/chart2/qa/extras/chart2dump/data/tdf118150.xlsx
new file mode 100644
index 0000000000..f29b9a1c2e
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/tdf118150.xlsx
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/data/vertical_grid.ods b/chart2/qa/extras/chart2dump/data/vertical_grid.ods
new file mode 100644
index 0000000000..9f2ed7838a
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/data/vertical_grid.ods
Binary files differ
diff --git a/chart2/qa/extras/chart2dump/reference/areacharttest/normal_area_chart.txt b/chart2/qa/extras/chart2dump/reference/areacharttest/normal_area_chart.txt
new file mode 100644
index 0000000000..4f4a5181fd
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/areacharttest/normal_area_chart.txt
@@ -0,0 +1,62 @@
+// nSeriesCount
+4
+/// Series 0
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+3295
+// aAreaSize.Height
+4052
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;4052;3295;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+1
+// static_cast<sal_Int32>(aAreaFillColor)
+16711680
+/// Series 1
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+3385
+// aAreaSize.Height
+3962
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;3962;3385;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+2
+// static_cast<sal_Int32>(aAreaFillColor)
+10079487
+/// Series 2
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+3345
+// aAreaSize.Height
+4002
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;4002;3345;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+4
+// static_cast<sal_Int32>(aAreaFillColor)
+10079487
+/// Series 3
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+2334
+// aAreaSize.Height
+5013
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;5013;2334;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+3
+// static_cast<sal_Int32>(aAreaFillColor)
+16777215
diff --git a/chart2/qa/extras/chart2dump/reference/areacharttest/percent_stacked_area_chart.txt b/chart2/qa/extras/chart2dump/reference/areacharttest/percent_stacked_area_chart.txt
new file mode 100644
index 0000000000..b8769b7ad3
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/areacharttest/percent_stacked_area_chart.txt
@@ -0,0 +1,62 @@
+// nSeriesCount
+4
+/// Series 0
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+5080
+// aAreaSize.Height
+2267
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;2267;5080;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+1
+// static_cast<sal_Int32>(aAreaFillColor)
+16711680
+/// Series 1
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+3458
+// aAreaSize.Height
+2693
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;2693;3458;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+2
+// static_cast<sal_Int32>(aAreaFillColor)
+10079487
+/// Series 2
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+2634
+// aAreaSize.Height
+2049
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;2049;2634;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+4
+// static_cast<sal_Int32>(aAreaFillColor)
+10079487
+/// Series 3
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+1344
+// aAreaSize.Height
+2157
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;2157;1344;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+3
+// static_cast<sal_Int32>(aAreaFillColor)
+16777215
diff --git a/chart2/qa/extras/chart2dump/reference/areacharttest/stacked_area_chart.txt b/chart2/qa/extras/chart2dump/reference/areacharttest/stacked_area_chart.txt
new file mode 100644
index 0000000000..00934b44bf
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/areacharttest/stacked_area_chart.txt
@@ -0,0 +1,62 @@
+// nSeriesCount
+4
+/// Series 0
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+5958
+// aAreaSize.Height
+1389
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;1389;5958;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+1
+// static_cast<sal_Int32>(aAreaFillColor)
+16711680
+/// Series 1
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+4882
+// aAreaSize.Height
+1710
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;1710;4882;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+2
+// static_cast<sal_Int32>(aAreaFillColor)
+10079487
+/// Series 2
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+3510
+// aAreaSize.Height
+2542
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;2542;3510;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+4
+// static_cast<sal_Int32>(aAreaFillColor)
+10079487
+/// Series 3
+// aAreaPosition.X
+5507
+// aAreaPosition.Y
+1792
+// aAreaSize.Height
+3985
+// aAreaSize.Width
+11328
+// aAreaTransformation
+11328;0;5507;0;3985;1792;0;0;1
+// static_cast<sal_Int32>(aAreaFillStyle)
+3
+// static_cast<sal_Int32>(aAreaFillColor)
+16777215
diff --git a/chart2/qa/extras/chart2dump/reference/axisgeometrytest/axis_special_positioning.txt b/chart2/qa/extras/chart2dump/reference/axisgeometrytest/axis_special_positioning.txt
new file mode 100644
index 0000000000..e34ef3c104
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/axisgeometrytest/axis_special_positioning.txt
@@ -0,0 +1,38 @@
+/// CID/D=0:CS=0:Axis=0,0
+// aAxisPosition.X
+5112
+// aAxisPosition.Y
+1990
+// aAxisSize.Height
+300
+// aAxisSize.Width
+17133
+// aAxisTransformation
+17134;0;5112;0;301;1990;0;0;1
+// nAxisGeometriesCount
+2
+// sAxisLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aAxisLineColor)
+0
+// nAxisLineWidth
+0
+/// CID/D=0:CS=0:Axis=1,0
+// aAxisPosition.X
+22245
+// aAxisPosition.Y
+2140
+// aAxisSize.Height
+8005
+// aAxisSize.Width
+150
+// aAxisTransformation
+151;0;22245;0;8006;2140;0;0;1
+// nAxisGeometriesCount
+3
+// sAxisLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aAxisLineColor)
+0
+// nAxisLineWidth
+0
diff --git a/chart2/qa/extras/chart2dump/reference/axisgeometrytest/default_formated_axis.txt b/chart2/qa/extras/chart2dump/reference/axisgeometrytest/default_formated_axis.txt
new file mode 100644
index 0000000000..46eec6d766
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/axisgeometrytest/default_formated_axis.txt
@@ -0,0 +1,38 @@
+/// CID/D=0:CS=0:Axis=0,0
+// aAxisPosition.X
+5393
+// aAxisPosition.Y
+11883
+// aAxisSize.Height
+150
+// aAxisSize.Width
+17455
+// aAxisTransformation
+17456;0;5393;0;151;11883;0;0;1
+// nAxisGeometriesCount
+2
+// sAxisLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aAxisLineColor)
+0
+// nAxisLineWidth
+0
+/// CID/D=0:CS=0:Axis=1,0
+// aAxisPosition.X
+5243
+// aAxisPosition.Y
+2507
+// aAxisSize.Height
+9376
+// aAxisSize.Width
+150
+// aAxisTransformation
+151;0;5243;0;9377;2507;0;0;1
+// nAxisGeometriesCount
+2
+// sAxisLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aAxisLineColor)
+0
+// nAxisLineWidth
+0
diff --git a/chart2/qa/extras/chart2dump/reference/axisgeometrytest/formated_axis_lines.txt b/chart2/qa/extras/chart2dump/reference/axisgeometrytest/formated_axis_lines.txt
new file mode 100644
index 0000000000..980e2592da
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/axisgeometrytest/formated_axis_lines.txt
@@ -0,0 +1,38 @@
+/// CID/D=0:CS=0:Axis=0,0
+// aAxisPosition.X
+3852
+// aAxisPosition.Y
+9713
+// aAxisSize.Height
+150
+// aAxisSize.Width
+15854
+// aAxisTransformation
+15855;0;3852;0;151;9713;0;0;1
+// nAxisGeometriesCount
+2
+// sAxisLineDash
+0;1;00;0;457
+// static_cast<sal_Int32>(aAxisLineColor)
+16711680
+// nAxisLineWidth
+100
+/// CID/D=0:CS=0:Axis=1,0
+// aAxisPosition.X
+3702
+// aAxisPosition.Y
+2051
+// aAxisSize.Height
+7662
+// aAxisSize.Width
+150
+// aAxisTransformation
+151;0;3702;0;7663;2051;0;0;1
+// nAxisGeometriesCount
+2
+// sAxisLineDash
+0;1;511;51;51
+// static_cast<sal_Int32>(aAxisLineColor)
+65280
+// nAxisLineWidth
+100
diff --git a/chart2/qa/extras/chart2dump/reference/axisgeometrytest/rotated_axis_labels.txt b/chart2/qa/extras/chart2dump/reference/axisgeometrytest/rotated_axis_labels.txt
new file mode 100644
index 0000000000..151ab21acb
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/axisgeometrytest/rotated_axis_labels.txt
@@ -0,0 +1,38 @@
+/// CID/D=0:CS=0:Axis=0,0
+// aAxisPosition.X
+3798
+// aAxisPosition.Y
+9860
+// aAxisSize.Height
+150
+// aAxisSize.Width
+16412
+// aAxisTransformation
+16413;0;3798;0;151;9860;0;0;1
+// nAxisGeometriesCount
+2
+// sAxisLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aAxisLineColor)
+0
+// nAxisLineWidth
+0
+/// CID/D=0:CS=0:Axis=1,0
+// aAxisPosition.X
+3648
+// aAxisPosition.Y
+2082
+// aAxisSize.Height
+7778
+// aAxisSize.Width
+150
+// aAxisTransformation
+151;0;3648;0;7779;2082;0;0;1
+// nAxisGeometriesCount
+2
+// sAxisLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aAxisLineColor)
+0
+// nAxisLineWidth
+0
diff --git a/chart2/qa/extras/chart2dump/reference/axislabeltest/date-categories.txt b/chart2/qa/extras/chart2dump/reference/axislabeltest/date-categories.txt
new file mode 100644
index 0000000000..a9274fd783
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/axislabeltest/date-categories.txt
@@ -0,0 +1,180 @@
+/// CID/D=0:CS=0:Axis=0,0
+// nAxisLabelsCount
+22
+// xLabel->getString()
+15/Jun/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+17/Jun/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+19/Jun/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+21/Jun/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+23/Jun/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+25/Jun/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+27/Jun/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+29/Jun/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+1/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+3/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+5/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+7/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+9/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+11/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+13/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+15/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+17/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+19/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+21/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+23/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+25/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+27/Jul/21
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+/// CID/D=0:CS=0:Axis=1,0
+// nAxisLabelsCount
+7
+// xLabel->getString()
+0
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+20
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+40
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+60
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+80
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+100
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
+// xLabel->getString()
+120
+// static_cast<sal_Int32>(aLabelFontColor)
+5855577
+// fLabelFontHeight
+9
diff --git a/chart2/qa/extras/chart2dump/reference/axislabeltest/default_formated_axis.txt b/chart2/qa/extras/chart2dump/reference/axislabeltest/default_formated_axis.txt
new file mode 100644
index 0000000000..51c1e37d63
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/axislabeltest/default_formated_axis.txt
@@ -0,0 +1,96 @@
+/// CID/D=0:CS=0:Axis=0,0
+// nAxisLabelsCount
+4
+// xLabel->getString()
+1. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+2. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+3. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+4. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+/// CID/D=0:CS=0:Axis=1,0
+// nAxisLabelsCount
+11
+// xLabel->getString()
+- Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+2000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+4000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+6000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+8000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+10000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+12000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+14000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+16000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+18000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+20000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
diff --git a/chart2/qa/extras/chart2dump/reference/axislabeltest/formated_axis_labels.txt b/chart2/qa/extras/chart2dump/reference/axislabeltest/formated_axis_labels.txt
new file mode 100644
index 0000000000..ffc0877e49
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/axislabeltest/formated_axis_labels.txt
@@ -0,0 +1,96 @@
+/// CID/D=0:CS=0:Axis=0,0
+// nAxisLabelsCount
+4
+// xLabel->getString()
+1. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+8388352
+// fLabelFontHeight
+12
+// xLabel->getString()
+2. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+8388352
+// fLabelFontHeight
+12
+// xLabel->getString()
+2. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+8388352
+// fLabelFontHeight
+12
+// xLabel->getString()
+2. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+8388352
+// fLabelFontHeight
+12
+/// CID/D=0:CS=0:Axis=1,0
+// nAxisLabelsCount
+11
+// xLabel->getString()
+- Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
+// xLabel->getString()
+2000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
+// xLabel->getString()
+4000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
+// xLabel->getString()
+6000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
+// xLabel->getString()
+8000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
+// xLabel->getString()
+10000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
+// xLabel->getString()
+12000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
+// xLabel->getString()
+14000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
+// xLabel->getString()
+16000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
+// xLabel->getString()
+18000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
+// xLabel->getString()
+20000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+16711935
+// fLabelFontHeight
+14
diff --git a/chart2/qa/extras/chart2dump/reference/axislabeltest/percent_stacked_column_chart.txt b/chart2/qa/extras/chart2dump/reference/axislabeltest/percent_stacked_column_chart.txt
new file mode 100644
index 0000000000..304f9abf03
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/axislabeltest/percent_stacked_column_chart.txt
@@ -0,0 +1,96 @@
+/// CID/D=0:CS=0:Axis=0,0
+// nAxisLabelsCount
+4
+// xLabel->getString()
+Inkjet
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Leser
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Multifunction
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Picture
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+/// CID/D=0:CS=0:Axis=1,0
+// nAxisLabelsCount
+11
+// xLabel->getString()
+0,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+10,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+20,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+30,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+40,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+50,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+60,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+70,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+80,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+90,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+100,00%
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
diff --git a/chart2/qa/extras/chart2dump/reference/axislabeltest/rotated_axis_labels.txt b/chart2/qa/extras/chart2dump/reference/axislabeltest/rotated_axis_labels.txt
new file mode 100644
index 0000000000..52aceba87b
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/axislabeltest/rotated_axis_labels.txt
@@ -0,0 +1,60 @@
+/// CID/D=0:CS=0:Axis=0,0
+// nAxisLabelsCount
+4
+// xLabel->getString()
+1. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+2. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+3. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+4. quarter
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+/// CID/D=0:CS=0:Axis=1,0
+// nAxisLabelsCount
+5
+// xLabel->getString()
+- Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+5000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+10000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+15000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+20000000 Ft
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
diff --git a/chart2/qa/extras/chart2dump/reference/axislabeltest/tdf118150.txt b/chart2/qa/extras/chart2dump/reference/axislabeltest/tdf118150.txt
new file mode 100644
index 0000000000..fabf4acac6
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/axislabeltest/tdf118150.txt
@@ -0,0 +1,216 @@
+/// CID/D=0:CS=0:Axis=0,0
+// nAxisLabelsCount
+28
+// xLabel->getString()
+Sep 2013
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Oct 2013
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Nov 2013
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Dec 2013
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Jan 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Feb 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Mar 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Apr 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+May 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Jun 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Jul 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Aug 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Sep 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Oct 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Nov 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Dec 2014
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Jan 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Feb 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Mar 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Apr 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+May 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Jun 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Jul 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Aug 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Sep 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Oct 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Nov 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+Dec 2015
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+/// CID/D=0:CS=0:Axis=1,0
+// nAxisLabelsCount
+7
+// xLabel->getString()
+0.00
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+2.00
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+4.00
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+6.00
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+8.00
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+10.00
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
+// xLabel->getString()
+12.00
+// static_cast<sal_Int32>(aLabelFontColor)
+0
+// fLabelFontHeight
+10
diff --git a/chart2/qa/extras/chart2dump/reference/chartdatatest/multiple_categories.txt b/chart2/qa/extras/chart2dump/reference/chartdatatest/multiple_categories.txt
new file mode 100644
index 0000000000..1d0e3ea39d
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/chartdatatest/multiple_categories.txt
@@ -0,0 +1,70 @@
+// sChartTitle
+Chart Title
+// sChartType
+com.sun.star.chart2.LineChartType
+// nXAxisNumberFormat
+0
+// nXAxisNumberType
+16
+// nYAxisNumberFormat
+0
+// nYAxisNumberType
+16
+// aColumnLabels.getLength()
+8
+// sColumnLabels
+A In0;A In100;A In200;A In400;B In0;B In100;B In200;B In400;
+// aRowLabels.getLength()
+49
+// sRowLabels
+M 14;M 15;M 99;M 22;M 17;M 25;M 28;M 25;M 26;M 24;M 25;M 22;M 33;M 22;M 25;M 32;M 19;M 14;M 18;F 22;F 16;F 26;F 18;F 48;F 19;F 24;F 22;F 25;F 28;F 23;F 25;F 29;F 24;F 27;F 24;F 27;F 27;F 31;F 17;F 50;F 17;F 16;F 17;F 15;F 17;F 17;F 17;F 17;F 18;
+// aDataSeriesYValues.size()
+8
+// aYValuesOfSeries.size()
+49
+// sYValuesOfSeries
+0.533;0.413;0.55;0.273;0.45;0.423;0.54;0.433;0.417;0.513;0.563;0.503;0.54;0.737;0.563;0.36;0.443;1.007;1.21;0.51;0.443;0.41;0.637;1.15;0.777;0.58;0.587;0.713;0.477;0.533;0.55;0.443;0.197;0.48;0.497;0.513;0.607;0.573;0.54;0.283;0.257;0.43;0.223;0.377;0.38;0.573;1.843;0.427;0.523;
+// aYValuesOfSeries.size()
+49
+// sYValuesOfSeries
+0.8;0.287;0.457;0.143;0.61;0.373;0.47;0.397;0.413;0.337;0.347;0.447;0.467;0.587;0.533;0.34;0.647;0.647;0.823;0.77;0.743;0.607;0.523;0.7;1.053;0.407;0.577;0.533;0.54;0.347;0.633;0.56;0.397;0.423;0.393;0.707;0.703;0.65;0.487;0.437;0.937;0.547;0.357;0.61;0.597;0.517;0.503;0.333;0.84;
+// aYValuesOfSeries.size()
+49
+// sYValuesOfSeries
+0.38;0.547;0.35;0.46;0.607;0.44;0.68;0.47;0.43;0.363;0.46;0.533;0.44;0.2;0.627;0.307;0.27;0.5;0.66;0.403;0.413;0.61;0.58;0.973;0.903;0.57;0.563;0.617;0.463;0.537;0.497;0.42;0.253;0.49;0.43;0.577;1.07;0.583;0.427;0.297;0.397;0.503;0.717;0.507;0.513;0.743;0.693;0.44;0.737;
+// aYValuesOfSeries.size()
+49
+// sYValuesOfSeries
+0.467;0.467;0.463;0.367;0.457;0.443;0.63;0.48;0.38;0.577;0.477;0.443;0.47;0.557;0.45;0.46;0.283;0.523;0.527;0.537;0.34;0.32;0.51;1.12;0.897;0.437;0.673;0.637;0.463;0.613;0.72;0.443;0.25;0.497;0.393;0.503;0.617;0.87;0.383;0.383;0.39;0.467;0.373;0.523;0.553;0.353;0.37;0.493;0.52;
+// aYValuesOfSeries.size()
+49
+// sYValuesOfSeries
+1.533;1.413;1.55;1.273;1.45;1.423;1.54;1.433;1.417;1.513;1.563;1.503;1.54;1.737;1.563;1.36;1.443;2.007;2.21;1.51;1.443;1.41;1.637;2.15;1.777;1.58;1.587;1.713;1.477;1.533;1.55;1.443;1.197;1.48;1.497;1.513;1.607;1.573;1.54;1.283;1.257;1.43;1.223;1.377;1.38;1.573;2.843;1.427;1.523;
+// aYValuesOfSeries.size()
+49
+// sYValuesOfSeries
+0.7;0.187;0.357;0.043;0.51;0.273;0.37;0.297;0.313;0.237;0.247;0.347;0.367;0.487;0.433;0.24;0.547;0.547;0.723;0.67;0.643;0.507;0.423;0.6;0.953;0.307;0.477;0.433;0.44;0.247;0.533;0.46;0.297;0.323;0.293;0.607;0.603;0.55;0.387;0.337;0.837;0.447;0.257;0.51;0.497;0.417;0.403;0.233;0.74;
+// aYValuesOfSeries.size()
+49
+// sYValuesOfSeries
+0.19;0.2735;0.175;0.23;0.3035;0.22;0.34;0.235;0.215;0.1815;0.23;0.2665;0.22;0.1;0.3135;0.1535;0.135;0.25;0.33;0.2015;0.2065;0.305;0.29;0.4865;0.4515;0.285;0.2815;0.3085;0.2315;0.2685;0.2485;0.21;0.1265;0.245;0.215;0.2885;0.535;0.2915;0.2135;0.1485;0.1985;0.2515;0.3585;0.2535;0.2565;0.3715;0.3465;0.22;0.3685;
+// aYValuesOfSeries.size()
+49
+// sYValuesOfSeries
+0.0667142857142857;0.0667142857142857;0.0661428571428571;0.0524285714285714;0.0652857142857143;0.0632857142857143;0.09;0.0685714285714286;0.0542857142857143;0.0824285714285714;0.0681428571428571;0.0632857142857143;0.0671428571428571;0.0795714285714286;0.0642857142857143;0.0657142857142857;0.0404285714285714;0.0747142857142857;0.0752857142857143;0.0767142857142857;0.0485714285714286;0.0457142857142857;0.0728571428571429;0.16;0.128142857142857;0.0624285714285714;0.0961428571428572;0.091;0.0661428571428571;0.0875714285714286;0.102857142857143;0.0632857142857143;0.0357142857142857;0.071;0.0561428571428572;0.0718571428571429;0.0881428571428572;0.124285714285714;0.0547142857142857;0.0547142857142857;0.0557142857142857;0.0667142857142857;0.0532857142857143;0.0747142857142857;0.079;0.0504285714285714;0.0528571428571429;0.0704285714285714;0.0742857142857143;
+// aYValuesSourceRange
+$Table.$E$3:$E$51
+// aYValuesSourceRange
+$Table.$F$3:$F$51
+// aYValuesSourceRange
+$Table.$G$3:$G$51
+// aYValuesSourceRange
+$Table.$H$3:$H$51
+// aYValuesSourceRange
+$Table.$I$3:$I$51
+// aYValuesSourceRange
+$Table.$J$3:$J$51
+// aYValuesSourceRange
+$Table.$K$3:$K$51
+// aYValuesSourceRange
+$Table.$L$3:$L$51
diff --git a/chart2/qa/extras/chart2dump/reference/chartdatatest/simple_chart.txt b/chart2/qa/extras/chart2dump/reference/chartdatatest/simple_chart.txt
new file mode 100644
index 0000000000..ec3bfa72e3
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/chartdatatest/simple_chart.txt
@@ -0,0 +1,50 @@
+// sChartTitle
+Annual Revenue
+// sChartType
+com.sun.star.chart2.ColumnChartType
+// sXAxisTitle
+Quarter
+// nXAxisNumberFormat
+0
+// nXAxisNumberType
+16
+// sYAxisTitle
+Income (Ft)
+// nYAxisNumberFormat
+159
+// nYAxisNumberType
+17
+// aColumnLabels.getLength()
+4
+// sColumnLabels
+1. quarter;2. quarter;3. quarter;4. quarter;
+// aRowLabels.getLength()
+4
+// sRowLabels
+Inkjet;Leser;Multifunction;Picture;
+// aDataSeriesYValues.size()
+4
+// aYValuesOfSeries.size()
+4
+// sYValuesOfSeries
+4399120;8098380;4799040;6448710;
+// aYValuesOfSeries.size()
+4
+// sYValuesOfSeries
+3149650;4499500;5399400;7919120;
+// aYValuesOfSeries.size()
+4
+// sYValuesOfSeries
+1599800;4399450;3199600;7999000;
+// aYValuesOfSeries.size()
+4
+// sYValuesOfSeries
+2504850;5009700;7514550;10019400;
+// aYValuesSourceRange
+$Mo_példa_06_a.$E$11:$H$11
+// aYValuesSourceRange
+$Mo_példa_06_a.$E$12:$H$12
+// aYValuesSourceRange
+$Mo_példa_06_a.$E$13:$H$13
+// aYValuesSourceRange
+$Mo_példa_06_a.$E$14:$H$14
diff --git a/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_with_titles.txt b/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_with_titles.txt
new file mode 100644
index 0000000000..83e9596f26
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_with_titles.txt
@@ -0,0 +1,10 @@
+// static_cast<sal_Int32>(aChartWallFillStyle)
+2
+// static_cast<sal_Int32>(aChartWallFillColor)
+15132390
+// sChartWallLineDash
+0;1;200710;0;152
+// static_cast<sal_Int32>(aChartWallLineColor)
+11010131
+// nChartWallLineWidth
+100
diff --git a/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_without_titles.txt b/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_without_titles.txt
new file mode 100644
index 0000000000..83e9596f26
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_auto_adjust_without_titles.txt
@@ -0,0 +1,10 @@
+// static_cast<sal_Int32>(aChartWallFillStyle)
+2
+// static_cast<sal_Int32>(aChartWallFillColor)
+15132390
+// sChartWallLineDash
+0;1;200710;0;152
+// static_cast<sal_Int32>(aChartWallLineColor)
+11010131
+// nChartWallLineWidth
+100
diff --git a/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_custom_positioning.txt b/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_custom_positioning.txt
new file mode 100644
index 0000000000..f689425eca
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/chartwalltest/chartwall_custom_positioning.txt
@@ -0,0 +1,10 @@
+// static_cast<sal_Int32>(aChartWallFillStyle)
+1
+// static_cast<sal_Int32>(aChartWallFillColor)
+13773611
+// sChartWallLineDash
+0;2;01;203;203
+// static_cast<sal_Int32>(aChartWallLineColor)
+8388352
+// nChartWallLineWidth
+110
diff --git a/chart2/qa/extras/chart2dump/reference/chartwalltest/formated_chartwall.txt b/chart2/qa/extras/chart2dump/reference/chartwalltest/formated_chartwall.txt
new file mode 100644
index 0000000000..83e9596f26
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/chartwalltest/formated_chartwall.txt
@@ -0,0 +1,10 @@
+// static_cast<sal_Int32>(aChartWallFillStyle)
+2
+// static_cast<sal_Int32>(aChartWallFillColor)
+15132390
+// sChartWallLineDash
+0;1;200710;0;152
+// static_cast<sal_Int32>(aChartWallLineColor)
+11010131
+// nChartWallLineWidth
+100
diff --git a/chart2/qa/extras/chart2dump/reference/columnbarcharttest/column_chart_small_spacing.txt b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/column_chart_small_spacing.txt
new file mode 100644
index 0000000000..f9ec3b65a2
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/column_chart_small_spacing.txt
@@ -0,0 +1,162 @@
+// nSeriesCount
+4
+/// Series 0 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+1
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aColumnOrBarPosition.X
+3698
+// aColumnOrBarPosition.Y
+4414
+// aColumnOrBarSize.Height
+2935
+// aColumnOrBarSize.Width
+1170
+// aColumnOrBarTransformation
+1170;0;3698;0;2935;4414;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aColumnOrBarPosition.X
+8610
+// aColumnOrBarPosition.Y
+1946
+// aColumnOrBarSize.Height
+5403
+// aColumnOrBarSize.Width
+1170
+// aColumnOrBarTransformation
+1170;0;8610;0;5403;1946;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aColumnOrBarPosition.X
+13522
+// aColumnOrBarPosition.Y
+4147
+// aColumnOrBarSize.Height
+3202
+// aColumnOrBarSize.Width
+1169
+// aColumnOrBarTransformation
+1169;0;13522;0;3202;4147;0;0;1
+/// Series 1 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aColumnOrBarPosition.X
+4868
+// aColumnOrBarPosition.Y
+5247
+// aColumnOrBarSize.Height
+2102
+// aColumnOrBarSize.Width
+1169
+// aColumnOrBarTransformation
+1169;0;4868;0;2102;5247;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aColumnOrBarPosition.X
+9780
+// aColumnOrBarPosition.Y
+4347
+// aColumnOrBarSize.Height
+3002
+// aColumnOrBarSize.Width
+1169
+// aColumnOrBarTransformation
+1169;0;9780;0;3002;4347;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aColumnOrBarPosition.X
+14691
+// aColumnOrBarPosition.Y
+3747
+// aColumnOrBarSize.Height
+3602
+// aColumnOrBarSize.Width
+1170
+// aColumnOrBarTransformation
+1170;0;14691;0;3602;3747;0;0;1
+/// Series 2 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aColumnOrBarPosition.X
+6037
+// aColumnOrBarPosition.Y
+6281
+// aColumnOrBarSize.Height
+1068
+// aColumnOrBarSize.Width
+1170
+// aColumnOrBarTransformation
+1170;0;6037;0;1068;6281;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aColumnOrBarPosition.X
+10949
+// aColumnOrBarPosition.Y
+4414
+// aColumnOrBarSize.Height
+2935
+// aColumnOrBarSize.Width
+1169
+// aColumnOrBarTransformation
+1169;0;10949;0;2935;4414;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aColumnOrBarPosition.X
+15861
+// aColumnOrBarPosition.Y
+5214
+// aColumnOrBarSize.Height
+2135
+// aColumnOrBarSize.Width
+1169
+// aColumnOrBarTransformation
+1169;0;15861;0;2135;5214;0;0;1
+/// Series 3 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+2
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aColumnOrBarPosition.X
+7207
+// aColumnOrBarPosition.Y
+5677
+// aColumnOrBarSize.Height
+1672
+// aColumnOrBarSize.Width
+1169
+// aColumnOrBarTransformation
+1169;0;7207;0;1672;5677;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aColumnOrBarPosition.X
+12118
+// aColumnOrBarPosition.Y
+4006
+// aColumnOrBarSize.Height
+3343
+// aColumnOrBarSize.Width
+1170
+// aColumnOrBarTransformation
+1170;0;12118;0;3343;4006;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aColumnOrBarPosition.X
+17030
+// aColumnOrBarPosition.Y
+2335
+// aColumnOrBarSize.Height
+5014
+// aColumnOrBarSize.Width
+1170
+// aColumnOrBarTransformation
+1170;0;17030;0;5014;2335;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/columnbarcharttest/normal_bar_chart.txt b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/normal_bar_chart.txt
new file mode 100644
index 0000000000..47a0a9b0ac
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/normal_bar_chart.txt
@@ -0,0 +1,162 @@
+// nSeriesCount
+4
+/// Series 0 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+1
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+6712
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+6482
+// aColumnOrBarTransformation
+6482;0;3582;0;364;6712;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+4710
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+11932
+// aColumnOrBarTransformation
+11932;0;3582;0;364;4710;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+2709
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+7071
+// aColumnOrBarTransformation
+7071;0;3582;0;364;2709;0;0;1
+/// Series 1 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+6348
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+4641
+// aColumnOrBarTransformation
+4641;0;3582;0;364;6348;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+4347
+// aColumnOrBarSize.Height
+363
+// aColumnOrBarSize.Width
+6630
+// aColumnOrBarTransformation
+6630;0;3582;0;363;4347;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+2345
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+7956
+// aColumnOrBarTransformation
+7956;0;3582;0;364;2345;0;0;1
+/// Series 2 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+5984
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+2357
+// aColumnOrBarTransformation
+2357;0;3582;0;364;5984;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+3983
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+6482
+// aColumnOrBarTransformation
+6482;0;3582;0;364;3983;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+1981
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+4714
+// aColumnOrBarTransformation
+4714;0;3582;0;364;1981;0;0;1
+/// Series 3 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+5620
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+3690
+// aColumnOrBarTransformation
+3690;0;3582;0;364;5620;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+3619
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+7381
+// aColumnOrBarTransformation
+7381;0;3582;0;364;3619;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+1617
+// aColumnOrBarSize.Height
+364
+// aColumnOrBarSize.Width
+11072
+// aColumnOrBarTransformation
+11072;0;3582;0;364;1617;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/columnbarcharttest/normal_column_chart.txt b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/normal_column_chart.txt
new file mode 100644
index 0000000000..d3a9646798
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/normal_column_chart.txt
@@ -0,0 +1,162 @@
+// nSeriesCount
+4
+/// Series 0 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+1
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aColumnOrBarPosition.X
+4359
+// aColumnOrBarPosition.Y
+4414
+// aColumnOrBarSize.Height
+2935
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;4359;0;2935;4414;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aColumnOrBarPosition.X
+9396
+// aColumnOrBarPosition.Y
+1946
+// aColumnOrBarSize.Height
+5403
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;9396;0;5403;1946;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aColumnOrBarPosition.X
+14433
+// aColumnOrBarPosition.Y
+4147
+// aColumnOrBarSize.Height
+3202
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;14433;0;3202;4147;0;0;1
+/// Series 1 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aColumnOrBarPosition.X
+5275
+// aColumnOrBarPosition.Y
+5247
+// aColumnOrBarSize.Height
+2102
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;5275;0;2102;5247;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aColumnOrBarPosition.X
+10312
+// aColumnOrBarPosition.Y
+4347
+// aColumnOrBarSize.Height
+3002
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;10312;0;3002;4347;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aColumnOrBarPosition.X
+15349
+// aColumnOrBarPosition.Y
+3747
+// aColumnOrBarSize.Height
+3602
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;15349;0;3602;3747;0;0;1
+/// Series 2 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aColumnOrBarPosition.X
+6191
+// aColumnOrBarPosition.Y
+6281
+// aColumnOrBarSize.Height
+1068
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;6191;0;1068;6281;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aColumnOrBarPosition.X
+11228
+// aColumnOrBarPosition.Y
+4414
+// aColumnOrBarSize.Height
+2935
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;11228;0;2935;4414;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aColumnOrBarPosition.X
+16265
+// aColumnOrBarPosition.Y
+5214
+// aColumnOrBarSize.Height
+2135
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;16265;0;2135;5214;0;0;1
+/// Series 3 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aColumnOrBarPosition.X
+7107
+// aColumnOrBarPosition.Y
+5677
+// aColumnOrBarSize.Height
+1672
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;7107;0;1672;5677;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aColumnOrBarPosition.X
+12144
+// aColumnOrBarPosition.Y
+4006
+// aColumnOrBarSize.Height
+3343
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;12144;0;3343;4006;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aColumnOrBarPosition.X
+17181
+// aColumnOrBarPosition.Y
+2335
+// aColumnOrBarSize.Height
+5014
+// aColumnOrBarSize.Width
+916
+// aColumnOrBarTransformation
+916;0;17181;0;5014;2335;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/columnbarcharttest/percent_stacked_bar_chart.txt b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/percent_stacked_bar_chart.txt
new file mode 100644
index 0000000000..1d53a339e4
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/percent_stacked_bar_chart.txt
@@ -0,0 +1,162 @@
+// nSeriesCount
+4
+/// Series 0 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+1
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+5681
+// aColumnOrBarSize.Height
+1334
+// aColumnOrBarSize.Width
+5562
+// aColumnOrBarTransformation
+5562;0;3582;0;1334;5681;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+3679
+// aColumnOrBarSize.Height
+1335
+// aColumnOrBarSize.Width
+5422
+// aColumnOrBarTransformation
+5422;0;3582;0;1335;3679;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+1678
+// aColumnOrBarSize.Height
+1334
+// aColumnOrBarSize.Width
+3381
+// aColumnOrBarTransformation
+3381;0;3582;0;1334;1678;0;0;1
+/// Series 1 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aColumnOrBarPosition.X
+9144
+// aColumnOrBarPosition.Y
+5681
+// aColumnOrBarSize.Height
+1334
+// aColumnOrBarSize.Width
+3982
+// aColumnOrBarTransformation
+3982;0;9144;0;1334;5681;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aColumnOrBarPosition.X
+9004
+// aColumnOrBarPosition.Y
+3679
+// aColumnOrBarSize.Height
+1335
+// aColumnOrBarSize.Width
+3013
+// aColumnOrBarTransformation
+3013;0;9004;0;1335;3679;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aColumnOrBarPosition.X
+6963
+// aColumnOrBarPosition.Y
+1678
+// aColumnOrBarSize.Height
+1334
+// aColumnOrBarSize.Width
+3804
+// aColumnOrBarTransformation
+3804;0;6963;0;1334;1678;0;0;1
+/// Series 2 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+1
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+255
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aColumnOrBarPosition.X
+13126
+// aColumnOrBarPosition.Y
+5681
+// aColumnOrBarSize.Height
+1334
+// aColumnOrBarSize.Width
+2023
+// aColumnOrBarTransformation
+2023;0;13126;0;1334;5681;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aColumnOrBarPosition.X
+12017
+// aColumnOrBarPosition.Y
+3679
+// aColumnOrBarSize.Height
+1335
+// aColumnOrBarSize.Width
+2945
+// aColumnOrBarTransformation
+2945;0;12017;0;1335;3679;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aColumnOrBarPosition.X
+10767
+// aColumnOrBarPosition.Y
+1678
+// aColumnOrBarSize.Height
+1334
+// aColumnOrBarSize.Width
+2255
+// aColumnOrBarTransformation
+2255;0;10767;0;1334;1678;0;0;1
+/// Series 3 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aColumnOrBarPosition.X
+15149
+// aColumnOrBarPosition.Y
+5681
+// aColumnOrBarSize.Height
+1334
+// aColumnOrBarSize.Width
+3168
+// aColumnOrBarTransformation
+3168;0;15149;0;1334;5681;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aColumnOrBarPosition.X
+14962
+// aColumnOrBarPosition.Y
+3679
+// aColumnOrBarSize.Height
+1335
+// aColumnOrBarSize.Width
+3355
+// aColumnOrBarTransformation
+3355;0;14962;0;1335;3679;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aColumnOrBarPosition.X
+13022
+// aColumnOrBarPosition.Y
+1678
+// aColumnOrBarSize.Height
+1334
+// aColumnOrBarSize.Width
+5295
+// aColumnOrBarTransformation
+5295;0;13022;0;1334;1678;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/columnbarcharttest/percent_stacked_column_chart.txt b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/percent_stacked_column_chart.txt
new file mode 100644
index 0000000000..75ee404178
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/percent_stacked_column_chart.txt
@@ -0,0 +1,162 @@
+// nSeriesCount
+4
+/// Series 0 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+1
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aColumnOrBarPosition.X
+5055
+// aColumnOrBarPosition.Y
+5082
+// aColumnOrBarSize.Height
+2267
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;5055;0;2267;5082;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aColumnOrBarPosition.X
+9967
+// aColumnOrBarPosition.Y
+5139
+// aColumnOrBarSize.Height
+2210
+// aColumnOrBarSize.Width
+1964
+// aColumnOrBarTransformation
+1964;0;9967;0;2210;5139;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aColumnOrBarPosition.X
+14878
+// aColumnOrBarPosition.Y
+5971
+// aColumnOrBarSize.Height
+1378
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;14878;0;1378;5971;0;0;1
+/// Series 1 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aColumnOrBarPosition.X
+5055
+// aColumnOrBarPosition.Y
+3459
+// aColumnOrBarSize.Height
+1623
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;5055;0;1623;3459;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aColumnOrBarPosition.X
+9967
+// aColumnOrBarPosition.Y
+3912
+// aColumnOrBarSize.Height
+1227
+// aColumnOrBarSize.Width
+1964
+// aColumnOrBarTransformation
+1964;0;9967;0;1227;3912;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aColumnOrBarPosition.X
+14878
+// aColumnOrBarPosition.Y
+4421
+// aColumnOrBarSize.Height
+1550
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;14878;0;1550;4421;0;0;1
+/// Series 2 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aColumnOrBarPosition.X
+5055
+// aColumnOrBarPosition.Y
+2635
+// aColumnOrBarSize.Height
+824
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;5055;0;824;2635;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aColumnOrBarPosition.X
+9967
+// aColumnOrBarPosition.Y
+2711
+// aColumnOrBarSize.Height
+1201
+// aColumnOrBarSize.Width
+1964
+// aColumnOrBarTransformation
+1964;0;9967;0;1201;2711;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aColumnOrBarPosition.X
+14878
+// aColumnOrBarPosition.Y
+3502
+// aColumnOrBarSize.Height
+919
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;14878;0;919;3502;0;0;1
+/// Series 3 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+2
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aColumnOrBarPosition.X
+5055
+// aColumnOrBarPosition.Y
+1345
+// aColumnOrBarSize.Height
+1290
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;5055;0;1290;1345;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aColumnOrBarPosition.X
+9967
+// aColumnOrBarPosition.Y
+1345
+// aColumnOrBarSize.Height
+1366
+// aColumnOrBarSize.Width
+1964
+// aColumnOrBarTransformation
+1964;0;9967;0;1366;1345;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aColumnOrBarPosition.X
+14878
+// aColumnOrBarPosition.Y
+1345
+// aColumnOrBarSize.Height
+2157
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;14878;0;2157;1345;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/columnbarcharttest/stacked_bar_chart.txt b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/stacked_bar_chart.txt
new file mode 100644
index 0000000000..f9bf6a20b1
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/stacked_bar_chart.txt
@@ -0,0 +1,162 @@
+// nSeriesCount
+4
+/// Series 0 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+1
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+5948
+// aColumnOrBarSize.Height
+800
+// aColumnOrBarSize.Width
+2592
+// aColumnOrBarTransformation
+2592;0;3582;0;800;5948;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+3946
+// aColumnOrBarSize.Height
+801
+// aColumnOrBarSize.Width
+4773
+// aColumnOrBarTransformation
+4773;0;3582;0;801;3946;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aColumnOrBarPosition.X
+3582
+// aColumnOrBarPosition.Y
+1945
+// aColumnOrBarSize.Height
+800
+// aColumnOrBarSize.Width
+2828
+// aColumnOrBarTransformation
+2828;0;3582;0;800;1945;0;0;1
+/// Series 1 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aColumnOrBarPosition.X
+6174
+// aColumnOrBarPosition.Y
+5948
+// aColumnOrBarSize.Height
+800
+// aColumnOrBarSize.Width
+1857
+// aColumnOrBarTransformation
+1857;0;6174;0;800;5948;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aColumnOrBarPosition.X
+8355
+// aColumnOrBarPosition.Y
+3946
+// aColumnOrBarSize.Height
+801
+// aColumnOrBarSize.Width
+2652
+// aColumnOrBarTransformation
+2652;0;8355;0;801;3946;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aColumnOrBarPosition.X
+6410
+// aColumnOrBarPosition.Y
+1945
+// aColumnOrBarSize.Height
+800
+// aColumnOrBarSize.Width
+3182
+// aColumnOrBarTransformation
+3182;0;6410;0;800;1945;0;0;1
+/// Series 2 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+1
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+255
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aColumnOrBarPosition.X
+8031
+// aColumnOrBarPosition.Y
+5948
+// aColumnOrBarSize.Height
+800
+// aColumnOrBarSize.Width
+943
+// aColumnOrBarTransformation
+943;0;8031;0;800;5948;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aColumnOrBarPosition.X
+11007
+// aColumnOrBarPosition.Y
+3946
+// aColumnOrBarSize.Height
+801
+// aColumnOrBarSize.Width
+2593
+// aColumnOrBarTransformation
+2593;0;11007;0;801;3946;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aColumnOrBarPosition.X
+9592
+// aColumnOrBarPosition.Y
+1945
+// aColumnOrBarSize.Height
+800
+// aColumnOrBarSize.Width
+1886
+// aColumnOrBarTransformation
+1886;0;9592;0;800;1945;0;0;1
+/// Series 3 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aColumnOrBarPosition.X
+8974
+// aColumnOrBarPosition.Y
+5948
+// aColumnOrBarSize.Height
+800
+// aColumnOrBarSize.Width
+1476
+// aColumnOrBarTransformation
+1476;0;8974;0;800;5948;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aColumnOrBarPosition.X
+13600
+// aColumnOrBarPosition.Y
+3946
+// aColumnOrBarSize.Height
+801
+// aColumnOrBarSize.Width
+2952
+// aColumnOrBarTransformation
+2952;0;13600;0;801;3946;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aColumnOrBarPosition.X
+11478
+// aColumnOrBarPosition.Y
+1945
+// aColumnOrBarSize.Height
+800
+// aColumnOrBarSize.Width
+4429
+// aColumnOrBarTransformation
+4429;0;11478;0;800;1945;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/columnbarcharttest/stacked_column_chart.txt b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/stacked_column_chart.txt
new file mode 100644
index 0000000000..dd34a49584
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/columnbarcharttest/stacked_column_chart.txt
@@ -0,0 +1,162 @@
+// nSeriesCount
+4
+/// Series 0 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+1
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aColumnOrBarPosition.X
+5055
+// aColumnOrBarPosition.Y
+6292
+// aColumnOrBarSize.Height
+1057
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;5055;0;1057;6292;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aColumnOrBarPosition.X
+9967
+// aColumnOrBarPosition.Y
+5404
+// aColumnOrBarSize.Height
+1945
+// aColumnOrBarSize.Width
+1964
+// aColumnOrBarTransformation
+1964;0;9967;0;1945;5404;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aColumnOrBarPosition.X
+14878
+// aColumnOrBarPosition.Y
+6196
+// aColumnOrBarSize.Height
+1153
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;14878;0;1153;6196;0;0;1
+/// Series 1 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aColumnOrBarPosition.X
+5055
+// aColumnOrBarPosition.Y
+5536
+// aColumnOrBarSize.Height
+756
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;5055;0;756;5536;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aColumnOrBarPosition.X
+9967
+// aColumnOrBarPosition.Y
+4323
+// aColumnOrBarSize.Height
+1081
+// aColumnOrBarSize.Width
+1964
+// aColumnOrBarTransformation
+1964;0;9967;0;1081;4323;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aColumnOrBarPosition.X
+14878
+// aColumnOrBarPosition.Y
+4899
+// aColumnOrBarSize.Height
+1297
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;14878;0;1297;4899;0;0;1
+/// Series 2 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+4
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aColumnOrBarPosition.X
+5055
+// aColumnOrBarPosition.Y
+5151
+// aColumnOrBarSize.Height
+385
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;5055;0;385;5151;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aColumnOrBarPosition.X
+9967
+// aColumnOrBarPosition.Y
+3266
+// aColumnOrBarSize.Height
+1057
+// aColumnOrBarSize.Width
+1964
+// aColumnOrBarTransformation
+1964;0;9967;0;1057;3266;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aColumnOrBarPosition.X
+14878
+// aColumnOrBarPosition.Y
+4131
+// aColumnOrBarSize.Height
+768
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;14878;0;768;4131;0;0;1
+/// Series 3 ColumnsOrBars
+// nColumnOrBarCountInSeries
+3
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)
+2
+// static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aColumnOrBarPosition.X
+5055
+// aColumnOrBarPosition.Y
+4550
+// aColumnOrBarSize.Height
+601
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;5055;0;601;4550;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aColumnOrBarPosition.X
+9967
+// aColumnOrBarPosition.Y
+2063
+// aColumnOrBarSize.Height
+1203
+// aColumnOrBarSize.Width
+1964
+// aColumnOrBarTransformation
+1964;0;9967;0;1203;2063;0;0;1
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aColumnOrBarPosition.X
+14878
+// aColumnOrBarPosition.Y
+2326
+// aColumnOrBarSize.Height
+1805
+// aColumnOrBarSize.Width
+1965
+// aColumnOrBarTransformation
+1965;0;14878;0;1805;2326;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/gridtest/formated_grid_line.txt b/chart2/qa/extras/chart2dump/reference/gridtest/formated_grid_line.txt
new file mode 100644
index 0000000000..b3d3c09875
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/gridtest/formated_grid_line.txt
@@ -0,0 +1,17 @@
+/// CID/D=0:CS=0:Axis=0,0:Grid=0
+// aGridPosition.X
+3763
+// aGridPosition.Y
+1344
+// aGridSize.Height
+6005
+// aGridSize.Width
+15480
+// aGridTransformation
+15481;0;3763;0;6006;1344;0;0;1
+// sGridLineDash
+2;1;1970;0;127
+// static_cast<sal_Int32>(aLineColor)
+65280
+// nLineWidth
+100
diff --git a/chart2/qa/extras/chart2dump/reference/gridtest/horizontal_grid.txt b/chart2/qa/extras/chart2dump/reference/gridtest/horizontal_grid.txt
new file mode 100644
index 0000000000..428a206de5
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/gridtest/horizontal_grid.txt
@@ -0,0 +1,17 @@
+/// CID/D=0:CS=0:Axis=1,0:Grid=0
+// aGridPosition.X
+3644
+// aGridPosition.Y
+1344
+// aGridSize.Height
+6005
+// aGridSize.Width
+14988
+// aGridTransformation
+14989;0;3644;0;6006;1344;0;0;1
+// sGridLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aLineColor)
+0
+// nLineWidth
+0
diff --git a/chart2/qa/extras/chart2dump/reference/gridtest/minor_grid.txt b/chart2/qa/extras/chart2dump/reference/gridtest/minor_grid.txt
new file mode 100644
index 0000000000..35f3d560e4
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/gridtest/minor_grid.txt
@@ -0,0 +1,68 @@
+/// CID/D=0:CS=0:Axis=1,0:Grid=0
+// aGridPosition.X
+3529
+// aGridPosition.Y
+1344
+// aGridSize.Height
+6005
+// aGridSize.Width
+14515
+// aGridTransformation
+14516;0;3529;0;6006;1344;0;0;1
+// sGridLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aLineColor)
+0
+// nLineWidth
+0
+/// CID/D=0:CS=0:Axis=0,0:Grid=0
+// aGridPosition.X
+3529
+// aGridPosition.Y
+1344
+// aGridSize.Height
+6005
+// aGridSize.Width
+14515
+// aGridTransformation
+14516;0;3529;0;6006;1344;0;0;1
+// sGridLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aLineColor)
+11776947
+// nLineWidth
+0
+/// CID/D=0:CS=0:Axis=1,0:Grid=0:SubGrid=0
+// aGridPosition.X
+3529
+// aGridPosition.Y
+1773
+// aGridSize.Height
+5147
+// aGridSize.Width
+14515
+// aGridTransformation
+14516;0;3529;0;5148;1773;0;0;1
+// sGridLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aLineColor)
+14540253
+// nLineWidth
+0
+/// CID/D=0:CS=0:Axis=0,0:Grid=0:SubGrid=0
+// aGridPosition.X
+5343
+// aGridPosition.Y
+1344
+// aGridSize.Height
+6005
+// aGridSize.Width
+10886
+// aGridTransformation
+10887;0;5343;0;6006;1344;0;0;1
+// sGridLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aLineColor)
+14540253
+// nLineWidth
+0
diff --git a/chart2/qa/extras/chart2dump/reference/gridtest/vertical_grid.txt b/chart2/qa/extras/chart2dump/reference/gridtest/vertical_grid.txt
new file mode 100644
index 0000000000..a0c341dc63
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/gridtest/vertical_grid.txt
@@ -0,0 +1,17 @@
+/// CID/D=0:CS=0:Axis=0,0:Grid=0
+// aGridPosition.X
+3620
+// aGridPosition.Y
+1343
+// aGridSize.Height
+6120
+// aGridSize.Width
+15109
+// aGridTransformation
+15110;0;3620;0;6121;1343;0;0;1
+// sGridLineDash
+0;1;201;20;20
+// static_cast<sal_Int32>(aLineColor)
+11776947
+// nLineWidth
+0
diff --git a/chart2/qa/extras/chart2dump/reference/legendtest/custom_legend_position.txt b/chart2/qa/extras/chart2dump/reference/legendtest/custom_legend_position.txt
new file mode 100644
index 0000000000..ad31f8c863
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/legendtest/custom_legend_position.txt
@@ -0,0 +1,50 @@
+// nLegendEntryCount
+4
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+43091
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+8388352
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16765728
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16711807
+// xLegendEntryText->getString()
+A
+// xLegendEntryText->getString()
+B
+// xLegendEntryText->getString()
+C
+// xLegendEntryText->getString()
+DD
diff --git a/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_bottom.txt b/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_bottom.txt
new file mode 100644
index 0000000000..5d2a2c0111
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_bottom.txt
@@ -0,0 +1,50 @@
+// nLegendEntryCount
+4
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+43091
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+8388352
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16765728
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16711807
+// xLegendEntryText->getString()
+AA
+// xLegendEntryText->getString()
+BB
+// xLegendEntryText->getString()
+CC
+// xLegendEntryText->getString()
+DD
diff --git a/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_left_side.txt b/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_left_side.txt
new file mode 100644
index 0000000000..7f55f89183
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_left_side.txt
@@ -0,0 +1,50 @@
+// nLegendEntryCount
+4
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+17798
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+8388352
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16765728
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+32767
+// xLegendEntryText->getString()
+AA
+// xLegendEntryText->getString()
+BB
+// xLegendEntryText->getString()
+CC
+// xLegendEntryText->getString()
+DD
diff --git a/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_right_side.txt b/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_right_side.txt
new file mode 100644
index 0000000000..78c83ef625
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_right_side.txt
@@ -0,0 +1,18 @@
+// nLegendEntryCount
+2
+// xLegendEntryContainer->getCount()
+2
+// sEntryGeomShapeType
+com.sun.star.drawing.RectangleShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+17798
+// xLegendEntryContainer->getCount()
+2
+// sEntryGeomShapeType
+com.sun.star.drawing.RectangleShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16728590
+// xLegendEntryText->getString()
+A
+// xLegendEntryText->getString()
+C-B
diff --git a/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_top.txt b/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_top.txt
new file mode 100644
index 0000000000..5d2a2c0111
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/legendtest/legend_on_top.txt
@@ -0,0 +1,50 @@
+// nLegendEntryCount
+4
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+43091
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+8388352
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16765728
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16711807
+// xLegendEntryText->getString()
+AA
+// xLegendEntryText->getString()
+BB
+// xLegendEntryText->getString()
+CC
+// xLegendEntryText->getString()
+DD
diff --git a/chart2/qa/extras/chart2dump/reference/legendtest/many_legend_entries.txt b/chart2/qa/extras/chart2dump/reference/legendtest/many_legend_entries.txt
new file mode 100644
index 0000000000..a3ef82203b
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/legendtest/many_legend_entries.txt
@@ -0,0 +1,182 @@
+// nLegendEntryCount
+15
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+43091
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+8388352
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16765728
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16711807
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+8257569
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+8637183
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+3227652
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+11456256
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+4923247
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16749838
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+12910603
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+34001
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+17798
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16728590
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+16765728
+// xLegendEntryText->getString()
+AA
+// xLegendEntryText->getString()
+BB
+// xLegendEntryText->getString()
+CC
+// xLegendEntryText->getString()
+DD
+// xLegendEntryText->getString()
+EE
+// xLegendEntryText->getString()
+FF
+// xLegendEntryText->getString()
+GG
+// xLegendEntryText->getString()
+HH
+// xLegendEntryText->getString()
+II
+// xLegendEntryText->getString()
+JJ
+// xLegendEntryText->getString()
+KK
+// xLegendEntryText->getString()
+LL
+// xLegendEntryText->getString()
+MM
+// xLegendEntryText->getString()
+NN
+// xLegendEntryText->getString()
+OO
diff --git a/chart2/qa/extras/chart2dump/reference/legendtest/minimal_legend_test.txt b/chart2/qa/extras/chart2dump/reference/legendtest/minimal_legend_test.txt
new file mode 100644
index 0000000000..63a2980cfa
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/legendtest/minimal_legend_test.txt
@@ -0,0 +1,14 @@
+// nLegendEntryCount
+1
+// xLegendEntryContainer->getCount()
+3
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// sEntryGeomShapeType
+com.sun.star.drawing.PolyPolygonShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+17798
+// xLegendEntryText->getString()
+Inkjet
diff --git a/chart2/qa/extras/chart2dump/reference/legendtest/multiple_categories.txt b/chart2/qa/extras/chart2dump/reference/legendtest/multiple_categories.txt
new file mode 100644
index 0000000000..9c207c9817
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/legendtest/multiple_categories.txt
@@ -0,0 +1,66 @@
+// nLegendEntryCount
+8
+// xLegendEntryContainer->getCount()
+2
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// xLegendEntryContainer->getCount()
+2
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// xLegendEntryContainer->getCount()
+2
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// xLegendEntryContainer->getCount()
+2
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// xLegendEntryContainer->getCount()
+2
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// xLegendEntryContainer->getCount()
+2
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// xLegendEntryContainer->getCount()
+2
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// xLegendEntryContainer->getCount()
+2
+// sEntryGeomShapeType
+com.sun.star.drawing.LineShape
+// static_cast<sal_Int32>(aEntryGeomColor)
+7512015
+// xLegendEntryText->getString()
+A In0
+// xLegendEntryText->getString()
+A In100
+// xLegendEntryText->getString()
+A In200
+// xLegendEntryText->getString()
+A In400
+// xLegendEntryText->getString()
+B In0
+// xLegendEntryText->getString()
+B In100
+// xLegendEntryText->getString()
+B In200
+// xLegendEntryText->getString()
+B In400
diff --git a/chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt b/chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt
new file mode 100644
index 0000000000..c1af41103d
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt
@@ -0,0 +1,194 @@
+// nSeriesCount
+4
+/// Series 0 slices
+// nSlicesCountInSeries
+3
+/// /D=0:CS=0:CT=0:Series=0:Point=0
+// aSlicePosition.X
+6089
+// aSlicePosition.Y
+2527
+// aSliceSize.Height
+2118
+// aSliceSize.Width
+4554
+// aSliceTransformation
+4554;0;6089;0;2118;2527;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+17798
+/// /D=0:CS=0:CT=0:Series=0:Point=1
+// aSlicePosition.X
+4353
+// aSlicePosition.Y
+2931
+// aSliceSize.Height
+6249
+// aSliceSize.Width
+4305
+// aSliceTransformation
+4305;0;4353;0;6249;2931;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16728590
+/// /D=0:CS=0:CT=0:Series=0:Point=2
+// aSlicePosition.X
+9033
+// aSlicePosition.Y
+4635
+// aSliceSize.Height
+4659
+// aSliceSize.Width
+2458
+// aSliceTransformation
+2458;0;9033;0;4659;4635;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16765728
+/// Series 1 slices
+// nSlicesCountInSeries
+3
+/// /D=0:CS=0:CT=0:Series=1:Point=0
+// aSlicePosition.X
+6601
+// aSlicePosition.Y
+3192
+// aSliceSize.Height
+1755
+// aSliceSize.Width
+3449
+// aSliceTransformation
+3449;0;6601;0;1755;3192;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+17798
+/// /D=0:CS=0:CT=0:Series=1:Point=1
+// aSlicePosition.X
+5018
+// aSlicePosition.Y
+3420
+// aSliceSize.Height
+4691
+// aSliceSize.Width
+1852
+// aSliceTransformation
+1852;0;5018;0;4691;3420;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16728590
+/// /D=0:CS=0:CT=0:Series=1:Point=2
+// aSlicePosition.X
+6270
+// aSlicePosition.Y
+4645
+// aSliceSize.Height
+3869
+// aSliceSize.Width
+4070
+// aSliceTransformation
+4070;0;6270;0;3869;4645;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16765728
+/// Series 2 slices
+// nSlicesCountInSeries
+3
+/// /D=0:CS=0:CT=0:Series=2:Point=0
+// aSlicePosition.X
+7688
+// aSlicePosition.Y
+3857
+// aSliceSize.Height
+1392
+// aSliceSize.Width
+1769
+// aSliceTransformation
+1769;0;7688;0;1392;3857;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+17798
+/// /D=0:CS=0:CT=0:Series=2:Point=1
+// aSlicePosition.X
+5683
+// aSlicePosition.Y
+3857
+// aSliceSize.Height
+3971
+// aSliceSize.Width
+2010
+// aSliceTransformation
+2010;0;5683;0;3971;3857;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16728590
+/// /D=0:CS=0:CT=0:Series=2:Point=2
+// aSlicePosition.X
+7394
+// aSlicePosition.Y
+4947
+// aSliceSize.Height
+2902
+// aSliceSize.Width
+2281
+// aSliceTransformation
+2281;0;7394;0;2902;4947;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16765728
+/// Series 3 slices
+// nSlicesCountInSeries
+3
+/// /D=0:CS=0:CT=0:Series=3:Point=0
+// aSlicePosition.X
+7714
+// aSlicePosition.Y
+4524
+// aSliceSize.Height
+1027
+// aSliceSize.Width
+1151
+// aSliceTransformation
+1151;0;7714;0;1027;4524;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+17798
+/// /D=0:CS=0:CT=0:Series=3:Point=1
+// aSlicePosition.X
+6348
+// aSlicePosition.Y
+4522
+// aSliceSize.Height
+1935
+// aSliceSize.Width
+1401
+// aSliceTransformation
+1401;0;6348;0;1935;4522;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16728590
+/// /D=0:CS=0:CT=0:Series=3:Point=2
+// aSlicePosition.X
+6493
+// aSlicePosition.Y
+5249
+// aSliceSize.Height
+1935
+// aSliceSize.Width
+2517
+// aSliceTransformation
+2517;0;6493;0;1935;5249;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16765728
diff --git a/chart2/qa/extras/chart2dump/reference/piecharttest/exploded_pie_chart.txt b/chart2/qa/extras/chart2dump/reference/piecharttest/exploded_pie_chart.txt
new file mode 100644
index 0000000000..9cbc93de42
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/piecharttest/exploded_pie_chart.txt
@@ -0,0 +1,50 @@
+// nSeriesCount
+4
+/// Series 0 slices
+// nSlicesCountInSeries
+3
+/// /D=0:CS=0:CT=0:Series=0:Point=0
+// aSlicePosition.X
+6018
+// aSlicePosition.Y
+2178
+// aSliceSize.Height
+2218
+// aSliceSize.Width
+3177
+// aSliceTransformation
+3177;0;6018;0;2218;2178;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+17798
+/// /D=0:CS=0:CT=0:Series=0:Point=1
+// aSlicePosition.X
+5246
+// aSlicePosition.Y
+3867
+// aSliceSize.Height
+3714
+// aSliceSize.Width
+3525
+// aSliceTransformation
+3525;0;5246;0;3714;3867;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16728590
+/// /D=0:CS=0:CT=0:Series=0:Point=2
+// aSlicePosition.X
+7679
+// aSlicePosition.Y
+3576
+// aSliceSize.Height
+3387
+// aSliceSize.Width
+2217
+// aSliceTransformation
+2217;0;7679;0;3387;3576;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16765728
diff --git a/chart2/qa/extras/chart2dump/reference/piecharttest/normal_pie_chart.txt b/chart2/qa/extras/chart2dump/reference/piecharttest/normal_pie_chart.txt
new file mode 100644
index 0000000000..1b97446cc2
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/piecharttest/normal_pie_chart.txt
@@ -0,0 +1,50 @@
+// nSeriesCount
+4
+/// Series 0 slices
+// nSlicesCountInSeries
+3
+/// /D=0:CS=0:CT=0:Series=0:Point=0
+// aSlicePosition.X
+4353
+// aSlicePosition.Y
+1846
+// aSliceSize.Height
+3416
+// aSliceSize.Width
+3326
+// aSliceTransformation
+3326;0;4353;0;3416;1846;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+17798
+/// /D=0:CS=0:CT=0:Series=0:Point=1
+// aSlicePosition.X
+4354
+// aSlicePosition.Y
+5172
+// aSliceSize.Height
+3326
+// aSliceSize.Width
+6601
+// aSliceTransformation
+6601;0;4354;0;3326;5172;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16728590
+/// /D=0:CS=0:CT=0:Series=0:Point=2
+// aSlicePosition.X
+7679
+// aSlicePosition.Y
+1846
+// aSliceSize.Height
+3896
+// aSliceSize.Width
+3326
+// aSliceTransformation
+3326;0;7679;0;3896;1846;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16765728
diff --git a/chart2/qa/extras/chart2dump/reference/piecharttest/pie_chart_many_slices.txt b/chart2/qa/extras/chart2dump/reference/piecharttest/pie_chart_many_slices.txt
new file mode 100644
index 0000000000..820a344443
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/piecharttest/pie_chart_many_slices.txt
@@ -0,0 +1,275 @@
+// nSeriesCount
+1
+/// Series 0 slices
+// nSlicesCountInSeries
+18
+/// /D=0:CS=0:CT=0:Series=0:Point=0
+// aSlicePosition.X
+10469
+// aSlicePosition.Y
+3869
+// aSliceSize.Height
+4104
+// aSliceSize.Width
+49
+// aSliceTransformation
+49;0;10469;0;4104;3869;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+17798
+/// /D=0:CS=0:CT=0:Series=0:Point=1
+// aSlicePosition.X
+10275
+// aSlicePosition.Y
+505
+// aSliceSize.Height
+4103
+// aSliceSize.Width
+158
+// aSliceTransformation
+158;0;10275;0;4103;505;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16728590
+/// /D=0:CS=0:CT=0:Series=0:Point=2
+// aSlicePosition.X
+10224
+// aSlicePosition.Y
+3872
+// aSliceSize.Height
+4101
+// aSliceSize.Width
+294
+// aSliceTransformation
+294;0;10224;0;4101;3872;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16765728
+/// /D=0:CS=0:CT=0:Series=0:Point=3
+// aSlicePosition.X
+10050
+// aSlicePosition.Y
+3879
+// aSliceSize.Height
+4094
+// aSliceSize.Width
+468
+// aSliceTransformation
+468;0;10050;0;4094;3879;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+5741852
+/// /D=0:CS=0:CT=0:Series=0:Point=4
+// aSlicePosition.X
+9734
+// aSlicePosition.Y
+3895
+// aSliceSize.Height
+4078
+// aSliceSize.Width
+784
+// aSliceTransformation
+784;0;9734;0;4078;3895;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+8257569
+/// /D=0:CS=0:CT=0:Series=0:Point=5
+// aSlicePosition.X
+9478
+// aSlicePosition.Y
+3944
+// aSliceSize.Height
+4029
+// aSliceSize.Width
+1040
+// aSliceTransformation
+1040;0;9478;0;4029;3944;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+8637183
+/// /D=0:CS=0:CT=0:Series=0:Point=6
+// aSlicePosition.X
+9184
+// aSlicePosition.Y
+4002
+// aSliceSize.Height
+3971
+// aSliceSize.Width
+1334
+// aSliceTransformation
+1334;0;9184;0;3971;4002;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+3227652
+/// /D=0:CS=0:CT=0:Series=0:Point=7
+// aSlicePosition.X
+8858
+// aSlicePosition.Y
+4091
+// aSliceSize.Height
+3882
+// aSliceSize.Width
+1660
+// aSliceTransformation
+1660;0;8858;0;3882;4091;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+11456256
+/// /D=0:CS=0:CT=0:Series=0:Point=8
+// aSlicePosition.X
+8506
+// aSlicePosition.Y
+4219
+// aSliceSize.Height
+3754
+// aSliceSize.Width
+2012
+// aSliceTransformation
+2012;0;8506;0;3754;4219;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+4923247
+/// /D=0:CS=0:CT=0:Series=0:Point=9
+// aSlicePosition.X
+8030
+// aSlicePosition.Y
+4395
+// aSliceSize.Height
+3578
+// aSliceSize.Width
+2488
+// aSliceTransformation
+2488;0;8030;0;3578;4395;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16749838
+/// /D=0:CS=0:CT=0:Series=0:Point=10
+// aSlicePosition.X
+7311
+// aSlicePosition.Y
+4708
+// aSliceSize.Height
+3265
+// aSliceSize.Width
+3207
+// aSliceTransformation
+3207;0;7311;0;3265;4708;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+12910603
+/// /D=0:CS=0:CT=0:Series=0:Point=11
+// aSlicePosition.X
+6490
+// aSlicePosition.Y
+5411
+// aSliceSize.Height
+2562
+// aSliceSize.Width
+4028
+// aSliceTransformation
+4028;0;6490;0;2562;5411;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+34001
+/// /D=0:CS=0:CT=0:Series=0:Point=12
+// aSlicePosition.X
+6414
+// aSlicePosition.Y
+7182
+// aSliceSize.Height
+2834
+// aSliceSize.Width
+4104
+// aSliceTransformation
+4104;0;6414;0;2834;7182;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+17798
+/// /D=0:CS=0:CT=0:Series=0:Point=13
+// aSlicePosition.X
+6959
+// aSlicePosition.Y
+7973
+// aSliceSize.Height
+3991
+// aSliceSize.Width
+3559
+// aSliceTransformation
+3559;0;6959;0;3991;7973;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16728590
+/// /D=0:CS=0:CT=0:Series=0:Point=14
+// aSlicePosition.X
+9562
+// aSlicePosition.Y
+7973
+// aSliceSize.Height
+4104
+// aSliceSize.Width
+3990
+// aSliceTransformation
+3990;0;9562;0;4104;7973;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16765728
+/// /D=0:CS=0:CT=0:Series=0:Point=15
+// aSlicePosition.X
+10518
+// aSlicePosition.Y
+6606
+// aSliceSize.Height
+4129
+// aSliceSize.Width
+4104
+// aSliceTransformation
+4104;0;10518;0;4129;6606;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+5741852
+/// /D=0:CS=0:CT=0:Series=0:Point=16
+// aSlicePosition.X
+10518
+// aSlicePosition.Y
+3909
+// aSliceSize.Height
+4064
+// aSliceSize.Width
+3869
+// aSliceTransformation
+3869;0;10518;0;4064;3909;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+8257569
+/// /D=0:CS=0:CT=0:Series=0:Point=17
+// aSlicePosition.X
+10658
+// aSlicePosition.Y
+1862
+// aSliceSize.Height
+4104
+// aSliceSize.Width
+573
+// aSliceTransformation
+573;0;10658;0;4104;1862;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+8637183
diff --git a/chart2/qa/extras/chart2dump/reference/piecharttest/rotated_pie_chart.txt b/chart2/qa/extras/chart2dump/reference/piecharttest/rotated_pie_chart.txt
new file mode 100644
index 0000000000..e1a3708593
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/piecharttest/rotated_pie_chart.txt
@@ -0,0 +1,50 @@
+// nSeriesCount
+4
+/// Series 0 slices
+// nSlicesCountInSeries
+3
+/// /D=0:CS=0:CT=0:Series=0:Point=0
+// aSlicePosition.X
+7679
+// aSlicePosition.Y
+2779
+// aSliceSize.Height
+4767
+// aSliceSize.Width
+3326
+// aSliceTransformation
+3326;0;7679;0;4767;2779;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+17798
+/// /D=0:CS=0:CT=0:Series=0:Point=1
+// aSlicePosition.X
+4353
+// aSlicePosition.Y
+3306
+// aSliceSize.Height
+5192
+// aSliceSize.Width
+5654
+// aSliceTransformation
+5654;0;4353;0;5192;3306;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16728590
+/// /D=0:CS=0:CT=0:Series=0:Point=2
+// aSlicePosition.X
+4925
+// aSlicePosition.Y
+1846
+// aSliceSize.Height
+3326
+// aSliceSize.Width
+5064
+// aSliceTransformation
+5064;0;4925;0;3326;1846;0;0;1
+// static_cast<sal_Int32>(aSliceFillStyle)
+1
+// static_cast<sal_Int32>(aSliceFillColor)
+16765728
diff --git a/chart2/qa/extras/chart2dump/reference/pivotchartdatabuttontest/pivotchart_data_button.txt b/chart2/qa/extras/chart2dump/reference/pivotchartdatabuttontest/pivotchart_data_button.txt
new file mode 100644
index 0000000000..3d7d8a55c6
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pivotchartdatabuttontest/pivotchart_data_button.txt
@@ -0,0 +1,2 @@
+// static_cast<sal_Int32>( aButtonFillColor )
+16185078
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_lines_and_points.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_lines_and_points.txt
new file mode 100644
index 0000000000..007a25ed48
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_lines_and_points.txt
@@ -0,0 +1,250 @@
+// nSeriesCount
+4
+/// Series 0
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+10215
+// aLinePosition.Y
+3360
+// aLineSize.Height
+4263
+// aLineSize.Width
+15800
+// aLineTransformation
+15800;0;10215;0;4263;3360;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+3
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aPointPosition.X
+10090
+// aPointPosition.Y
+7498
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;10090;0;250;7498;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aPointPosition.X
+17990
+// aPointPosition.Y
+3235
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;17990;0;250;3235;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aPointPosition.X
+25890
+// aPointPosition.Y
+7037
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;25890;0;250;7037;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16711807
+/// Series 1
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+10215
+// aLinePosition.Y
+6470
+// aLineSize.Height
+2592
+// aLineSize.Width
+15800
+// aLineTransformation
+15800;0;10215;0;2592;6470;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+3
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aPointPosition.X
+10090
+// aPointPosition.Y
+8937
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;10090;0;250;8937;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aPointPosition.X
+17990
+// aPointPosition.Y
+7382
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;17990;0;250;7382;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aPointPosition.X
+25890
+// aPointPosition.Y
+6345
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;25890;0;250;6345;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// Series 2
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+10215
+// aLinePosition.Y
+7622
+// aLineSize.Height
+3226
+// aLineSize.Width
+15800
+// aLineTransformation
+15800;0;10215;0;3226;7622;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+3
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aPointPosition.X
+10090
+// aPointPosition.Y
+10723
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;10090;0;250;10723;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aPointPosition.X
+17990
+// aPointPosition.Y
+7497
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;17990;0;250;7497;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aPointPosition.X
+25890
+// aPointPosition.Y
+8880
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;25890;0;250;8880;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// Series 3
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+10215
+// aLinePosition.Y
+4033
+// aLineSize.Height
+5772
+// aLineSize.Width
+15800
+// aLineTransformation
+15800;0;10215;0;5772;4033;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+3
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aPointPosition.X
+10090
+// aPointPosition.Y
+9680
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;10090;0;250;9680;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16776960
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aPointPosition.X
+17990
+// aPointPosition.Y
+6794
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;17990;0;250;6794;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16776960
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aPointPosition.X
+25890
+// aPointPosition.Y
+3908
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;25890;0;250;3908;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16776960
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_lines_only.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_lines_only.txt
new file mode 100644
index 0000000000..c92fbb1bfa
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_lines_only.txt
@@ -0,0 +1,58 @@
+// nSeriesCount
+4
+/// Series 0
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+10215
+// aLinePosition.Y
+3360
+// aLineSize.Height
+4263
+// aLineSize.Width
+15800
+// aLineTransformation
+15800;0;10215;0;4263;3360;0;0;1
+/// Series 1
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+10215
+// aLinePosition.Y
+6470
+// aLineSize.Height
+2592
+// aLineSize.Width
+15800
+// aLineTransformation
+15800;0;10215;0;2592;6470;0;0;1
+/// Series 2
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+10215
+// aLinePosition.Y
+7622
+// aLineSize.Height
+3226
+// aLineSize.Width
+15800
+// aLineTransformation
+15800;0;10215;0;3226;7622;0;0;1
+/// Series 3
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+2
+// aLinePosition.X
+10215
+// aLinePosition.Y
+4033
+// aLineSize.Height
+5772
+// aLineSize.Width
+15800
+// aLineTransformation
+15800;0;10215;0;5772;4033;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_points_only.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_points_only.txt
new file mode 100644
index 0000000000..61c521ff3a
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/normal_line_chart_points_only.txt
@@ -0,0 +1,198 @@
+// nSeriesCount
+4
+/// Series 0
+/// Points are displayed
+// nPointCountInSeries
+3
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aPointPosition.X
+10090
+// aPointPosition.Y
+7498
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;10090;0;250;7498;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aPointPosition.X
+17990
+// aPointPosition.Y
+3235
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;17990;0;250;3235;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16711807
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aPointPosition.X
+25890
+// aPointPosition.Y
+7037
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;25890;0;250;7037;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16711807
+/// Series 1
+/// Points are displayed
+// nPointCountInSeries
+3
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aPointPosition.X
+10090
+// aPointPosition.Y
+8937
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;10090;0;250;8937;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aPointPosition.X
+17990
+// aPointPosition.Y
+7382
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;17990;0;250;7382;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aPointPosition.X
+25890
+// aPointPosition.Y
+6345
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;25890;0;250;6345;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// Series 2
+/// Points are displayed
+// nPointCountInSeries
+3
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aPointPosition.X
+10090
+// aPointPosition.Y
+10723
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;10090;0;250;10723;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aPointPosition.X
+17990
+// aPointPosition.Y
+7497
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;17990;0;250;7497;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aPointPosition.X
+25890
+// aPointPosition.Y
+8880
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;25890;0;250;8880;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+10079487
+/// Series 3
+/// Points are displayed
+// nPointCountInSeries
+3
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aPointPosition.X
+10090
+// aPointPosition.Y
+9680
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;10090;0;250;9680;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16776960
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aPointPosition.X
+17990
+// aPointPosition.Y
+6794
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;17990;0;250;6794;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16776960
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aPointPosition.X
+25890
+// aPointPosition.Y
+3908
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;25890;0;250;3908;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16776960
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_lines_and_points.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_lines_and_points.txt
new file mode 100644
index 0000000000..01c6448c29
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_lines_and_points.txt
@@ -0,0 +1,310 @@
+// nSeriesCount
+4
+/// Series 0
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+8218
+// aLineSize.Height
+2227
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;2227;8218;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+8093
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;8093;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+8212
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;8212;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+9941
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;9941;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+10320
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;10320;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// Series 1
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+4844
+// aLineSize.Height
+2549
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;2549;4844;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+4719
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;4719;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+5660
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;5660;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+6718
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;6718;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+7268
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;7268;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// Series 2
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+3131
+// aLineSize.Height
+1802
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;1802;3131;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+3006
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;3006;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+3164
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;3164;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+4808
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;4808;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+4184
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;4184;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// Series 3
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+448
+// aLineSize.Height
+0
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;0;448;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+323
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;323;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+323
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;323;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+323
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;323;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+323
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;323;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_lines_only.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_lines_only.txt
new file mode 100644
index 0000000000..42eaae0b23
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_lines_only.txt
@@ -0,0 +1,58 @@
+// nSeriesCount
+4
+/// Series 0
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+8218
+// aLineSize.Height
+2227
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;2227;8218;0;0;1
+/// Series 1
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+4844
+// aLineSize.Height
+2549
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;2549;4844;0;0;1
+/// Series 2
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+3131
+// aLineSize.Height
+1802
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;1802;3131;0;0;1
+/// Series 3
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+448
+// aLineSize.Height
+0
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;0;448;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_points_only.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_points_only.txt
new file mode 100644
index 0000000000..c8d1819f90
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/percent_stacked_line_chart_points_only.txt
@@ -0,0 +1,258 @@
+// nSeriesCount
+4
+/// Series 0
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aPointPosition.X
+2980
+// aPointPosition.Y
+8115
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2980;0;250;8115;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aPointPosition.X
+9124
+// aPointPosition.Y
+8234
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9124;0;250;8234;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aPointPosition.X
+15268
+// aPointPosition.Y
+9967
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15268;0;250;9967;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=3
+// aPointPosition.X
+21412
+// aPointPosition.Y
+10347
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21412;0;250;10347;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// Series 1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aPointPosition.X
+2980
+// aPointPosition.Y
+4732
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2980;0;250;4732;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aPointPosition.X
+9124
+// aPointPosition.Y
+5675
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9124;0;250;5675;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aPointPosition.X
+15268
+// aPointPosition.Y
+6736
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15268;0;250;6736;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=3
+// aPointPosition.X
+21412
+// aPointPosition.Y
+7287
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21412;0;250;7287;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// Series 2
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aPointPosition.X
+2980
+// aPointPosition.Y
+3014
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2980;0;250;3014;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aPointPosition.X
+9124
+// aPointPosition.Y
+3173
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9124;0;250;3173;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aPointPosition.X
+15268
+// aPointPosition.Y
+4821
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15268;0;250;4821;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=3
+// aPointPosition.X
+21412
+// aPointPosition.Y
+4196
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21412;0;250;4196;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// Series 3
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aPointPosition.X
+2980
+// aPointPosition.Y
+324
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2980;0;250;324;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aPointPosition.X
+9124
+// aPointPosition.Y
+324
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9124;0;250;324;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aPointPosition.X
+15268
+// aPointPosition.Y
+324
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15268;0;250;324;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=3
+// aPointPosition.X
+21412
+// aPointPosition.Y
+324
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21412;0;250;324;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_lines_and_points.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_lines_and_points.txt
new file mode 100644
index 0000000000..c6ef9431cd
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_lines_and_points.txt
@@ -0,0 +1,310 @@
+// nSeriesCount
+4
+/// Series 0
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+4801
+// aLinePosition.Y
+3760
+// aLineSize.Height
+3138
+// aLineSize.Width
+7912
+// aLineTransformation
+7912;0;4801;0;3138;3760;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aPointPosition.X
+4676
+// aPointPosition.Y
+6773
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;4676;0;250;6773;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aPointPosition.X
+7313
+// aPointPosition.Y
+3635
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;7313;0;250;3635;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aPointPosition.X
+9951
+// aPointPosition.Y
+6434
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9951;0;250;6434;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=3
+// aPointPosition.X
+12588
+// aPointPosition.Y
+5034
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;12588;0;250;5034;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// Series 1
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+4801
+// aLinePosition.Y
+3912
+// aLineSize.Height
+4045
+// aLineSize.Width
+7912
+// aLineTransformation
+7912;0;4801;0;4045;3912;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aPointPosition.X
+4676
+// aPointPosition.Y
+7832
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;4676;0;250;7832;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aPointPosition.X
+7313
+// aPointPosition.Y
+6688
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;7313;0;250;6688;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aPointPosition.X
+9951
+// aPointPosition.Y
+5924
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9951;0;250;5924;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=3
+// aPointPosition.X
+12588
+// aPointPosition.Y
+3787
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;12588;0;250;3787;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// Series 2
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+4801
+// aLinePosition.Y
+3845
+// aLineSize.Height
+5427
+// aLineSize.Width
+7912
+// aLineTransformation
+7912;0;4801;0;5427;3845;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aPointPosition.X
+4676
+// aPointPosition.Y
+9147
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;4676;0;250;9147;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aPointPosition.X
+7313
+// aPointPosition.Y
+6772
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;7313;0;250;6772;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aPointPosition.X
+9951
+// aPointPosition.Y
+7790
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9951;0;250;7790;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=3
+// aPointPosition.X
+12588
+// aPointPosition.Y
+3720
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;12588;0;250;3720;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// Series 3
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+4801
+// aLinePosition.Y
+2131
+// aLineSize.Height
+6373
+// aLineSize.Width
+7912
+// aLineTransformation
+7912;0;4801;0;6373;2131;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aPointPosition.X
+4676
+// aPointPosition.Y
+8379
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;4676;0;250;8379;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aPointPosition.X
+7313
+// aPointPosition.Y
+6255
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;7313;0;250;6255;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aPointPosition.X
+9951
+// aPointPosition.Y
+4131
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9951;0;250;4131;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=3
+// aPointPosition.X
+12588
+// aPointPosition.Y
+2006
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;12588;0;250;2006;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_lines_only.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_lines_only.txt
new file mode 100644
index 0000000000..55a84b00fd
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_lines_only.txt
@@ -0,0 +1,58 @@
+// nSeriesCount
+4
+/// Series 0
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+5069
+// aLinePosition.Y
+3954
+// aLineSize.Height
+3299
+// aLineSize.Width
+8352
+// aLineTransformation
+8352;0;5069;0;3299;3954;0;0;1
+/// Series 1
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+5069
+// aLinePosition.Y
+4114
+// aLineSize.Height
+4253
+// aLineSize.Width
+8352
+// aLineTransformation
+8352;0;5069;0;4253;4114;0;0;1
+/// Series 2
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+5069
+// aLinePosition.Y
+4043
+// aLineSize.Height
+5706
+// aLineSize.Width
+8352
+// aLineTransformation
+8352;0;5069;0;5706;4043;0;0;1
+/// Series 3
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+5069
+// aLinePosition.Y
+2242
+// aLineSize.Height
+6700
+// aLineSize.Width
+8352
+// aLineTransformation
+8352;0;5069;0;6700;2242;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_points_only.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_points_only.txt
new file mode 100644
index 0000000000..1107f97cd0
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/scatter_chart_points_only.txt
@@ -0,0 +1,258 @@
+// nSeriesCount
+4
+/// Series 0
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aPointPosition.X
+4695
+// aPointPosition.Y
+7540
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;4695;0;250;7540;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aPointPosition.X
+8618
+// aPointPosition.Y
+4016
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;8618;0;250;4016;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aPointPosition.X
+12540
+// aPointPosition.Y
+7159
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;12540;0;250;7159;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=3
+// aPointPosition.X
+16463
+// aPointPosition.Y
+5588
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;16463;0;250;5588;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// Series 1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aPointPosition.X
+4695
+// aPointPosition.Y
+8730
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;4695;0;250;8730;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aPointPosition.X
+8618
+// aPointPosition.Y
+7444
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;8618;0;250;7444;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aPointPosition.X
+12540
+// aPointPosition.Y
+6587
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;12540;0;250;6587;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=3
+// aPointPosition.X
+16463
+// aPointPosition.Y
+4187
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;16463;0;250;4187;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// Series 2
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aPointPosition.X
+4695
+// aPointPosition.Y
+10207
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;4695;0;250;10207;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aPointPosition.X
+8618
+// aPointPosition.Y
+7540
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;8618;0;250;7540;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aPointPosition.X
+12540
+// aPointPosition.Y
+8683
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;12540;0;250;8683;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=3
+// aPointPosition.X
+16463
+// aPointPosition.Y
+4111
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;16463;0;250;4111;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// Series 3
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aPointPosition.X
+4695
+// aPointPosition.Y
+9344
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;4695;0;250;9344;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aPointPosition.X
+8618
+// aPointPosition.Y
+6958
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;8618;0;250;6958;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aPointPosition.X
+12540
+// aPointPosition.Y
+4572
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;12540;0;250;4572;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=3
+// aPointPosition.X
+16463
+// aPointPosition.Y
+2186
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;16463;0;250;2186;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_lines_and_points.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_lines_and_points.txt
new file mode 100644
index 0000000000..d58d57d1e8
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_lines_and_points.txt
@@ -0,0 +1,310 @@
+// nSeriesCount
+4
+/// Series 0
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+10042
+// aLineSize.Height
+1320
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;1320;10042;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+11237
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;11237;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+9917
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;9917;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+11094
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;11094;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+10506
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;10506;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// Series 1
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+7806
+// aLineSize.Height
+2432
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;2432;7806;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+10113
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;10113;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+8312
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;8312;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+9168
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;9168;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+7681
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;7681;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// Series 2
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+4953
+// aLineSize.Height
+4715
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;4715;4953;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+9543
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;9543;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+6743
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;6743;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+8027
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;8027;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+4828
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;4828;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// Series 3
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3101
+// aLinePosition.Y
+1380
+// aLineSize.Height
+7394
+// aLineSize.Width
+18406
+// aLineTransformation
+18406;0;3101;0;7394;1380;0;0;1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+8649
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;8649;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+4957
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;4957;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+5347
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;5347;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+1255
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;1255;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16744192
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_lines_only.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_lines_only.txt
new file mode 100644
index 0000000000..b8d7c7a241
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_lines_only.txt
@@ -0,0 +1,58 @@
+// nSeriesCount
+4
+/// Series 0
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3100
+// aLinePosition.Y
+10256
+// aLineSize.Height
+1221
+// aLineSize.Width
+18405
+// aLineTransformation
+18405;0;3100;0;1221;10256;0;0;1
+/// Series 1
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3100
+// aLinePosition.Y
+8187
+// aLineSize.Height
+2250
+// aLineSize.Width
+18405
+// aLineTransformation
+18405;0;3100;0;2250;8187;0;0;1
+/// Series 2
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3100
+// aLinePosition.Y
+5547
+// aLineSize.Height
+4362
+// aLineSize.Width
+18405
+// aLineTransformation
+18405;0;3100;0;4362;5547;0;0;1
+/// Series 3
+/// Lines are displayed
+// static_cast<sal_Int32>(aSeriesLineStyle)
+1
+// aLinePosition.X
+3100
+// aLinePosition.Y
+2240
+// aLineSize.Height
+6843
+// aLineSize.Width
+18405
+// aLineTransformation
+18405;0;3100;0;6843;2240;0;0;1
diff --git a/chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_points_only.txt b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_points_only.txt
new file mode 100644
index 0000000000..8803c6e02d
--- /dev/null
+++ b/chart2/qa/extras/chart2dump/reference/pointlinecharttest/stacked_line_chart_points_only.txt
@@ -0,0 +1,258 @@
+// nSeriesCount
+4
+/// Series 0
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+11237
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;11237;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+9917
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;9917;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+11094
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;11094;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+10506
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;10506;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+17798
+/// Series 1
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+10113
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;10113;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+8312
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;8312;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+9168
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;9168;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+7681
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;7681;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16728590
+/// Series 2
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+9543
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;9543;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+6743
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;6743;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+8027
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;8027;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=2:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+4828
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;4828;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+16765728
+/// Series 3
+/// Points are displayed
+// nPointCountInSeries
+4
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=0
+// aPointPosition.X
+2976
+// aPointPosition.Y
+8649
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;2976;0;250;8649;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=1
+// aPointPosition.X
+9111
+// aPointPosition.Y
+4957
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;9111;0;250;4957;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=2
+// aPointPosition.X
+15246
+// aPointPosition.Y
+5347
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;15246;0;250;5347;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
+/// CID/MultiClick/D=0:CS=0:CT=0:Series=3:Point=3
+// aPointPosition.X
+21382
+// aPointPosition.Y
+1255
+// aPointSize.Height
+250
+// aPointSize.Width
+250
+// aPointTransformation
+250;0;21382;0;250;1255;0;0;1
+// static_cast<sal_Int32>(aPointFillStyle)
+1
+// static_cast<sal_Int32>(aPointFillColor)
+5741852
diff --git a/chart2/qa/extras/chart2export.cxx b/chart2/qa/extras/chart2export.cxx
new file mode 100644
index 0000000000..6958876b1d
--- /dev/null
+++ b/chart2/qa/extras/chart2export.cxx
@@ -0,0 +1,1258 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "charttest.hxx"
+
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+#include <com/sun/star/chart2/MovingAverageType.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+
+using uno::Reference;
+using beans::XPropertySet;
+
+class Chart2ExportTest : public ChartTest
+{
+public:
+ Chart2ExportTest() : ChartTest("/chart2/qa/extras/data/") {}
+};
+
+namespace {
+
+void testErrorBar( Reference< XPropertySet > const & xErrorBar )
+{
+ sal_Int32 nErrorBarStyle;
+ CPPUNIT_ASSERT(
+ xErrorBar->getPropertyValue("ErrorBarStyle") >>= nErrorBarStyle);
+ CPPUNIT_ASSERT_EQUAL(chart::ErrorBarStyle::RELATIVE, nErrorBarStyle);
+ bool bShowPositive = bool(), bShowNegative = bool();
+ CPPUNIT_ASSERT(
+ xErrorBar->getPropertyValue("ShowPositiveError") >>= bShowPositive);
+ CPPUNIT_ASSERT(bShowPositive);
+ CPPUNIT_ASSERT(
+ xErrorBar->getPropertyValue("ShowNegativeError") >>= bShowNegative);
+ CPPUNIT_ASSERT(bShowNegative);
+ double nVal = 0.0;
+ CPPUNIT_ASSERT(xErrorBar->getPropertyValue("PositiveError") >>= nVal);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, nVal, 1e-10);
+}
+
+void checkCommonTrendline(
+ Reference<chart2::XRegressionCurve> const & xCurve,
+ double aExpectedExtrapolateForward, double aExpectedExtrapolateBackward,
+ bool aExpectedForceIntercept, double aExpectedInterceptValue,
+ bool aExpectedShowEquation, bool aExpectedR2, bool aExpectedMayHaveR2)
+{
+ Reference<XPropertySet> xProperties( xCurve , uno::UNO_QUERY );
+ CPPUNIT_ASSERT(xProperties.is());
+
+ double aExtrapolateForward = 0.0;
+ CPPUNIT_ASSERT(xProperties->getPropertyValue("ExtrapolateForward") >>= aExtrapolateForward);
+ CPPUNIT_ASSERT_EQUAL(aExpectedExtrapolateForward, aExtrapolateForward);
+
+ double aExtrapolateBackward = 0.0;
+ CPPUNIT_ASSERT(xProperties->getPropertyValue("ExtrapolateBackward") >>= aExtrapolateBackward);
+ CPPUNIT_ASSERT_EQUAL(aExpectedExtrapolateBackward, aExtrapolateBackward);
+
+ bool bForceIntercept = false;
+ CPPUNIT_ASSERT(xProperties->getPropertyValue("ForceIntercept") >>= bForceIntercept);
+ CPPUNIT_ASSERT_EQUAL(aExpectedForceIntercept, bForceIntercept);
+
+ if (bForceIntercept)
+ {
+ double aInterceptValue = 0.0;
+ CPPUNIT_ASSERT(xProperties->getPropertyValue("InterceptValue") >>= aInterceptValue);
+ CPPUNIT_ASSERT_EQUAL(aExpectedInterceptValue, aInterceptValue);
+ }
+
+ Reference< XPropertySet > xEquationProperties( xCurve->getEquationProperties() );
+ CPPUNIT_ASSERT(xEquationProperties.is());
+
+ bool bShowEquation = false;
+ CPPUNIT_ASSERT(xEquationProperties->getPropertyValue("ShowEquation") >>= bShowEquation);
+ CPPUNIT_ASSERT_EQUAL(aExpectedShowEquation, bShowEquation);
+
+ bool bShowCorrelationCoefficient = false;
+ CPPUNIT_ASSERT(xEquationProperties->getPropertyValue("ShowCorrelationCoefficient") >>= bShowCorrelationCoefficient);
+ CPPUNIT_ASSERT_EQUAL(aExpectedR2, bShowCorrelationCoefficient);
+
+ bool bMayHaveR2 = false;
+ CPPUNIT_ASSERT(xEquationProperties->getPropertyValue("MayHaveCorrelationCoefficient") >>= bMayHaveR2);
+ CPPUNIT_ASSERT_EQUAL(aExpectedMayHaveR2, bMayHaveR2);
+}
+
+void checkNameAndType(Reference<XPropertySet> const & xProperties, const OUString& aExpectedName, const OUString& aExpectedServiceName)
+{
+ Reference< lang::XServiceName > xServiceName( xProperties, UNO_QUERY );
+ CPPUNIT_ASSERT(xServiceName.is());
+
+ OUString aServiceName = xServiceName->getServiceName();
+ CPPUNIT_ASSERT_EQUAL(aExpectedServiceName, aServiceName);
+
+ OUString aCurveName;
+ CPPUNIT_ASSERT(xProperties->getPropertyValue("CurveName") >>= aCurveName);
+ CPPUNIT_ASSERT_EQUAL(aExpectedName, aCurveName);
+}
+
+void checkLinearTrendline(
+ Reference<chart2::XRegressionCurve> const & xCurve, const OUString& aExpectedName,
+ double aExpectedExtrapolateForward, double aExpectedExtrapolateBackward,
+ double aExpectedInterceptValue)
+{
+ Reference<XPropertySet> xProperties( xCurve , uno::UNO_QUERY );
+ CPPUNIT_ASSERT(xProperties.is());
+
+ checkNameAndType(xProperties, aExpectedName, "com.sun.star.chart2.LinearRegressionCurve");
+
+ checkCommonTrendline(
+ xCurve,
+ aExpectedExtrapolateForward, aExpectedExtrapolateBackward,
+ /*aExpectedForceIntercept*/false, aExpectedInterceptValue,
+ /*aExpectedShowEquation*/true, /*aExpectedR2*/false, /*aExpectedMayHaveR2*/true);
+}
+
+void checkPolynomialTrendline(
+ Reference<chart2::XRegressionCurve> const & xCurve, const OUString& aExpectedName,
+ sal_Int32 aExpectedDegree,
+ double aExpectedExtrapolateForward, double aExpectedExtrapolateBackward,
+ double aExpectedInterceptValue)
+{
+ Reference<XPropertySet> xProperties( xCurve , uno::UNO_QUERY );
+ CPPUNIT_ASSERT(xProperties.is());
+
+ checkNameAndType(xProperties, aExpectedName, "com.sun.star.chart2.PolynomialRegressionCurve");
+
+ sal_Int32 aDegree = 2;
+ CPPUNIT_ASSERT(xProperties->getPropertyValue("PolynomialDegree") >>= aDegree);
+ CPPUNIT_ASSERT_EQUAL(aExpectedDegree, aDegree);
+
+ checkCommonTrendline(
+ xCurve,
+ aExpectedExtrapolateForward, aExpectedExtrapolateBackward,
+ /*aExpectedForceIntercept*/true, aExpectedInterceptValue,
+ /*aExpectedShowEquation*/true, /*aExpectedR2*/true, /*aExpectedMayHaveR2*/true);
+}
+
+void checkMovingAverageTrendline(
+ Reference<chart2::XRegressionCurve> const & xCurve, const OUString& aExpectedName, sal_Int32 aExpectedPeriod)
+{
+ Reference<XPropertySet> xProperties( xCurve , uno::UNO_QUERY );
+ CPPUNIT_ASSERT(xProperties.is());
+
+ checkNameAndType(xProperties, aExpectedName, "com.sun.star.chart2.MovingAverageRegressionCurve");
+
+ sal_Int32 aPeriod = 2;
+ CPPUNIT_ASSERT(xProperties->getPropertyValue("MovingAveragePeriod") >>= aPeriod);
+ CPPUNIT_ASSERT_EQUAL(aExpectedPeriod, aPeriod);
+
+ checkCommonTrendline(
+ xCurve,
+ /*aExpectedExtrapolateForward*/0.0, /*aExpectedExtrapolateBackward*/0.0,
+ /*aExpectedForceIntercept*/false, /*aExpectedInterceptValue*/0.0,
+ /*aExpectedShowEquation*/false, /*aExpectedR2*/false, /*aExpectedMayHaveR2*/false);
+}
+
+void checkTrendlinesInChart(uno::Reference< chart2::XChartDocument > const & xChartDoc)
+{
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT( xDataSeries.is() );
+
+ Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xDataSeries, UNO_QUERY );
+ CPPUNIT_ASSERT( xRegressionCurveContainer.is() );
+
+ Sequence< Reference< chart2::XRegressionCurve > > xRegressionCurveSequence = xRegressionCurveContainer->getRegressionCurves();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xRegressionCurveSequence.getLength());
+
+ Reference<chart2::XRegressionCurve> xCurve;
+
+ xCurve = xRegressionCurveSequence[0];
+ CPPUNIT_ASSERT(xCurve.is());
+ checkPolynomialTrendline(xCurve, "col2_poly", 3, 0.1, -0.1, -1.0);
+
+ xCurve = xRegressionCurveSequence[1];
+ CPPUNIT_ASSERT(xCurve.is());
+ checkLinearTrendline(xCurve, "col2_linear", -0.5, -0.5, 0.0);
+
+ xCurve = xRegressionCurveSequence[2];
+ CPPUNIT_ASSERT(xCurve.is());
+ checkMovingAverageTrendline(xCurve, "col2_moving_avg", 3);
+}
+
+}
+
+// improve the test
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testErrorBarXLSX)
+{
+ loadFromFile(u"ods/error_bar.ods");
+ {
+ // make sure the ODS import was successful
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT( xDataSeries.is() );
+
+ Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW );
+
+ // test that y error bars are there
+ Reference< beans::XPropertySet > xErrorBarYProps;
+ xPropSet->getPropertyValue(CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarYProps;
+ testErrorBar(xErrorBarYProps);
+ }
+
+ saveAndReload("Calc Office Open XML");
+ {
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT( xDataSeries.is() );
+
+ Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW );
+
+ // test that y error bars are there
+ Reference< beans::XPropertySet > xErrorBarYProps;
+ xPropSet->getPropertyValue(CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarYProps;
+ testErrorBar(xErrorBarYProps);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testErrorBarPropXLSX)
+{
+ loadFromFile(u"xlsx/testErrorBarProp.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // test y error bars property
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[1]/c:errDir"_ostr, "val"_ostr, "y");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[1]/c:spPr/a:ln"_ostr, "w"_ostr, "12600");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[1]/c:spPr/a:ln/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "ff0000");
+
+ // test x error bars property
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[2]/c:errDir"_ostr, "val"_ostr, "x");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[2]/c:spPr/a:ln"_ostr, "w"_ostr, "9360");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:errBars[2]/c:spPr/a:ln/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "595959");
+}
+
+// This method tests the preservation of properties for trendlines / regression curves
+// in an export -> import cycle using different file formats - ODS, XLS and XLSX.
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testTrendline)
+{
+ // Validation fails with
+ // Error: tag name "chart:symbol-image" is not allowed. Possible tag names are: <label-separator>
+ skipValidation();
+ loadFromFile(u"ods/trendline.ods");
+ checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
+ saveAndReload("calc8");
+ checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testTrendlineOOXML)
+{
+ loadFromFile(u"ods/trendline.ods");
+ checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
+ saveAndReload("Calc Office Open XML");
+ checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testTrendlineXLS)
+{
+ loadFromFile(u"ods/trendline.ods");
+ checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
+ saveAndReload("MS Excel 97");
+ checkTrendlinesInChart(getChartDocFromSheet( 0, mxComponent));
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testMovingAverage)
+{
+ loadFromFile(u"ods/moving-type.ods");
+ saveAndReload("calc8");
+
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT( xDataSeries.is() );
+
+ Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xDataSeries, UNO_QUERY );
+ CPPUNIT_ASSERT( xRegressionCurveContainer.is() );
+
+ Sequence< Reference< chart2::XRegressionCurve > > xRegressionCurveSequence = xRegressionCurveContainer->getRegressionCurves();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xRegressionCurveSequence.getLength());
+
+ Reference<chart2::XRegressionCurve> xCurve = xRegressionCurveSequence[0];
+ CPPUNIT_ASSERT(xCurve.is());
+
+ Reference<XPropertySet> xProperties( xCurve , uno::UNO_QUERY );
+ CPPUNIT_ASSERT(xProperties.is());
+
+ sal_Int32 nMovingAverageType = 0;
+ xProperties->getPropertyValue("MovingAverageType") >>= nMovingAverageType;
+ CPPUNIT_ASSERT_EQUAL(chart2::MovingAverageType::Central, nMovingAverageType);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testStockChart)
+{
+ /* For attached file Stock_Chart.docx, in chart1.xml,
+ * <c:stockChart>, there are four types of series as
+ * Open,Low,High and Close.
+ * For Open series, in <c:idx val="0" />
+ * an attribute val of index should start from 1 and not from 0.
+ * Which was problem area.
+ */
+ loadFromFile(u"docx/testStockChart.docx");
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:idx"_ostr, "val"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:order"_ostr, "val"_ostr, "1");
+ assertXPathContent(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:stockChart/c:ser[1]/c:tx/c:strRef/c:strCache/c:pt/c:v"_ostr,
+ "Open");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testBarChart)
+{
+ loadFromFile(u"docx/testBarChart.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:barDir"_ostr, "val"_ostr, "col");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testCrosses)
+{
+ // test crosses val="autoZero" with DOCX
+ {
+ loadFromFile(u"docx/Bar_horizontal_cone.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:crosses"_ostr, "val"_ostr, "autoZero");
+ }
+ // tdf#142351: test crossesAt val="-50" with XLSX
+ {
+ loadFromFile(u"xlsx/tdf142351.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:crossesAt"_ostr, "val"_ostr, "-50");
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testScatterChartTextXValues)
+{
+ loadFromFile(u"docx/scatter-chart-text-x-values.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XChartType> xCT = getChartTypeFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xCT.is());
+
+ // Make sure we have exactly 3 data series.
+ std::vector<uno::Sequence<uno::Any> > aLabels = getDataSeriesLabelsFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("Series 1"), aLabels[0][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("Series 2"), aLabels[1][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("Series 3"), aLabels[2][0].get<OUString>());
+
+ std::vector<std::vector<double> > aYValues = getDataSeriesYValuesFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aYValues.size());
+
+ // Check the Y values of "Series 1".
+ CPPUNIT_ASSERT_EQUAL(size_t(4), aYValues[0].size());
+ CPPUNIT_ASSERT_EQUAL(4.3, aYValues[0][0]);
+ CPPUNIT_ASSERT_EQUAL(2.5, aYValues[0][1]);
+ CPPUNIT_ASSERT_EQUAL(3.5, aYValues[0][2]);
+ CPPUNIT_ASSERT_EQUAL(4.5, aYValues[0][3]);
+
+ // And "Series 2".
+ CPPUNIT_ASSERT_EQUAL(size_t(4), aYValues[1].size());
+ CPPUNIT_ASSERT_EQUAL(2.4, aYValues[1][0]);
+ CPPUNIT_ASSERT_EQUAL(4.4, aYValues[1][1]);
+ CPPUNIT_ASSERT_EQUAL(1.8, aYValues[1][2]);
+ CPPUNIT_ASSERT_EQUAL(2.8, aYValues[1][3]);
+
+ // And "Series 3".
+ CPPUNIT_ASSERT_EQUAL(size_t(4), aYValues[2].size());
+ CPPUNIT_ASSERT_EQUAL(2.0, aYValues[2][0]);
+ CPPUNIT_ASSERT_EQUAL(2.0, aYValues[2][1]);
+ CPPUNIT_ASSERT_EQUAL(3.0, aYValues[2][2]);
+ CPPUNIT_ASSERT_EQUAL(5.0, aYValues[2][3]);
+
+ // Test the export.
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser[1]/c:xVal[1]/c:numRef[1]/c:numCache[1]/c:pt[1]/c:v[1]"_ostr, "1");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testScatterXAxisValues)
+{
+ loadFromFile(u"odt/tdf114657.odt");
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "//c:scatterChart/c:ser/c:xVal/c:numRef/c:numCache/c:ptCount"_ostr, "val"_ostr, "5");
+ assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser/c:xVal/c:numRef/c:numCache/c:pt[1]/c:v"_ostr, "15");
+ assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser/c:xVal/c:numRef/c:numCache/c:pt[2]/c:v"_ostr, "11");
+ assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser/c:xVal/c:numRef/c:numCache/c:pt[3]/c:v"_ostr, "20");
+ assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser/c:xVal/c:numRef/c:numCache/c:pt[4]/c:v"_ostr, "16");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testScatterXAxisCategories)
+{
+ loadFromFile(u"odt/tdf131143.odt");
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "//c:scatterChart/c:ser[1]/c:xVal/c:strRef/c:strCache/c:ptCount"_ostr, "val"_ostr, "4");
+ assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser[1]/c:xVal/c:strRef/c:strCache/c:pt[1]/c:v"_ostr, "Row 1");
+ assertXPathContent(pXmlDoc, "//c:scatterChart/c:ser[1]/c:xVal/c:strRef/c:strCache/c:pt[2]/c:v"_ostr, "Row 2");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testChartDataTable)
+{
+ loadFromFile(u"docx/testChartDataTable.docx");
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dTable/c:showHorzBorder"_ostr, "val"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dTable/c:showVertBorder"_ostr, "val"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dTable/c:showOutline"_ostr, "val"_ostr, "1");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testChartExternalData)
+{
+ loadFromFile(u"docx/testMultipleChart.docx");
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:externalData"_ostr);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testEmbeddingsGrabBag)
+{
+ // The problem was that .xlsx files were missing from docx file from embeddings folder
+ // after saving file.
+ // This test case tests whether embeddings files grabbagged properly in correct object.
+
+ loadFromFile(u"docx/testMultiplechartembeddings.docx" );
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xTextDocumentPropertySet(xTextDocument, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> aGrabBag(0);
+ xTextDocumentPropertySet->getPropertyValue("InteropGrabBag") >>= aGrabBag;
+ CPPUNIT_ASSERT(aGrabBag.hasElements()); // Grab Bag not empty
+ bool bEmbeddings = false;
+ const char* const testEmbeddedFileNames[] {"word/embeddings/Microsoft_Excel_Worksheet3.xlsx",
+ "word/embeddings/Microsoft_Excel_Worksheet2.xlsx",
+ "word/embeddings/Microsoft_Excel_Worksheet1.xlsx"};
+ for(beans::PropertyValue const & prop : std::as_const(aGrabBag))
+ {
+ if (prop.Name == "OOXEmbeddings")
+ {
+ bEmbeddings = true;
+ uno::Sequence<beans::PropertyValue> aEmbeddingsList(0);
+ uno::Reference<io::XInputStream> aEmbeddingXlsxStream;
+ OUString aEmbeddedfileName;
+ CPPUNIT_ASSERT(prop.Value >>= aEmbeddingsList); // PropertyValue of proper type
+ sal_Int32 length = aEmbeddingsList.getLength();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), length);
+ for(int j = 0; j < length; ++j)
+ {
+ aEmbeddingsList[j].Value >>= aEmbeddingXlsxStream;
+ aEmbeddedfileName = aEmbeddingsList[j].Name;
+ CPPUNIT_ASSERT(aEmbeddingXlsxStream); // Reference not empty
+ CPPUNIT_ASSERT_EQUAL(OUString::createFromAscii(testEmbeddedFileNames[j]),aEmbeddedfileName);
+ }
+ }
+ }
+ CPPUNIT_ASSERT(bEmbeddings); // Grab Bag has all the expected elements
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testAreaChartLoad)
+{
+ loadFromFile(u"docx/testAreaChartLoad.docx");
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:areaChart/c:ser/c:dLbls/c:showVal"_ostr, "val"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:areaChart/c:ser/c:dLbls/c:dLbl"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testUpDownBars)
+{
+ loadFromFile(u"docx/UpDownBars.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:upDownBars"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testDoughnutChart)
+{
+ loadFromFile(u"docx/doughnutChart.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:doughnutChart"_ostr);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testDisplayUnits)
+{
+ loadFromFile(u"docx/DisplayUnits.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:dispUnits/c:builtInUnit"_ostr, "val"_ostr, "billions");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testFdo74115WallGradientFill)
+{
+ loadFromFile(u"docx/fdo74115_WallGradientFill.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill"_ostr);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testFdo74115WallBitmapFill)
+{
+ loadFromFile(u"docx/fdo74115_WallBitmapFill.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:blipFill"_ostr);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testPieChartWallLineStyle)
+{
+ loadFromFile(u"odt/testPieChartWallLineStyle.odt");
+
+ // FIXME: validation error in OOXML export: Errors: 9
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:ln/a:noFill"_ostr);
+}
+
+//The below test case tests the built in marker 'x' for Office 2010 in Line charts
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testFdo78290LineChartMarkerX)
+{
+ loadFromFile(u"docx/fdo78290_Line_Chart_Marker_x.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:marker[1]/c:symbol[1]"_ostr,"val"_ostr,"x");
+ assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:marker[1]/c:size[1]"_ostr,"val"_ostr,"7");
+}
+
+// We can also use the built in marker 'x' in scatter chart, hence writing the test case for the same.
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testFdo78290ScatterChartMarkerX)
+{
+ loadFromFile(u"docx/fdo78290_Scatter_Chart_Marker_x.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:scatterChart[1]/c:ser[1]/c:marker[1]/c:symbol[1]"_ostr,"val"_ostr,"x");
+ assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:scatterChart[1]/c:ser[1]/c:marker[1]/c:size[1]"_ostr,"val"_ostr,"7");
+}
+
+// Also in a combination of charts like a column chart and line chart, we can use the built in marker 'x'
+// for the line chart too. hence put a test case for the combination chart also.
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testFdo78290CombinationChartMarkerX)
+{
+ loadFromFile(u"docx/fdo78290_Combination_Chart_Marker_x.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:marker[1]/c:symbol[1]"_ostr,"val"_ostr,"x");
+ assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:marker[1]/c:size[1]"_ostr,"val"_ostr,"7");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testTdf126115IndividualMarker)
+{
+ // Check individual marker properties.
+ loadFromFile(u"xlsx/tdf126115.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // 1. series
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:dPt/c:marker/c:symbol"_ostr, "val"_ostr, "square");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:dPt/c:marker/c:size"_ostr, "val"_ostr, "8");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:dPt/c:marker/c:spPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "ff0000");
+ // 2. series
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[2]/c:dPt/c:marker/c:symbol"_ostr, "val"_ostr, "x");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[2]/c:dPt/c:marker/c:size"_ostr, "val"_ostr, "15");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[2]/c:dPt/c:marker/c:spPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "7030a0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testAxisNumberFormatODS)
+{
+ struct
+ {
+ void check( const Reference<chart2::XChartDocument>& xChartDoc )
+ {
+ Reference<chart2::XAxis> xAxisX = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ Reference<chart2::XTitled> xTitle(xAxisX, UNO_QUERY_THROW);
+ OUString aTitleText = getTitleString(xTitle);
+ CPPUNIT_ASSERT_EQUAL(OUString("Linked To Source"), aTitleText);
+
+ sal_Int32 nNumFmt = getNumberFormatFromAxis(xAxisX);
+ sal_Int16 nType = getNumberFormatType(xChartDoc, nNumFmt);
+ CPPUNIT_ASSERT_MESSAGE("X axis should be percentage format.", (nType & util::NumberFormat::PERCENT));
+
+ bool bNumFmtLinked = false;
+ Reference<beans::XPropertySet> xPS(xAxisX, uno::UNO_QUERY_THROW);
+ xPS->getPropertyValue("LinkNumberFormatToSource") >>= bNumFmtLinked;
+ CPPUNIT_ASSERT_MESSAGE("X axis should have its number format linked to source.", bNumFmtLinked);
+
+ Reference<chart2::XAxis> xAxisY = getAxisFromDoc(xChartDoc, 0, 1, 0);
+ xTitle.set(xAxisY, UNO_QUERY_THROW);
+ aTitleText = getTitleString(xTitle);
+ CPPUNIT_ASSERT_EQUAL(OUString("Not Linked"), aTitleText);
+
+ nNumFmt = getNumberFormatFromAxis(xAxisY);
+ nType = getNumberFormatType(xChartDoc, nNumFmt);
+ CPPUNIT_ASSERT_MESSAGE("Y axis should be a normal number format.", (nType & util::NumberFormat::NUMBER));
+
+ bNumFmtLinked = true;
+ xPS.set(xAxisY, uno::UNO_QUERY_THROW);
+ xPS->getPropertyValue("LinkNumberFormatToSource") >>= bNumFmtLinked;
+ CPPUNIT_ASSERT_MESSAGE("Y axis should not have its number format linked to source.", !bNumFmtLinked);
+ }
+
+ } aTest;
+
+ loadFromFile(u"ods/axis-numformats-linked.ods");
+
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ aTest.check(xChartDoc);
+
+ // Reload the document and make sure everything remains intact.
+ saveAndReload("calc8");
+ xChartDoc = getChartDocFromSheet(0, mxComponent);
+ aTest.check(xChartDoc);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testAxisNumberFormatXLS)
+{
+ struct
+ {
+ void check( const Reference<chart2::XChartDocument>& xChartDoc, bool bNumFmtLinkedActual, sal_Int16 nNumFmtTypeFlag ) const
+ {
+ Reference<chart2::XAxis> xAxisY = getAxisFromDoc( xChartDoc, 0, 1, 0 );
+ bool bNumFmtLinked = false;
+ Reference<beans::XPropertySet> xPS( xAxisY, uno::UNO_QUERY_THROW );
+ xPS->getPropertyValue( "LinkNumberFormatToSource" ) >>= bNumFmtLinked;
+
+ if ( bNumFmtLinkedActual )
+ CPPUNIT_ASSERT_MESSAGE( "Y axis should have its number format linked to source.", bNumFmtLinked );
+ else
+ {
+ CPPUNIT_ASSERT_MESSAGE( "Y axis should not have its number format linked to source.", !bNumFmtLinked );
+
+ sal_Int32 nNumFmt = getNumberFormatFromAxis( xAxisY );
+ sal_Int16 nType = getNumberFormatType( xChartDoc, nNumFmt );
+ if ( nNumFmtTypeFlag == util::NumberFormat::PERCENT )
+ CPPUNIT_ASSERT_MESSAGE( "Y axis should be percentage format.", ( nType & util::NumberFormat::PERCENT ) );
+ else
+ CPPUNIT_ASSERT_MESSAGE( "Y axis should be number format.", ( nType & util::NumberFormat::NUMBER ) );
+ }
+ }
+
+ void change( const Reference<chart2::XChartDocument>& xChartDoc, sal_Int16 nNumFmtTypeFlag )
+ {
+ Reference<chart2::XAxis> xAxisY = getAxisFromDoc( xChartDoc, 0, 1, 0 );
+ Reference<beans::XPropertySet> xPS( xAxisY, uno::UNO_QUERY_THROW );
+ Any aAny( false );
+ xPS->setPropertyValue( "LinkNumberFormatToSource", aAny );
+
+ Reference<util::XNumberFormatsSupplier> xNFS( xChartDoc, uno::UNO_QUERY_THROW );
+ Reference<util::XNumberFormats> xNumberFormats = xNFS->getNumberFormats();
+ CPPUNIT_ASSERT( xNumberFormats.is() );
+ lang::Locale aLocale{ "en", "US", "" };
+ Sequence<sal_Int32> aNumFmts = xNumberFormats->queryKeys( nNumFmtTypeFlag, aLocale, false );
+ CPPUNIT_ASSERT( aNumFmts.hasElements() );
+ aAny <<= aNumFmts[0];
+ xPS->setPropertyValue( CHART_UNONAME_NUMFMT, aAny );
+ }
+
+ } aTest;
+
+ loadFromFile(u"xls/axis_sourceformatting.xls" );
+
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ aTest.check( xChartDoc, true, util::NumberFormat::PERCENT );
+
+ aTest.change( xChartDoc, util::NumberFormat::NUMBER );
+ // Write the document(xls) with changes made close it, load it and check if changes are intact
+ saveAndReload( "MS Excel 97" );
+ xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ aTest.check( xChartDoc, false, util::NumberFormat::NUMBER );
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testDataLabelBordersDOCX)
+{
+ struct Check
+ {
+ sal_Int32 mnIndex;
+ css::drawing::LineStyle meStyle;
+ Color mnColor;
+ };
+
+ struct
+ {
+ /**
+ * Chart 1 has 4 bars of which 1st and 3rd have labels with borders
+ * around them.
+ */
+ void checkObject1( const Reference<chart2::XChartDocument>& xChartDoc )
+ {
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ // Check to make sure that data points 0 and 2 have local properties.
+ Reference<beans::XPropertySet> xPropSet(xDataSeries, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPropSet.is());
+
+ Sequence<sal_Int32> aIndices;
+ xPropSet->getPropertyValue("AttributedDataPoints") >>= aIndices;
+ /*
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be 2 data points with local properties.", sal_Int32(2), aIndices.getLength());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aIndices[0]);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aIndices[1]);
+ */
+
+ static const Check aDataPoints[] =
+ {
+ { 0, css::drawing::LineStyle_SOLID, 0x00FFFF00 }, // solid yellow
+ { 2, css::drawing::LineStyle_SOLID, 0x00FF0000 } // solid red
+ };
+
+ for (size_t i = 0; i < std::size(aDataPoints); ++i)
+ {
+ xPropSet = xDataSeries->getDataPointByIndex(aDataPoints[i].mnIndex);
+ CPPUNIT_ASSERT(xPropSet.is());
+
+ css::drawing::LineStyle eLineStyle = css::drawing::LineStyle_NONE;
+ xPropSet->getPropertyValue(CHART_UNONAME_LABEL_BORDER_STYLE) >>= eLineStyle;
+ CPPUNIT_ASSERT_EQUAL(aDataPoints[i].meStyle, eLineStyle);
+
+ sal_Int32 nWidth = -1;
+ xPropSet->getPropertyValue(CHART_UNONAME_LABEL_BORDER_WIDTH) >>= nWidth;
+ CPPUNIT_ASSERT(nWidth > 0);
+
+ Color nColor;
+ xPropSet->getPropertyValue(CHART_UNONAME_LABEL_BORDER_COLOR) >>= nColor;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Border color is wrong.", aDataPoints[i].mnColor, nColor);
+ }
+ }
+
+ /**
+ * Chart 2 has all its data labels with identical borders.
+ */
+ void checkObject2( const Reference<chart2::XChartDocument>& xChartDoc )
+ {
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ Reference<beans::XPropertySet> xPropSet(xDataSeries, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPropSet.is());
+
+ css::drawing::LineStyle eLineStyle = css::drawing::LineStyle_NONE;
+ xPropSet->getPropertyValue(CHART_UNONAME_LABEL_BORDER_STYLE) >>= eLineStyle;
+ CPPUNIT_ASSERT_EQUAL(css::drawing::LineStyle_SOLID, eLineStyle);
+
+ sal_Int32 nWidth = -1;
+ xPropSet->getPropertyValue(CHART_UNONAME_LABEL_BORDER_WIDTH) >>= nWidth;
+ CPPUNIT_ASSERT(nWidth > 0);
+
+ Color nColor;
+ xPropSet->getPropertyValue(CHART_UNONAME_LABEL_BORDER_COLOR) >>= nColor;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Border color should be green.", COL_LIGHTGREEN, nColor);
+ }
+
+ } aTest;
+
+ loadFromFile(u"docx/data-label-borders.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+
+ // "Automatic" chart background fill in docx should be loaded as solid white.
+ Reference<beans::XPropertySet> xPropSet = xChartDoc->getPageBackground();
+ CPPUNIT_ASSERT(xPropSet.is());
+ drawing::FillStyle eStyle = xPropSet->getPropertyValue("FillStyle").get<drawing::FillStyle>();
+ sal_Int32 nColor = xPropSet->getPropertyValue("FillColor").get<sal_Int32>();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chart background fill in docx should be loaded as solid fill.",
+ drawing::FillStyle_SOLID, eStyle);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chart background fill in docx should be loaded as solid white.",
+ sal_Int32(0x00FFFFFF), sal_Int32(nColor & 0x00FFFFFF)); // highest 2 bytes are transparency which we ignore here.
+
+ aTest.checkObject1(xChartDoc);
+ xChartDoc.set(getChartDocFromWriter(1), uno::UNO_QUERY);
+ aTest.checkObject2(xChartDoc);
+
+ // FIXME: validation error in OOXML export: Errors: 3
+ skipValidation();
+
+ saveAndReload("Office Open XML Text");
+
+ xChartDoc.set(getChartDocFromWriter(0), uno::UNO_QUERY);
+ aTest.checkObject1(xChartDoc);
+ xChartDoc.set(getChartDocFromWriter(1), uno::UNO_QUERY);
+ aTest.checkObject2(xChartDoc);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testDataLabel3DChartDOCX)
+{
+ loadFromFile(u"docx/3d-bar-label.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // We must not export label position attributes for 3D bar charts. The
+ // same rule also applies to several other 3D charts, apparently.
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bar3DChart/c:ser/c:dLbls/c:dLblPos"_ostr, 0);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bar3DChart/c:ser/c:dLbls/c:dLbl/c:dLblPos"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testDataLabelBarChartDOCX)
+{
+ loadFromFile(u"docx/bar-chart-labels.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls/c:dLblPos"_ostr, "val"_ostr, "ctr");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[2]/c:dLbls/c:dLblPos"_ostr, "val"_ostr, "inEnd");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[3]/c:dLbls/c:dLblPos"_ostr, "val"_ostr, "inBase");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testDataLabelClusteredBarChartDOCX)
+{
+ loadFromFile(u"docx/clustered-bar-chart-labels.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // FIXME: validation error in OOXML export: Errors: 9
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // This was "t", should be one of the allowed values.
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls/c:dLbl[2]/c:dLblPos"_ostr, "val"_ostr, "outEnd");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testDataLabelRadarChartDOCX)
+{
+ loadFromFile(u"docx/radar-chart-labels.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // We must not export label position attributes for radar charts.
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:radarChart/c:ser/c:dLbls/c:dLblPos"_ostr, 0);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:radarChart/c:ser/c:dLbls/c:dLbl/c:dLblPos"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testDataLabelDoughnutChartDOCX)
+{
+ loadFromFile(u"docx/doughnut-chart-labels.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // We must not export label position attributes for doughnut charts.
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:doughnutChart/c:ser/c:dLbls/c:dLblPos"_ostr, 0);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:doughnutChart/c:ser/c:dLbls/c:dLbl/c:dLblPos"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testDataLabelAreaChartDOCX)
+{
+ loadFromFile(u"docx/area-chart-labels.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // We must not export label position attributes for area charts.
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:areaChart/c:ser/c:dLbls/c:dLblPos"_ostr, 0);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:areaChart/c:ser/c:dLbls/c:dLbl/c:dLblPos"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testDataLabelDefaultLineChartDOCX)
+{
+ // This file was created by Word 2007, which doesn't provide default data
+ // label position (2010 does). Make sure its default data label position
+ // is RIGHT when exporting.
+
+ loadFromFile(u"docx/line-chart-label-default-placement.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ saveAndReload("Office Open XML Text");
+
+ xChartDoc.set(getChartDocFromWriter(0), uno::UNO_QUERY);
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ Reference<beans::XPropertySet> xPropSet(xDataSeries, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPropSet.is());
+ sal_Int32 nLabelPlacement = -1;
+ if (xPropSet->getPropertyValue("LabelPlacement") >>= nLabelPlacement)
+ // This option may not be set. Check its value only when it's set.
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Line chart's default label placement should be 'right'.", chart::DataLabelPlacement::RIGHT, nLabelPlacement );
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testIndividualDataLabelProps)
+{
+ loadFromFile(u"xlsx/tdf122915.xlsx");
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[3]/c:dLbls/c:dLbl/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "b"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[3]/c:dLbls/c:dLbl/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "sz"_ostr, "1600");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[3]/c:dLbls/c:dLbl/c:txPr/a:p/a:pPr/a:defRPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "ff0000");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[3]/c:dLbls/c:dLbl/c:txPr/a:p/a:pPr/a:defRPr/a:latin"_ostr, "typeface"_ostr, "Times New Roman");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testBarChartRotation)
+{
+ loadFromFile(u"docx/barChartRotation.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotX"_ostr, "val"_ostr, "30");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotY"_ostr, "val"_ostr, "50");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testShapeFollowedByChart)
+{
+ /* If there is a scenario where a chart is followed by a shape
+ which is being exported as an alternate content then, the
+ docPr Id is being repeated, ECMA 20.4.2.5 says that the
+ docPr Id should be unique, ensuring the same here.
+ */
+ loadFromFile(u"docx/FDO74430.docx");
+
+ // FIXME: validation error in OOXML export: Errors: 5
+ skipValidation();
+
+ save("Office Open XML Text" );
+ xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ OUString aValueOfFirstDocPR = getXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r[1]/w:drawing[1]/wp:inline[1]/wp:docPr[1]"_ostr, "id"_ostr);
+ OUString aValueOfSecondDocPR = getXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/wp:docPr[1]"_ostr, "id"_ostr);
+
+ CPPUNIT_ASSERT( aValueOfFirstDocPR != aValueOfSecondDocPR );
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testPieChartDataLabels)
+{
+ loadFromFile(u"docx/PieChartDataLabels.docx");
+
+ // FIXME: validation error in OOXML export: Errors: 19
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pie3DChart/c:ser[1]/c:dLbls/c:dLbl[1]/c:dLblPos"_ostr, "val"_ostr, "outEnd");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testSeriesIdxOrder)
+{
+ loadFromFile(u"docx/testSeriesIdxOrder.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:idx[1]"_ostr, "val"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace[1]/c:chart[1]/c:plotArea[1]/c:lineChart[1]/c:ser[1]/c:order[1]"_ostr, "val"_ostr, "1");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testScatterPlotLabels)
+{
+ loadFromFile(u"odt/scatter-plot-labels.odt");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XChartType> xCT = getChartTypeFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xCT.is());
+
+ // Make sure the original chart has 'a', 'b', 'c' as its data labels.
+ std::vector<uno::Sequence<uno::Any> > aLabels = getDataSeriesLabelsFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("a"), aLabels[0][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("b"), aLabels[1][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("c"), aLabels[2][0].get<OUString>());
+
+ // Reload the doc and check again. The labels should not change.
+ saveAndReload("writer8");
+
+ xChartDoc.set(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ xCT = getChartTypeFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xCT.is());
+
+ aLabels = getDataSeriesLabelsFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("a"), aLabels[0][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("b"), aLabels[1][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("c"), aLabels[2][0].get<OUString>());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testErrorBarDataRangeODS)
+{
+ loadFromFile(u"ods/ErrorBarRange.ods");
+ saveAndReload("calc8");
+
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT( xDataSeries.is() );
+
+ Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW );
+
+ // test that y error bars are there
+ Reference< beans::XPropertySet > xErrorBarYProps;
+ xPropSet->getPropertyValue(CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarYProps;
+ uno::Any aAny = xErrorBarYProps->getPropertyValue("ErrorBarRangePositive");
+ CPPUNIT_ASSERT(aAny.hasValue());
+ OUString aPosRange;
+ aAny >>= aPosRange;
+ CPPUNIT_ASSERT_EQUAL(OUString("$Sheet1.$B$1:$B$3"), aPosRange);
+
+ aAny = xErrorBarYProps->getPropertyValue("ErrorBarRangeNegative");
+ CPPUNIT_ASSERT(aAny.hasValue());
+ OUString aNegRange;
+ aAny >>= aNegRange;
+ CPPUNIT_ASSERT_EQUAL(OUString("$Sheet1.$C$1:$C$3"), aNegRange);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testChartCrash)
+{
+ loadFromFile(u"docx/FDO75975.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testPieChartRotation)
+{
+ loadFromFile(u"docx/pieChartRotation.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotX"_ostr, "val"_ostr, "40");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:view3D/c:rotY"_ostr, "val"_ostr, "30");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testEmbeddingsOleObjectGrabBag)
+{
+ // The problem was that .bin files were missing from docx file from embeddings folder
+ // after saving file.
+ // This test case tests whether embeddings files grabbagged properly in correct object.
+
+ loadFromFile(u"docx/testchartoleobjectembeddings.docx" );
+ uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xTextDocumentPropertySet(xTextDocument, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> aGrabBag(0);
+ xTextDocumentPropertySet->getPropertyValue("InteropGrabBag") >>= aGrabBag;
+ CPPUNIT_ASSERT(aGrabBag.hasElements()); // Grab Bag not empty
+ bool bEmbeddings = false;
+ const char* const testEmbeddedFileNames[] = {"word/embeddings/oleObject1.bin"};
+ for(beans::PropertyValue const & prop : std::as_const(aGrabBag))
+ {
+ if (prop.Name == "OOXEmbeddings")
+ {
+ bEmbeddings = true;
+ uno::Sequence<beans::PropertyValue> aEmbeddingsList(0);
+ uno::Reference<io::XInputStream> aEmbeddingXlsxStream;
+ OUString aEmbeddedfileName;
+ CPPUNIT_ASSERT(prop.Value >>= aEmbeddingsList); // PropertyValue of proper type
+ sal_Int32 length = aEmbeddingsList.getLength();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), length);
+ for(int j = 0; j < length; ++j)
+ {
+ aEmbeddingsList[j].Value >>= aEmbeddingXlsxStream;
+ aEmbeddedfileName = aEmbeddingsList[j].Name;
+ CPPUNIT_ASSERT(aEmbeddingXlsxStream); // Reference not empty
+ CPPUNIT_ASSERT_EQUAL(OUString::createFromAscii(testEmbeddedFileNames[j]),aEmbeddedfileName);
+ }
+ }
+ }
+ CPPUNIT_ASSERT(bEmbeddings); // Grab Bag has all the expected elements
+}
+
+namespace {
+
+void checkGapWidth(Reference<beans::XPropertySet> const & xPropSet, sal_Int32 nValue)
+{
+ uno::Any aAny = xPropSet->getPropertyValue("GapwidthSequence");
+ CPPUNIT_ASSERT(aAny.hasValue());
+ uno::Sequence< sal_Int32 > aSequence;
+ aAny >>= aSequence;
+ CPPUNIT_ASSERT(aSequence.hasElements());
+ CPPUNIT_ASSERT_EQUAL(nValue, aSequence[0]);
+}
+
+void checkOverlap(Reference<beans::XPropertySet> const & xPropSet, sal_Int32 nValue)
+{
+ uno::Any aAny = xPropSet->getPropertyValue("OverlapSequence");
+ CPPUNIT_ASSERT(aAny.hasValue());
+ uno::Sequence< sal_Int32 > aSequence;
+ aAny >>= aSequence;
+ CPPUNIT_ASSERT(aSequence.hasElements());
+ CPPUNIT_ASSERT_EQUAL(nValue, aSequence[0]);
+}
+
+void checkSheetForGapWidthAndOverlap(uno::Reference< chart2::XChartDocument > const & xChartDoc,
+ sal_Int32 nExpectedGapWidth, sal_Int32 nExpectedOverlap)
+{
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XChartType > xChartType = getChartTypeFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT(xChartType.is());
+
+ Reference< beans::XPropertySet > xPropSet( xChartType, uno::UNO_QUERY_THROW );
+ checkGapWidth(xPropSet, nExpectedGapWidth);
+ checkOverlap(xPropSet, nExpectedOverlap);
+
+}
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testGapWidthXLSX)
+{
+ loadFromFile(u"xlsx/gapWidth.xlsx");
+
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ checkSheetForGapWidthAndOverlap(xChartDoc, 120, -60);
+
+ xChartDoc = getChartDocFromSheet( 1, mxComponent );
+ checkSheetForGapWidthAndOverlap(xChartDoc, 50, 30);
+
+ saveAndReload("Calc Office Open XML");
+
+ xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ checkSheetForGapWidthAndOverlap(xChartDoc, 120, -60);
+
+ xChartDoc = getChartDocFromSheet( 1, mxComponent );
+ checkSheetForGapWidthAndOverlap(xChartDoc, 50, 30);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testSmoothedLines)
+{
+ loadFromFile(u"ods/smoothedLines.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[1]/c:smooth"_ostr, "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest, testLabelStringODS)
+{
+ loadFromFile(u"ods/labelString.ods");
+
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ Reference< chart2::data::XDataSequence > xLabelSeq =
+ getLabelDataSequenceFromDoc(xChartDoc);
+ CPPUNIT_ASSERT(xLabelSeq.is());
+
+ OUString aLabelString = xLabelSeq->getSourceRangeRepresentation();
+ CPPUNIT_ASSERT_EQUAL(OUString("\"LabelName\""), aLabelString);
+
+ saveAndReload("calc8");
+
+ xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ xLabelSeq = getLabelDataSequenceFromDoc(xChartDoc);
+ CPPUNIT_ASSERT(xLabelSeq.is());
+
+ aLabelString = xLabelSeq->getSourceRangeRepresentation();
+ CPPUNIT_ASSERT_EQUAL(OUString("\"LabelName\""), aLabelString);
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/chart2export2.cxx b/chart2/qa/extras/chart2export2.cxx
new file mode 100644
index 0000000000..f5378dc944
--- /dev/null
+++ b/chart2/qa/extras/chart2export2.cxx
@@ -0,0 +1,1685 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "charttest.hxx"
+
+#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+
+using uno::Reference;
+using beans::XPropertySet;
+
+class Chart2ExportTest2 : public ChartTest
+{
+public:
+ Chart2ExportTest2()
+ : ChartTest("/chart2/qa/extras/data/")
+ {
+ }
+};
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testSetSeriesToSecondaryAxisXLSX)
+{
+ loadFromFile(u"xlsx/add_series_secondary_axis.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ // Second series
+ Reference<chart2::XDataSeries> xSeries = getDataSeriesFromDoc(xChartDoc, 1);
+ CPPUNIT_ASSERT(xSeries.is());
+
+ Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY_THROW);
+ sal_Int32 AxisIndex = 1;
+ // Attach the second series to the secondary axis. (The third series is already attached.)
+ xPropSet->setPropertyValue("AttachedAxisIndex", uno::Any(AxisIndex));
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // Check there are only two <lineChart> tag in the XML, one for the primary and one for the secondary axis.
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart"_ostr, 2);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCombinedChartSecondaryAxisXLSX)
+{
+ // Original file was created with MS Office
+ loadFromFile(u"xlsx/combined_chart_secondary_axis.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // Collect barchart axID on secondary Axis
+ OUString XValueIdOfBarchart = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[1]"_ostr, "val"_ostr);
+ OUString YValueIdOfBarchart = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[2]"_ostr, "val"_ostr);
+ // Collect linechart axID on primary Axis
+ OUString XValueIdOfLinechart = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[1]"_ostr, "val"_ostr);
+ OUString YValueIdOfLinechart = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[2]"_ostr, "val"_ostr);
+ // Check which c:catAx and c:valAx contain the AxisId of charttypes
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx[1]/c:axId"_ostr, "val"_ostr,
+ XValueIdOfLinechart);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[1]/c:axId"_ostr, "val"_ostr,
+ YValueIdOfLinechart);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx[2]/c:axId"_ostr, "val"_ostr,
+ XValueIdOfBarchart);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:axId"_ostr, "val"_ostr,
+ YValueIdOfBarchart);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCombinedChartSecondaryAxisODS)
+{
+ // Original file was created with LibreOffice
+ loadFromFile(u"ods/combined_chart_secondary_axis.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // Collect barchart axID on secondary Axis
+ OUString XValueIdOfBarchart = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[1]"_ostr, "val"_ostr);
+ OUString YValueIdOfBarchart = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[2]"_ostr, "val"_ostr);
+ // Collect linechart axID on primary Axis
+ OUString XValueIdOfLinechart = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[1]"_ostr, "val"_ostr);
+ OUString YValueIdOfLinechart = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[2]"_ostr, "val"_ostr);
+ // Check which c:catAx and c:valAx contain the AxisId of charttypes
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx[1]/c:axId"_ostr, "val"_ostr,
+ XValueIdOfLinechart);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[1]/c:axId"_ostr, "val"_ostr,
+ YValueIdOfLinechart);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx[2]/c:axId"_ostr, "val"_ostr,
+ XValueIdOfBarchart);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:axId"_ostr, "val"_ostr,
+ YValueIdOfBarchart);
+ // do not need CT_crosses tag if the actual axis is deleted, so we need to make sure it is not saved
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx[2]/c:crosses"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCrossBetweenXLSX)
+{
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ // Original files were created with MS Office
+ {
+ loadFromFile(u"xlsx/tdf127777.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween"_ostr,
+ "val"_ostr, "between");
+ }
+ {
+ loadFromFile(u"xlsx/tdf132076.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween"_ostr,
+ "val"_ostr, "between");
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCrossBetweenWithDeletedAxis)
+{
+ // Original file was created with MS Office (the category axis is deleted in the file)
+ loadFromFile(u"xlsx/tdf128633.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween"_ostr, "val"_ostr,
+ "between");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCrossBetweenODS)
+{
+ // Original file was created with LibreOffice
+ loadFromFile(u"ods/test_CrossBetween.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween"_ostr, "val"_ostr,
+ "between");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testAxisTitleRotationXLSX)
+{
+ loadFromFile(u"xlsx/axis_title_rotation.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:title/c:tx/c:rich/a:bodyPr"_ostr,
+ "rot"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testAxisTitlePositionDOCX)
+{
+ loadFromFile(u"docx/testAxisTitlePosition.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // test X Axis title position
+ OUString aXVal = getXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:title/c:layout/c:manualLayout/c:x"_ostr,
+ "val"_ostr);
+ double nX = aXVal.toDouble();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.698208543867708, nX, 1e-3);
+ OUString aYVal = getXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:title/c:layout/c:manualLayout/c:y"_ostr,
+ "val"_ostr);
+ double nY = aYVal.toDouble();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.805152435594555, nY, 1e-3);
+
+ // test Y Axis title position
+ aXVal = getXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:title/c:layout/c:manualLayout/c:x"_ostr,
+ "val"_ostr);
+ nX = aXVal.toDouble();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0253953671500755, nX, 1e-3);
+ aYVal = getXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:title/c:layout/c:manualLayout/c:y"_ostr,
+ "val"_ostr);
+ nY = aYVal.toDouble();
+ // just test the first two decimal digits because it is not perfect in docx yet.
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.384070199122511, nY, 1e-2);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testAxisCrossBetweenDOCX)
+{
+ loadFromFile(u"odt/axis-position.odt");
+
+ // FIXME: validation error in OOXML export: Errors: 3
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ assertXPath(pXmlDoc, "(//c:crossBetween)[1]"_ostr, "val"_ostr, "midCat");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testPieChartDataPointExplosionXLSX)
+{
+ loadFromFile(u"xlsx/pie_chart_datapoint_explosion.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dPt/c:explosion"_ostr,
+ "val"_ostr, "28");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCustomDataLabel)
+{
+ loadFromFile(u"pptx/tdf115107.pptx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ float nFontSize;
+ sal_Int64 nFontColor;
+ sal_Int32 nCharUnderline;
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+
+ // 1
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT,
+ aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("90.0 = "), aFields[0]->getString());
+ aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xed7d31), nFontColor);
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE,
+ aFields[1]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("90"), aFields[1]->getString());
+ CPPUNIT_ASSERT_EQUAL(OUString("{0C576297-5A9F-4B4E-A675-B6BA406B7D87}"), aFields[1]->getGuid());
+
+ // 2
+ xPropertySet.set(xDataSeries->getDataPointByIndex(1), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(8), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT,
+ aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("Text"), aFields[0]->getString());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT,
+ aFields[1]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString(" : "), aFields[1]->getString());
+
+ CPPUNIT_ASSERT_EQUAL(
+ chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CATEGORYNAME,
+ aFields[2]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("B"), aFields[2]->getString());
+ CPPUNIT_ASSERT_EQUAL(OUString("{0CCAAACD-B393-42CE-8DBD-82F9F9ADC852}"), aFields[2]->getGuid());
+ aFields[2]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[2]->getPropertyValue("CharColor") >>= nFontColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(16), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xed7d31), nFontColor);
+
+ CPPUNIT_ASSERT_EQUAL(
+ chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE,
+ aFields[3]->getFieldType());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT,
+ aFields[4]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("Multi"), aFields[4]->getString());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT,
+ aFields[5]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("line"), aFields[5]->getString());
+ aFields[5]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[5]->getPropertyValue("CharColor") >>= nFontColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(11.97), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xbf9000), nFontColor);
+
+ CPPUNIT_ASSERT_EQUAL(
+ chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE,
+ aFields[6]->getFieldType());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT,
+ aFields[7]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("Abc"), aFields[7]->getString());
+ aFields[7]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[7]->getPropertyValue("CharColor") >>= nFontColor;
+ aFields[7]->getPropertyValue("CharUnderline") >>= nCharUnderline;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(12), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xa9d18e), nFontColor);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nCharUnderline);
+
+ // 3
+ xPropertySet.set(xDataSeries->getDataPointByIndex(2), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(
+ chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME,
+ aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("DATA"), aFields[0]->getString());
+ CPPUNIT_ASSERT_EQUAL(OUString("{C8F3EB90-8960-4F9A-A3AD-B4FAC4FE4566}"), aFields[0]->getGuid());
+
+ // 4
+ xPropertySet.set(xDataSeries->getDataPointByIndex(3), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(
+ chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLREF,
+ aFields[0]->getFieldType());
+ //CPPUNIT_ASSERT_EQUAL(OUString("70"), aFields[0]->getString()); TODO: Not implemented yet
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT,
+ aFields[1]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString(" <CELLREF"), aFields[1]->getString());
+
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // Check the data labels font color for the complete data series
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:txPr/a:p/a:pPr/"
+ "a:defRPr/a:solidFill/a:srgbClr"_ostr,
+ "val"_ostr, "404040");
+}
+
+/// Test for tdf#94235
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testDataSeriesName)
+{
+ // ODF
+ {
+ loadFromFile(u"ods/ser_labels.ods");
+ saveAndReload("calc8");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ chart2::DataPointLabel aDataPointLabel;
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("Label") >>= aDataPointLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_True, aDataPointLabel.ShowSeriesName);
+ }
+
+ // OOXML
+ {
+ loadFromFile(u"xlsx/ser_labels.xlsx");
+ saveAndReload("Calc Office Open XML");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ chart2::DataPointLabel aDataPointLabel;
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("Label") >>= aDataPointLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_True, aDataPointLabel.ShowSeriesName);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCustomPositionofDataLabel)
+{
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ loadFromFile(u"xlsx/testCustomPosDataLabels.xlsx");
+ {
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // test custom position of data label (xlsx)
+ assertXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:dLbls/c:dLbl[1]/c:idx"_ostr,
+ "val"_ostr, "2");
+ OUString aXVal = getXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:dLbls/"
+ "c:dLbl[1]/c:layout/c:manualLayout/c:x"_ostr,
+ "val"_ostr);
+ double nX = aXVal.toDouble();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.11027682973075476, nX, 1e-7);
+
+ OUString aYVal = getXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:dLbls/"
+ "c:dLbl[1]/c:layout/c:manualLayout/c:y"_ostr,
+ "val"_ostr);
+ double nY = aYVal.toDouble();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.0742140311063737, nY, 1e-7);
+ }
+
+ loadFromFile(u"docx/testTdf108110.docx");
+ {
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // test custom position of data label (docx)
+ assertXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:dLbls/c:dLbl[2]/c:idx"_ostr,
+ "val"_ostr, "2");
+ OUString aXVal = getXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:dLbls/"
+ "c:dLbl[2]/c:layout/c:manualLayout/c:x"_ostr,
+ "val"_ostr);
+ double nX = aXVal.toDouble();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0227256488772236, nX, 1e-7);
+
+ OUString aYVal = getXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:dLbls/"
+ "c:dLbl[2]/c:layout/c:manualLayout/c:y"_ostr,
+ "val"_ostr);
+ double nY = aYVal.toDouble();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.172648731408574, nY, 1e-7);
+ }
+
+ loadFromFile(u"ods/tdf136024.ods");
+ {
+ saveAndReload("calc8");
+ // tdf#136024: test custom position of pie chart data label after an ods export
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(0),
+ uno::UNO_SET_THROW);
+
+ chart2::RelativePosition aCustomLabelPosition;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("CustomLabelPosition")
+ >>= aCustomLabelPosition);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.0961935120945059, aCustomLabelPosition.Primary, 1e-5);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.209578842093566, aCustomLabelPosition.Secondary, 1e-5);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCustomDataLabelMultipleSeries)
+{
+ loadFromFile(u"pptx/tdf115107-2.pptx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ float nFontSize;
+ sal_Int64 nFontColor;
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+
+ // First series
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE,
+ aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("4.3"), aFields[0]->getString());
+ aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xc00000), nFontColor);
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT,
+ aFields[1]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString(" "), aFields[1]->getString());
+
+ CPPUNIT_ASSERT_EQUAL(
+ chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME,
+ aFields[2]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("Bars"), aFields[2]->getString());
+
+ // Second series
+ xDataSeries = getDataSeriesFromDoc(xChartDoc, 0, 1);
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE,
+ aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("2"), aFields[0]->getString());
+ aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xffd966), nFontColor);
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT,
+ aFields[1]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString(" "), aFields[1]->getString());
+
+ CPPUNIT_ASSERT_EQUAL(
+ chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME,
+ aFields[2]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("Line"), aFields[2]->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testLeaderLines)
+{
+ // FIXME: validation error in OOXML export: Errors: 2
+ skipValidation();
+
+ loadFromFile(u"xlsx/testTdf90749.xlsx");
+ {
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[1]/c:dLbls/c:extLst/c:ext/"
+ "c15:showLeaderLines"_ostr,
+ "val"_ostr, "1");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[2]/c:dLbls/c:extLst/c:ext/"
+ "c15:showLeaderLines"_ostr,
+ "val"_ostr, "0");
+ }
+ loadFromFile(u"docx/MSO_Custom_Leader_Line.docx");
+ {
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // tdf#134571: Check the leader line is switch off.
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:extLst/c:ext/"
+ "c15:showLeaderLines"_ostr,
+ "val"_ostr, "0");
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testNumberFormatExportPPTX)
+{
+ loadFromFile(u"pptx/tdf115859.pptx");
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:numFmt"_ostr,
+ "formatCode"_ostr, "#,##0.00,\\K");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:numFmt"_ostr,
+ "sourceLinked"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testLabelSeparatorExportDOCX)
+{
+ loadFromFile(u"docx/testLabelSeparator.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // The text separator should be a new line
+ assertXPathContent(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls/c:separator"_ostr,
+ "\n");
+ // The text separator should be a comma
+ assertXPathContent(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[2]/c:dLbls/c:separator"_ostr,
+ ", ");
+ // The text separator should be a semicolon
+ assertXPathContent(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[3]/c:dLbls/c:separator"_ostr,
+ "; ");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartTitlePropertiesColorFillPPTX)
+{
+ loadFromFile(u"pptx/testChartTitlePropertiesColorFill.pptx");
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:solidFill/a:srgbClr"_ostr,
+ "val"_ostr, "ff0000");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartTitlePropertiesGradientFillPPTX)
+{
+ loadFromFile(u"pptx/testChartTitlePropertiesGradientFill.pptx");
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr"_ostr,
+ "val"_ostr, "f6f8fc");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr"_ostr,
+ "val"_ostr, "c7d5ed");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testChartTitlePropertiesBitmapFillPPTX)
+{
+ loadFromFile(u"pptx/testChartTitlePropertiesBitmapFill.pptx");
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:blipFill/a:blip"_ostr,
+ "embed"_ostr, "rId1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testxAxisLabelsRotation)
+{
+ loadFromFile(u"xlsx/xAxisLabelsRotation.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc1 = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc1);
+
+ // Chart1 xAxis labels should be 45 degree
+ assertXPath(pXmlDoc1, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:bodyPr"_ostr,
+ "rot"_ostr, "2700000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testMultipleCategoryAxisLablesXLSX)
+{
+ loadFromFile(u"ods/multilevelcat.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // check category axis labels number of first level
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/c:multiLvlStrRef/"
+ "c:multiLvlStrCache/c:ptCount"_ostr,
+ "val"_ostr, "6");
+ // check category axis labels text of first level
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/"
+ "c:multiLvlStrRef/c:multiLvlStrCache/c:lvl[1]/c:pt[1]/c:v"_ostr,
+ "Categoria 1");
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/"
+ "c:multiLvlStrRef/c:multiLvlStrCache/c:lvl[1]/c:pt[6]/c:v"_ostr,
+ "Categoria 6");
+ // check category axis labels text of second level
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/"
+ "c:multiLvlStrRef/c:multiLvlStrCache/c:lvl[2]/c:pt[1]/c:v"_ostr,
+ "2011");
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/"
+ "c:multiLvlStrRef/c:multiLvlStrCache/c:lvl[2]/c:pt[3]/c:v"_ostr,
+ "2013");
+ // check the 'noMultiLvlLbl' tag - ChartExport.cxx:2950 FIXME: seems not support, so check the default noMultiLvlLbl value.
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:noMultiLvlLbl"_ostr,
+ "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testMultipleCategoryAxisLablesDOCX)
+{
+ loadFromFile(u"odt/multilevelcat.odt");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // check category axis labels number of first level
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/c:multiLvlStrRef/"
+ "c:multiLvlStrCache/c:ptCount"_ostr,
+ "val"_ostr, "4");
+ // check category axis labels text of first level
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/"
+ "c:multiLvlStrRef/c:multiLvlStrCache/c:lvl[1]/c:pt[1]/c:v"_ostr,
+ "Categoria 1");
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/"
+ "c:multiLvlStrRef/c:multiLvlStrCache/c:lvl[1]/c:pt[4]/c:v"_ostr,
+ "Categoria 4");
+ // check category axis labels text of second level
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/"
+ "c:multiLvlStrRef/c:multiLvlStrCache/c:lvl[2]/c:pt[1]/c:v"_ostr,
+ "2011");
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/"
+ "c:multiLvlStrRef/c:multiLvlStrCache/c:lvl[2]/c:pt[2]/c:v"_ostr,
+ "2012");
+ // check the 'noMultiLvlLbl' tag - ChartExport.cxx:2950 FIXME: seems not support, so check the default noMultiLvlLbl value.
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:noMultiLvlLbl"_ostr,
+ "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf116163)
+{
+ loadFromFile(u"pptx/tdf116163.pptx");
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:bodyPr"_ostr,
+ "rot"_ostr, "-5400000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf111824)
+{
+ loadFromFile(u"xlsx/tdf111824.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // Collect 3D barchart Z axID
+ OUString zAxisIdOf3DBarchart = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bar3DChart/c:axId[3]"_ostr, "val"_ostr);
+ // 3D barchart Z axis properties should be in a serAx OOXML tag instead of catAx
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:serAx/c:axId"_ostr, "val"_ostr,
+ zAxisIdOf3DBarchart);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, test3DAreaChartZAxis)
+{
+ loadFromFile(u"xlsx/test3DAreaChartZAxis.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // Collect 3D area chart Z axID
+ OUString zAxisIdOf3DAreachart = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:area3DChart/c:axId[3]"_ostr, "val"_ostr);
+ // 3D area chart z-axis properties should be in a serAx OOXML element instead of catAx
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:serAx/c:axId"_ostr, "val"_ostr,
+ zAxisIdOf3DAreachart);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf119029)
+{
+ loadFromFile(u"odp/tdf119029.odp");
+ // Only use "chart", without number, because the number depends on the previous tests
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:txPr/a:bodyPr"_ostr,
+ "rot"_ostr, "-5400000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf108022)
+{
+ loadFromFile(u"odt/tdf108022.odt");
+ saveAndReload("Office Open XML Text");
+
+ // assert we really have two charts
+ Reference<chart2::XChartDocument> xChartDoc1(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc1.is());
+ Reference<chart2::XChartDocument> xChartDoc2(getChartDocFromWriter(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc2.is());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf121744)
+{
+ loadFromFile(u"docx/tdf121744.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ OUString XValueId = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[1]"_ostr, "val"_ostr);
+ OUString YValueId = getXPath(
+ pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:axId[2]"_ostr, "val"_ostr);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[1]"_ostr, "val"_ostr,
+ XValueId);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:axId[2]"_ostr, "val"_ostr,
+ YValueId);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf121189)
+{
+ loadFromFile(u"odp/tdf121189.odp");
+ saveAndReload("Impress Office Open XML");
+
+ uno::Reference<drawing::XDrawPagesSupplier> xDoc(mxComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0),
+ uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xPage->getCount());
+ uno::Reference<drawing::XShape> xShape(xPage->getByIndex(0), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.OLE2Shape"), xShape->getShapeType());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf122031)
+{
+ //Checks pie chart data label format.
+ loadFromFile(u"xlsx/tdf122031.xlsx");
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:numFmt"_ostr,
+ "formatCode"_ostr, "0.000%");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[1]/c:numFmt"_ostr,
+ "formatCode"_ostr, "0.000%");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[2]/c:numFmt"_ostr,
+ "formatCode"_ostr, "0.000%");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[3]/c:numFmt"_ostr,
+ "formatCode"_ostr, "0.000%");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf115012)
+{
+ loadFromFile(u"xlsx/tdf115012.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // workaround: use-zero instead of leave-gap to show the original line chart
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:dispBlanksAs"_ostr, "val"_ostr, "zero");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf134118)
+{
+ loadFromFile(u"xlsx/tdf134118.xlsx");
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // workaround: use leave-gap instead of zero to show the original line chart
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:dispBlanksAs"_ostr, "val"_ostr, "gap");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf123206_customLabelText)
+{
+ loadFromFile(u"docx/tdf123206.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // FIXME: validation error in OOXML export: Errors: 2
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[2]/c:tx/"
+ "c:rich/a:p/a:r/a:t"_ostr,
+ "kiscica");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCustomLabelText)
+{
+ loadFromFile(u"docx/testCustomlabeltext.docx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // FIXME: validation error in OOXML export: Errors: 3
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl[1]/c:idx"_ostr,
+ "val"_ostr, "2");
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl[1]/c:tx/"
+ "c:rich/a:p/a:r[1]/a:t"_ostr,
+ "3.5");
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl[1]/c:tx/"
+ "c:rich/a:p/a:r[3]/a:t"_ostr,
+ "CustomLabel 1");
+
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl[2]/c:idx"_ostr,
+ "val"_ostr, "3");
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl[2]/c:tx/"
+ "c:rich/a:p/a:r[1]/a:t"_ostr,
+ "4.5");
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl[2]/c:tx/"
+ "c:rich/a:p/a:r[3]/a:t"_ostr,
+ "CustomLabel 2");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testDeletedLegendEntries)
+{
+ loadFromFile(u"xlsx/deleted_legend_entry.xlsx");
+ {
+ saveAndReload("Calc Office Open XML");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 1));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropertySet(xDataSeries, uno::UNO_QUERY_THROW);
+ bool bShowLegendEntry = true;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("ShowLegendEntry") >>= bShowLegendEntry);
+ CPPUNIT_ASSERT(!bShowLegendEntry);
+ }
+
+ loadFromFile(u"xlsx/deleted_legend_entry2.xlsx");
+ {
+ saveAndReload("Calc Office Open XML");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropertySet(xDataSeries, uno::UNO_QUERY_THROW);
+ bool bShowLegendEntry = true;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("ShowLegendEntry") >>= bShowLegendEntry);
+ CPPUNIT_ASSERT(!bShowLegendEntry);
+
+ Reference<chart2::XChartDocument> xChartDoc2 = getChartDocFromSheet(1, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries2(getDataSeriesFromDoc(xChartDoc2, 0));
+ CPPUNIT_ASSERT(xDataSeries2.is());
+ Reference<beans::XPropertySet> xPropertySet2(xDataSeries2, uno::UNO_QUERY_THROW);
+ Sequence<sal_Int32> deletedLegendEntriesSeq;
+ CPPUNIT_ASSERT(xPropertySet2->getPropertyValue("DeletedLegendEntries")
+ >>= deletedLegendEntriesSeq);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), deletedLegendEntriesSeq[0]);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf60316)
+{
+ loadFromFile(u"pptx/tdf60316.pptx");
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // Without the fix in place, the shape would have had a solidFill background
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:noFill"_ostr, 1);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:solidFill"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf130225)
+{
+ loadFromFile(u"docx/piechart_deleted_legend_entry.docx");
+ saveAndReload("Office Open XML Text");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropertySet(xDataSeries, uno::UNO_QUERY_THROW);
+ Sequence<sal_Int32> deletedLegendEntriesSeq;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("DeletedLegendEntries")
+ >>= deletedLegendEntriesSeq);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), deletedLegendEntriesSeq[0]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf59857)
+{
+ loadFromFile(u"ods/tdf59857.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:floor/c:spPr/a:ln/a:noFill"_ostr, 1);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:floor/c:spPr/a:solidFill/a:srgbClr"_ostr,
+ "val"_ostr, "cccccc");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:backWall/c:spPr/a:ln/a:noFill"_ostr, 0);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:backWall/c:spPr/a:ln/a:solidFill/a:srgbClr"_ostr,
+ "val"_ostr, "b3b3b3");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf126076)
+{
+ loadFromFile(u"xlsx/auto_marker_excel10.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // This was 12: all series exported with square markers
+ assertXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:marker/c:symbol[@val='square']"_ostr,
+ 0);
+ // instead of skipping markers
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:marker"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf75330)
+{
+ loadFromFile(u"ods/legend_overlay.ods");
+ saveAndReload("calc8");
+ {
+ uno::Reference<chart2::XChartDocument> xChart2Doc = getChartDocFromSheet(0, mxComponent);
+ uno::Reference<chart::XChartDocument> xChartDoc(xChart2Doc, uno::UNO_QUERY);
+ uno::Reference<drawing::XShape> xLegend = xChartDoc->getLegend();
+ Reference<beans::XPropertySet> xPropertySet(xLegend, uno::UNO_QUERY_THROW);
+ bool bOverlay = false;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("Overlay") >>= bOverlay);
+ CPPUNIT_ASSERT(bOverlay);
+ }
+ saveAndReload("Calc Office Open XML");
+ {
+ uno::Reference<chart2::XChartDocument> xChart2Doc = getChartDocFromSheet(0, mxComponent);
+ uno::Reference<chart::XChartDocument> xChartDoc(xChart2Doc, uno::UNO_QUERY);
+ uno::Reference<drawing::XShape> xLegend = xChartDoc->getLegend();
+ Reference<beans::XPropertySet> xPropertySet(xLegend, uno::UNO_QUERY_THROW);
+ bool bOverlay = false;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("Overlay") >>= bOverlay);
+ CPPUNIT_ASSERT(bOverlay);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf127792)
+{
+ loadFromFile(u"docx/MSO_axis_position.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween"_ostr, "val"_ostr,
+ "between");
+
+ pXmlDoc = parseExport("word/charts/chart2.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:crossBetween"_ostr, "val"_ostr,
+ "midCat");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf131979)
+{
+ loadFromFile(u"ods/tdf131115.ods");
+ {
+ saveAndReload("calc8");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropertySet;
+ xPropertySet.set(xDataSeries->getDataPointByIndex(2), uno::UNO_SET_THROW);
+ bool blinknumberformattosource = true;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT)
+ >>= blinknumberformattosource);
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to false.",
+ !blinknumberformattosource);
+ }
+
+ loadFromFile(u"ods/tdf131979.ods");
+ {
+ saveAndReload("calc8");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropertySet;
+ xPropertySet.set(xDataSeries->getDataPointByIndex(2), uno::UNO_SET_THROW);
+ bool blinknumberformattosource = true;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT)
+ >>= blinknumberformattosource);
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to true.",
+ blinknumberformattosource);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf132076)
+{
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ {
+ loadFromFile(u"ods/tdf132076.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:numFmt"_ostr,
+ "formatCode"_ostr, "dd");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:numFmt"_ostr,
+ "sourceLinked"_ostr, "0");
+ }
+ {
+ loadFromFile(u"xlsx/tdf132076.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dateAx/c:numFmt"_ostr,
+ "formatCode"_ostr, "dd");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dateAx/c:numFmt"_ostr,
+ "sourceLinked"_ostr, "0");
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf125812)
+{
+ loadFromFile(u"odp/ellipticalGradientFill.odp");
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path"_ostr,
+ "path"_ostr, "circle");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path/a:fillToRect"_ostr,
+ "l"_ostr, "50000");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path/a:fillToRect"_ostr,
+ "t"_ostr, "49000");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path/a:fillToRect"_ostr,
+ "r"_ostr, "50000");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path/a:fillToRect"_ostr,
+ "b"_ostr, "51000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf133190)
+{
+ loadFromFile(u"xlsx/tdf133190_tdf133191.xlsx");
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // Test word wrap of data point label
+ assertXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[1]/c:txPr/a:bodyPr"_ostr,
+ "wrap"_ostr, "none");
+ assertXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[2]/c:txPr/a:bodyPr"_ostr,
+ "wrap"_ostr, "square");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf133191)
+{
+ loadFromFile(u"xlsx/tdf133190_tdf133191.xlsx");
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // Test rotation of data point label
+ assertXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[3]/c:txPr/a:bodyPr"_ostr,
+ "rot"_ostr, "-4500000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf132594)
+{
+ loadFromFile(u"xlsx/chart_pie2007.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:cat"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf134255)
+{
+ loadFromFile(u"docx/tdf134255.docx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // import test
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropSet(xDataSeries, UNO_QUERY_THROW);
+ bool bWrap = false;
+ CPPUNIT_ASSERT((xPropSet->getPropertyValue("TextWordWrap") >>= bWrap));
+ CPPUNIT_ASSERT(bWrap);
+
+ // FIXME: validation error in OOXML export: Errors: 11
+ skipValidation();
+
+ // export test
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:txPr/a:bodyPr"_ostr,
+ "wrap"_ostr, "square");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf134977)
+{
+ loadFromFile(u"xlsx/custom_data_label.xlsx");
+
+ //import test
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(0),
+ uno::UNO_SET_THROW);
+ uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+ float nFontSize;
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(9), nFontSize);
+
+ // FIXME: validation error in OOXML export: Errors: 2
+ skipValidation();
+
+ //export test
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl/c:tx/c:rich/a:p/"
+ "a:r/a:rPr"_ostr,
+ "sz"_ostr, "900");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf123647)
+{
+ loadFromFile(u"xlsx/empty_chart.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf136267)
+{
+ loadFromFile(u"xlsx/tdf136267.xlsx");
+
+ // FIXME: validation error in OOXML export: Errors: 2
+ skipValidation();
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPathContent(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:cat/c:strRef/c:strCache/c:pt/c:v"_ostr,
+ "John");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testDataLabelPlacementPieChart)
+{
+ loadFromFile(u"xlsx/tdf134978.xlsx");
+ saveAndReload("calc8");
+ uno::Reference<chart::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ UNO_QUERY_THROW);
+ // test the placement of the manually positioned label
+ Reference<beans::XPropertySet> xDataPointPropSet(
+ xChartDoc->getDiagram()->getDataPointProperties(2, 0), uno::UNO_SET_THROW);
+ uno::Any aAny = xDataPointPropSet->getPropertyValue("LabelPlacement");
+ CPPUNIT_ASSERT(aAny.hasValue());
+ sal_Int32 nLabelPlacement = 0;
+ CPPUNIT_ASSERT(aAny >>= nLabelPlacement);
+ CPPUNIT_ASSERT_EQUAL(chart::DataLabelPlacement::OUTSIDE, nLabelPlacement);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf137917)
+{
+ loadFromFile(u"xlsx/tdf137917.xlsx");
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dateAx/c:baseTimeUnit"_ostr,
+ "val"_ostr, "days");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dateAx/c:majorUnit"_ostr, "val"_ostr,
+ "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dateAx/c:majorTimeUnit"_ostr,
+ "val"_ostr, "months");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dateAx/c:minorUnit"_ostr, "val"_ostr,
+ "7");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:dateAx/c:minorTimeUnit"_ostr,
+ "val"_ostr, "days");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf138204)
+{
+ loadFromFile(u"xlsx/tdf138204.xlsx");
+
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ struct CustomLabelsTestData
+ {
+ sal_Int32 nSeriesIdx;
+ sal_Int32 nNumFields;
+ // First field attributes.
+ chart2::DataPointCustomLabelFieldType eFieldType;
+ OUString aCellRange;
+ OUString aString;
+ };
+
+ const CustomLabelsTestData aTestEntries[2] = {
+ {
+ // series id of c:ser[1] is 0.
+ 0, // nSeriesIdx
+ 1, // nNumFields
+ chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLRANGE,
+ "Munka1!$F$9", // aCellRange
+ "67,5%", // aString
+ },
+ {
+
+ // series id of c:ser[2] is 1.
+ 1, // nSeriesIdx
+ 1, // nNumFields
+ chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLRANGE,
+ "Munka1!$G$9", // aCellRange
+ "32,3%", // aString
+ },
+ };
+
+ for (const auto& aTestEntry : aTestEntries)
+ {
+ uno::Reference<chart2::XDataSeries> xDataSeries(
+ getDataSeriesFromDoc(xChartDoc, aTestEntry.nSeriesIdx));
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(aTestEntry.nNumFields, aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(aTestEntry.eFieldType, aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(aTestEntry.aCellRange, aFields[0]->getCellRange());
+ CPPUNIT_ASSERT_EQUAL(aTestEntry.aString, aFields[0]->getString());
+ }
+
+ // FIXME: validation error in OOXML export: Errors: 2
+ skipValidation();
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // Check the first data label field type
+ assertXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls/c:dLbl/c:tx/c:rich/a:p/a:fld"_ostr,
+ "type"_ostr, "CELLRANGE");
+
+ assertXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[2]/c:dLbls/c:dLbl/c:tx/c:rich/a:p/a:fld"_ostr,
+ "type"_ostr, "CELLRANGE");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf138181)
+{
+ loadFromFile(u"xlsx/piechart_deleted_legendentry.xlsx");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xLegendEntry1, xLegendEntry2, xLegendEntry3;
+
+ // first legend entry is visible
+ xLegendEntry1
+ = getShapeByName(xShapes, "CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0:LegendEntry=0");
+ CPPUNIT_ASSERT(xLegendEntry1.is());
+
+ // second legend entry is not visible
+ xLegendEntry2
+ = getShapeByName(xShapes, "CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1:LegendEntry=0");
+ CPPUNIT_ASSERT(!xLegendEntry2.is());
+
+ // third legend entry is visible
+ xLegendEntry3
+ = getShapeByName(xShapes, "CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2:LegendEntry=0");
+ CPPUNIT_ASSERT(xLegendEntry3.is());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testCustomShapeText)
+{
+ loadFromFile(u"ods/tdf72776.ods");
+ saveAndReload("calc8");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+ // test that the text of custom shape exists inside the chart
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShape> xCustomShape(xDrawPage->getByIndex(1), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xCustomShape.is());
+
+ Reference<text::XText> xRange(xCustomShape, uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(!xRange->getString().isEmpty());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testuserShapesXLSX)
+{
+ loadFromFile(u"xlsx/tdf128621.xlsx");
+ saveAndReload("Calc Office Open XML");
+
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // test that the custom shape exists
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShape> xCustomShape(xDrawPage->getByIndex(1), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xCustomShape.is());
+ // test type of shape
+ CPPUNIT_ASSERT(xCustomShape->getShapeType().endsWith("CustomShape"));
+ // test custom shape position
+ awt::Point aPosition = xCustomShape->getPosition();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1356, aPosition.X, 300);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(9107, aPosition.Y, 300);
+ // test custom shape size
+ awt::Size aSize = xCustomShape->getSize();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(9520, aSize.Width, 300);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1805, aSize.Height, 300);
+ // test custom shape text
+ Reference<text::XText> xRange(xCustomShape, uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(!xRange->getString().isEmpty());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testuserShapesDOCX)
+{
+ loadFromFile(u"docx/tdf143130.docx");
+ saveAndReload("Office Open XML Text");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // test that the custom shape exists
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShape> xCustomShape(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xCustomShape.is());
+ // test type of shape
+ CPPUNIT_ASSERT(xCustomShape->getShapeType().endsWith("CustomShape"));
+ // test custom shape position
+ awt::Point aPosition = xCustomShape->getPosition();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(9824, aPosition.X, 300);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(547, aPosition.Y, 300);
+ // test custom shape size
+ awt::Size aSize = xCustomShape->getSize();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1848, aSize.Width, 300);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1003, aSize.Height, 300);
+ // test custom shape text
+ Reference<text::XText> xRange(xCustomShape, uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(!xRange->getString().isEmpty());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testGraphicBlipXLSX)
+{
+ loadFromFile(u"xlsx/tdf143127.xlsx");
+ saveAndReload("Calc Office Open XML");
+
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // test that the Graphic shape exists
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShape> xCustomShape(xDrawPage->getByIndex(1), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xCustomShape.is());
+ // test type of shape
+ CPPUNIT_ASSERT(xCustomShape->getShapeType().endsWith("GraphicObjectShape"));
+ Reference<XPropertySet> xShapeProps(xCustomShape, UNO_QUERY);
+
+ uno::Reference<graphic::XGraphic> xGraphic;
+ CPPUNIT_ASSERT(xShapeProps->getPropertyValue("Graphic") >>= xGraphic);
+
+ Graphic aGraphic(xGraphic);
+ GfxLink aLink = aGraphic.GetGfxLink();
+ std::size_t nDataSize = aLink.GetDataSize();
+
+ // test the image size is bigger then 0.
+ CPPUNIT_ASSERT_GREATER(size_t(0), nDataSize);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testNameRangeXLSX)
+{
+ loadFromFile(u"xlsx/chart_with_name_range.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // test the syntax of local range name on the local sheet.
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:cat/c:strRef/c:f"_ostr,
+ "Sheet1!local_name_range");
+ // test the syntax of a global range name.
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:val/c:numRef/c:f"_ostr,
+ "[0]!series1");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testTdf143942)
+{
+ loadFromFile(u"xlsx/tdf143942.xlsx");
+
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ constexpr size_t nLabels = 4;
+ OUString aCellRange = "Sheet1!$A$2:$A$5";
+ OUString aLabels[nLabels] = {
+ "Test1",
+ "Test2",
+ "Tes3",
+ "Test4",
+ };
+
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+ for (size_t i = 0; i < nLabels; ++i)
+ {
+ xPropertySet.set(xDataSeries->getDataPointByIndex(i), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aFields.getLength());
+ CPPUNIT_ASSERT_EQUAL(
+ chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLRANGE,
+ aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(aCellRange, aFields[0]->getCellRange());
+ CPPUNIT_ASSERT_EQUAL(aLabels[i], aFields[0]->getString());
+ }
+
+ // FIXME: validation error in OOXML export: Errors: 4
+ skipValidation();
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:extLst/c:ext"_ostr,
+ "uri"_ostr, "{02D57815-91ED-43cb-92C2-25804820EDAC}");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:extLst/c:ext/"
+ "c15:datalabelsRange/c15:dlblRangeCache/c:ptCount"_ostr,
+ "val"_ostr, "4");
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:extLst/c:ext/"
+ "c15:datalabelsRange/c15:f"_ostr,
+ aCellRange);
+ for (size_t i = 0; i < nLabels; ++i)
+ {
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:dLbls/c:dLbl["
+ + OString::number(i + 1) + "]/c:tx/c:rich/a:p/a:fld",
+ "type"_ostr, "CELLRANGE");
+ assertXPath(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:dLbls/c:dLbl["
+ + OString::number(i + 1) + "]/c:extLst/c:ext/c15:showDataLabelsRange",
+ "val"_ostr, "1");
+ // Check if the actual label is stored under c15:datalabelsRange
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser[1]/c:extLst/"
+ "c:ext/c15:datalabelsRange/c15:dlblRangeCache/c:pt["
+ + OString::number(i + 1) + "]/c:v",
+ aLabels[i]);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testDateCategoriesPPTX)
+{
+ loadFromFile(u"pptx/bnc889755.pptx");
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Impress Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ constexpr size_t nCats = 16;
+ double aDates[nCats] = {
+ 41183, 41214, 41244, 41275, 41306, 41334, 41365, 41395,
+ 41426, 41456, 41487, 41518, 41548, 41579, 41609, 41640,
+ };
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat"_ostr);
+ assertXPathContent(pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/c:numRef/"
+ "c:numCache/c:formatCode"_ostr,
+ "mmm\\-yy");
+ assertXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/c:numRef/c:numCache/c:ptCount"_ostr,
+ "val"_ostr, OUString::number(nCats));
+
+ for (size_t i = 0; i < nCats; ++i)
+ {
+ assertXPath(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/c:numRef/c:numCache/c:pt["
+ + OString::number(i + 1) + "]",
+ "idx"_ostr, OUString::number(i));
+ assertXPathContent(
+ pXmlDoc,
+ "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:cat/c:numRef/c:numCache/c:pt["
+ + OString::number(i + 1) + "]/c:v",
+ OUString::number(aDates[i]));
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest2, testDataTableImportExport)
+{
+ loadFromFile(u"xlsx/ChartDataTable.xlsx");
+ {
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ auto xDiagram = xChartDoc->getFirstDiagram();
+ CPPUNIT_ASSERT(xDiagram.is());
+ auto xDataTable = xDiagram->getDataTable();
+ CPPUNIT_ASSERT(xDataTable.is());
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataTable, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPropertySet.is());
+ bool bHBorder;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("HBorder") >>= bHBorder);
+ CPPUNIT_ASSERT_EQUAL(true, bHBorder);
+ bool bVBorder;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("VBorder") >>= bVBorder);
+ CPPUNIT_ASSERT_EQUAL(true, bVBorder);
+ bool bOutline;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("Outline") >>= bOutline);
+ CPPUNIT_ASSERT_EQUAL(false, bOutline);
+ bool bKeys;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("Keys") >>= bKeys);
+ CPPUNIT_ASSERT_EQUAL(false, bKeys);
+ }
+ saveAndReload("calc8");
+ {
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ auto xDiagram = xChartDoc->getFirstDiagram();
+ CPPUNIT_ASSERT(xDiagram.is());
+ auto xDataTable = xDiagram->getDataTable();
+ CPPUNIT_ASSERT(xDataTable.is());
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataTable, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPropertySet.is());
+ bool bHBorder;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("HBorder") >>= bHBorder);
+ CPPUNIT_ASSERT_EQUAL(true, bHBorder);
+ bool bVBorder;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("VBorder") >>= bVBorder);
+ CPPUNIT_ASSERT_EQUAL(true, bVBorder);
+ bool bOutline;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("Outline") >>= bOutline);
+ CPPUNIT_ASSERT_EQUAL(false, bOutline);
+ bool bKeys;
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("Keys") >>= bKeys);
+ CPPUNIT_ASSERT_EQUAL(false, bKeys);
+ }
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/chart2export3.cxx b/chart2/qa/extras/chart2export3.cxx
new file mode 100644
index 0000000000..838da77191
--- /dev/null
+++ b/chart2/qa/extras/chart2export3.cxx
@@ -0,0 +1,767 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "charttest.hxx"
+
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+#include <com/sun/star/chart2/MovingAverageType.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+
+using uno::Reference;
+using beans::XPropertySet;
+
+class Chart2ExportTest3 : public ChartTest
+{
+public:
+ Chart2ExportTest3() : ChartTest("/chart2/qa/extras/data/") {}
+};
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testTdf108107)
+{
+ loadFromFile(u"xlsx/tdf108107.xlsx");
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:dLbls/c:dLbl[1]/c:idx"_ostr, "val"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:dLbls/c:dLbl[1]/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "b"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser/c:dLbls/c:dLbl[1]/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "sz"_ostr, "2000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testTdf114139)
+{
+ loadFromFile(u"xlsx/tdf114139.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pie3DChart"_ostr, 1);
+ //no fill
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr"_ostr, 0);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:solidFill"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testTdf64224)
+{
+ loadFromFile(u"ods/tdf64224.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ //no fill
+ assertXPath(pXmlDoc, "/c:chartSpace/c:spPr/a:noFill"_ostr, 1);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:spPr/a:solidFill"_ostr, 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testChartTitlePropertiesColorFillDOCX)
+{
+ loadFromFile(u"docx/testChartTitlePropertiesColorFill.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "ff0000");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testChartTitlePropertiesGradientFillDOCX)
+{
+ loadFromFile(u"docx/testChartTitlePropertiesGradientFill.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr"_ostr, "val"_ostr, "cccccc");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr"_ostr, "val"_ostr, "666666");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testChartTitlePropertiesBitmapFillDOCX)
+{
+ loadFromFile(u"docx/testChartTitlePropertiesBitmapFill.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:blipFill/a:blip"_ostr, "embed"_ostr, "rId1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill"_ostr, 1);
+}
+
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testColorGradientWithTransparencyDOCX)
+{
+ // Test color gradient (two color) with gradient transparency
+ loadFromFile(u"docx/testColorGradientWithTransparency.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // Test the transparency of the first color
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr/a:alpha"_ostr, "val"_ostr, "60000");
+ // Test the transparency of the second color
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr/a:alpha"_ostr, "val"_ostr, "90000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testColorGradientWithTransparencyODS)
+{
+ // Test color gradient (two color) with simple transparency
+ loadFromFile(u"ods/testColorGradientWithTransparency.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // Test the transparency of the first color
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr/a:alpha"_ostr, "val"_ostr, "60000");
+ // Test the transparency of the second color
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr/a:alpha"_ostr, "val"_ostr, "60000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testColorGradientStopXLSX)
+{
+ // Test color gradient (two color) stop of the first color
+ loadFromFile(u"xlsx/tdf128619.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // Test the position of the first color
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:spPr/a:gradFill/a:gsLst/a:gs[1]"_ostr, "pos"_ostr, "45000");
+ // Test the position of the second color
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:spPr/a:gradFill/a:gsLst/a:gs[2]"_ostr, "pos"_ostr, "100000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testRadialColorGradientDOCX)
+{
+ loadFromFile(u"docx/tdf128794.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // Test the gradient style (if there is no 'a:path' attribute, it is a linear gradient)
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:path"_ostr, 0);
+ // Test the linear gradient angle
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill/a:lin"_ostr, "ang"_ostr, "13500000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testBarChartDataPointPropDOCX)
+{
+ loadFromFile(u"docx/testBarChartDataPointPropDOCX.docx");
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:varyColors"_ostr, "val"_ostr, "0");
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:idx"_ostr, "val"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr"_ostr, "val"_ostr, "f6f8fc");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr"_ostr, "val"_ostr, "c7d5ed");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:spPr/a:ln/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "70ad47");
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:idx"_ostr, "val"_ostr, "2");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:spPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "ff0000");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:spPr/a:ln/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "000000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testFdo83058dlblPos)
+{
+ loadFromFile(u"docx/fdo83058_dlblPos.docx");
+
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ save("Office Open XML Text");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls[1]/c:dLbl[2]/c:dLblPos"_ostr, "val"_ostr, "outEnd");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls[1]/c:dLbl[3]/c:dLblPos"_ostr, "val"_ostr, "outEnd");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls[1]/c:dLbl[4]/c:dLblPos"_ostr, "val"_ostr, "outEnd");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser[1]/c:dLbls[1]/c:dLbl[5]/c:dLblPos"_ostr, "val"_ostr, "outEnd");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testAutoTitleDelXLSX)
+{
+ loadFromFile(u"xlsx/autotitledel_2007.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:autoTitleDeleted"_ostr, "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testDispBlanksAsXLSX)
+{
+ loadFromFile(u"xlsx/dispBlanksAs_2007.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:dispBlanksAs"_ostr, "val"_ostr, "gap");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testMarkerColorXLSX)
+{
+ loadFromFile(u"xlsx/markerColor.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser/c:marker/c:spPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "92d050");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testRoundedCornersXLSX)
+{
+ loadFromFile(u"xlsx/markerColor.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:roundedCorners"_ostr, "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testAxisNumberFormatXLSX)
+{
+ loadFromFile(u"ods/axis_number_format.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx"_ostr, 2);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[1]/c:numFmt"_ostr, "formatCode"_ostr, "0.00E+000");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[1]/c:numFmt"_ostr, "sourceLinked"_ostr, "0");
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:numFmt"_ostr, "formatCode"_ostr, "[$$-409]#,##0;\\-[$$-409]#,##0");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:numFmt"_ostr, "sourceLinked"_ostr, "1");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testDataPointLabelNumberFormatXLSX)
+{
+ // FIXME: validation error in OOXML export: Errors: 1
+ skipValidation();
+
+ loadFromFile(u"ods/tdf123774.ods");
+ {
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:numFmt"_ostr, "formatCode"_ostr, "[$-40E]0.00%");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:numFmt"_ostr, "sourceLinked"_ostr, "0");
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[1]/c:numFmt"_ostr, "formatCode"_ostr, "[$-40E]0.00%");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:pieChart/c:ser/c:dLbls/c:dLbl[1]/c:numFmt"_ostr, "sourceLinked"_ostr, "0");
+ }
+
+ loadFromFile(u"xlsx/tdf130986.xlsx");
+ {
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl/c:idx"_ostr, "val"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl/c:numFmt"_ostr, "formatCode"_ostr, "0.00E+00");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLbl/c:numFmt"_ostr, "sourceLinked"_ostr, "0");
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testDataLabelDefaultValuesXLSX)
+{
+ loadFromFile(u"xlsx/data_label.xlsx");
+ Reference< chart2::XChartDocument> xDoc = getChartDocFromSheet(0, mxComponent);
+ Reference<chart2::XDataSeries> xSeries = getDataSeriesFromDoc(xDoc, 0);
+ Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("Label");
+ chart2::DataPointLabel aLabel;
+ CPPUNIT_ASSERT(aAny >>= aLabel);
+ CPPUNIT_ASSERT(aLabel.ShowNumber);
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:showVal"_ostr, "val"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:dLblPos"_ostr, "val"_ostr, "outEnd");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testDataLabelFillColor)
+{
+ loadFromFile(u"xlsx/data_labels_fill_color.xlsx");
+ Reference< chart2::XChartDocument> xDoc = getChartDocFromSheet(0, mxComponent);
+ Reference<chart2::XDataSeries> xSeries = getDataSeriesFromDoc(xDoc, 0);
+ Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("LabelFillColor");
+ sal_Int32 nLabelFillColor;
+ CPPUNIT_ASSERT(aAny >>= nLabelFillColor);
+
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dLbls/c:spPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "F79646");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testTitleOverlayXLSX)
+{
+ loadFromFile(u"xlsx/chart_title.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:overlay"_ostr, "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testInvertIfNegativeXLSX)
+{
+ loadFromFile(u"xlsx/bar_chart_simple.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:invertIfNegative"_ostr, "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testBubble3DXLSX)
+{
+ loadFromFile(u"xlsx/bubble_chart_simple.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bubbleChart/c:ser[1]/c:bubble3D"_ostr, "val"_ostr, "0");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bubbleChart/c:ser[2]/c:bubble3D"_ostr, "val"_ostr, "0");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:bubbleChart/c:ser[3]/c:bubble3D"_ostr, "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testNoMarkerXLSX)
+{
+ loadFromFile(u"xlsx/no_marker.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[1]/c:marker/c:symbol"_ostr, "val"_ostr, "none");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:ser[2]/c:marker/c:symbol"_ostr, "val"_ostr, "none");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:marker"_ostr, "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testTitleManualLayoutXLSX)
+{
+ loadFromFile(u"xlsx/title_manual_layout.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:layout/c:manualLayout/c:layoutTarget"_ostr, 0);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:layout/c:manualLayout/c:xMode"_ostr, "val"_ostr, "edge");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:layout/c:manualLayout/c:yMode"_ostr, "val"_ostr, "edge");
+
+ OUString aXVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:layout/c:manualLayout/c:x"_ostr, "val"_ostr);
+ double nX = aXVal.toDouble();
+ CPPUNIT_ASSERT(nX > 0);
+ CPPUNIT_ASSERT(nX < 1);
+
+ OUString aYVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:layout/c:manualLayout/c:y"_ostr, "val"_ostr);
+ double nY = aYVal.toDouble();
+ CPPUNIT_ASSERT(nY > 0);
+ CPPUNIT_ASSERT(nY < 1);
+ CPPUNIT_ASSERT(nX != nY);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:bodyPr"_ostr, "rot"_ostr, "1200000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testPlotAreaManualLayoutXLSX)
+{
+ loadFromFile(u"xlsx/plot_area_manual_layout.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:layoutTarget"_ostr, "val"_ostr, "inner");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:xMode"_ostr, "val"_ostr, "edge");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:yMode"_ostr, "val"_ostr, "edge");
+
+ OUString aXVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:x"_ostr, "val"_ostr);
+ double nX = aXVal.toDouble();
+ CPPUNIT_ASSERT(nX > 0);
+ CPPUNIT_ASSERT(nX < 1);
+
+ OUString aYVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:y"_ostr, "val"_ostr);
+ double nY = aYVal.toDouble();
+ CPPUNIT_ASSERT(nY > 0);
+ CPPUNIT_ASSERT(nY < 1);
+ CPPUNIT_ASSERT(nX != nY);
+
+ OUString aWVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:w"_ostr, "val"_ostr);
+ double nW = aWVal.toDouble();
+ CPPUNIT_ASSERT(nW > 0);
+ CPPUNIT_ASSERT(nW < 1);
+
+ OUString aHVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:h"_ostr, "val"_ostr);
+ double nH = aHVal.toDouble();
+ CPPUNIT_ASSERT(nH > 0);
+ CPPUNIT_ASSERT(nH < 1);
+ CPPUNIT_ASSERT(nH != nW);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testLegendManualLayoutXLSX)
+{
+ loadFromFile(u"xlsx/legend_manual_layout.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:layout/c:manualLayout/c:layoutTarget"_ostr, 0);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:xMode"_ostr, "val"_ostr, "edge");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:yMode"_ostr, "val"_ostr, "edge");
+
+ OUString aXVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:x"_ostr, "val"_ostr);
+ double nX = aXVal.toDouble();
+ CPPUNIT_ASSERT(nX > 0);
+ CPPUNIT_ASSERT(nX < 1);
+
+ OUString aYVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:y"_ostr, "val"_ostr);
+ double nY = aYVal.toDouble();
+ CPPUNIT_ASSERT(nY > 0);
+ CPPUNIT_ASSERT(nY < 1);
+ CPPUNIT_ASSERT(nX != nY);
+
+ OUString aWVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:w"_ostr, "val"_ostr);
+ double nW = aWVal.toDouble();
+ CPPUNIT_ASSERT(nW > 0);
+ CPPUNIT_ASSERT(nW < 1);
+
+ OUString aHVal = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:layout/c:manualLayout/c:h"_ostr, "val"_ostr);
+ double nH = aHVal.toDouble();
+ CPPUNIT_ASSERT(nH > 0);
+ CPPUNIT_ASSERT(nH < 1);
+ CPPUNIT_ASSERT(nH != nW);
+
+ // Make sure that default text font size is preserved after export
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:legend/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "sz"_ostr, "900");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testChartSubTitle)
+{
+ loadFromFile(u"ods/testChartSubTitle.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // test properties of subtitle
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr"_ostr, "sz"_ostr, "1100");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr"_ostr, "b"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "00a933");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:rPr/a:latin"_ostr, "typeface"_ostr, "Times New Roman");
+ assertXPathContent(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:t"_ostr, "It is a Subtitle");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "b2b2b2");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testChartMainWithSubTitle)
+{
+ loadFromFile(u"ods/testChartMainWithSubTitle.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // test properties of title
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr"_ostr, "sz"_ostr, "1300");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr"_ostr, "b"_ostr, "0");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr"_ostr, "i"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "f10d0c");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:rPr/a:latin"_ostr, "typeface"_ostr, "Arial");
+ assertXPathContent(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:t"_ostr, "It is a Maintitle\nIt is a Subtitle");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "81d41a");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testAutoTitleDeleted)
+{
+ loadFromFile(u"xlsx/testAutoTitleDeleted.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:autoTitleDeleted"_ostr, "val"_ostr, "1");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testChartTitlePropertiesColorFillXLSX)
+{
+ loadFromFile(u"xlsx/testChartTitlePropertiesColorFill.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "ff0000");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testChartTitlePropertiesGradientFillXLSX)
+{
+ loadFromFile(u"xlsx/testChartTitlePropertiesGradientFill.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr"_ostr, "val"_ostr, "cccccc");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr"_ostr, "val"_ostr, "666666");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testChartTitlePropertiesBitmapFillXLSX)
+{
+ loadFromFile(u"xlsx/testChartTitlePropertiesBitmapFill.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:blipFill/a:blip"_ostr, "embed"_ostr, "rId1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:spPr/a:ln/a:noFill"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testBarChartDataPointPropXLSX)
+{
+ loadFromFile(u"xlsx/testBarChartDataPointPropXLSX.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:varyColors"_ostr, "val"_ostr, "0");
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:idx"_ostr, "val"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:spPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "ff0000");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[1]/c:spPr/a:ln/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "000000");
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:idx"_ostr, "val"_ostr, "2");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr"_ostr, "val"_ostr, "f6f8fc");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr"_ostr, "val"_ostr, "c7d5ed");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:ser/c:dPt[2]/c:spPr/a:ln/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "70ad47");
+}
+
+namespace {
+
+void checkGapWidth(Reference<beans::XPropertySet> const & xPropSet, sal_Int32 nValue)
+{
+ uno::Any aAny = xPropSet->getPropertyValue("GapwidthSequence");
+ CPPUNIT_ASSERT(aAny.hasValue());
+ uno::Sequence< sal_Int32 > aSequence;
+ aAny >>= aSequence;
+ CPPUNIT_ASSERT(aSequence.hasElements());
+ CPPUNIT_ASSERT_EQUAL(nValue, aSequence[0]);
+}
+
+void checkOverlap(Reference<beans::XPropertySet> const & xPropSet, sal_Int32 nValue)
+{
+ uno::Any aAny = xPropSet->getPropertyValue("OverlapSequence");
+ CPPUNIT_ASSERT(aAny.hasValue());
+ uno::Sequence< sal_Int32 > aSequence;
+ aAny >>= aSequence;
+ CPPUNIT_ASSERT(aSequence.hasElements());
+ CPPUNIT_ASSERT_EQUAL(nValue, aSequence[0]);
+}
+
+void checkSheetForGapWidthAndOverlap(uno::Reference< chart2::XChartDocument > const & xChartDoc,
+ sal_Int32 nExpectedGapWidth, sal_Int32 nExpectedOverlap)
+{
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XChartType > xChartType = getChartTypeFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT(xChartType.is());
+
+ Reference< beans::XPropertySet > xPropSet( xChartType, uno::UNO_QUERY_THROW );
+ checkGapWidth(xPropSet, nExpectedGapWidth);
+ checkOverlap(xPropSet, nExpectedOverlap);
+
+}
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testDataseriesOverlapStackedChartXLSX)
+{
+ loadFromFile(u"xlsx/testDataseriesOverlapStackedChart.xlsx");
+
+ // test the overlap value of a simple Stacked Column Chart
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ checkSheetForGapWidthAndOverlap(xChartDoc, 100, 0);
+
+ // test the overlap value of a Percent Stacked Bar Chart
+ xChartDoc = getChartDocFromSheet( 1, mxComponent );
+ checkSheetForGapWidthAndOverlap(xChartDoc, 100, 35);
+
+ saveAndReload("Calc Office Open XML");
+
+ xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ checkSheetForGapWidthAndOverlap(xChartDoc, 100, 100);
+
+ xChartDoc = getChartDocFromSheet( 1, mxComponent );
+ checkSheetForGapWidthAndOverlap(xChartDoc, 100, 100);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testAxisCharacterPropertiesXLSX)
+{
+ loadFromFile(u"xlsx/axis_character_properties.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "sz"_ostr, "1000");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "b"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "i"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "u"_ostr, "sng");
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "sz"_ostr, "900");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "b"_ostr, "1");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:txPr/a:p/a:pPr/a:defRPr"_ostr, "strike"_ostr, "sngStrike");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:txPr/a:p/a:pPr/a:defRPr/a:solidFill/a:srgbClr"_ostr, "val"_ostr, "ff0000");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testTitleCharacterPropertiesXLSX)
+{
+ loadFromFile(u"xlsx/title_character_properties.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr"_ostr, "sz"_ostr, "2400");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:pPr/a:defRPr"_ostr, "b"_ostr, "1");
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:rPr"_ostr, "sz"_ostr, "2400");
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:title/c:tx/c:rich/a:p/a:r/a:rPr"_ostr, "b"_ostr, "1");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testPlotVisOnlyXLSX)
+{
+ loadFromFile(u"xlsx/hidden_cells.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotVisOnly"_ostr, "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testBarChartVaryColorsXLSX)
+{
+ loadFromFile(u"xlsx/tdf90876.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart/c:varyColors"_ostr, "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testTdf96161)
+{
+ loadFromFile(u"ods/tdf96161.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart/c:varyColors"_ostr, "val"_ostr, "0");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testTableOnPage3)
+{
+ loadFromFile(u"docx/TableOnPage3.docx");
+
+ // FIXME: validation error in OOXML export: Errors: 2
+ skipValidation();
+
+ saveAndReload("Office Open XML Text");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference< chart::XChartDataArray > xDataArray(xChartDoc->getDataProvider(), UNO_QUERY_THROW);
+ Sequence<OUString> aColumnDesc = xDataArray->getColumnDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There must be 4 columns and descriptions", static_cast<sal_Int32>(4), aColumnDesc.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("If oversubscription relative to allowance increases at the same average rate B15-B17"), aColumnDesc[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Known requirements"), aColumnDesc[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Allowance"), aColumnDesc[2]);
+ CPPUNIT_ASSERT_EQUAL(OUString("If oversubscription relative to allowance holds steady at average oversubscription level B15-B17"), aColumnDesc[3]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, tdf137691)
+{
+ // given a doc where the banana negative data formats as ($123) and the pineapple data as $(123)
+ loadFromFile(u"pptx/tdf137691_dataTable.pptx");
+ saveAndReload("Impress MS PowerPoint 2007 XML");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+
+ Reference< chart2::data::XDataSequence > xDataSeq;
+ xDataSeq.set(getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0));
+ const sal_Int32 nKey_bananas = xDataSeq->getNumberFormatKeyByIndex(-1);
+ // This should not be General format (0), but a defined format (129)
+ CPPUNIT_ASSERT(nKey_bananas);
+
+ xDataSeq.set(getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1));
+ const sal_Int32 nKey_pineapples = xDataSeq->getNumberFormatKeyByIndex(-1);
+ // This should not be General format (0), but a defined format (130)
+ CPPUNIT_ASSERT(nKey_pineapples);
+ CPPUNIT_ASSERT(nKey_pineapples != nKey_bananas);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testMultipleAxisXLSX)
+{
+ loadFromFile(u"ods/multiple_axis.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart"_ostr, 2);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart[1]/c:ser"_ostr, 1);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:scatterChart[2]/c:ser"_ostr, 1);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx"_ostr, 4);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:delete[@val='1']"_ostr, 1);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:axPos[@val='l']"_ostr, 1);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx/c:axPos[@val='r']"_ostr, 1);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testSecondaryAxisXLSX)
+{
+ loadFromFile(u"ods/secondary_axis.ods");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart"_ostr, 2);
+ // test there is just those series in the first <lineChart> tag which are attached to the primary axis
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart[1]/c:ser"_ostr, 2);
+ assertXPathContent(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart[1]/c:ser[1]/c:tx/c:strRef/c:strCache/c:pt/c:v"_ostr, "b");
+ assertXPathContent(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart[1]/c:ser[2]/c:tx/c:strRef/c:strCache/c:pt/c:v"_ostr, "c");
+ // test there is just those series in the second <lineChart> tag which are attached to the secondary axis
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart[2]/c:ser"_ostr, 1);
+ assertXPathContent(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:lineChart[2]/c:ser[1]/c:tx/c:strRef/c:strCache/c:pt/c:v"_ostr, "a");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testBarChartSecondaryAxisXLSX)
+{
+ loadFromFile(u"xlsx/testSecondaryAxis.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ // Collect barchart axID on primary Axis
+ OUString XValueIdOf1Barchart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart[1]/c:axId[1]"_ostr, "val"_ostr);
+ OUString YValueIdOf1Barchart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart[1]/c:axId[2]"_ostr, "val"_ostr);
+ // Collect barchart axID on secondary Axis
+ OUString XValueIdOf2Barchart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart[2]/c:axId[1]"_ostr, "val"_ostr);
+ OUString YValueIdOf2Barchart = getXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:barChart[2]/c:axId[2]"_ostr, "val"_ostr);
+ // Check which c:catAx and c:valAx contain the AxisId of barcharts
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx[1]/c:axId"_ostr, "val"_ostr, XValueIdOf1Barchart);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[1]/c:axId"_ostr, "val"_ostr, YValueIdOf1Barchart);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:catAx[2]/c:axId"_ostr, "val"_ostr, XValueIdOf2Barchart);
+ assertXPath(pXmlDoc, "/c:chartSpace/c:chart/c:plotArea/c:valAx[2]/c:axId"_ostr, "val"_ostr, YValueIdOf2Barchart);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ExportTest3, testTdf148142)
+{
+ // The document contains a line chart with "Between tick marks" X axis position.
+ loadFromFile(u"ods/tdf148142.ods");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xAxis.is());
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition);
+
+ // Set the X axis position to "On tick marks".
+ aScaleData.ShiftedCategoryPosition = false;
+ xAxis->setScaleData(aScaleData);
+
+ // Check the X axis position after export.
+ saveAndReload("calc8");
+ Reference<chart2::XChartDocument> xChartDoc2 = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc2.is());
+ Reference<chart2::XAxis> xAxis2 = getAxisFromDoc(xChartDoc2, 0, 0, 0);
+ CPPUNIT_ASSERT(xAxis2.is());
+ chart2::ScaleData aScaleData2 = xAxis2->getScaleData();
+ CPPUNIT_ASSERT(!aScaleData2.ShiftedCategoryPosition);
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/chart2geometry.cxx b/chart2/qa/extras/chart2geometry.cxx
new file mode 100644
index 0000000000..c7de713df1
--- /dev/null
+++ b/chart2/qa/extras/chart2geometry.cxx
@@ -0,0 +1,493 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "charttest.hxx"
+
+#include <test/xmltesttools.hxx>
+
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+
+#include <unotools/saveopt.hxx>
+
+#include <string_view>
+
+using uno::Reference;
+using beans::XPropertySet;
+
+class Chart2GeometryTest : public ChartTest
+{
+public:
+ Chart2GeometryTest()
+ : ChartTest("/chart2/qa/extras/data/")
+ {
+ }
+ // Mostly tests for line and fill properties
+ void testTdf135184RoundLineCap();
+ void testTdf135184RoundLineCap2();
+ void testTdf135184RoundLineCap3();
+ void testTdf135184RoundLineCap4();
+ void testTdf128345ChartArea_CG_TS_export();
+ void testTdf128345ChartArea_CG_TS_import();
+ void testTdf128345ChartWall_CS_TG_export();
+ void testTdf128345ChartWall_CS_TG_import();
+ void testTdf128345Legend_CS_TG_axial_export();
+ void testTdf128345Legend_CS_TG_axial_import();
+ void testTdf135366LabelOnSeries();
+ void testTdf135366LabelOnPoint();
+ void testTdf135366LabelExport();
+ void testTdf135366_CustomLabelText();
+
+ CPPUNIT_TEST_SUITE(Chart2GeometryTest);
+ CPPUNIT_TEST(testTdf135184RoundLineCap);
+ CPPUNIT_TEST(testTdf135184RoundLineCap2);
+ CPPUNIT_TEST(testTdf135184RoundLineCap3);
+ CPPUNIT_TEST(testTdf135184RoundLineCap4);
+ CPPUNIT_TEST(testTdf128345ChartArea_CG_TS_export);
+ CPPUNIT_TEST(testTdf128345ChartArea_CG_TS_import);
+ CPPUNIT_TEST(testTdf128345ChartWall_CS_TG_export);
+ CPPUNIT_TEST(testTdf128345ChartWall_CS_TG_import);
+ CPPUNIT_TEST(testTdf128345Legend_CS_TG_axial_export);
+ CPPUNIT_TEST(testTdf128345Legend_CS_TG_axial_import);
+ CPPUNIT_TEST(testTdf135366LabelOnSeries);
+ CPPUNIT_TEST(testTdf135366LabelOnPoint);
+ CPPUNIT_TEST(testTdf135366LabelExport);
+ CPPUNIT_TEST(testTdf135366_CustomLabelText);
+
+ CPPUNIT_TEST_SUITE_END();
+};
+
+static OString OU2O(std::u16string_view sOUSource)
+{
+ return rtl::OUStringToOString(sOUSource, RTL_TEXTENCODING_UTF8);
+}
+
+// Without the patch for tdf#135184, charts were not able to use linecap at all.
+// These two tests verify, that round linecaps in the xlsx file are saved in ods.
+void Chart2GeometryTest::testTdf135184RoundLineCap()
+{
+ // It tests chart area, data series line and regression-curve line.
+ loadFromFile(u"xlsx/tdf135184RoundLineCap.xlsx");
+ save("calc8");
+ xmlDocUniquePtr pXmlDoc = parseExport("Object 1/content.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ static constexpr OString sStyleStart("/office:document-content/office:automatic-styles"_ostr);
+ static constexpr OString sCap("/style:graphic-properties[@svg:stroke-linecap='round']"_ostr);
+ static constexpr OString sChartStart(
+ "/office:document-content/office:body/office:chart/chart:chart"_ostr);
+ OString sPredicate;
+ // chart area
+ const OUString sOUAreaStyleName = getXPathContent(pXmlDoc, sChartStart + "/@chart:style-name");
+ sPredicate = "[@style:name='" + OU2O(sOUAreaStyleName) + "']";
+ assertXPath(pXmlDoc, sStyleStart + "/style:style" + sPredicate + sCap);
+ // data series line
+ const OString sSeries(sChartStart + "/chart:plot-area/chart:series");
+ const OUString sOUSeriesStyleName = getXPathContent(pXmlDoc, sSeries + "/@chart:style-name");
+ sPredicate = "[@style:name='" + OU2O(sOUSeriesStyleName) + "']";
+ assertXPath(pXmlDoc, sStyleStart + "/style:style" + sPredicate + sCap);
+ // regression-curve (trend line)
+ const OString sTrend(sChartStart + "/chart:plot-area/chart:series/chart:regression-curve");
+ const OUString sOUTrendStyleName = getXPathContent(pXmlDoc, sTrend + "/@chart:style-name");
+ sPredicate = "[@style:name='" + OU2O(sOUTrendStyleName) + "']";
+ assertXPath(pXmlDoc, sStyleStart + "/style:style" + sPredicate + sCap);
+}
+
+void Chart2GeometryTest::testTdf135184RoundLineCap2()
+{
+ // It tests legend, data series sector and title.
+ loadFromFile(u"xlsx/tdf135184RoundLineCap2.xlsx");
+ save("calc8");
+ xmlDocUniquePtr pXmlDoc = parseExport("Object 1/content.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ static constexpr OString sStyleStart("/office:document-content/office:automatic-styles"_ostr);
+ static constexpr OString sCap("/style:graphic-properties[@svg:stroke-linecap='round']"_ostr);
+ static constexpr OString sChartStart(
+ "/office:document-content/office:body/office:chart/chart:chart"_ostr);
+ OString sPredicate;
+ // legend
+ const OString sLegend(sChartStart + "/chart:legend");
+ const OUString sOULegendStyleName = getXPathContent(pXmlDoc, sLegend + "/@chart:style-name");
+ sPredicate = "[@style:name='" + OU2O(sOULegendStyleName) + "']";
+ assertXPath(pXmlDoc, sStyleStart + "/style:style" + sPredicate + sCap);
+ // title
+ const OString sTitle(sChartStart + "/chart:title");
+ const OUString sOUTitleStyleName = getXPathContent(pXmlDoc, sTitle + "/@chart:style-name");
+ sPredicate = "[@style:name='" + OU2O(sOUTitleStyleName) + "']";
+ assertXPath(pXmlDoc, sStyleStart + "/style:style" + sPredicate + sCap);
+ // sector
+ const OString sSector(sChartStart + "/chart:plot-area/chart:series/chart:data-point[3]");
+ const OUString sOUSectorStyleName = getXPathContent(pXmlDoc, sSector + "/@chart:style-name");
+ sPredicate = "[@style:name='" + OU2O(sOUSectorStyleName) + "']";
+ assertXPath(pXmlDoc, sStyleStart + "/style:style" + sPredicate + sCap);
+}
+
+// These two tests verify the round-trip of preset dash styles in the xlsx file.
+void Chart2GeometryTest::testTdf135184RoundLineCap3()
+{
+ // It tests chart area, data series line and regression-curve line.
+ loadFromFile(u"xlsx/tdf135184RoundLineCap.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ static constexpr OString sDash("/c:spPr/a:ln/a:prstDash"_ostr);
+ // chart area
+ assertXPath(pXmlDoc, "/c:chartSpace" + sDash, "val"_ostr, "dashDot");
+ // data series line
+ static constexpr OString sStart("/c:chartSpace/c:chart/c:plotArea/c:scatterChart/c:ser"_ostr);
+ assertXPath(pXmlDoc, sStart + sDash, "val"_ostr, "dash");
+ // regression-curve (trendline)
+ assertXPath(pXmlDoc, sStart + "/c:trendline" + sDash, "val"_ostr, "sysDot");
+}
+
+void Chart2GeometryTest::testTdf135184RoundLineCap4()
+{
+ // It tests legend, data series sector and title.
+ loadFromFile(u"xlsx/tdf135184RoundLineCap2.xlsx");
+ save("Calc Office Open XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("xl/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ static constexpr OString sChartStart("/c:chartSpace/c:chart"_ostr);
+ static constexpr OString sDash("/c:spPr/a:ln/a:prstDash"_ostr);
+ assertXPath(pXmlDoc, sChartStart + "/c:legend" + sDash, "val"_ostr, "sysDot");
+ const OString sSeries(sChartStart + "/c:plotArea/c:pieChart/c:ser/c:dPt[3]");
+ assertXPath(pXmlDoc, sSeries + sDash, "val"_ostr, "dash");
+ assertXPath(pXmlDoc, sChartStart + "/c:title" + sDash, "val"_ostr, "dashDot");
+}
+
+void Chart2GeometryTest::testTdf128345ChartArea_CG_TS_export()
+{
+ // chart area with color gradient and solid transparency
+ // Without the patch the transparency was lost in saved pptx file.
+ loadFromFile(u"odp/tdf128345_ChartArea_CG_TS.odp");
+
+ // MCGR: Similar to testTdf128345Legend_CS_TG_axial_export:
+ // Checked that it works with the existing import file,
+ // but will change with ODF MCGR im/export again.
+ // Adapting for now, but need to re-check values after
+ // ODF im/export for MCGR is integrated
+
+ // Make sure the chart area has a transparency in gradient stops in saved pptx file.
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ OString sPathStart("//c:chartSpace/c:spPr/a:gradFill"_ostr);
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs", 2);
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]/a:srgbClr/a:alpha", "val"_ostr, "30000");
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr/a:alpha", "val"_ostr, "30000");
+}
+
+void Chart2GeometryTest::testTdf128345ChartArea_CG_TS_import()
+{
+ // This works on the file, which was exported from file tdf128345_ChartArea_CG_TS.odp to pptx.
+ // It has gradient stops with identical transparency values.
+ // Make sure chart area has transparency when pptx document is opened and resaved as odp.
+ // As of Aug 2020, the import generates a transparency gradient. When import is changed to
+ // generate solid transparency, the test needs to be adapted.
+
+ // MCGR: Similar to testTdf128345Legend_CS_TG_axial_export:
+ // Checked that it works with the existing import file,
+ // but will change with ODF MCGR im/export again. We will need to
+ // update the *.odp input file. Disable unclear values for now and
+ // adapt when ODF im/export for MCGR is integrated
+ loadFromFile(u"pptx/tdf128345_ChartArea_CG_TS.pptx");
+
+ // Find transparency gradient name
+ save("impress8");
+ xmlDocUniquePtr pXmlDoc = parseExport("Object 1/content.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ const OUString sOUChartStyleName = getXPathContent(
+ pXmlDoc,
+ "//office:document-content/office:body/office:chart/chart:chart/@chart:style-name"_ostr);
+ const OString sStylePath(
+ "//office:document-content/office:automatic-styles/style:style[@style:name='"
+ + OU2O(sOUChartStyleName) + "']");
+ assertXPath(pXmlDoc, sStylePath, 1);
+ assertXPath(pXmlDoc, sStylePath + "/style:graphic-properties/@draw:opacity-name", 1);
+ const OUString sOUOpacityName
+ = getXPathContent(pXmlDoc, sStylePath + "/style:graphic-properties/@draw:opacity-name");
+
+ // Verify the content of the opacity definition
+ save("impress8");
+ xmlDocUniquePtr pXmlDoc2 = parseExport("Object 1/styles.xml");
+ CPPUNIT_ASSERT(pXmlDoc2);
+ const OString sAttribute("@draw:name='" + OU2O(sOUOpacityName) + "'");
+ const OString sStart("//office:document-styles/office:styles/draw:opacity[" + sAttribute);
+ assertXPath(pXmlDoc2, sStart + "]", 1);
+ assertXPath(pXmlDoc2, sStart + " and @draw:style='linear']");
+ assertXPath(pXmlDoc2, sStart + " and @draw:start='30%']");
+ assertXPath(pXmlDoc2, sStart + " and @draw:end='30%']");
+ assertXPath(pXmlDoc2, sStart + " and @draw:angle='30deg']");
+ assertXPath(pXmlDoc2, sStart + " and @draw:border='0%']"); // MCGR: no border anymore 20% -> 0%
+}
+
+void Chart2GeometryTest::testTdf128345ChartWall_CS_TG_export()
+{
+ // chart wall with solid color and transparency gradient
+ // Without the patch the transparency was lost.
+ loadFromFile(u"odp/tdf128345_ChartWall_CS_TG.odp");
+
+ // Make sure the chart has a gradient with transparency in gradient stops in saved pptx file.
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ OString sPathStart("//c:chartSpace/c:chart/c:plotArea/c:spPr/a:gradFill"_ostr);
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs", 2); //linear
+ // MS Office has opacity, so 100% transparency is val="0"
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]/a:srgbClr/a:alpha", "val"_ostr, "0");
+ // no element for 0% transparent
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr/a:alpha", 0);
+}
+
+void Chart2GeometryTest::testTdf128345ChartWall_CS_TG_import()
+{
+ // This works on the file, which was exported from file tdf128345_ChartWall_CS_TG.odp to pptx.
+ // Make sure chart wall has transparency when pptx document is resaved as odp.
+ loadFromFile(u"pptx/tdf128345_ChartWall_CS_TG.pptx");
+
+ // Find transparency gradient name
+ save("impress8");
+ xmlDocUniquePtr pXmlDoc = parseExport("Object 1/content.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ const OUString sOUChartStyleName
+ = getXPathContent(pXmlDoc, "//office:document-content/office:body/office:chart/chart:chart/"
+ "chart:plot-area/chart:wall/@chart:style-name"_ostr);
+ const OString sStylePath(
+ "//office:document-content/office:automatic-styles/style:style[@style:name='"
+ + OU2O(sOUChartStyleName) + "']");
+ assertXPath(pXmlDoc, sStylePath, 1);
+ assertXPath(pXmlDoc, sStylePath + "/style:graphic-properties/@draw:opacity-name", 1);
+ const OUString sOUOpacityName
+ = getXPathContent(pXmlDoc, sStylePath + "/style:graphic-properties/@draw:opacity-name");
+
+ // Verify content of the opacity definition
+ save("impress8");
+ xmlDocUniquePtr pXmlDoc2 = parseExport("Object 1/styles.xml");
+ CPPUNIT_ASSERT(pXmlDoc2);
+ const OString sAttribute("@draw:name='" + OU2O(sOUOpacityName) + "'");
+ const OString sStart("//office:document-styles/office:styles/draw:opacity[" + sAttribute);
+ assertXPath(pXmlDoc2, sStart + "]", 1);
+ assertXPath(pXmlDoc2, sStart + " and @draw:style='linear']");
+ assertXPath(pXmlDoc2, sStart + " and @draw:start='0%']");
+ assertXPath(pXmlDoc2, sStart + " and @draw:end='100%']");
+}
+
+void Chart2GeometryTest::testTdf128345Legend_CS_TG_axial_export()
+{
+ // legend with solid color and transparency gradient
+ // Without the patch the transparency was lost.
+ loadFromFile(u"odp/tdf128345_Legend_CS_TG_axial.odp");
+
+ // Make sure the chart has a gradient with transparency in gradient stops in saved pptx file.
+ save("Impress MS PowerPoint 2007 XML");
+ xmlDocUniquePtr pXmlDoc = parseExport("ppt/charts/chart1.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ OString sPathStart("//c:chartSpace/c:chart/c:legend/c:spPr/a:gradFill"_ostr);
+
+ // MCGR: three entries due to axial being mirrored+expanded to linear
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs", 3);
+
+ // MCGR: start entry, no transparence, pos zero
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]/a:srgbClr/a:alpha", 0);
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[1]", "pos"_ostr, "0");
+
+ // MCGR: middle entry, 100% transparence, pos 0.5
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]/a:srgbClr/a:alpha", "val"_ostr, "0");
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[2]", "pos"_ostr, "50000");
+
+ // MCGR: end entry, no transparence, pos 1.0
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[3]/a:srgbClr/a:alpha", 0);
+ assertXPath(pXmlDoc, sPathStart + "/a:gsLst/a:gs[3]", "pos"_ostr, "100000");
+}
+
+void Chart2GeometryTest::testTdf128345Legend_CS_TG_axial_import()
+{
+ // This works on the file, which was exported from file tdf128345_Legend_CS_TG_axial.odp to pptx.
+ // Error was, that in case of axial not the middle value was taken but start and end value.
+ loadFromFile(u"pptx/tdf128345_Legend_CS_TG_axial.pptx");
+
+ // Find transparency gradient name
+ save("impress8");
+ xmlDocUniquePtr pXmlDoc = parseExport("Object 1/content.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+ const OUString sOUChartStyleName
+ = getXPathContent(pXmlDoc, "//office:document-content/office:body/office:chart/chart:chart/"
+ "chart:legend/@chart:style-name"_ostr);
+ const OString sStylePath(
+ "//office:document-content/office:automatic-styles/style:style[@style:name='"
+ + OU2O(sOUChartStyleName) + "']");
+ assertXPath(pXmlDoc, sStylePath, 1);
+ assertXPath(pXmlDoc, sStylePath + "/style:graphic-properties/@draw:opacity-name", 1);
+ const OUString sOUOpacityName
+ = getXPathContent(pXmlDoc, sStylePath + "/style:graphic-properties/@draw:opacity-name");
+
+ // Verify content of the opacity definition
+ save("impress8");
+ xmlDocUniquePtr pXmlDoc2 = parseExport("Object 1/styles.xml");
+ CPPUNIT_ASSERT(pXmlDoc2);
+ const OString sAttribute("@draw:name='" + OU2O(sOUOpacityName) + "'");
+ const OString sStart("//office:document-styles/office:styles/draw:opacity[" + sAttribute);
+ assertXPath(pXmlDoc2, sStart + "]", 1);
+ assertXPath(pXmlDoc2, sStart + " and @draw:style='axial']");
+ assertXPath(pXmlDoc2, sStart + " and @draw:start='0%']");
+ assertXPath(pXmlDoc2, sStart + " and @draw:end='100%']");
+}
+
+void Chart2GeometryTest::testTdf135366LabelOnSeries()
+{
+ // Error was, that the fill and line properties of a <chart:data-label> were not
+ // imported at all. Here they should be at the series.
+ loadFromFile(u"ods/tdf135366_data_label_series.ods");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropSet(xDataSeries, UNO_QUERY_THROW);
+ uno::Any aAny;
+
+ aAny = xPropSet->getPropertyValue("LabelBorderStyle");
+ drawing::LineStyle eLineStyle;
+ CPPUNIT_ASSERT_MESSAGE("No LabelBorderStyle set.", aAny >>= eLineStyle);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("solid line expected", drawing::LineStyle_SOLID, eLineStyle);
+
+ sal_Int32 nBorderWidth;
+ sal_Int32 nExpectedWidth = 95;
+ xPropSet->getPropertyValue("LabelBorderWidth") >>= nBorderWidth;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("LabelBorderWidth", nExpectedWidth, nBorderWidth);
+
+ sal_Int32 nLineColor;
+ sal_Int32 nExpectedLineColor = 255;
+ xPropSet->getPropertyValue("LabelBorderColor") >>= nLineColor;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("line color blue, 255=#0000FF", nExpectedLineColor, nLineColor);
+
+ aAny = xPropSet->getPropertyValue("LabelFillStyle");
+ drawing::FillStyle eFillStyle;
+ CPPUNIT_ASSERT_MESSAGE("No LabelFillStyle set", aAny >>= eFillStyle);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("solid fill expected", drawing::FillStyle_SOLID, eFillStyle);
+
+ sal_Int32 nFillColor;
+ sal_Int32 nExpectedFillColor = 65280;
+ xPropSet->getPropertyValue("LabelFillColor") >>= nFillColor;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("fill color green, 65280=#00FF00", nExpectedFillColor, nFillColor);
+}
+
+void Chart2GeometryTest::testTdf135366LabelOnPoint()
+{
+ // Error was, that the fill and line properties of a <chart:data-label> were not
+ // imported at all. Here they should be at point 2.
+ loadFromFile(u"odt/tdf135366_data_label_point.odt");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropSet(xDataSeries->getDataPointByIndex(2),
+ uno::UNO_SET_THROW);
+ uno::Any aAny;
+
+ aAny = xPropSet->getPropertyValue("LabelBorderStyle");
+ drawing::LineStyle eLineStyle;
+ CPPUNIT_ASSERT_MESSAGE("No LabelBorderStyle set.", aAny >>= eLineStyle);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("solid line expected", drawing::LineStyle_SOLID, eLineStyle);
+
+ sal_Int32 nBorderWidth;
+ sal_Int32 nExpectedWidth = 381;
+ xPropSet->getPropertyValue("LabelBorderWidth") >>= nBorderWidth;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("LabelBorderWidth", nExpectedWidth, nBorderWidth);
+
+ sal_Int32 nLineTransparency;
+ sal_Int32 nExpectedTransparency = 30;
+ xPropSet->getPropertyValue("LabelBorderTransparency") >>= nLineTransparency;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("line transparency", nExpectedTransparency, nLineTransparency);
+
+ sal_Int32 nLineColor;
+ sal_Int32 nExpectedLineColor = 10206041;
+ xPropSet->getPropertyValue("LabelBorderColor") >>= nLineColor;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("line color greenish, 10206041=#9BBB59", nExpectedLineColor,
+ nLineColor);
+
+ aAny = xPropSet->getPropertyValue("LabelFillStyle");
+ drawing::FillStyle eFillStyle;
+ CPPUNIT_ASSERT_MESSAGE("No LabelFillStyle set", aAny >>= eFillStyle);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("solid fill expected", drawing::FillStyle_SOLID, eFillStyle);
+
+ sal_Int32 nFillColor;
+ sal_Int32 nExpectedFillColor = 14277081;
+ xPropSet->getPropertyValue("LabelFillColor") >>= nFillColor;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("fill color gray, 14277081=#d9d9d9", nExpectedFillColor,
+ nFillColor);
+}
+
+void Chart2GeometryTest::testTdf135366LabelExport()
+{
+ // Error was, that line and fill properties were not exported as
+ // graphic-properties of a <chart:data-label> element, but only
+ // as loext chart-properties of the <chart:data-point> element.
+ loadFromFile(u"odt/tdf135366_data_label_export.odt");
+
+ // FIXME: Error: unexpected attribute "loext:label-stroke-color"
+ skipValidation();
+
+ save("writer8");
+ xmlDocUniquePtr pXmlDoc = parseExport("Object 1/content.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // Find label style
+ const OUString sOULabelStyleName = getXPathContent(
+ pXmlDoc, "//office:document-content/office:body/office:chart/chart:chart/chart:plot-area"
+ "/chart:series/chart:data-point[1]/chart:data-label/@chart:style-name"_ostr);
+
+ // Verify content of graphic properties of label style
+ const OString sStylePath(
+ "//office:document-content/office:automatic-styles/style:style[@style:name='"
+ + OU2O(sOULabelStyleName) + "']/style:graphic-properties");
+ assertXPath(pXmlDoc, sStylePath, 1);
+ assertXPath(pXmlDoc, sStylePath + "[@draw:fill='solid']");
+ assertXPath(pXmlDoc, sStylePath + "[@draw:fill-color='#5050a0']");
+ assertXPath(pXmlDoc, sStylePath + "[@draw:stroke='solid']");
+ assertXPath(pXmlDoc, sStylePath + "[@svg:stroke-width='0.254cm']");
+ assertXPath(pXmlDoc, sStylePath + "[@svg:stroke-color='#00ffff']");
+}
+
+void Chart2GeometryTest::testTdf135366_CustomLabelText()
+{
+ // Error was, that custom text in a data label was only exported in ODF extended,
+ // although the used <chart:data-label> element exists since ODF 1.2.
+ const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion(GetODFDefaultVersion());
+ SetODFDefaultVersion(SvtSaveOptions::ODFVER_012);
+ loadFromFile(u"pptx/tdf135366_CustomLabelText.pptx");
+ save("impress8");
+ xmlDocUniquePtr pXmlDoc = parseExport("Object 1/content.xml");
+ CPPUNIT_ASSERT(pXmlDoc);
+
+ // Find custom text. As of version 7.0 it is in a <text:span> element.
+ static constexpr OString sCustomTextPath(
+ "//office:document-content/office:body/office:chart/chart:chart/chart:plot-area"
+ "/chart:series/chart:data-point[2]/chart:data-label/text:p/text:span"_ostr);
+ assertXPath(pXmlDoc, sCustomTextPath, 1);
+
+ // Verify text content
+ const OUString sOUTextContent = getXPathContent(pXmlDoc, sCustomTextPath);
+ CPPUNIT_ASSERT_EQUAL(OUString("Custom"), sOUTextContent);
+
+ SetODFDefaultVersion(nCurrentODFVersion);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Chart2GeometryTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/chart2import.cxx b/chart2/qa/extras/chart2import.cxx
new file mode 100644
index 0000000000..f7324c9475
--- /dev/null
+++ b/chart2/qa/extras/chart2import.cxx
@@ -0,0 +1,2242 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "charttest.hxx"
+#include <com/sun/star/chart2/CurveStyle.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/chart/XChartDataArray.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/chart/XAxisXSupplier.hpp>
+#include <com/sun/star/chart/XAxisYSupplier.hpp>
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/chart2/TickmarkStyle.hpp>
+#include <com/sun/star/chart2/SymbolStyle.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <iterator>
+
+#include <com/sun/star/util/Color.hpp>
+#include <com/sun/star/awt/Gradient2.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <basegfx/utils/gradienttools.hxx>
+#include <docmodel/uno/UnoGradientTools.hxx>
+
+class Chart2ImportTest : public ChartTest
+{
+public:
+ Chart2ImportTest() : ChartTest("/chart2/qa/extras/data/") {}
+
+protected:
+ void testTransparentBackground(std::u16string_view filename);
+};
+
+// error bar import
+// split method up into smaller chunks for more detailed tests
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testFdo60083)
+{
+ loadFromFile(u"ods/fdo60083.ods");
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT( xDataSeries.is() );
+
+ Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW );
+
+ // test that y error bars are there
+ Reference< beans::XPropertySet > xErrorBarYProps;
+ xPropSet->getPropertyValue(CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarYProps;
+ CPPUNIT_ASSERT(xErrorBarYProps.is());
+ {
+ sal_Int32 nErrorBarStyle;
+ CPPUNIT_ASSERT(
+ xErrorBarYProps->getPropertyValue("ErrorBarStyle")
+ >>= nErrorBarStyle);
+ CPPUNIT_ASSERT_EQUAL(
+ chart::ErrorBarStyle::RELATIVE,
+ nErrorBarStyle);
+
+ double nVal = 0.0;
+ CPPUNIT_ASSERT(
+ xErrorBarYProps->getPropertyValue("PositiveError") >>= nVal);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(5.0, nVal, 1e-8);
+
+ CPPUNIT_ASSERT(
+ xErrorBarYProps->getPropertyValue("NegativeError") >>= nVal);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(5.0, nVal, 1e-8);
+
+ bool bVal;
+ CPPUNIT_ASSERT(
+ xErrorBarYProps->getPropertyValue("ShowPositiveError") >>= bVal);
+ CPPUNIT_ASSERT_EQUAL(true, bVal);
+
+ CPPUNIT_ASSERT(
+ xErrorBarYProps->getPropertyValue("ShowNegativeError") >>= bVal);
+ CPPUNIT_ASSERT_EQUAL(true, bVal);
+ }
+
+ // test that x error bars are not imported
+ Reference< beans::XPropertySet > xErrorBarXProps;
+ xPropSet->getPropertyValue(CHART_UNONAME_ERRORBAR_X) >>= xErrorBarXProps;
+ CPPUNIT_ASSERT(!xErrorBarXProps.is());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testErrorBarRange)
+{
+ loadFromFile(u"ods/error_bar_range.ods");
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT( xDataSeries.is() );
+
+ Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW );
+
+ // test that y error bars are there
+ Reference< beans::XPropertySet > xErrorBarYProps;
+ xPropSet->getPropertyValue(CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarYProps;
+ CPPUNIT_ASSERT(xErrorBarYProps.is());
+
+ sal_Int32 nErrorBarStyle;
+ CPPUNIT_ASSERT(
+ xErrorBarYProps->getPropertyValue("ErrorBarStyle")
+ >>= nErrorBarStyle);
+ CPPUNIT_ASSERT_EQUAL(
+ chart::ErrorBarStyle::FROM_DATA,
+ nErrorBarStyle);
+
+ OUString aRangePos;
+ CPPUNIT_ASSERT(xErrorBarYProps->getPropertyValue("ErrorBarRangePositive") >>= aRangePos);
+ CPPUNIT_ASSERT_EQUAL(OUString("$Sheet1.$C$2:$C$4"), aRangePos);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testErrorBarFormatting)
+{
+ loadFromFile(u"ods/error_bar_properties.ods");
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT( xDataSeries.is() );
+
+ Reference< beans::XPropertySet > xPropSet( xDataSeries, UNO_QUERY_THROW );
+
+ // test that y error bars are there
+ Reference< beans::XPropertySet > xErrorBarYProps;
+ xPropSet->getPropertyValue(CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarYProps;
+ CPPUNIT_ASSERT(xErrorBarYProps.is());
+
+ util::Color aColor(0);
+ xErrorBarYProps->getPropertyValue("LineColor") >>= aColor;
+ sal_uInt32 nColorValue = aColor;
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(0xff3333), nColorValue);
+}
+
+// stepped line interpolation
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testSteppedLines)
+{
+ const sal_Int32 MAXSHEET = 14;
+ chart2::CurveStyle const curveStyle[] = {
+ chart2::CurveStyle_LINES,
+ chart2::CurveStyle_CUBIC_SPLINES,
+ chart2::CurveStyle_B_SPLINES,
+ chart2::CurveStyle_STEP_START,
+ chart2::CurveStyle_STEP_END,
+ chart2::CurveStyle_STEP_CENTER_X,
+ chart2::CurveStyle_STEP_CENTER_Y,
+ chart2::CurveStyle_LINES,
+ chart2::CurveStyle_CUBIC_SPLINES,
+ chart2::CurveStyle_B_SPLINES,
+ chart2::CurveStyle_STEP_START,
+ chart2::CurveStyle_STEP_END,
+ chart2::CurveStyle_STEP_CENTER_X,
+ chart2::CurveStyle_STEP_CENTER_Y
+ };
+
+ loadFromFile(u"ods/stepped_lines.ods");
+ for(sal_Int32 nSheet = 0; nSheet < MAXSHEET; ++nSheet)
+ {
+ uno::Reference< chart2::XChartDocument > xChart2Doc = getChartDocFromSheet( nSheet, mxComponent );
+ CPPUNIT_ASSERT(xChart2Doc.is());
+
+ Reference< chart2::XChartType > xChartType = getChartTypeFromDoc( xChart2Doc, 0 );
+ CPPUNIT_ASSERT(xChartType.is());
+
+ Reference< beans::XPropertySet > xPropSet( xChartType, UNO_QUERY );
+ CPPUNIT_ASSERT(xPropSet.is());
+
+ chart2::CurveStyle eCurveStyle;
+ xPropSet->getPropertyValue("CurveStyle") >>= eCurveStyle;
+ CPPUNIT_ASSERT_EQUAL(eCurveStyle, curveStyle[nSheet]);
+ }
+}
+
+static uno::Sequence < OUString > getChartColumnDescriptions( uno::Reference< chart::XChartDocument > const & xChart1Doc)
+{
+ CPPUNIT_ASSERT(xChart1Doc.is());
+ uno::Reference< chart::XChartDataArray > xChartData ( xChart1Doc->getData(), UNO_QUERY_THROW);
+ uno::Sequence < OUString > seriesList = xChartData->getColumnDescriptions();
+ return seriesList;
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testODSChartSeries)
+{
+ loadFromFile(u"ods/chart.ods");
+ uno::Reference< chart::XChartDocument > xChart1Doc ( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW);
+ uno::Sequence < OUString > seriesList = getChartColumnDescriptions( xChart1Doc);
+ CPPUNIT_ASSERT_EQUAL(OUString("Col 1"), seriesList[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Col2"), seriesList[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Col 33"), seriesList[2]);
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testXLSXChartSeries)
+{
+ loadFromFile(u"xlsx/chart.xlsx");
+ uno::Reference< chart::XChartDocument > xChart1Doc ( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW);
+ uno::Sequence < OUString > seriesList = getChartColumnDescriptions(xChart1Doc );
+ CPPUNIT_ASSERT_EQUAL(OUString("Col 1"), seriesList[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Col2"), seriesList[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Col 33"), seriesList[2]);
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testXLSChartSeries)
+{
+ loadFromFile(u"xls/chart.xls");
+ uno::Reference< chart::XChartDocument > xChart1Doc ( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW);
+ uno::Sequence < OUString > seriesList = getChartColumnDescriptions(xChart1Doc );
+ CPPUNIT_ASSERT_EQUAL(OUString("Col 1"), seriesList[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Col 2"), seriesList[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Col 3"), seriesList[2]);
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testODTChartSeries)
+{
+ loadFromFile(u"odt/chart.odt");
+ uno::Sequence< OUString > seriesList = getWriterChartColumnDescriptions(mxComponent);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 1"), seriesList[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 2"), seriesList[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 3"), seriesList[2]);
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testDOCChartSeries)
+{
+ loadFromFile(u"doc/chart.doc");
+ uno::Sequence< OUString > seriesList = getWriterChartColumnDescriptions(mxComponent);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 1"), seriesList[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 2"), seriesList[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 3"), seriesList[2]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testDOCXChartSeries)
+{
+ loadFromFile(u"docx/chart.docx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XChartType> xCT = getChartTypeFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xCT.is());
+
+ std::vector<uno::Sequence<uno::Any> > aLabels = getDataSeriesLabelsFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("Series 1"), aLabels[0][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("Series 2"), aLabels[1][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("Series 3"), aLabels[2][0].get<OUString>());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testDOCXChartEmptySeries)
+{
+ loadFromFile(u"docx/tdf125337.docx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XChartType> xCT = getChartTypeFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xCT.is());
+
+ std::vector<uno::Sequence<uno::Any> > aLabels = getDataSeriesLabelsFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("1. dataseries"), aLabels[0][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("2. dataseries"), aLabels[1][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 3"), aLabels[2][0].get<OUString>());
+
+ //test chart series sparse data for docx
+ std::vector<std::vector<double> > aValues = getDataSeriesYValuesFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aValues.size());
+ //test the second series values
+ CPPUNIT_ASSERT_EQUAL(2.4, aValues[1][0]);
+ CPPUNIT_ASSERT_EQUAL(4.4, aValues[1][1]);
+ //test the third series (empty) values
+ CPPUNIT_ASSERT(std::isnan(aValues[2][0]));
+ CPPUNIT_ASSERT(std::isnan(aValues[2][1]));
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf81396)
+{
+ loadFromFile(u"xlsx/tdf81396.xlsx");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+
+ Reference<chart2::XChartDocument> xChartDoc2(xChartDoc, UNO_QUERY_THROW);
+ Reference<chart2::XChartType> xChartType(getChartTypeFromDoc(xChartDoc2, 0), UNO_SET_THROW);
+ std::vector aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aDataSeriesYValues.size());
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 105.210801910481
+ // - Actual : nan
+ CPPUNIT_ASSERT_EQUAL(105.210801910481, aDataSeriesYValues[0][0]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPPTXChartErrorBars)
+{
+ loadFromFile(u"pptx/tdf127720.pptx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ uno::Reference< chart::XChartDataArray > xDataArray(xChartDoc->getDataProvider(), UNO_QUERY_THROW);
+ Sequence<OUString> aColumnDesc = xDataArray->getColumnDescriptions();
+ // Number of columns = 4 (Y-values, X-values and positive/negative error bars).
+ // Without the fix there would only be 2 columns (no error range).
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("There must be 4 columns and descriptions", static_cast<sal_Int32>(4), aColumnDesc.getLength());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testDOCXChartValuesSize)
+{
+ loadFromFile(u"docx/bubblechart.docx" );
+ Reference<chart2::XChartDocument> xChartDoc( getChartDocFromWriter(0), uno::UNO_QUERY );
+ CPPUNIT_ASSERT( xChartDoc.is() );
+
+ uno::Reference< chart::XChartDataArray > xDataArray( xChartDoc->getDataProvider(), UNO_QUERY_THROW );
+ Sequence<OUString> aColumnDesc = xDataArray->getColumnDescriptions();
+ // Number of columns = 3 (Y-values, X-values and bubble sizes).
+ // Without the fix there would only be 2 columns (no bubble sizes).
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "There must be 3 columns and descriptions", static_cast<sal_Int32>(3), aColumnDesc.getLength() );
+ Sequence<Sequence<double>> aData = xDataArray->getData();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "There must be exactly 3 data points", static_cast<sal_Int32>(3), aData.getLength() );
+
+ std::vector<std::vector<double>> aExpected = { { 2.7, 0.7, 10.0 }, { 3.2, 1.8, 4.0 }, { 0.8, 2.6, 8.0 } };
+
+ for ( sal_Int32 nRowIdx = 0; nRowIdx < 3; ++nRowIdx )
+ for( sal_Int32 nColIdx = 0; nColIdx < 3; ++nColIdx )
+ CPPUNIT_ASSERT_DOUBLES_EQUAL( aExpected[nRowIdx][nColIdx], aData[nRowIdx][nColIdx], 1e-1 );
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPPTChartSeries)
+{
+ //test chart series names for ppt
+ loadFromFile(u"ppt/chart.ppt");
+ uno::Sequence < OUString > seriesList = getImpressChartColumnDescriptions(0, 0);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 1"), seriesList[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 2"), seriesList[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 3"), seriesList[2]);
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPPTXChartSeries)
+{
+ //test chart series names for pptx
+ loadFromFile(u"pptx/chart.pptx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XChartType> xCT = getChartTypeFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xCT.is());
+
+ std::vector<uno::Sequence<uno::Any> > aLabels = getDataSeriesLabelsFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aLabels.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 1"), aLabels[0][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 2"), aLabels[1][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 3"), aLabels[2][0].get<OUString>());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPPTXSparseChartSeries)
+{
+ //test chart series sparse data for pptx
+ loadFromFile(u"pptx/sparse-chart.pptx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XChartType> xCT = getChartTypeFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xCT.is());
+
+ std::vector<std::vector<double> > aValues = getDataSeriesYValuesFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), aValues.size());
+ CPPUNIT_ASSERT( std::isnan( aValues[0][0] ) );
+ CPPUNIT_ASSERT_EQUAL(2.5, aValues[0][1]);
+ CPPUNIT_ASSERT_EQUAL(3.5, aValues[0][2]);
+ CPPUNIT_ASSERT( std::isnan( aValues[0][3] ) );
+ CPPUNIT_ASSERT_EQUAL(-2.4, aValues[1][0]);
+ CPPUNIT_ASSERT( std::isnan( aValues[1][1] ) );
+ CPPUNIT_ASSERT( std::isnan( aValues[1][2] ) );
+ CPPUNIT_ASSERT_EQUAL(-2.8, aValues[1][3]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPPTXHiddenDataSeries)
+{
+ /**
+ * Original data contains 3 series but 2 of them are hidden. For now, we
+ * detect and skip those hidden series on import (since we don't support
+ * hidden columns for internal data table yet).
+ */
+ loadFromFile(u"pptx/stacked-bar-chart-hidden-series.pptx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // "Automatic" chart background fill in pptx should be loaded as no fill.
+ Reference<beans::XPropertySet> xPropSet = xChartDoc->getPageBackground();
+ CPPUNIT_ASSERT(xPropSet.is());
+ drawing::FillStyle eStyle = xPropSet->getPropertyValue("FillStyle").get<drawing::FillStyle>();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chart background fill in pptx should be loaded as no fill (transparent).",
+ drawing::FillStyle_NONE, eStyle);
+
+ Reference<chart2::XChartType> xCT = getChartTypeFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xCT.is());
+
+ // There should be only one data series present.
+ std::vector<uno::Sequence<uno::Any> > aLabels = getDataSeriesLabelsFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aLabels.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("Series 3"), aLabels[0][0].get<OUString>());
+
+ // Test the internal data.
+ CPPUNIT_ASSERT(xChartDoc->hasInternalDataProvider());
+
+ Reference<chart2::XInternalDataProvider> xInternalProvider(xChartDoc->getDataProvider(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xInternalProvider.is());
+
+ Reference<chart::XComplexDescriptionAccess> xDescAccess(xInternalProvider, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDescAccess.is());
+
+ // Get the category labels.
+ Sequence<Sequence<OUString> > aCategories = xDescAccess->getComplexRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aCategories.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("Category 1"), aCategories[0][0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Category 2"), aCategories[1][0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Category 3"), aCategories[2][0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Category 4"), aCategories[3][0]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPPTXPercentageNumberFormats)
+{
+ loadFromFile(u"pptx/percentage-number-formats.pptx");
+
+ // 1st chart
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ chart2::DataPointLabel aLabel;
+ sal_Int32 nNumberFormat;
+ const sal_Int32 nPercentFormatSimple = getNumberFormat(xChartDoc, "0%");
+ const sal_Int32 nPercentFormatDecimal = getNumberFormat(xChartDoc, "0.00%");
+
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("Label") >>= aLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumber);
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumberInPercent);
+ xPropertySet->getPropertyValue("PercentageNumberFormat") >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(nPercentFormatSimple, nNumberFormat);
+
+ xPropertySet.set(xDataSeries->getDataPointByIndex(1), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("Label") >>= aLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumber);
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumberInPercent);
+ xPropertySet->getPropertyValue("PercentageNumberFormat") >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(nPercentFormatDecimal, nNumberFormat);
+
+ xPropertySet.set(xDataSeries->getDataPointByIndex(2), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("Label") >>= aLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_False, aLabel.ShowNumber);
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumberInPercent);
+ xPropertySet->getPropertyValue("PercentageNumberFormat") >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(nPercentFormatSimple, nNumberFormat);
+
+ xPropertySet.set(xDataSeries->getDataPointByIndex(3), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("Label") >>= aLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_False, aLabel.ShowNumber);
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumberInPercent);
+ xPropertySet->getPropertyValue("PercentageNumberFormat") >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(nPercentFormatDecimal, nNumberFormat);
+
+ // 2nd chart
+ xChartDoc.set(getChartDocFromDrawImpress(1, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 0);
+ CPPUNIT_ASSERT(xYAxis.is());
+
+ Reference<beans::XPropertySet> xPS(xYAxis, uno::UNO_QUERY_THROW);
+ bool bLinkNumberFormatToSource = true;
+ bool bSuccess = xPS->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkNumberFormatToSource;
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to false.", bSuccess);
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to false.", !bLinkNumberFormatToSource);
+
+ // FIXME: This should be in fact "0.00%".
+ // see TODO in oox/source/drawingml/chart/modelbase.cxx
+ const sal_Int32 nPercentFormatDecimalShort = getNumberFormat(xChartDoc, "0.0%");
+ nNumberFormat = getNumberFormatFromAxis(xYAxis);
+ CPPUNIT_ASSERT_EQUAL(nPercentFormatDecimalShort, nNumberFormat);
+ sal_Int16 nType = getNumberFormatType(xChartDoc, nNumberFormat);
+ CPPUNIT_ASSERT_MESSAGE("Y axis should be a percent format.", (nType & util::NumberFormat::PERCENT));
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPieChartLabelsNumFormat)
+{
+ loadFromFile(u"xlsx/tdfPieNumFormat.xlsx");
+ uno::Reference< chart::XChartDocument > xChartDoc(getChartCompFromSheet(0, 0, mxComponent), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ // test data point labels format
+ Reference<beans::XPropertySet> xDataPointPropSet(xChartDoc->getDiagram()->getDataPointProperties(0, 0), uno::UNO_SET_THROW);
+ chart2::DataPointLabel aLabel;
+ xDataPointPropSet->getPropertyValue("Label") >>= aLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumber);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPPTXStackedNonStackedYAxis)
+{
+ loadFromFile(u"pptx/stacked-non-stacked-mix-y-axis.pptx");
+
+ // 1st chart is a normal stacked column.
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XTitled> xTitled(xChartDoc, uno::UNO_QUERY_THROW);
+ OUString aTitle = getTitleString(xTitled);
+ CPPUNIT_ASSERT_EQUAL(OUString("Stacked"), aTitle);
+
+ // Get the Y-axis.
+ Reference<chart2::XAxis> xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 0);
+ CPPUNIT_ASSERT(xYAxis.is());
+
+ sal_Int32 nNumberFormat = getNumberFormatFromAxis(xYAxis);
+ sal_Int16 nType = getNumberFormatType(xChartDoc, nNumberFormat);
+ CPPUNIT_ASSERT_MESSAGE("Y axis should be a normal number format.", (nType & util::NumberFormat::NUMBER));
+ CPPUNIT_ASSERT_MESSAGE("Y axis should NOT be a percent format.", !(nType & util::NumberFormat::PERCENT));
+
+ // 2nd chart is a percent-stacked column.
+ xChartDoc.set(getChartDocFromDrawImpress(1, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ xTitled.set(xChartDoc, uno::UNO_QUERY_THROW);
+ aTitle = getTitleString(xTitled);
+ CPPUNIT_ASSERT_EQUAL(OUString("100% Stacked"), aTitle);
+
+ // Get the Y-axis.
+ xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 0);
+ CPPUNIT_ASSERT(xYAxis.is());
+
+ // Get the number format of the Y-axis.
+ nNumberFormat = getNumberFormatFromAxis(xYAxis);
+ nType = getNumberFormatType(xChartDoc, nNumberFormat);
+ CPPUNIT_ASSERT_MESSAGE("Y axis should be a percent format.", (nType & util::NumberFormat::PERCENT));
+
+ // 3rd chart is a mixture of normal-stacked column with a percent-stacked
+ // area chart series. Excel in this case sets the Y-axis to be
+ // non-percent axis and we should do the same for interoperability.
+ xChartDoc.set(getChartDocFromDrawImpress(2, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ xTitled.set(xChartDoc, uno::UNO_QUERY_THROW);
+ aTitle = getTitleString(xTitled);
+ CPPUNIT_ASSERT_EQUAL(OUString("Stacked column mixed with 100% stacked area"), aTitle);
+
+ // Get the Y-axis.
+ xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 0);
+ CPPUNIT_ASSERT(xYAxis.is());
+
+ // Get the number format of the Y-axis.
+ nNumberFormat = getNumberFormatFromAxis(xYAxis);
+ nType = getNumberFormatType(xChartDoc, nNumberFormat);
+ CPPUNIT_ASSERT_MESSAGE("Y axis should be a normal number format.", (nType & util::NumberFormat::NUMBER));
+ CPPUNIT_ASSERT_MESSAGE("Y axis should NOT be a percent format.", !(nType & util::NumberFormat::PERCENT));
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testODPChartSeries)
+{
+ //test chart series names for odp
+ loadFromFile(u"odp/chart.odp");
+ uno::Sequence < OUString > seriesList = getImpressChartColumnDescriptions(0, 0);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 1"), seriesList[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 2"), seriesList[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Column 3"), seriesList[2]);
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testBnc864396)
+{
+ loadFromFile(u"pptx/bnc864396.pptx");
+ uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0,0), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xChartDoc->hasInternalDataProvider());
+
+ uno::Reference< chart2::XInternalDataProvider > xDataProvider( xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW );
+ uno::Reference< chart::XChartDataArray > xChartDataArray(xDataProvider, uno::UNO_QUERY_THROW);
+ uno::Sequence< OUString > aRowLabels = xChartDataArray->getRowDescriptions();
+ for(sal_Int32 i = 0; i < aRowLabels.getLength(); ++i)
+ {
+ OUString aExpected = "cat" + OUString::number(i+1);
+ CPPUNIT_ASSERT_EQUAL(aExpected, aRowLabels[i]);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testBnc889755)
+{
+ loadFromFile(u"pptx/bnc889755.pptx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 5), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xChartDoc->hasInternalDataProvider());
+
+ constexpr sal_Int32 nNumCategories = 16;
+ Sequence<OUString> aDateSeq = getFormattedDateCategories(xChartDoc);
+
+ CPPUNIT_ASSERT_EQUAL(nNumCategories, aDateSeq.getLength());
+
+ const OUString aExpectedDateCategories[nNumCategories] = {
+ "Oct-12", "Nov-12", "Dec-12", "Jan-13",
+ "Feb-13", "Mar-13", "Apr-13", "May-13",
+ "Jun-13", "Jul-13", "Aug-13", "Sep-13",
+ "Oct-13", "Nov-13", "Dec-13", "Jan-14",
+ };
+
+ for (size_t nIdx = 0; nIdx < nNumCategories; ++nIdx)
+ CPPUNIT_ASSERT_EQUAL(aExpectedDateCategories[nIdx], aDateSeq[nIdx]);
+
+ //tdf#139940 - the title's gradient was lost and was filled with solid blue, instead of a "blue underline".
+ uno::Reference<drawing::XDrawPagesSupplier> xDoc(mxComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY_THROW);
+
+ // Shape "Title 3"
+ // MCGR: Use the whole completely imported transparency gradient to check for correctness
+ uno::Reference<beans::XPropertySet> xShapeProps(xPage->getByIndex(4), uno::UNO_QUERY_THROW);
+ awt::Gradient2 aTransparence;
+ xShapeProps->getPropertyValue("FillTransparenceGradient") >>= aTransparence;
+ const basegfx::BColorStops aColorStops = model::gradient::getColorStopsFromUno(aTransparence.ColorStops);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aColorStops.size());
+ CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0));
+ CPPUNIT_ASSERT_EQUAL(Color(0x404040), Color(aColorStops[0].getStopColor()));
+ CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 0.070000000000000007));
+ CPPUNIT_ASSERT_EQUAL(Color(0x404040), Color(aColorStops[1].getStopColor()));
+ CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[2].getStopOffset(), 0.080000000000000002));
+ CPPUNIT_ASSERT_EQUAL(Color(0xffffff), Color(aColorStops[2].getStopColor()));
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testBnc882383)
+{
+ loadFromFile(u"pptx/bnc882383.pptx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY_THROW);
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ OUString sGradientName;
+ xPropertySet->getPropertyValue("GradientName") >>= sGradientName;
+ CPPUNIT_ASSERT(!sGradientName.isEmpty());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTransparencyGradientValue)
+{
+ loadFromFile(u"xlsx/tdf128732.xlsx");
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ OUString sTranspGradientName;
+ xPropertySet->getPropertyValue("FillTransparenceGradientName") >>= sTranspGradientName;
+ CPPUNIT_ASSERT(!sTranspGradientName.isEmpty());
+
+ awt::Gradient2 aTransparenceGradient;
+ uno::Reference< lang::XMultiServiceFactory > xFact(xChartDoc, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xFact.is());
+ uno::Reference< container::XNameAccess > xTransparenceGradient(xFact->createInstance("com.sun.star.drawing.TransparencyGradientTable"), uno::UNO_QUERY);
+ uno::Any rTransparenceValue = xTransparenceGradient->getByName(sTranspGradientName);
+ CPPUNIT_ASSERT(rTransparenceValue >>= aTransparenceGradient);
+ const basegfx::BColorStops aColorStops = model::gradient::getColorStopsFromUno(aTransparenceGradient.ColorStops);
+
+ // MCGR: Use the whole completely imported transparency gradient to check for correctness
+ CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size());
+ CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0));
+ CPPUNIT_ASSERT_EQUAL(Color(0x4d4d4d), Color(aColorStops[0].getStopColor()));
+ CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0));
+ CPPUNIT_ASSERT_EQUAL(Color(0x333333), Color(aColorStops[1].getStopColor()));
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testSimpleStrictXLSX)
+{
+ loadFromFile(u"xlsx/strict_chart.xlsx");
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XDataSeries > xDataSeries = getDataSeriesFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testDelayedCellImport)
+{
+ // chart range referencing content on later sheets
+ loadFromFile(u"xlsx/fdo70609.xlsx");
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet( 0, mxComponent );
+ Reference< chart2::data::XDataSequence > xDataSeq =
+ getDataSequenceFromDocByRole(xChartDoc, u"values-x");
+
+ OUString aRange = xDataSeq->getSourceRangeRepresentation();
+ CPPUNIT_ASSERT_EQUAL(OUString("$Sheet2.$C$5:$C$9"), aRange);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testFlatODSStackedColumnChart)
+{
+ loadFromFile(u"fods/stacked-column-chart.fods");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xChartType.is());
+
+ Reference<chart2::XDataSeriesContainer> xDSCont(xChartType, UNO_QUERY);
+ CPPUNIT_ASSERT(xDSCont.is());
+ Sequence<Reference<chart2::XDataSeries> > aSeriesSeq = xDSCont->getDataSeries();
+
+ // The stacked column chart should consist of 5 data series.
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aSeriesSeq.getLength());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testFdo78080)
+{
+ loadFromFile(u"xlsx/fdo78080.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XTitled> xTitled(xChartDoc, uno::UNO_QUERY_THROW);
+ Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+ CPPUNIT_ASSERT(!xTitle.is());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf127811)
+{
+ loadFromFile(u"pptx/tdf127811.pptx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XChartType> xCT = getChartTypeFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xCT.is());
+
+ std::vector<uno::Sequence<uno::Any> > aLabels = getDataSeriesLabelsFromChartType(xCT);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), aLabels.size());
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 1. first
+ // - Actual : 2. second
+ CPPUNIT_ASSERT_EQUAL(OUString("1. first"), aLabels[0][0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("2. second"), aLabels[1][0].get<OUString>());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf86624)
+{
+ // manually placed legends
+ loadFromFile(u"ods/tdf86624.ods");
+ uno::Reference< chart2::XChartDocument > xChart2Doc = getChartDocFromSheet(0, mxComponent);
+ uno::Reference< chart::XChartDocument > xChartDoc (xChart2Doc, uno::UNO_QUERY);
+ uno::Reference<drawing::XShape> xLegend = xChartDoc->getLegend();
+ awt::Point aPos = xLegend->getPosition();
+ CPPUNIT_ASSERT(aPos.X > 5000); // real value for me is above 8000 but before bug fix is below 1000
+ CPPUNIT_ASSERT(aPos.Y > 4000); // real value for ms is above 7000
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf105517)
+{
+ loadFromFile(u"pptx/tdf105517.pptx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XCoordinateSystemContainer> xCoordContainer(xChartDoc->getFirstDiagram(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xCoordContainer.is());
+ Reference<chart2::XChartTypeContainer> xChartTypeContainer(xCoordContainer->getCoordinateSystems()[0], uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartTypeContainer.is());
+ Reference<chart2::XDataSeriesContainer> xDSContainer(xChartTypeContainer->getChartTypes()[0], uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDSContainer.is());
+ Reference<beans::XPropertySet> xPropSet1(xDSContainer->getDataSeries()[0], uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPropSet1.is());
+
+ tools::Long lineColor;
+ xPropSet1->getPropertyValue("Color") >>= lineColor;
+ // incorrect line color was 0x4a7ebb due to not handling themeOverride
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0xeaa700), lineColor);
+
+ Reference<beans::XPropertySet> xPropSet2(xDSContainer->getDataSeries()[1], uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPropSet2.is());
+
+ xPropSet2->getPropertyValue("Color") >>= lineColor;
+ // incorrect line color was 0x98b855
+ CPPUNIT_ASSERT_EQUAL(tools::Long(0x1e69a8), lineColor);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf106217)
+{
+ loadFromFile(u"pptx/tdf106217.pptx");
+ uno::Reference< chart::XChartDocument > xChartDoc = getChartDocFromDrawImpress(0, 0);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShape> xCircle(xDrawPage->getByIndex(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xCircle.is());
+
+ uno::Reference<container::XNamed> xNamedShape(xCircle, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Oval 1"), xNamedShape->getName());
+
+ awt::Point aPosition = xCircle->getPosition();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(6870), aPosition.X);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(7261), aPosition.Y);
+ awt::Size aSize = xCircle->getSize();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2701), aSize.Width);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2700), aSize.Height);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf108021)
+{
+ // Tdf108021 : To check TextBreak value is true.
+ loadFromFile(u"ods/tdf108021.ods");
+ uno::Reference< chart::XDiagram > mxDiagram;
+ uno::Reference< beans::XPropertySet > xAxisProp;
+ bool bTextBreak = false;
+ uno::Reference< chart::XChartDocument > xChartDoc ( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW);
+ mxDiagram.set(xChartDoc->getDiagram());
+ CPPUNIT_ASSERT(mxDiagram.is());
+ uno::Reference< chart::XAxisXSupplier > xAxisXSupp( mxDiagram, uno::UNO_QUERY );
+ CPPUNIT_ASSERT(xAxisXSupp.is());
+ xAxisProp = xAxisXSupp->getXAxis();
+ xAxisProp->getPropertyValue("TextBreak") >>= bTextBreak;
+ // Expected value of 'TextBreak' is true
+ CPPUNIT_ASSERT(bTextBreak);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf100084)
+{
+ // The test file was created with IBM Cognos, make sure there is a diagram.
+ loadFromFile(u"xlsx/tdf100084.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ Reference<beans::XPropertySet> xDiagram(xChartDoc->getFirstDiagram(), UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("There should be a Diagram.", xDiagram.is());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf124817)
+{
+ loadFromFile(u"xlsx/tdf124817.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ uno::Reference<chart2::XDataSeries> xDataSeries;
+ chart2::Symbol aSymblProp;
+
+ // Check the symbol of data series 1 (marker style none)
+ xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ uno::Reference<beans::XPropertySet> xPropSet_0(xDataSeries, uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT((xPropSet_0->getPropertyValue("Symbol") >>= aSymblProp));
+ CPPUNIT_ASSERT_EQUAL(chart2::SymbolStyle_NONE, aSymblProp.Style);
+
+ // Check the symbol of data series 2 (marker style square)
+ xDataSeries = getDataSeriesFromDoc(xChartDoc, 1);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ uno::Reference<beans::XPropertySet> xPropSet_1(xDataSeries, uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT((xPropSet_1->getPropertyValue("Symbol") >>= aSymblProp));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0xED7D31), aSymblProp.FillColor);
+
+ // Check the symbol of data series 3 (marker style diagonal cross)
+ xDataSeries = getDataSeriesFromDoc(xChartDoc, 2);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ uno::Reference<beans::XPropertySet> xPropSet_2(xDataSeries, uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT((xPropSet_2->getPropertyValue("Symbol") >>= aSymblProp));
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0xFF0000), aSymblProp.BorderColor);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf126033)
+{
+ loadFromFile(u"xlsx/tdf126033.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ // Check symbol style and size of data points
+ chart2::Symbol aSymblProp;
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ CPPUNIT_ASSERT(xPropertySet->getPropertyValue("Symbol") >>= aSymblProp);
+ CPPUNIT_ASSERT_EQUAL(chart2::SymbolStyle_NONE, aSymblProp.Style);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(176), aSymblProp.Size.Width);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(176), aSymblProp.Size.Height);
+}
+
+void Chart2ImportTest::testTransparentBackground(std::u16string_view filename)
+{
+ loadFromFile(filename);
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ uno::Reference< chart::XChartDocument > xChart2Doc (xChartDoc, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChart2Doc.is());
+
+ Reference< beans::XPropertySet > xPropSet = xChart2Doc->getArea();
+ CPPUNIT_ASSERT_MESSAGE("failed to get Area", xPropSet.is());
+
+ css::drawing::FillStyle aStyle;
+ xPropSet -> getPropertyValue("FillStyle") >>= aStyle;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Background needs to be with solid fill style", css::drawing::FillStyle_SOLID, aStyle);
+}
+
+// 2 test methods here so that tearDown() can dispose the document
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testFdo54361)
+{
+ testTransparentBackground(u"xlsx/fdo54361.xlsx");
+}
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testFdo54361_1)
+{
+ testTransparentBackground(u"xlsx/fdo54361-1.xlsx");
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testAutoBackgroundXLSX)
+{
+ loadFromFile(u"xlsx/chart-auto-background.xlsx");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ // "Automatic" chart background fill in xlsx should be loaded as solid white.
+ Reference<beans::XPropertySet> xPropSet = xChartDoc->getPageBackground();
+ CPPUNIT_ASSERT(xPropSet.is());
+ drawing::FillStyle eStyle = xPropSet->getPropertyValue("FillStyle").get<drawing::FillStyle>();
+ sal_Int32 nColor = xPropSet->getPropertyValue("FillColor").get<sal_Int32>();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chart background fill in xlsx should be loaded as solid fill.",
+ drawing::FillStyle_SOLID, eStyle);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chart background fill in xlsx should be loaded as solid white.",
+ sal_Int32(0x00FFFFFF), sal_Int32(nColor & 0x00FFFFFF)); // highest 2 bytes are transparency which we ignore here.
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testAutoChartAreaBorderPropXLSX)
+{
+ loadFromFile(u"xlsx/chart-area-style-border.xlsx");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ // Test "Automatic" chartarea border style/color/width.
+ Reference<beans::XPropertySet> xPropSet = xChartDoc->getPageBackground();
+ CPPUNIT_ASSERT(xPropSet.is());
+ drawing::LineStyle eStyle = xPropSet->getPropertyValue("LineStyle").get<drawing::LineStyle>();
+ sal_Int32 nColor = xPropSet->getPropertyValue("LineColor").get<sal_Int32>();
+ sal_Int32 nWidth = xPropSet->getPropertyValue("LineWidth").get<sal_Int32>();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chartarea border should be loaded as solid style.",
+ drawing::LineStyle_SOLID, eStyle);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chartarea border color should be loaded as light gray.",
+ sal_Int32(0xD9D9D9), nColor);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chartarea border width should be loaded as 0.75 pt (~0.026 cm)",
+ sal_Int32(26), nWidth);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testAutoChartAreaBorderPropPPTX)
+{
+ loadFromFile(u"pptx/tdf150176.pptx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ // Test "Automatic" chartarea border style/color/width.
+ Reference<beans::XPropertySet> xPropSet = xChartDoc->getPageBackground();
+ CPPUNIT_ASSERT(xPropSet.is());
+ drawing::LineStyle eStyle = xPropSet->getPropertyValue("LineStyle").get<drawing::LineStyle>();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chartarea border should be loaded as none style for pptx.",
+ drawing::LineStyle_NONE, eStyle);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testChartAreaStyleBackgroundXLSX)
+{
+ loadFromFile(u"xlsx/chart-area-style-background.xlsx");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ // "Automatic" chart background fill in xlsx should be loaded as solid white.
+ Reference<beans::XPropertySet> xPropSet = xChartDoc->getPageBackground();
+ CPPUNIT_ASSERT(xPropSet.is());
+ drawing::FillStyle eStyle = xPropSet->getPropertyValue("FillStyle").get<drawing::FillStyle>();
+ sal_Int32 nColor = xPropSet->getPropertyValue("FillColor").get<sal_Int32>();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chart background fill in xlsx should be loaded as solid fill.",
+ drawing::FillStyle_SOLID, eStyle);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("'Automatic' chart background fill in xlsx should be loaded as solid white.",
+ sal_Int32(0), nColor);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testChartHatchFillXLSX)
+{
+ loadFromFile(u"xlsx/chart-hatch-fill.xlsx");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ // Check the chart background FillStyle is HATCH
+ Reference<beans::XPropertySet> xPropSet = xChartDoc->getPageBackground();
+ CPPUNIT_ASSERT(xPropSet.is());
+ drawing::FillStyle eStyle = xPropSet->getPropertyValue("FillStyle").get<drawing::FillStyle>();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Chart background fill in this xlsx should be loaded as hatch fill.",
+ drawing::FillStyle_HATCH, eStyle);
+
+ // Check the FillBackground of chart background
+ bool bBackgroundFill = false;
+ xPropSet->getPropertyValue("FillBackground") >>= bBackgroundFill;
+ CPPUNIT_ASSERT(bBackgroundFill);
+
+ Color nBackgroundColor;
+ xPropSet->getPropertyValue("FillColor") >>= nBackgroundColor;
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, nBackgroundColor);
+
+ // Check the datapoint has HatchName value
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(1), uno::UNO_SET_THROW);
+ OUString sHatchName;
+ xPropertySet->getPropertyValue("HatchName") >>= sHatchName;
+ CPPUNIT_ASSERT(!sHatchName.isEmpty());
+
+ // Check the FillBackground of datapoint
+ bool bBackgroundFillofDatapoint = false;
+ xPropertySet->getPropertyValue("FillBackground") >>= bBackgroundFillofDatapoint;
+ CPPUNIT_ASSERT(bBackgroundFillofDatapoint);
+
+ sal_Int32 nBackgroundColorofDatapoint;
+ xPropertySet->getPropertyValue("FillColor") >>= nBackgroundColorofDatapoint;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0x00B050), nBackgroundColorofDatapoint);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testAxisTextRotationXLSX)
+{
+ loadFromFile(u"xlsx/axis-label-rotation.xlsx");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ Reference<chart2::XAxis> xYAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xYAxis.is());
+
+ Reference<beans::XPropertySet> xPS(xYAxis, uno::UNO_QUERY_THROW);
+ double nRotation = 0;
+ bool bSuccess = xPS->getPropertyValue("TextRotation") >>= nRotation;
+
+ CPPUNIT_ASSERT(bSuccess);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(90, nRotation, 1e-10);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTextCanOverlapXLSX)
+{
+ // fdo#84647 : To check textoverlap value is imported correctly.
+ loadFromFile(u"xlsx/chart-text-can-overlap.xlsx");
+ uno::Reference< chart::XDiagram > mxDiagram;
+ uno::Reference< beans::XPropertySet > xAxisProp;
+ bool bTextCanOverlap = false;
+ uno::Reference< chart::XChartDocument > xChartDoc ( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW);
+ mxDiagram.set(xChartDoc->getDiagram());
+ CPPUNIT_ASSERT(mxDiagram.is());
+ uno::Reference< chart::XAxisXSupplier > xAxisXSupp( mxDiagram, uno::UNO_QUERY );
+ CPPUNIT_ASSERT(xAxisXSupp.is());
+ xAxisProp = xAxisXSupp->getXAxis();
+ xAxisProp->getPropertyValue("TextCanOverlap") >>= bTextCanOverlap;
+ CPPUNIT_ASSERT(!bTextCanOverlap);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTextBreakXLSX)
+{
+ // tdf#122091: To check textbreak value is true in case of 0° degree of Axis label rotation.
+ loadFromFile(u"xlsx/chart_label_text_break.xlsx");
+ uno::Reference< chart::XDiagram > mxDiagram;
+ uno::Reference< beans::XPropertySet > xAxisProp;
+ bool textBreak = false;
+ uno::Reference< chart::XChartDocument > xChartDoc ( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ mxDiagram.set(xChartDoc->getDiagram());
+ CPPUNIT_ASSERT(mxDiagram.is());
+ uno::Reference< chart::XAxisXSupplier > xAxisXSupp( mxDiagram, uno::UNO_QUERY );
+ CPPUNIT_ASSERT(xAxisXSupp.is());
+ xAxisProp = xAxisXSupp->getXAxis();
+ xAxisProp->getPropertyValue("TextBreak") >>= textBreak;
+ // Expected value of 'TextBreak' is true
+ CPPUNIT_ASSERT(textBreak);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testNumberFormatsXLSX)
+{
+ loadFromFile(u"xlsx/number-formats.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ chart2::DataPointLabel aLabel;
+ sal_Int32 nNumberFormat;
+ bool bLinkNumberFormatToSource = false;
+ const sal_Int32 nChartDataNumberFormat = getNumberFormat(
+ xChartDoc, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"??_);_(@_)");
+
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("Label") >>= aLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumber);
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumberInPercent);
+ xPropertySet->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(nChartDataNumberFormat, nNumberFormat);
+ bool bSuccess = xPropertySet->getPropertyValue("PercentageNumberFormat") >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(false, bSuccess);
+ bSuccess = xPropertySet->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkNumberFormatToSource;
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to true.", bSuccess);
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to true.", bLinkNumberFormatToSource);
+
+ xPropertySet.set(xDataSeries->getDataPointByIndex(1), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("Label") >>= aLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumber);
+ CPPUNIT_ASSERT_EQUAL(sal_False, aLabel.ShowNumberInPercent);
+ xPropertySet->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(nChartDataNumberFormat, nNumberFormat);
+ bSuccess = xPropertySet->getPropertyValue("PercentageNumberFormat") >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(false, bSuccess);
+ bSuccess = xPropertySet->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkNumberFormatToSource;
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to true.", bSuccess);
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to true.", bLinkNumberFormatToSource);
+
+ xPropertySet.set(xDataSeries->getDataPointByIndex(2), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("Label") >>= aLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_False, aLabel.ShowNumber);
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumberInPercent);
+ xPropertySet->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(nChartDataNumberFormat, nNumberFormat);
+ bSuccess = xPropertySet->getPropertyValue("PercentageNumberFormat") >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(false, bSuccess);
+ bSuccess = xPropertySet->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkNumberFormatToSource;
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to true.", bSuccess);
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to true.", bLinkNumberFormatToSource);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testNumberFormatsDOCX)
+{
+ loadFromFile(u"docx/tdf132174.docx");
+ {
+ uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ css::uno::Reference<chart2::XDiagram> xDiagram(xChartDoc->getFirstDiagram(), UNO_SET_THROW);
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries, uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xPropertySet.is());
+
+ sal_Int32 nNumberFormat;
+ bool bLinkNumberFormatToSource = true;
+ const sal_Int32 nChartDataNumberFormat = getNumberFormat(xChartDoc, "0%");
+ xPropertySet->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(nChartDataNumberFormat, nNumberFormat);
+ xPropertySet->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkNumberFormatToSource;
+ // LinkNumberFormatToSource should be set to false even if the original OOXML contain a true value,
+ // because the inner data table of charts have no own number format!
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to false.", !bLinkNumberFormatToSource);
+ }
+
+ loadFromFile(u"docx/tdf136650.docx");
+ {
+ uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ css::uno::Reference<chart2::XDiagram> xDiagram(xChartDoc->getFirstDiagram(), UNO_SET_THROW);
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(1), uno::UNO_SET_THROW);
+
+ sal_Int32 nNumberFormat;
+ bool bLinkNumberFormatToSource = true;
+ const sal_Int32 nChartDataNumberFormat = getNumberFormat(xChartDoc, "0%");
+ xPropertySet->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormat;
+ CPPUNIT_ASSERT_EQUAL(nChartDataNumberFormat, nNumberFormat);
+ xPropertySet->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkNumberFormatToSource;
+ // LinkNumberFormatToSource should be set to false even if the original OOXML file contain a true value,
+ // because the inner data table of charts have no own number format!
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to false.", !bLinkNumberFormatToSource);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPercentageNumberFormatsDOCX)
+{
+ loadFromFile(u"docx/tdf133632.docx");
+ uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ css::uno::Reference<chart2::XDiagram> xDiagram(xChartDoc->getFirstDiagram(), UNO_SET_THROW);
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries, uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xPropertySet.is());
+
+ bool bLinkNumberFormatToSource = false;
+ chart2::DataPointLabel aLabel;
+ xPropertySet->getPropertyValue("Label") >>= aLabel;
+ CPPUNIT_ASSERT_EQUAL(sal_False, aLabel.ShowNumber);
+ CPPUNIT_ASSERT_EQUAL(sal_True, aLabel.ShowNumberInPercent);
+ bool bSuccess = xPropertySet->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkNumberFormatToSource;
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to true.", bSuccess);
+ CPPUNIT_ASSERT_MESSAGE("\"LinkNumberFormatToSource\" should be set to true.", bLinkNumberFormatToSource);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testAutoTitleDelDefaultValue2007XLSX)
+{
+ // below are OOXML default value tests for cases
+ // where we fixed the handling of MSO 2007 vs OOXML
+ loadFromFile(u"xlsx/autotitledel_2007.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ Reference<chart2::XTitled> xTitled(xChartDoc, uno::UNO_QUERY_THROW);
+ OUString aTitle = getTitleString(xTitled);
+ CPPUNIT_ASSERT_MESSAGE("autoTitleDel default value is false in MSO 2007 documents",
+ !aTitle.isEmpty());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testAutoTitleDelDefaultValue2013XLSX)
+{
+ loadFromFile(u"xlsx/autotitledel_2013.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ Reference<chart2::XTitled> xTitled(xChartDoc, uno::UNO_QUERY_THROW);
+ uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+ CPPUNIT_ASSERT_MESSAGE("autoTitleDel default value is true in the OOXML spec",
+ !xTitle.is());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testDispBlanksAsDefaultValue2007XLSX)
+{
+ loadFromFile(u"xlsx/dispBlanksAs_2007.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ Reference<beans::XPropertySet> xDiagram(xChartDoc->getFirstDiagram(), UNO_QUERY);
+ CPPUNIT_ASSERT(xDiagram.is());
+ uno::Any aAny = xDiagram->getPropertyValue("MissingValueTreatment");
+ sal_Int32 nMissingValueTreatment = -2;
+ CPPUNIT_ASSERT(aAny >>= nMissingValueTreatment);
+ CPPUNIT_ASSERT_EQUAL(chart::MissingValueTreatment::LEAVE_GAP, nMissingValueTreatment);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testDispBlanksAsDefaultValue2013XLSX)
+{
+ loadFromFile(u"xlsx/dispBlanksAs_2013.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ Reference<beans::XPropertySet> xDiagram(xChartDoc->getFirstDiagram(), UNO_QUERY);
+ CPPUNIT_ASSERT(xDiagram.is());
+ uno::Any aAny = xDiagram->getPropertyValue("MissingValueTreatment");
+ sal_Int32 nMissingValueTreatment = -2;
+ CPPUNIT_ASSERT(aAny >>= nMissingValueTreatment);
+ CPPUNIT_ASSERT_EQUAL(chart::MissingValueTreatment::USE_ZERO, nMissingValueTreatment);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testSmoothDefaultValue2007XLSX)
+{
+ loadFromFile(u"xlsx/smoothed_series2007.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XChartType > xChartType = getChartTypeFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT(xChartType.is());
+
+ Reference< beans::XPropertySet > xPropSet( xChartType, UNO_QUERY );
+ CPPUNIT_ASSERT(xPropSet.is());
+
+ chart2::CurveStyle eCurveStyle;
+ xPropSet->getPropertyValue("CurveStyle") >>= eCurveStyle;
+ CPPUNIT_ASSERT_EQUAL(chart2::CurveStyle_LINES, eCurveStyle);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testSmoothDefaultValue2013XLSX)
+{
+ loadFromFile(u"xlsx/smoothed_series.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference< chart2::XChartType > xChartType = getChartTypeFromDoc( xChartDoc, 0 );
+ CPPUNIT_ASSERT(xChartType.is());
+
+ Reference< beans::XPropertySet > xPropSet( xChartType, UNO_QUERY );
+ CPPUNIT_ASSERT(xPropSet.is());
+
+ chart2::CurveStyle eCurveStyle;
+ xPropSet->getPropertyValue("CurveStyle") >>= eCurveStyle;
+ CPPUNIT_ASSERT(eCurveStyle != chart2::CurveStyle_LINES);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTrendlineDefaultValue2007XLSX)
+{
+ loadFromFile(u"xlsx/trendline2007.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<chart2::XRegressionCurveContainer> xRegressionCurveContainer(xDataSeries, UNO_QUERY_THROW);
+ Sequence< Reference<chart2::XRegressionCurve> > xRegressionCurveSequence = xRegressionCurveContainer->getRegressionCurves();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xRegressionCurveSequence.getLength());
+
+ Reference<chart2::XRegressionCurve> xCurve = xRegressionCurveSequence[0];
+
+ Reference<beans::XPropertySet> xPropSet(xCurve->getEquationProperties(), uno::UNO_SET_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("ShowEquation");
+ bool bShowEquation = true;
+ CPPUNIT_ASSERT(aAny >>= bShowEquation);
+ CPPUNIT_ASSERT(!bShowEquation);
+
+ aAny = xPropSet->getPropertyValue("ShowCorrelationCoefficient");
+ bool bShowCorrelation = true;
+ CPPUNIT_ASSERT(aAny >>= bShowCorrelation);
+ CPPUNIT_ASSERT(!bShowCorrelation);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTrendlineDefaultValue2013XLSX)
+{
+ loadFromFile(u"xlsx/trendline.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<chart2::XRegressionCurveContainer> xRegressionCurveContainer(xDataSeries, UNO_QUERY_THROW);
+ Sequence< Reference<chart2::XRegressionCurve> > xRegressionCurveSequence = xRegressionCurveContainer->getRegressionCurves();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xRegressionCurveSequence.getLength());
+
+ Reference<chart2::XRegressionCurve> xCurve = xRegressionCurveSequence[0];
+
+ Reference<beans::XPropertySet> xPropSet(xCurve->getEquationProperties(), uno::UNO_SET_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("ShowEquation");
+ bool bShowEquation = false;
+ CPPUNIT_ASSERT(aAny >>= bShowEquation);
+ CPPUNIT_ASSERT(bShowEquation);
+
+ aAny = xPropSet->getPropertyValue("ShowCorrelationCoefficient");
+ bool bShowCorrelation = false;
+ CPPUNIT_ASSERT(aAny >>= bShowCorrelation);
+ CPPUNIT_ASSERT(bShowCorrelation);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testVaryColorDefaultValues2007XLSX)
+{
+ loadFromFile(u"xlsx/vary_color2007.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropSet(xDataSeries, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("VaryColorsByPoint");
+ bool bVaryColor = true;
+ CPPUNIT_ASSERT(aAny >>= bVaryColor);
+ CPPUNIT_ASSERT(!bVaryColor);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testVaryColorDefaultValues2013XLSX)
+{
+ loadFromFile(u"xlsx/vary_color.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropSet(xDataSeries, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("VaryColorsByPoint");
+ bool bVaryColor = false;
+ CPPUNIT_ASSERT(aAny >>= bVaryColor);
+ CPPUNIT_ASSERT(!bVaryColor);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPlotVisOnlyDefaultValue2013XLSX)
+{
+ loadFromFile(u"xlsx/plotVisOnly.xlsx");
+ uno::Reference< chart::XChartDocument > xChart1Doc ( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW);
+ Reference<beans::XPropertySet> xPropSet(xChart1Doc->getDiagram(), uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("IncludeHiddenCells");
+ CPPUNIT_ASSERT(aAny.hasValue());
+ bool bShowHiddenValues = true;
+ CPPUNIT_ASSERT(aAny >>= bShowHiddenValues);
+ CPPUNIT_ASSERT(!bShowHiddenValues);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testRAngAxDefaultValue2013XLSX)
+{
+ loadFromFile(u"xlsx/rAngAx.xlsx");
+ uno::Reference< chart::XChartDocument > xChart1Doc ( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW);
+ Reference<beans::XPropertySet> xPropSet(xChart1Doc->getDiagram(), uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("RightAngledAxes");
+ CPPUNIT_ASSERT(aAny.hasValue());
+ bool bRightAngleAxes = false;
+ CPPUNIT_ASSERT(aAny >>= bRightAngleAxes);
+ CPPUNIT_ASSERT(bRightAngleAxes);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testMajorTickMarksDefaultValue2013XLSX)
+{
+ loadFromFile(u"xlsx/majorTickMark.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ Reference<chart2::XAxis> xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xXAxis.is());
+ Reference<beans::XPropertySet> xPropSet(xXAxis, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("MajorTickmarks");
+ sal_Int32 nMajorTickmarks = chart2::TickmarkStyle::NONE;
+ CPPUNIT_ASSERT(aAny.hasValue());
+ CPPUNIT_ASSERT(aAny >>= nMajorTickmarks);
+ CPPUNIT_ASSERT_EQUAL(chart2::TickmarkStyle::INNER | chart2::TickmarkStyle::OUTER, nMajorTickmarks);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testMinorTickMarksDefaultValue2013XLSX)
+{
+ loadFromFile(u"xlsx/minorTickMark.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ Reference<chart2::XAxis> xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xXAxis.is());
+ Reference<beans::XPropertySet> xPropSet(xXAxis, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("MinorTickmarks");
+ sal_Int32 nMajorTickmarks = chart2::TickmarkStyle::NONE;
+ CPPUNIT_ASSERT(aAny.hasValue());
+ CPPUNIT_ASSERT(aAny >>= nMajorTickmarks);
+ CPPUNIT_ASSERT_EQUAL(chart2::TickmarkStyle::INNER | chart2::TickmarkStyle::OUTER, nMajorTickmarks);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testAxisTitleDefaultRotationXLSX)
+{
+ loadFromFile(u"xlsx/axis_title_default_rotation.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ Reference<chart2::XAxis> xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 0);
+ CPPUNIT_ASSERT(xYAxis.is());
+ Reference<chart2::XTitled> xTitled(xYAxis, uno::UNO_QUERY_THROW);
+ Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+ CPPUNIT_ASSERT(xTitle.is());
+ Reference<beans::XPropertySet> xPropSet(xTitle, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("TextRotation");
+ double nRotation = 0;
+ CPPUNIT_ASSERT(aAny >>= nRotation);
+ CPPUNIT_ASSERT_EQUAL(90.0, nRotation);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testSecondaryAxisTitleDefaultRotationXLSX)
+{
+ loadFromFile(u"xlsx/secondary_axis_title_default_rotation.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ Reference<chart2::XAxis> xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 1);
+ CPPUNIT_ASSERT(xYAxis.is());
+ Reference<chart2::XTitled> xTitled(xYAxis, uno::UNO_QUERY_THROW);
+ Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+ CPPUNIT_ASSERT(xTitle.is());
+ Reference<beans::XPropertySet> xPropSet(xTitle, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("TextRotation");
+ double nRotation = 0;
+ CPPUNIT_ASSERT(aAny >>= nRotation);
+ CPPUNIT_ASSERT_EQUAL(90.0, nRotation);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testAxisTitleRotationXLSX)
+{
+ loadFromFile(u"xlsx/axis_title_rotated.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ {
+ Reference<chart2::XAxis> xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 0);
+ CPPUNIT_ASSERT(xYAxis.is());
+ Reference<chart2::XTitled> xTitled(xYAxis, uno::UNO_QUERY_THROW);
+ Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+ CPPUNIT_ASSERT(xTitle.is());
+ Reference<beans::XPropertySet> xPropSet(xTitle, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("TextRotation");
+ double nRotation = 0;
+ CPPUNIT_ASSERT(aAny >>= nRotation);
+ CPPUNIT_ASSERT_EQUAL(340.0, nRotation);
+ }
+ {
+ Reference<chart2::XAxis> xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 1);
+ CPPUNIT_ASSERT(xYAxis.is());
+ Reference<chart2::XTitled> xTitled(xYAxis, uno::UNO_QUERY_THROW);
+ Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+ CPPUNIT_ASSERT(xTitle.is());
+ Reference<beans::XPropertySet> xPropSet(xTitle, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("TextRotation");
+ double nRotation = 0;
+ CPPUNIT_ASSERT(aAny >>= nRotation);
+ CPPUNIT_ASSERT_EQUAL(270.0, nRotation);
+ }
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testAxisTitlePositionDOCX)
+{
+ loadFromFile(u"docx/testAxisTitlePosition.docx");
+ uno::Reference< chart::XDiagram > mxDiagram;
+ uno::Reference< drawing::XShape > xAxisTitle;
+ uno::Reference< chart::XChartDocument > xChartDoc = getChartDocFromWriter(0);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ mxDiagram.set(xChartDoc->getDiagram());
+ CPPUNIT_ASSERT(mxDiagram.is());
+ // test X Axis title position
+ uno::Reference< chart::XAxisXSupplier > xAxisXSupp(mxDiagram, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xAxisXSupp.is());
+
+ xAxisTitle = xAxisXSupp->getXAxisTitle();
+ CPPUNIT_ASSERT(xAxisTitle.is());
+
+ awt::Point aPos = xAxisTitle->getPosition();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(10640, aPos.X, 2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(7157, aPos.Y, 2);
+
+ // test Y Axis title position
+ uno::Reference< chart::XAxisYSupplier > xAxisYSupp(mxDiagram, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xAxisYSupp.is());
+
+ xAxisTitle = xAxisYSupp->getYAxisTitle();
+ CPPUNIT_ASSERT(xAxisTitle.is());
+
+ aPos = xAxisTitle->getPosition();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(387, aPos.X, 2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6378, aPos.Y, 300);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testCombinedChartAttachedAxisXLSX)
+{
+ loadFromFile(u"xlsx/testCombinedChartAxis.xlsx");
+ Reference< chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ // First series
+ Reference<chart2::XDataSeries> xSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xSeries.is());
+
+ Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY_THROW);
+ sal_Int32 nAxisIndex = -1;
+ // First series (column chart) should be attached to secondary axis!
+ uno::Any aAny = xPropSet->getPropertyValue("AttachedAxisIndex");
+ CPPUNIT_ASSERT(aAny >>= nAxisIndex);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), nAxisIndex);
+
+ // Second series
+ xSeries = getDataSeriesFromDoc(xChartDoc, 0, 1);
+ CPPUNIT_ASSERT(xSeries.is());
+
+ xPropSet.set(xSeries, uno::UNO_QUERY_THROW);
+ // Second series (line chart) should be attached to primary axis!
+ aAny = xPropSet->getPropertyValue("AttachedAxisIndex");
+ CPPUNIT_ASSERT(aAny >>= nAxisIndex);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nAxisIndex);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf140489MultiSeriesChartAxisXLSX)
+{
+ loadFromFile(u"xlsx/tdf140489.xlsx");
+ Reference< chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ // First series
+ Reference<chart2::XDataSeries> xSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xSeries.is());
+
+ Reference<beans::XPropertySet> xPropSet(xSeries, uno::UNO_QUERY_THROW);
+ sal_Int32 nAxisIndex = -1;
+ uno::Any aAny = xPropSet->getPropertyValue("AttachedAxisIndex");
+ CPPUNIT_ASSERT(aAny >>= nAxisIndex);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nAxisIndex);
+
+ // Second series
+ xSeries = getDataSeriesFromDoc(xChartDoc, 0, 1);
+ CPPUNIT_ASSERT(xSeries.is());
+
+ xPropSet.set(xSeries, uno::UNO_QUERY_THROW);
+ aAny = xPropSet->getPropertyValue("AttachedAxisIndex");
+ CPPUNIT_ASSERT(aAny >>= nAxisIndex);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nAxisIndex);
+
+ // Third series
+ xSeries = getDataSeriesFromDoc(xChartDoc, 0, 2);
+ CPPUNIT_ASSERT(xSeries.is());
+
+ xPropSet.set(xSeries, uno::UNO_QUERY_THROW);
+ aAny = xPropSet->getPropertyValue("AttachedAxisIndex");
+ CPPUNIT_ASSERT(aAny >>= nAxisIndex);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), nAxisIndex);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testInternalDataProvider)
+{
+ loadFromFile(u"odp/chart.odp");
+ uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0,0), uno::UNO_QUERY_THROW);
+ const uno::Reference< chart2::data::XDataProvider >& rxDataProvider = xChartDoc->getDataProvider();
+
+ // Parse 42 array
+ Reference<chart2::data::XDataSequence> xDataSeq = rxDataProvider->createDataSequenceByValueArray("values-y", "{42;42;42;42}", "");
+ Sequence<Any> xSequence = xDataSeq->getData();
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(42)), xSequence[0]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(42)), xSequence[1]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(42)), xSequence[2]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(42)), xSequence[3]);
+
+ // Parse empty first and last
+ xDataSeq = rxDataProvider->createDataSequenceByValueArray("values-y", "{\"\";42;42;\"\"}", "");
+ xSequence = xDataSeq->getData();
+ CPPUNIT_ASSERT( std::isnan( *static_cast<const double*>(xSequence[0].getValue())));
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(42)), xSequence[1]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(42)), xSequence[2]);
+ CPPUNIT_ASSERT( std::isnan( *static_cast<const double*>(xSequence[3].getValue())));
+
+ // Parse empty middle
+ xDataSeq = rxDataProvider->createDataSequenceByValueArray("values-y", "{42;\"\";\"\";42}", "");
+ xSequence = xDataSeq->getData();
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(42)), xSequence[0]);
+ CPPUNIT_ASSERT( std::isnan( *static_cast<const double*>(xSequence[1].getValue())) );
+ CPPUNIT_ASSERT( std::isnan( *static_cast<const double*>(xSequence[2].getValue())) );
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(42)), xSequence[3]);
+
+ // Parse mixed types, numeric only role
+ xDataSeq = rxDataProvider->createDataSequenceByValueArray("values-y", "{42;\"hello\";0;\"world\"}", "");
+ xSequence = xDataSeq->getData();
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(42)), xSequence[0]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(0)), xSequence[1]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(0)), xSequence[2]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(0)), xSequence[3]);
+
+ // Parse mixed types, mixed role
+ xDataSeq = rxDataProvider->createDataSequenceByValueArray("categories", "{42;\"hello\";0;\"world\"}", "");
+ xSequence = xDataSeq->getData();
+ CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 1 42")), xSequence[0]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 2 hello")), xSequence[1]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 3 0")), xSequence[2]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 4 world")), xSequence[3]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf90510)
+{
+ // Pie chart label placement settings(XLS)
+ loadFromFile(u"xls/piechart_outside.xls");
+ uno::Reference< chart::XChartDocument > xChart1Doc( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW );
+ Reference<beans::XPropertySet> xPropSet( xChart1Doc->getDiagram()->getDataPointProperties( 0, 0 ), uno::UNO_SET_THROW );
+ uno::Any aAny = xPropSet->getPropertyValue( "LabelPlacement" );
+ CPPUNIT_ASSERT( aAny.hasValue() );
+ sal_Int32 nLabelPlacement = 0;
+ CPPUNIT_ASSERT( aAny >>= nLabelPlacement );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Data labels should be placed outside", chart::DataLabelPlacement::OUTSIDE, nLabelPlacement );
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf109858)
+{
+ // Pie chart label placement settings(XLSX)
+ loadFromFile(u"xlsx/piechart_outside.xlsx");
+ uno::Reference< chart::XChartDocument > xChart1Doc( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW );
+
+ // test data point labels position
+ Reference<beans::XPropertySet> xDataPointPropSet( xChart1Doc->getDiagram()->getDataPointProperties( 0, 0 ), uno::UNO_SET_THROW );
+ uno::Any aAny = xDataPointPropSet->getPropertyValue( "LabelPlacement" );
+ CPPUNIT_ASSERT( aAny.hasValue() );
+ sal_Int32 nLabelPlacement = 0;
+ CPPUNIT_ASSERT( aAny >>= nLabelPlacement );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Data point label should be placed bestfit", chart::DataLabelPlacement::CUSTOM, nLabelPlacement );
+
+ // test data series label position
+ Reference<beans::XPropertySet> xSeriesPropSet(xChart1Doc->getDiagram()->getDataRowProperties(0), uno::UNO_SET_THROW);
+ aAny = xSeriesPropSet->getPropertyValue( "LabelPlacement" );
+ CPPUNIT_ASSERT( aAny >>= nLabelPlacement );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Data series labels should be placed outside", chart::DataLabelPlacement::OUTSIDE, nLabelPlacement );
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf130105)
+{
+ loadFromFile(u"xlsx/barchart_outend.xlsx");
+ uno::Reference< chart2::XChartDocument > xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ uno::Any aAny = xPropertySet->getPropertyValue("LabelPlacement");
+ CPPUNIT_ASSERT(aAny.hasValue());
+ sal_Int32 nLabelPlacement = 0;
+ CPPUNIT_ASSERT(aAny >>= nLabelPlacement);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Data label should be placed outend", chart::DataLabelPlacement::OUTSIDE, nLabelPlacement);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf111173)
+{
+ loadFromFile(u"xlsx/tdf111173.xlsx");
+ uno::Reference< chart::XChartDocument > xChart1Doc( getChartCompFromSheet( 0, 0, mxComponent ), UNO_QUERY_THROW );
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf122226)
+{
+ loadFromFile(u"docx/testTdf122226.docx" );
+ uno::Reference< chart2::XChartDocument > xChartDoc ( getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT( xChartDoc.is() );
+
+ css::uno::Reference<chart2::XDiagram> xDiagram(xChartDoc->getFirstDiagram(), UNO_SET_THROW);
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ CPPUNIT_ASSERT(xPropertySet.is());
+
+ uno::Any aAny = xPropertySet->getPropertyValue( "LabelSeparator" );
+ CPPUNIT_ASSERT( aAny.hasValue() );
+ OUString nLabelSeparator;
+ CPPUNIT_ASSERT( aAny >>= nLabelSeparator );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "Data labels should be separated into new lines", OUString("\n"), nLabelSeparator );
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf115107)
+{
+ // import complex data point labels
+ loadFromFile(u"pptx/tdf115107.pptx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ float nFontSize;
+ sal_Int64 nFontColor;
+ sal_Int32 nCharUnderline;
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+
+ // 1
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("90.0 = "), aFields[0]->getString());
+ aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xed7d31), nFontColor);
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE, aFields[1]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("90"), aFields[1]->getString());
+
+ // 2
+ xPropertySet.set(xDataSeries->getDataPointByIndex(1), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(8), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("Text"), aFields[0]->getString());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString(" : "), aFields[1]->getString());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CATEGORYNAME, aFields[2]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("B"), aFields[2]->getString());
+ aFields[2]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[2]->getPropertyValue("CharColor") >>= nFontColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(16), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xed7d31), nFontColor);
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE, aFields[3]->getFieldType());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[4]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("Multi"), aFields[4]->getString());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[5]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("line"), aFields[5]->getString());
+ aFields[5]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[5]->getPropertyValue("CharColor") >>= nFontColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(11.97), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xbf9000), nFontColor);
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE, aFields[6]->getFieldType());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[7]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("Abc"), aFields[7]->getString());
+ aFields[7]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[7]->getPropertyValue("CharColor") >>= nFontColor;
+ aFields[7]->getPropertyValue("CharUnderline") >>= nCharUnderline;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(12), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xa9d18e), nFontColor);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nCharUnderline);
+
+ // 3
+ xPropertySet.set(xDataSeries->getDataPointByIndex(2), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME, aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("DATA"), aFields[0]->getString());
+
+ // 4
+ xPropertySet.set(xDataSeries->getDataPointByIndex(3), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLREF, aFields[0]->getFieldType());
+ //CPPUNIT_ASSERT_EQUAL(OUString("70"), aFields[0]->getString()); TODO: Not implemented yet
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString(" <CELLREF"), aFields[1]->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf115107_2)
+{
+ // import complex data point labels in cobo charts with multiple data series
+ loadFromFile(u"pptx/tdf115107-2.pptx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ float nFontSize;
+ sal_Int64 nFontColor;
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+
+ // First series
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE, aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("4.3"), aFields[0]->getString());
+ aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xc00000), nFontColor);
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString(" "), aFields[1]->getString());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME, aFields[2]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("Bars"), aFields[2]->getString());
+
+ // Second series
+ xDataSeries = getDataSeriesFromDoc(xChartDoc, 0, 1);
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_SET_THROW);
+ xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aFields.getLength());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE, aFields[0]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("2"), aFields[0]->getString());
+ aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+ aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+ CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xffd966), nFontColor);
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString(" "), aFields[1]->getString());
+
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME, aFields[2]->getFieldType());
+ CPPUNIT_ASSERT_EQUAL(OUString("Line"), aFields[2]->getString());
+
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf116163)
+{
+ loadFromFile(u"pptx/tdf116163.pptx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xHAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xHAxis.is());
+
+ chart2::ScaleData aScaleData = xHAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Categories.is());
+
+ Reference<chart2::data::XLabeledDataSequence> xLabeledDataSequence = aScaleData.Categories;
+ CPPUNIT_ASSERT(xLabeledDataSequence.is());
+
+ Reference<chart2::data::XDataSequence> xDataSequence = xLabeledDataSequence->getValues();
+ CPPUNIT_ASSERT(xDataSequence.is());
+
+ Reference<chart2::data::XTextualDataSequence> xTextualDataSequence(xDataSequence, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xTextualDataSequence.is());
+
+ std::vector<OUString> aCategories;
+ const Sequence<OUString> aTextData(xTextualDataSequence->getTextualData());
+ ::std::copy(aTextData.begin(), aTextData.end(),
+ ::std::back_inserter(aCategories));
+
+ CPPUNIT_ASSERT_EQUAL(OUString("Aaaa"), aCategories[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Bbbbbbb"), aCategories[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Ccc"), aCategories[2]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Ddddddddddddd"), aCategories[3]);
+
+ // Check visible text
+
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference<drawing::XShape> xXAxis = getShapeByName(xShapes, "CID/D=0:CS=0:Axis=0,0",
+ // Axis occurs twice in chart xshape representation so need to get the one related to labels
+ [](const uno::Reference<drawing::XShape>& rXShape) -> bool
+ {
+ uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xAxisShapes.is());
+ uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xChildShape, uno::UNO_QUERY_THROW);
+ return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape");
+ });
+ CPPUNIT_ASSERT(xXAxis.is());
+
+ uno::Reference<container::XIndexAccess> xIndexAccess(xXAxis, UNO_QUERY_THROW);
+
+ // Check text
+ uno::Reference<text::XTextRange> xLabel0(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Aaaa"), xLabel0->getString());
+ uno::Reference<text::XTextRange> xLabel1(xIndexAccess->getByIndex(1), uno::UNO_QUERY);
+ // If there is space for 3 chars only then don't show "..."
+ CPPUNIT_ASSERT_EQUAL(OUString("Bbb"), xLabel1->getString());
+ uno::Reference<text::XTextRange> xLabel2(xIndexAccess->getByIndex(2), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Ccc"), xLabel2->getString());
+ uno::Reference<text::XTextRange> xLabel3(xIndexAccess->getByIndex(3), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Dddd..."), xLabel3->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf48041)
+{
+ loadFromFile(u"pptx/tdf48041.pptx");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xYAxis = getAxisFromDoc(xChartDoc, 0, 1, 0);
+ CPPUNIT_ASSERT(xYAxis.is());
+
+ chart2::ScaleData aScaleData = xYAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Scaling.is());
+
+ // Check visible text
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference<drawing::XShape> xYAxisShape = getShapeByName(xShapes, "CID/D=0:CS=0:Axis=1,0", // Y Axis
+ // Axis occurs twice in chart xshape representation so need to get the one related to labels
+ [](const uno::Reference<drawing::XShape>& rXShape) -> bool
+ {
+ uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xAxisShapes.is());
+ uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xChildShape, uno::UNO_QUERY_THROW);
+ return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape");
+ });
+ CPPUNIT_ASSERT(xYAxisShape.is());
+
+ // Check label count
+ uno::Reference<container::XIndexAccess> xIndexAccess(xYAxisShape, UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(6), xIndexAccess->getCount());
+
+ // Check text
+ uno::Reference<text::XTextRange> xLabel0(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("0"), xLabel0->getString());
+ uno::Reference<text::XTextRange> xLabel1(xIndexAccess->getByIndex(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), xLabel1->getString());
+ uno::Reference<text::XTextRange> xLabel2(xIndexAccess->getByIndex(2), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("2"), xLabel2->getString());
+ uno::Reference<text::XTextRange> xLabel3(xIndexAccess->getByIndex(3), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("3"), xLabel3->getString());
+ uno::Reference<text::XTextRange> xLabel4(xIndexAccess->getByIndex(4), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("4"), xLabel4->getString());
+ uno::Reference<text::XTextRange> xLabel5(xIndexAccess->getByIndex(5), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("5"), xLabel5->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTdf121205)
+{
+ loadFromFile(u"pptx/tdf121205.pptx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+
+ uno::Reference<chart2::XTitled> xTitled(xChartDoc, uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_MESSAGE("chart doc does not have title", xTitled.is());
+ OUString aTitle = getTitleString(xTitled);
+
+ // We expect title split in 3 lines
+ CPPUNIT_ASSERT_EQUAL(OUString("Firstline\nSecondline\nThirdline"), aTitle);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testFixedSizeBarChartVeryLongLabel)
+{
+ // Bar chart area size is fixed (not automatic) so we can't resize
+ // the chart area to let the label break into multiple lines. In this
+ // case the best course of action is to just crop the label text. This
+ // test checks that the rendered text is actually cropped.
+
+ loadFromFile(u"odp/BarChartVeryLongLabel.odp");
+
+ // Select shape 0 which has fixed size chart
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xHAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xHAxis.is());
+
+ chart2::ScaleData aScaleData = xHAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Categories.is());
+
+ Reference<chart2::data::XLabeledDataSequence> xLabeledDataSequence = aScaleData.Categories;
+ CPPUNIT_ASSERT(xLabeledDataSequence.is());
+
+ Reference<chart2::data::XDataSequence> xDataSequence = xLabeledDataSequence->getValues();
+ CPPUNIT_ASSERT(xDataSequence.is());
+
+ Reference<chart2::data::XTextualDataSequence> xTextualDataSequence(xDataSequence, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xTextualDataSequence.is());
+
+ std::vector<OUString> aCategories;
+ const Sequence<OUString> aTextData(xTextualDataSequence->getTextualData());
+ ::std::copy(aTextData.begin(), aTextData.end(),
+ ::std::back_inserter(aCategories));
+
+ // Check that we have a very very long label text
+ CPPUNIT_ASSERT_EQUAL(OUString("Very very very very very very very very very very very loooooooooooong label"), aCategories[0]);
+
+ // Check visible text
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference<drawing::XShape> xXAxis = getShapeByName(xShapes, "CID/D=0:CS=0:Axis=0,0",
+ // Axis occurs twice in chart xshape representation so need to get the one related to labels
+ [](const uno::Reference<drawing::XShape>& rXShape) -> bool
+ {
+ uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xAxisShapes.is());
+ uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xChildShape, uno::UNO_QUERY_THROW);
+ return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape");
+ });
+ CPPUNIT_ASSERT(xXAxis.is());
+
+ uno::Reference<container::XIndexAccess> xIndexAccess(xXAxis, UNO_QUERY_THROW);
+
+ // Check text is actually cropped. Depending on DPI,
+ // it may be "Very very very very very very..." or "Very very very very very ver..."
+ uno::Reference<text::XTextRange> xLabel(xIndexAccess->getByIndex(0), uno::UNO_QUERY_THROW);
+ const OUString aLabelString = xLabel->getString();
+ CPPUNIT_ASSERT_LESSEQUAL(sal_Int32(32), aLabelString.getLength());
+ CPPUNIT_ASSERT(aLabelString.endsWith(u"..."));
+
+ uno::Reference<drawing::XShape> xChartWall = getShapeByName(xShapes, "CID/DiagramWall=");
+ CPPUNIT_ASSERT(xChartWall.is());
+
+ // The text shape width should be smaller than the chart wall
+ CPPUNIT_ASSERT_LESS(xChartWall->getSize().Width, xXAxis->getSize().Width);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(7113, xChartWall->getSize().Height, 100);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(398, xXAxis->getSize().Height, 100);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testAutomaticSizeBarChartVeryLongLabel)
+{
+ // Bar chart area size is automatic so we expect the label to be broken
+ // into multiple lines.
+
+ loadFromFile(u"odp/BarChartVeryLongLabel.odp");
+
+ // Select shape 1, which has an automatic sized chart
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xHAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xHAxis.is());
+
+ chart2::ScaleData aScaleData = xHAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Categories.is());
+
+ Reference<chart2::data::XLabeledDataSequence> xLabeledDataSequence = aScaleData.Categories;
+ CPPUNIT_ASSERT(xLabeledDataSequence.is());
+
+ Reference<chart2::data::XDataSequence> xDataSequence = xLabeledDataSequence->getValues();
+ CPPUNIT_ASSERT(xDataSequence.is());
+
+ Reference<chart2::data::XTextualDataSequence> xTextualDataSequence(xDataSequence, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xTextualDataSequence.is());
+
+ std::vector<OUString> aCategories;
+ const Sequence<OUString> aTextData(xTextualDataSequence->getTextualData());
+ ::std::copy(aTextData.begin(), aTextData.end(),
+ ::std::back_inserter(aCategories));
+
+ // Check that we have a very very long label text
+ CPPUNIT_ASSERT_EQUAL(OUString("Very very very very very very very very very very very loooooooooooong label"), aCategories[0]);
+
+ // Check visible text
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference<drawing::XShape> xXAxis = getShapeByName(xShapes, "CID/D=0:CS=0:Axis=0,0",
+ // Axis occurs twice in chart xshape representation so need to get the one related to labels
+ [](const uno::Reference<drawing::XShape>& rXShape) -> bool
+ {
+ uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xAxisShapes.is());
+ uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xChildShape, uno::UNO_QUERY_THROW);
+ return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape");
+ });
+ CPPUNIT_ASSERT(xXAxis.is());
+
+ uno::Reference<container::XIndexAccess> xIndexAccess(xXAxis, UNO_QUERY_THROW);
+
+ // Check text is unmodified
+ uno::Reference<text::XTextRange> xLabel(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("Very very very very very very very very very very very loooooooooooong label"), xLabel->getString());
+
+ uno::Reference<drawing::XShape> xChartWall = getShapeByName(xShapes, "CID/DiagramWall=");
+ CPPUNIT_ASSERT(xChartWall.is());
+
+ // The text shape width should be smaller than the chart wall
+ CPPUNIT_ASSERT_LESS(xChartWall->getSize().Width, xXAxis->getSize().Width);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(7200, xChartWall->getSize().Height, 100);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1192, xXAxis->getSize().Height, 100);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testTotalsRowIgnored)
+{
+ loadFromFile(u"xlsx/barchart_totalsrow.xlsx");
+ {
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::data::XDataSequence> xDataSeq =
+ getDataSequenceFromDocByRole(xChartDoc, u"values-y");
+ CPPUNIT_ASSERT(xDataSeq.is());
+
+ // Table data range is D2:D9 (8 rows) but because last row is totals row it is ignored
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(7u), xDataSeq->getData().size());
+ }
+ {
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(1, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::data::XDataSequence> xDataSeq =
+ getDataSequenceFromDocByRole(xChartDoc, u"values-y");
+ CPPUNIT_ASSERT(xDataSeq.is());
+
+ // Table data range is D2:D10 (9 rows) and totals row isn't the last row so it's not ignored
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(9u), xDataSeq->getData().size());
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest, testPieChartPlotAreaMarginWithAutomaticLayout)
+{
+ // tdf#91265
+ // Checks the margin and calculation of the plot area for the pie chart inside the chart area.
+
+ loadFromFile(u"pptx/PieChartWithAutomaticLayout_SizeAndPosition.pptx");
+
+ OUString aCheckShapeName = "CID/D=0:CS=0:CT=0:Series=0";
+ // Chart Wuse case Width == Height
+ {
+ // Load chart Chart_2_2 - 2cm x 2cm -
+ auto xDocument = getChartDocFromDrawImpressNamed(0, u"Chart_2_2");
+ CPPUNIT_ASSERT(xDocument.is());
+
+ uno::Reference<chart2::XChartDocument>xChartDocument(xDocument, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDocument.is());
+
+ // Get the shape of the diagram / chart
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDocument, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDrawPageSupplier.is());
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference<drawing::XShape> xChartDiagramShape = getShapeByName(xShapes, aCheckShapeName);
+ CPPUNIT_ASSERT(xChartDiagramShape.is());
+
+ // Size
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1300, xChartDiagramShape->getSize().Width, 5); // calculated chart area size - 2 * margin
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1300, xChartDiagramShape->getSize().Height, 5); // calculated chart area size - 2 * margin
+ // Position
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(350, xChartDiagramShape->getPosition().X, 5); // margin
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(350, xChartDiagramShape->getPosition().Y, 5); // margin
+ }
+
+ // Chart use case - Width < Height
+ {
+ // Load chart Chart_3_4 - 3cm x 4cm
+ auto xDocument = getChartDocFromDrawImpressNamed(0, u"Chart_3_4");
+ CPPUNIT_ASSERT(xDocument.is());
+
+ uno::Reference<chart2::XChartDocument>xChartDocument(xDocument, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDocument.is());
+
+ // Get the shape of the diagram / chart
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDocument, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDrawPageSupplier.is());
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference<drawing::XShape> xChartDiagramShape = getShapeByName(xShapes, aCheckShapeName);
+ CPPUNIT_ASSERT(xChartDiagramShape.is());
+
+ // Size
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2300, xChartDiagramShape->getSize().Width, 5); // calculated chart area size - 2 * margin
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2300, xChartDiagramShape->getSize().Height, 5); // calculated chart area size - 2 * margin
+ // Position
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(350, xChartDiagramShape->getPosition().X, 5); // margin
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(850, xChartDiagramShape->getPosition().Y, 5); // margin + calculated centering
+ }
+
+ // Chart use case - Width > Height
+ {
+ // Load chart Chart_3_2 - 3cm x 2cm
+ auto xDocument = getChartDocFromDrawImpressNamed(0, u"Chart_3_2");
+ CPPUNIT_ASSERT(xDocument.is());
+
+ uno::Reference<chart2::XChartDocument>xChartDocument(xDocument, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDocument.is());
+
+ // Get the shape of the diagram / chart
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDocument, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDrawPageSupplier.is());
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference<drawing::XShape> xChartDiagramShape = getShapeByName(xShapes, aCheckShapeName);
+ CPPUNIT_ASSERT(xChartDiagramShape.is());
+
+ // Size
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1300, xChartDiagramShape->getSize().Width, 5); // calculated chart area size - 2 * margin
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1300, xChartDiagramShape->getSize().Height, 5); // calculated chart area size - 2 * margin
+ // Position
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(850, xChartDiagramShape->getPosition().X, 5); // margin + calculated centering
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(350, xChartDiagramShape->getPosition().Y, 5); // margin
+ }
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/chart2import2.cxx b/chart2/qa/extras/chart2import2.cxx
new file mode 100644
index 0000000000..863d425ae9
--- /dev/null
+++ b/chart2/qa/extras/chart2import2.cxx
@@ -0,0 +1,892 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "charttest.hxx"
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/chart/XAxisXSupplier.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/text/XText.hpp>
+
+class Chart2ImportTest2 : public ChartTest
+{
+public:
+ Chart2ImportTest2()
+ : ChartTest("/chart2/qa/extras/data/")
+ {
+ }
+};
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf114179)
+{
+ loadFromFile(u"docx/testTdf114179.docx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ css::uno::Reference<chart2::XDiagram> xDiagram;
+ xDiagram.set(xChartDoc->getFirstDiagram());
+ CPPUNIT_ASSERT_MESSAGE("There is a Diagram.", xDiagram.is());
+ awt::Size aPage = getPageSize(xChartDoc);
+ awt::Size aSize = getSize(xDiagram, aPage);
+ CPPUNIT_ASSERT(aSize.Width > 0);
+ CPPUNIT_ASSERT(aSize.Height > 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf124243)
+{
+ loadFromFile(u"docx/tdf124243.docx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xAxis.is());
+
+ Reference<beans::XPropertySet> xPS(xAxis, uno::UNO_QUERY_THROW);
+ bool bShow = true;
+ // test X Axis is not visible.
+ bool bSuccess = xPS->getPropertyValue("Show") >>= bShow;
+ CPPUNIT_ASSERT(bSuccess);
+ CPPUNIT_ASSERT(!bShow);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf127393)
+{
+ loadFromFile(u"pptx/tdf127393.pptx");
+
+ // 1st chart
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xAxis.is());
+
+ chart2::ScaleData aScaleData1 = xAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData1.Categories.is());
+ CPPUNIT_ASSERT(aScaleData1.ShiftedCategoryPosition);
+
+ // 2nd chart
+ xChartDoc.set(getChartDocFromDrawImpress(1, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ xAxis.set(getAxisFromDoc(xChartDoc, 0, 0, 0));
+ CPPUNIT_ASSERT(xAxis.is());
+
+ chart2::ScaleData aScaleData2 = xAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData2.Categories.is());
+ CPPUNIT_ASSERT(!aScaleData2.ShiftedCategoryPosition);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf128733)
+{
+ loadFromFile(u"odt/tdf128733.odt");
+
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ // test secondary X axis ShiftedCategoryPosition value
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 1);
+ CPPUNIT_ASSERT(xAxis.is());
+
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Categories.is());
+ CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf128432)
+{
+ loadFromFile(u"ods/tdf128432.ods");
+
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xAxis.is());
+
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Categories.is());
+ CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf128627)
+{
+ loadFromFile(u"xlsx/tdf128627.xlsx");
+ // Test ShiftedCategoryPosition for Radar Chart
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xAxis.is());
+
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Categories.is());
+ CPPUNIT_ASSERT(!aScaleData.ShiftedCategoryPosition);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf128634)
+{
+ loadFromFile(u"xlsx/tdf128634.xlsx");
+ // Test ShiftedCategoryPosition for 3D Charts
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xAxis.is());
+
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Categories.is());
+ CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf130657)
+{
+ loadFromFile(u"xlsx/tdf130657.xlsx");
+ // Test ShiftedCategoryPosition for charts which is not contain a "crossbetween" OOXML tag.
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xAxis.is());
+
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Categories.is());
+ CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition);
+}
+
+namespace
+{
+void checkDataLabelProperties(const Reference<chart2::XDataSeries>& xDataSeries,
+ sal_Int32 nDataPointIndex, bool bValueVisible)
+{
+ uno::Reference<beans::XPropertySet> xPropertySet(
+ xDataSeries->getDataPointByIndex(nDataPointIndex), uno::UNO_SET_THROW);
+ chart2::DataPointLabel aLabel;
+ xPropertySet->getPropertyValue("Label") >>= aLabel;
+ CPPUNIT_ASSERT_EQUAL(bValueVisible, static_cast<bool>(aLabel.ShowNumber));
+ CPPUNIT_ASSERT_EQUAL(false, static_cast<bool>(aLabel.ShowNumberInPercent));
+}
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testDeletedDataLabel)
+{
+ loadFromFile(u"xlsx/deleted_data_labels.xlsx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ UNO_QUERY_THROW);
+ Reference<chart2::XDataSeries> xDataSeries0 = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries0.is());
+ checkDataLabelProperties(xDataSeries0, 0, true);
+ checkDataLabelProperties(xDataSeries0, 1, false);
+ checkDataLabelProperties(xDataSeries0, 2, true);
+ Reference<chart2::XDataSeries> xDataSeries1 = getDataSeriesFromDoc(xChartDoc, 1);
+ CPPUNIT_ASSERT(xDataSeries1.is());
+ checkDataLabelProperties(xDataSeries1, 0, false);
+ checkDataLabelProperties(xDataSeries1, 1, false);
+ checkDataLabelProperties(xDataSeries1, 2, false);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testDataPointInheritedColorDOCX)
+{
+ loadFromFile(u"docx/data_point_inherited_color.docx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ css::uno::Reference<chart2::XDiagram> xDiagram(xChartDoc->getFirstDiagram(), UNO_SET_THROW);
+
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(0),
+ uno::UNO_SET_THROW);
+ CPPUNIT_ASSERT(xPropertySet.is());
+ sal_Int32 nColor = xPropertySet->getPropertyValue("FillColor").get<sal_Int32>();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(16776960), nColor);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testExternalStrRefsXLSX)
+{
+ loadFromFile(u"xlsx/external_str_ref.xlsx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ css::uno::Sequence<css::uno::Any> aValues = aScaleData.Categories->getValues()->getData();
+ CPPUNIT_ASSERT_EQUAL(OUString("test1"), aValues[0].get<OUString>());
+ CPPUNIT_ASSERT_EQUAL(OUString("test2"), aValues[1].get<OUString>());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testSourceNumberFormatComplexCategoriesXLS)
+{
+ loadFromFile(u"xls/source_number_format_axis.xls");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ sal_Int32 nNumberFormat = aScaleData.Categories->getValues()->getNumberFormatKeyByIndex(-1);
+ CPPUNIT_ASSERT(nNumberFormat != 0);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testSimpleCategoryAxis)
+{
+ loadFromFile(u"docx/testSimpleCategoryAxis.docx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // Test the internal data.
+ CPPUNIT_ASSERT(xChartDoc->hasInternalDataProvider());
+
+ Reference<chart2::XInternalDataProvider> xInternalProvider(xChartDoc->getDataProvider(),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xInternalProvider.is());
+
+ Reference<chart::XComplexDescriptionAccess> xDescAccess(xInternalProvider, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDescAccess.is());
+
+ // Get the category labels.
+ Sequence<Sequence<OUString>> aCategories = xDescAccess->getComplexRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aCategories[0].getLength());
+ CPPUNIT_ASSERT(aCategories[0][0].endsWith("ria 1"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aCategories[1].getLength());
+ CPPUNIT_ASSERT(aCategories[1][0].endsWith("ria 2"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aCategories[2].getLength());
+ CPPUNIT_ASSERT(aCategories[2][0].endsWith("ria 3"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aCategories[3].getLength());
+ CPPUNIT_ASSERT(aCategories[3][0].endsWith("ria 4"));
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testMultilevelCategoryAxis)
+{
+ loadFromFile(u"docx/testMultilevelCategoryAxis.docx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ // Test the internal data.
+ CPPUNIT_ASSERT(xChartDoc->hasInternalDataProvider());
+
+ Reference<chart2::XInternalDataProvider> xInternalProvider(xChartDoc->getDataProvider(),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xInternalProvider.is());
+
+ Reference<chart::XComplexDescriptionAccess> xDescAccess(xInternalProvider, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDescAccess.is());
+
+ // Get the complex category labels.
+ Sequence<Sequence<OUString>> aCategories = xDescAccess->getComplexRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aCategories.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("2011"), aCategories[0][0]);
+ CPPUNIT_ASSERT_EQUAL(OUString(""), aCategories[1][0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("2012"), aCategories[2][0]);
+ CPPUNIT_ASSERT_EQUAL(OUString(""), aCategories[3][0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Categoria 1"), aCategories[0][1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Categoria 2"), aCategories[1][1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Categoria 3"), aCategories[2][1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("Categoria 4"), aCategories[3][1]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testXaxisValues)
+{
+ loadFromFile(u"docx/tdf124083.docx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ const uno::Reference<chart2::data::XDataSequence> xDataSeq
+ = getDataSequenceFromDocByRole(xChartDoc, u"values-x");
+ Sequence<uno::Any> xSequence = xDataSeq->getData();
+ // test X values
+ CPPUNIT_ASSERT_EQUAL(uno::Any(0.04), xSequence[0]);
+ CPPUNIT_ASSERT(std::isnan(*static_cast<const double*>(xSequence[1].getValue())));
+ CPPUNIT_ASSERT_EQUAL(uno::Any(0.16), xSequence[2]);
+ CPPUNIT_ASSERT_EQUAL(uno::Any(0.11), xSequence[3]);
+ CPPUNIT_ASSERT(std::isnan(*static_cast<const double*>(xSequence[4].getValue())));
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf123504)
+{
+ loadFromFile(u"ods/pie_chart_100_and_0.ods");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+
+ Reference<chart2::XChartDocument> xChartDoc2(xChartDoc, UNO_QUERY_THROW);
+ Reference<chart2::XChartType> xChartType(getChartTypeFromDoc(xChartDoc2, 0), UNO_SET_THROW);
+ std::vector aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), aDataSeriesYValues.size());
+
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xSeriesSlices(getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=0"),
+ UNO_SET_THROW);
+
+ Reference<container::XIndexAccess> xIndexAccess(xSeriesSlices, UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
+ Reference<drawing::XShape> xSlice(xIndexAccess->getByIndex(0), UNO_QUERY_THROW);
+
+ // Check size and position of the only slice in the chart (100%)
+ // In the regressed state, it used to be 0-sized at position 0,0
+ awt::Point aSlicePosition = xSlice->getPosition();
+ CPPUNIT_ASSERT_GREATER(sal_Int32(3000), aSlicePosition.X);
+ CPPUNIT_ASSERT_GREATER(sal_Int32(150), aSlicePosition.Y);
+ awt::Size aSliceSize = xSlice->getSize();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8300.0, aSliceSize.Height, 10);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8300.0, aSliceSize.Width, 10);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf122765)
+{
+ // The horizontal position of the slices was wrong.
+ loadFromFile(u"pptx/tdf122765.pptx");
+ Reference<chart::XChartDocument> xChartDoc = getChartDocFromDrawImpress(0, 0);
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xSeriesSlices(getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=0"),
+ UNO_SET_THROW);
+
+ Reference<container::XIndexAccess> xIndexAccess(xSeriesSlices, UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(9), xIndexAccess->getCount());
+ Reference<drawing::XShape> xSlice(xIndexAccess->getByIndex(0), UNO_QUERY_THROW);
+
+ // Check position of the first slice, all slices move together, so enough to check only one.
+ // Wrong position was around 5856.
+ awt::Point aSlicePosition = xSlice->getPosition();
+ CPPUNIT_ASSERT_GREATER(sal_Int32(7000), aSlicePosition.X);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf123206CustomLabelField)
+{
+ // File contains the deprecated "custom-label-field" attribute of the
+ // "data-point" element. It should be interpreted and stored as a data point
+ // property.
+ loadFromFile(u"odp/tdf123206.odp");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0),
+ uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xDp = xDataSeries->getDataPointByIndex(1);
+ Sequence<Reference<chart2::XDataPointCustomLabelField>> aLabelFields;
+ CPPUNIT_ASSERT(xDp->getPropertyValue("CustomLabelFields") >>= aLabelFields);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aLabelFields.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("Kiskacsa"), aLabelFields[0]->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf125444PercentageCustomLabel)
+{
+ loadFromFile(u"pptx/tdf125444.pptx");
+
+ // 1st chart
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xDp = xDataSeries->getDataPointByIndex(1);
+ Sequence<Reference<chart2::XDataPointCustomLabelField>> aLabelFields;
+ CPPUNIT_ASSERT(xDp->getPropertyValue("CustomLabelFields") >>= aLabelFields);
+ // There are three label field: a value label, a newline and a percentage label. We want
+ // to assert the latter.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aLabelFields.getLength());
+ CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType_PERCENTAGE,
+ aLabelFields[2]->getFieldType());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testDataPointLabelCustomPos)
+{
+ // test CustomLabelPosition on Bar chart
+ loadFromFile(u"xlsx/testDataPointLabelCustomPos.xlsx");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(0),
+ uno::UNO_SET_THROW);
+ CPPUNIT_ASSERT(xPropertySet.is());
+
+ chart2::RelativePosition aCustomLabelPosition;
+ xPropertySet->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.14621409921671025, aCustomLabelPosition.Primary, 1e-7);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-5.2887961029923464E-2, aCustomLabelPosition.Secondary, 1e-7);
+
+ sal_Int32 aPlacement;
+ xPropertySet->getPropertyValue("LabelPlacement") >>= aPlacement;
+ CPPUNIT_ASSERT_EQUAL(chart::DataLabelPlacement::OUTSIDE, aPlacement);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf130032)
+{
+ // test CustomLabelPosition on Line chart
+ loadFromFile(u"xlsx/testTdf130032.xlsx");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(1),
+ uno::UNO_SET_THROW);
+ CPPUNIT_ASSERT(xPropertySet.is());
+
+ chart2::RelativePosition aCustomLabelPosition;
+ xPropertySet->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.0438333333333334, aCustomLabelPosition.Primary, 1e-7);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.086794050743657, aCustomLabelPosition.Secondary, 1e-7);
+
+ sal_Int32 aPlacement;
+ xPropertySet->getPropertyValue("LabelPlacement") >>= aPlacement;
+ CPPUNIT_ASSERT_EQUAL(chart::DataLabelPlacement::RIGHT, aPlacement);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf134978)
+{
+ // test CustomLabelPosition on Pie chart
+ loadFromFile(u"xlsx/tdf134978.xlsx");
+ uno::Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+ CPPUNIT_ASSERT(xDataSeries.is());
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xDataSeries->getDataPointByIndex(2),
+ uno::UNO_SET_THROW);
+ CPPUNIT_ASSERT(xPropertySet.is());
+
+ chart2::RelativePosition aCustomLabelPosition;
+ xPropertySet->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.040273622047244093, aCustomLabelPosition.Primary, 1e-7);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.25635352872557599, aCustomLabelPosition.Secondary, 1e-7);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf119138MissingAutoTitleDeleted)
+{
+ loadFromFile(u"xlsx/tdf119138-missing-autotitledeleted.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+
+ Reference<chart2::XTitled> xTitled(xChartDoc, uno::UNO_QUERY_THROW);
+ uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+ CPPUNIT_ASSERT_MESSAGE(
+ "Missing autoTitleDeleted is implied to be True if title text is present", xTitle.is());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testStockChartShiftedCategoryPosition)
+{
+ loadFromFile(u"odt/stock_chart_LO_6_2.odt");
+
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+
+ Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xAxis.is());
+
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ CPPUNIT_ASSERT(aScaleData.Categories.is());
+ CPPUNIT_ASSERT(aScaleData.ShiftedCategoryPosition);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf133376)
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ loadFromFile(u"xlsx/tdf133376.xlsx");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xDataPointLabel(
+ getShapeByName(xShapes,
+ "CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=2"),
+ UNO_SET_THROW);
+
+ CPPUNIT_ASSERT(xDataPointLabel.is());
+ // Check the position of the 3rd data point label, which is out from the pie slice
+ awt::Point aLabelPosition = xDataPointLabel->getPosition();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1208, aLabelPosition.X, 30);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(5370, aLabelPosition.Y, 30);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf134225)
+{
+ loadFromFile(u"xlsx/tdf134225.xlsx");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xDataPointLabel1(
+ getShapeByName(xShapes,
+ "CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0"),
+ UNO_SET_THROW);
+ CPPUNIT_ASSERT(xDataPointLabel1.is());
+
+ Reference<drawing::XShape> xDataPointLabel2(
+ getShapeByName(xShapes,
+ "CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=1"),
+ UNO_SET_THROW);
+ CPPUNIT_ASSERT(xDataPointLabel2.is());
+
+#if defined(_WIN32)
+ // font is MS Comic Sans which we can only assume is available under windows
+ awt::Point aLabelPosition1 = xDataPointLabel1->getPosition();
+ awt::Point aLabelPosition2 = xDataPointLabel2->getPosition();
+
+ // Check the distance between the position of the 1st data point label and the second one
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1493, sal_Int32(aLabelPosition2.X - aLabelPosition1.X), 30);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2015, sal_Int32(aLabelPosition2.Y - aLabelPosition1.Y), 30);
+#endif
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf136105)
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ loadFromFile(u"xlsx/tdf136105.xlsx");
+ // 1st chart with fix inner position and size
+ {
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xDataPointLabel(
+ getShapeByName(xShapes,
+ "CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0"),
+ UNO_SET_THROW);
+
+ CPPUNIT_ASSERT(xDataPointLabel.is());
+ // Check the position of the 1st data point label, which is out from the pie slice
+ awt::Point aLabelPosition = xDataPointLabel->getPosition();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8797, aLabelPosition.X, 500);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1374, aLabelPosition.Y, 500);
+ }
+ // 2nd chart with auto inner position and size
+ {
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(1, mxComponent),
+ UNO_QUERY_THROW);
+
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xDataPointLabel(
+ getShapeByName(xShapes,
+ "CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0"),
+ UNO_SET_THROW);
+
+ CPPUNIT_ASSERT(xDataPointLabel.is());
+ // Check the position of the 1st data point label, which is out from the pie slice
+ awt::Point aLabelPosition = xDataPointLabel->getPosition();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(7978, aLabelPosition.X, 500);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1550, aLabelPosition.Y, 500);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf91250)
+{
+ loadFromFile(u"docx/tdf91250.docx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XInternalDataProvider> xInternalProvider(xChartDoc->getDataProvider(),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xInternalProvider.is());
+
+ Reference<chart::XComplexDescriptionAccess> xDescAccess(xInternalProvider, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDescAccess.is());
+
+ // Get the category labels.
+ Sequence<OUString> aCategories = xDescAccess->getRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aCategories.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("12.3254"), aCategories[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("11.62315"), aCategories[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("9.26"), aCategories[2]);
+ CPPUNIT_ASSERT_EQUAL(OUString("8.657"), aCategories[3]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf134111)
+{
+ // tdf134111 : To check TextBreak value is true
+ loadFromFile(u"docx/tdf134111.docx");
+ uno::Reference<chart::XChartDocument> xChartDoc = getChartDocFromWriter(0);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ uno::Reference<chart::XDiagram> mxDiagram(xChartDoc->getDiagram());
+ CPPUNIT_ASSERT(mxDiagram.is());
+ uno::Reference<chart::XAxisXSupplier> xAxisXSupp(mxDiagram, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xAxisXSupp.is());
+ uno::Reference<beans::XPropertySet> xAxisProp(xAxisXSupp->getXAxis());
+ bool bTextBreak = false;
+ xAxisProp->getPropertyValue("TextBreak") >>= bTextBreak;
+ // Expected value of 'TextBreak' is true
+ CPPUNIT_ASSERT(bTextBreak);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf136752)
+{
+ loadFromFile(u"xlsx/tdf136752.xlsx");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xDataPointLabel(
+ getShapeByName(xShapes,
+ "CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0"),
+ UNO_SET_THROW);
+
+ CPPUNIT_ASSERT(xDataPointLabel.is());
+ // Check the position of the 1st data point label, which is out from the pie slice
+ awt::Point aLabelPosition = xDataPointLabel->getPosition();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8675, aLabelPosition.X, 500);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1458, aLabelPosition.Y, 500);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf137505)
+{
+ loadFromFile(u"xlsx/tdf137505.xlsx");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShape> xCustomShape(xDrawPage->getByIndex(1), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xCustomShape.is());
+
+ float nFontSize;
+ Reference<text::XText> xRange(xCustomShape, uno::UNO_QUERY_THROW);
+ Reference<text::XTextCursor> xAt = xRange->createTextCursor();
+ Reference<beans::XPropertySet> xProps(xAt, UNO_QUERY);
+ // check the text size of custom shape, inside the chart.
+ CPPUNIT_ASSERT(xProps->getPropertyValue("CharHeight") >>= nFontSize);
+ CPPUNIT_ASSERT_EQUAL(float(12), nFontSize);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf137734)
+{
+ loadFromFile(u"xlsx/tdf137734.xlsx");
+ Reference<chart2::XChartDocument> xChartDoc = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT_MESSAGE("failed to load chart", xChartDoc.is());
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XDataSeries> xDataSeries = getDataSeriesFromDoc(xChartDoc, 0);
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference<beans::XPropertySet> xPropSet(xDataSeries, uno::UNO_QUERY_THROW);
+ uno::Any aAny = xPropSet->getPropertyValue("VaryColorsByPoint");
+ bool bVaryColor = true;
+ CPPUNIT_ASSERT(aAny >>= bVaryColor);
+ CPPUNIT_ASSERT(!bVaryColor);
+
+ // tdf#126133 Test primary X axis Rotation value
+ Reference<chart2::XAxis> xXAxis = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ CPPUNIT_ASSERT(xXAxis.is());
+ Reference<chart2::XTitled> xTitled(xXAxis, uno::UNO_QUERY_THROW);
+ Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+ CPPUNIT_ASSERT(xTitle.is());
+ Reference<beans::XPropertySet> xTitlePropSet(xTitle, uno::UNO_QUERY_THROW);
+ uno::Any aAny2 = xTitlePropSet->getPropertyValue("TextRotation");
+ double nRotation = -1;
+ CPPUNIT_ASSERT(aAny2 >>= nRotation);
+ CPPUNIT_ASSERT_EQUAL(0.0, nRotation);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf137874)
+{
+ loadFromFile(u"xlsx/piechart_legend.xlsx");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xLegendEntry;
+ xLegendEntry
+ = getShapeByName(xShapes, "CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0:LegendEntry=0");
+ CPPUNIT_ASSERT(xLegendEntry.is());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf146463)
+{
+ loadFromFile(u"ods/tdf146463.ods");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent));
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc, 0);
+ std::vector<std::vector<double>> aDataSeriesYValues
+ = getDataSeriesYValuesFromChartType(xChartType);
+ size_t nLegendEntryCount = aDataSeriesYValues.size();
+ CPPUNIT_ASSERT_EQUAL(size_t(14), nLegendEntryCount);
+
+ for (size_t nSeriesIndex = 0; nSeriesIndex < nLegendEntryCount; ++nSeriesIndex)
+ {
+ uno::Reference<drawing::XShape> xLegendEntry
+ = getShapeByName(xShapes, "CID/MultiClick/D=0:CS=0:CT=0:Series="
+ + OUString::number(nSeriesIndex) + ":LegendEntry=0");
+ if (nSeriesIndex == 0)
+ CPPUNIT_ASSERT_MESSAGE("Legend 0 is not visible", xLegendEntry.is());
+ else
+ CPPUNIT_ASSERT_MESSAGE(
+ OString("Legend " + OString::number(nSeriesIndex) + " is visible").getStr(),
+ !xLegendEntry.is());
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdfCustomShapePos)
+{
+ loadFromFile(u"docx/testcustomshapepos.docx");
+ Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), UNO_QUERY_THROW);
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ // test position and size of a custom shape within a chart, rotated by 0 degree.
+ {
+ Reference<drawing::XShape> xCustomShape(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ awt::Point aPosition = xCustomShape->getPosition();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8845, aPosition.X, 300);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(855, aPosition.Y, 300);
+ awt::Size aSize = xCustomShape->getSize();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(4831, aSize.Width, 300);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1550, aSize.Height, 300);
+ }
+ // test position and size of a custom shape within a chart, rotated by 90 degree.
+ {
+ Reference<drawing::XShape> xCustomShape(xDrawPage->getByIndex(1), UNO_QUERY_THROW);
+ awt::Point aPosition = xCustomShape->getPosition();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1658, aPosition.X, 300);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6119, aPosition.Y, 300);
+ awt::Size aSize = xCustomShape->getSize();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(4165, aSize.Width, 300);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1334, aSize.Height, 300);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf121281)
+{
+ loadFromFile(u"xlsx/incorrect_label_position.xlsx");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xDataPointLabel(
+ getShapeByName(xShapes,
+ "CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0"),
+ UNO_SET_THROW);
+
+ CPPUNIT_ASSERT(xDataPointLabel.is());
+ awt::Point aLabelPosition = xDataPointLabel->getPosition();
+ // This failed, if the data label flowed out of the chart area.
+ CPPUNIT_ASSERT_GREATEREQUAL(static_cast<sal_Int32>(0), aLabelPosition.Y);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf139658)
+{
+ loadFromFile(u"docx/tdf139658.docx");
+ uno::Reference<chart2::XChartDocument> xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ Reference<chart2::XInternalDataProvider> xInternalProvider(xChartDoc->getDataProvider(),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xInternalProvider.is());
+
+ Reference<chart::XComplexDescriptionAccess> xDescAccess(xInternalProvider, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDescAccess.is());
+
+ // Get the category labels.
+ Sequence<OUString> aCategories = xDescAccess->getRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aCategories.getLength());
+ CPPUNIT_ASSERT_EQUAL(OUString("category1"), aCategories[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("\"category2\""), aCategories[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("category\"3"), aCategories[2]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf146066)
+{
+ loadFromFile(u"ods/tdf146066.ods");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapes.is());
+
+ uno::Reference<drawing::XShape> xYAxisShape = getShapeByName(
+ xShapes, "CID/D=0:CS=0:Axis=1,0", // Y Axis
+ // Axis occurs twice in chart xshape representation so need to get the one related to labels
+ [](const uno::Reference<drawing::XShape>& rXShape) -> bool {
+ uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xAxisShapes.is());
+ uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<drawing::XShapeDescriptor> xShapeDescriptor(xChildShape,
+ uno::UNO_QUERY_THROW);
+ return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape");
+ });
+ CPPUNIT_ASSERT(xYAxisShape.is());
+
+ // Check label count
+ uno::Reference<container::XIndexAccess> xIndexAccess(xYAxisShape, UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(8), xIndexAccess->getCount());
+
+ // Check text
+ uno::Reference<text::XTextRange> xLabel0(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("0"), xLabel0->getString());
+ uno::Reference<text::XTextRange> xLabel1(xIndexAccess->getByIndex(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("5"), xLabel1->getString());
+ uno::Reference<text::XTextRange> xLabel2(xIndexAccess->getByIndex(2), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("10"), xLabel2->getString());
+ uno::Reference<text::XTextRange> xLabel3(xIndexAccess->getByIndex(3), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("15"), xLabel3->getString());
+ uno::Reference<text::XTextRange> xLabel4(xIndexAccess->getByIndex(4), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("20"), xLabel4->getString());
+ uno::Reference<text::XTextRange> xLabel5(xIndexAccess->getByIndex(5), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("25"), xLabel5->getString());
+ uno::Reference<text::XTextRange> xLabel6(xIndexAccess->getByIndex(6), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("30"), xLabel6->getString());
+ uno::Reference<text::XTextRange> xLabel7(xIndexAccess->getByIndex(7), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("35"), xLabel7->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf150434)
+{
+ loadFromFile(u"xlsx/tdf150434.xlsx");
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xLegend = getShapeByName(xShapes, "CID/D=0:Legend=");
+ CPPUNIT_ASSERT(xLegend.is());
+ awt::Point aPosition = xLegend->getPosition();
+
+ // This failed, if the legend flowed out of the chart area.
+ CPPUNIT_ASSERT_GREATEREQUAL(static_cast<sal_Int32>(0), aPosition.Y);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testChartDataTableWithMultipleLegendEntriesForOneDataSeries)
+{
+ loadFromFile(u"xlsx/DataTable-MultipleLegendEntriesForOneDataSeries.xlsx");
+ // Loading this file caused a crash in the data table code
+
+ Reference<chart::XChartDocument> xChartDoc(getChartDocFromSheet(0, mxComponent),
+ UNO_QUERY_THROW);
+ Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, UNO_QUERY_THROW);
+ Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage(), UNO_SET_THROW);
+ Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), UNO_QUERY_THROW);
+ Reference<drawing::XShape> xDataTableShape = getShapeByName(xShapes, "CID/D=0:DataTable=");
+ CPPUNIT_ASSERT(xDataTableShape.is());
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/charttest.hxx b/chart2/qa/extras/charttest.hxx
new file mode 100644
index 0000000000..db416affaa
--- /dev/null
+++ b/chart2/qa/extras/charttest.hxx
@@ -0,0 +1,605 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <test/unoapixml_test.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysequence.hxx>
+
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+
+#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/table/XTableChartsSupplier.hpp>
+#include <com/sun/star/table/XTableChart.hpp>
+#include <com/sun/star/table/XTablePivotChartsSupplier.hpp>
+#include <com/sun/star/table/XTablePivotChart.hpp>
+#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+
+#include <o3tl/string_view.hxx>
+#include <unotools/tempfile.hxx>
+#include <rtl/math.hxx>
+#include <svx/charthelper.hxx>
+
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart2/XChartTypeContainer.hpp>
+#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+#include <com/sun/star/chart2/XFormattedString.hpp>
+#include <com/sun/star/chart2/XTitle.hpp>
+#include <com/sun/star/chart2/XTitled.hpp>
+#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <com/sun/star/chart/XChartDataArray.hpp>
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/chart/XDateCategories.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+
+#include <unonames.hxx>
+
+#include <iostream>
+#include <memory>
+#include <string_view>
+
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/XVisualObject.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+
+using namespace css;
+using namespace css::uno;
+
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::table { class XTableCharts; }
+namespace com::sun::star::table { class XTablePivotCharts; }
+
+class ChartTest : public UnoApiXmlTest
+{
+public:
+ ChartTest(OUString path)
+ : UnoApiXmlTest(path)
+ {
+ }
+
+ uno::Sequence < OUString > getImpressChartColumnDescriptions(sal_Int32 nPage, sal_Int32 nShape);
+
+ uno::Reference<chart::XChartDocument> getChartDocFromDrawImpress( sal_Int32 nPage, sal_Int32 nShape );
+ uno::Reference<chart::XChartDocument> getChartDocFromDrawImpressNamed( sal_Int32 nPage, std::u16string_view rName);
+
+
+ uno::Reference<chart::XChartDocument> getChartDocFromWriter( sal_Int32 nShape );
+ Sequence< OUString > getFormattedDateCategories( const Reference<chart2::XChartDocument>& xChartDoc );
+ awt::Size getPageSize( const Reference< chart2::XChartDocument > & xChartDoc );
+ awt::Size getSize(css::uno::Reference<chart2::XDiagram> xDiagram, const awt::Size& rPageSize);
+};
+
+Reference< lang::XComponent > getChartCompFromSheet( sal_Int32 nSheet, sal_Int32 nChart, uno::Reference< lang::XComponent > const & xComponent )
+{
+ // let us assume that we only have one chart per sheet
+
+ uno::Reference< sheet::XSpreadsheetDocument > xDoc(xComponent, UNO_QUERY_THROW);
+
+ uno::Reference< container::XIndexAccess > xIA(xDoc->getSheets(), UNO_QUERY_THROW);
+
+ uno::Reference< table::XTableChartsSupplier > xChartSupplier( xIA->getByIndex(nSheet), UNO_QUERY_THROW);
+
+ uno::Reference< table::XTableCharts > xCharts = xChartSupplier->getCharts();
+ CPPUNIT_ASSERT(xCharts.is());
+
+ uno::Reference< container::XIndexAccess > xIACharts(xCharts, UNO_QUERY_THROW);
+ uno::Reference< table::XTableChart > xChart( xIACharts->getByIndex(nChart), UNO_QUERY_THROW);
+
+ uno::Reference< document::XEmbeddedObjectSupplier > xEmbObjectSupplier(xChart, UNO_QUERY_THROW);
+
+ uno::Reference< lang::XComponent > xChartComp( xEmbObjectSupplier->getEmbeddedObject(), UNO_SET_THROW );
+
+ return xChartComp;
+
+}
+
+Reference< chart2::XChartDocument > getChartDocFromSheet( sal_Int32 nSheet, uno::Reference< lang::XComponent > const & xComponent )
+{
+ uno::Reference< chart2::XChartDocument > xChartDoc ( getChartCompFromSheet(nSheet, 0, xComponent), UNO_QUERY_THROW );
+
+ // Update the chart view, so that its draw page is updated and ready for the test
+ css::uno::Reference<css::frame::XModel> xModel(xChartDoc, css::uno::UNO_QUERY_THROW);
+ ChartHelper::updateChart(xModel);
+
+ return xChartDoc;
+}
+
+uno::Reference<table::XTablePivotCharts> getTablePivotChartsFromSheet(sal_Int32 nSheet, uno::Reference<lang::XComponent> const & xComponent)
+{
+ uno::Reference<sheet::XSpreadsheetDocument> xDoc(xComponent, UNO_QUERY_THROW);
+
+ uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW);
+
+ uno::Reference<table::XTablePivotChartsSupplier> xChartSupplier(xIA->getByIndex(nSheet), UNO_QUERY_THROW);
+
+ uno::Reference<table::XTablePivotCharts> xTablePivotCharts = xChartSupplier->getPivotCharts();
+ CPPUNIT_ASSERT(xTablePivotCharts.is());
+
+ return xTablePivotCharts;
+}
+
+Reference<lang::XComponent> getPivotChartCompFromSheet(sal_Int32 nSheet, uno::Reference<lang::XComponent> const & xComponent)
+{
+ uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet(nSheet, xComponent);
+
+ uno::Reference<container::XIndexAccess> xIACharts(xTablePivotCharts, UNO_QUERY_THROW);
+ uno::Reference<table::XTablePivotChart> xTablePivotChart(xIACharts->getByIndex(0), UNO_QUERY_THROW);
+
+ uno::Reference<document::XEmbeddedObjectSupplier> xEmbObjectSupplier(xTablePivotChart, UNO_QUERY_THROW);
+
+ uno::Reference<lang::XComponent> xChartComp(xEmbObjectSupplier->getEmbeddedObject(), UNO_SET_THROW);
+
+ return xChartComp;
+}
+
+Reference<chart2::XChartDocument> getPivotChartDocFromSheet(sal_Int32 nSheet, uno::Reference<lang::XComponent> const & xComponent)
+{
+ uno::Reference<chart2::XChartDocument> xChartDoc(getPivotChartCompFromSheet(nSheet, xComponent), UNO_QUERY_THROW);
+ return xChartDoc;
+}
+
+Reference<chart2::XChartDocument> getPivotChartDocFromSheet(uno::Reference<table::XTablePivotCharts> const & xTablePivotCharts, sal_Int32 nIndex)
+{
+ uno::Reference<container::XIndexAccess> xIACharts(xTablePivotCharts, UNO_QUERY_THROW);
+ uno::Reference<table::XTablePivotChart> xTablePivotChart(xIACharts->getByIndex(nIndex), UNO_QUERY_THROW);
+
+ uno::Reference<document::XEmbeddedObjectSupplier> xEmbObjectSupplier(xTablePivotChart, UNO_QUERY_THROW);
+
+ uno::Reference<lang::XComponent> xChartComp(xEmbObjectSupplier->getEmbeddedObject(), UNO_SET_THROW);
+
+ uno::Reference<chart2::XChartDocument> xChartDoc(xChartComp, UNO_QUERY_THROW);
+ return xChartDoc;
+}
+
+Reference< chart2::XChartType > getChartTypeFromDoc( Reference< chart2::XChartDocument > const & xChartDoc,
+ sal_Int32 nChartType, sal_Int32 nCooSys = 0 )
+{
+ CPPUNIT_ASSERT( xChartDoc.is() );
+
+ Reference <chart2::XDiagram > xDiagram = xChartDoc->getFirstDiagram();
+ CPPUNIT_ASSERT( xDiagram.is() );
+
+ Reference< chart2::XCoordinateSystemContainer > xCooSysContainer( xDiagram, UNO_QUERY_THROW );
+
+ Sequence< Reference< chart2::XCoordinateSystem > > xCooSysSequence( xCooSysContainer->getCoordinateSystems());
+ CPPUNIT_ASSERT( xCooSysSequence.getLength() > nCooSys );
+
+ Reference< chart2::XChartTypeContainer > xChartTypeContainer( xCooSysSequence[nCooSys], UNO_QUERY_THROW );
+
+ Sequence< Reference< chart2::XChartType > > xChartTypeSequence( xChartTypeContainer->getChartTypes() );
+ CPPUNIT_ASSERT( xChartTypeSequence.getLength() > nChartType );
+
+ return xChartTypeSequence[nChartType];
+}
+
+Reference<chart2::XAxis> getAxisFromDoc(
+ const Reference<chart2::XChartDocument>& xChartDoc, sal_Int32 nCooSys, sal_Int32 nAxisDim, sal_Int32 nAxisIndex )
+{
+ Reference<chart2::XDiagram> xDiagram = xChartDoc->getFirstDiagram();
+ CPPUNIT_ASSERT(xDiagram.is());
+
+ Reference<chart2::XCoordinateSystemContainer> xCooSysContainer(xDiagram, UNO_QUERY_THROW);
+
+ Sequence<Reference<chart2::XCoordinateSystem> > xCooSysSequence = xCooSysContainer->getCoordinateSystems();
+ CPPUNIT_ASSERT(xCooSysSequence.getLength() > nCooSys);
+
+ Reference<chart2::XCoordinateSystem> xCoord = xCooSysSequence[nCooSys];
+ CPPUNIT_ASSERT(xCoord.is());
+
+ Reference<chart2::XAxis> xAxis = xCoord->getAxisByDimension(nAxisDim, nAxisIndex);
+ CPPUNIT_ASSERT(xAxis.is());
+
+ return xAxis;
+}
+
+sal_Int32 getNumberOfDataSeries(uno::Reference<chart2::XChartDocument> const & xChartDoc,
+ sal_Int32 nChartType = 0, sal_Int32 nCooSys = 0)
+{
+ Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc, nChartType, nCooSys);
+ Reference<chart2::XDataSeriesContainer> xDataSeriesContainer(xChartType, UNO_QUERY_THROW);
+
+ uno::Sequence<uno::Reference<chart2::XDataSeries>> xSeriesSequence(xDataSeriesContainer->getDataSeries());
+ return xSeriesSequence.getLength();
+}
+
+Reference< chart2::XDataSeries > getDataSeriesFromDoc(uno::Reference<chart2::XChartDocument> const & xChartDoc,
+ sal_Int32 nDataSeries, sal_Int32 nChartType = 0,
+ sal_Int32 nCooSys = 0)
+{
+ Reference< chart2::XChartType > xChartType = getChartTypeFromDoc( xChartDoc, nChartType, nCooSys );
+ Reference< chart2::XDataSeriesContainer > xDataSeriesContainer( xChartType, UNO_QUERY_THROW );
+
+ Sequence< Reference< chart2::XDataSeries > > xSeriesSequence( xDataSeriesContainer->getDataSeries() );
+ CPPUNIT_ASSERT( xSeriesSequence.getLength() > nDataSeries );
+
+ Reference< chart2::XDataSeries > xSeries = xSeriesSequence[nDataSeries];
+
+ return xSeries;
+}
+
+Reference< chart2::data::XDataSequence > getLabelDataSequenceFromDoc(
+ Reference< chart2::XChartDocument > const & xChartDoc,
+ sal_Int32 nDataSeries = 0, sal_Int32 nChartType = 0 )
+{
+ Reference< chart2::XDataSeries > xDataSeries =
+ getDataSeriesFromDoc( xChartDoc, nDataSeries, nChartType );
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference< chart2::data::XDataSource > xDataSource( xDataSeries, uno::UNO_QUERY_THROW );
+ const Sequence< Reference< chart2::data::XLabeledDataSequence > > xDataSequences =
+ xDataSource->getDataSequences();
+ for(auto const & lds : xDataSequences)
+ {
+ Reference< chart2::data::XDataSequence> xLabelSeq = lds->getLabel();
+ if(!xLabelSeq.is())
+ continue;
+
+ return xLabelSeq;
+ }
+
+ CPPUNIT_FAIL("no Label sequence found");
+}
+
+Reference< chart2::data::XDataSequence > getDataSequenceFromDocByRole(
+ Reference< chart2::XChartDocument > const & xChartDoc, std::u16string_view rRole,
+ sal_Int32 nDataSeries = 0, sal_Int32 nChartType = 0 )
+{
+ Reference< chart2::XDataSeries > xDataSeries =
+ getDataSeriesFromDoc( xChartDoc, nDataSeries, nChartType );
+ CPPUNIT_ASSERT(xDataSeries.is());
+ Reference< chart2::data::XDataSource > xDataSource( xDataSeries, uno::UNO_QUERY_THROW );
+ const Sequence< Reference< chart2::data::XLabeledDataSequence > > xDataSequences =
+ xDataSource->getDataSequences();
+ for(auto const & lds : xDataSequences)
+ {
+ Reference< chart2::data::XDataSequence> xLabelSeq = lds->getValues();
+ uno::Reference< beans::XPropertySet > xProps(xLabelSeq, uno::UNO_QUERY);
+ if(!xProps.is())
+ continue;
+
+ OUString aRoleName = xProps->getPropertyValue("Role").get<OUString>();
+
+ if(aRoleName == rRole)
+ return xLabelSeq;
+ }
+
+ return Reference< chart2::data::XDataSequence > ();
+}
+
+uno::Sequence < OUString > getWriterChartColumnDescriptions( Reference< lang::XComponent > const & mxComponent )
+{
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT( xShape.is() );
+ uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
+ uno::Reference< chart2::XChartDocument > xChartDoc;
+ xChartDoc.set( xPropertySet->getPropertyValue( "Model" ), uno::UNO_QUERY );
+ CPPUNIT_ASSERT( xChartDoc.is() );
+ CPPUNIT_ASSERT( xChartDoc->getDataProvider().is() );
+ uno::Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess ( xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW );
+ uno::Sequence< OUString > seriesList = xAnyDescriptionAccess->getColumnDescriptions();
+ return seriesList;
+}
+
+std::vector<std::vector<double> > getDataSeriesYValuesFromChartType( const Reference<chart2::XChartType>& xCT )
+{
+ Reference<chart2::XDataSeriesContainer> xDSCont(xCT, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDSCont.is());
+ const Sequence<uno::Reference<chart2::XDataSeries> > aDataSeriesSeq = xDSCont->getDataSeries();
+
+ std::vector<std::vector<double> > aRet;
+ for (uno::Reference<chart2::XDataSeries> const & ds : aDataSeriesSeq)
+ {
+ uno::Reference<chart2::data::XDataSource> xDSrc(ds, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDSrc.is());
+ const uno::Sequence<Reference<chart2::data::XLabeledDataSequence> > aDataSeqs = xDSrc->getDataSequences();
+ for (auto const & lds : aDataSeqs)
+ {
+ Reference<chart2::data::XDataSequence> xValues = lds->getValues();
+ CPPUNIT_ASSERT(xValues.is());
+ Reference<beans::XPropertySet> xPropSet(xValues, uno::UNO_QUERY);
+ if (!xPropSet.is())
+ continue;
+
+ OUString aRoleName;
+ xPropSet->getPropertyValue("Role") >>= aRoleName;
+ if (aRoleName == "values-y")
+ {
+ const uno::Sequence<uno::Any> aData = xValues->getData();
+ std::vector<double> aValues;
+ aValues.reserve(aData.getLength());
+ for (uno::Any const & any : aData)
+ {
+ double fVal;
+ if (any >>= fVal)
+ aValues.push_back(fVal);
+ else
+ aValues.push_back(std::numeric_limits<double>::quiet_NaN());
+ }
+ aRet.push_back(aValues);
+ }
+ }
+ }
+
+ return aRet;
+}
+
+std::vector<uno::Sequence<uno::Any> > getDataSeriesLabelsFromChartType( const Reference<chart2::XChartType>& xCT )
+{
+ OUString aLabelRole = xCT->getRoleOfSequenceForSeriesLabel();
+
+ Reference<chart2::XDataSeriesContainer> xDSCont(xCT, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDSCont.is());
+ const Sequence<uno::Reference<chart2::XDataSeries> > aDataSeriesSeq = xDSCont->getDataSeries();
+
+ std::vector<uno::Sequence<uno::Any> > aRet;
+ for (auto const & ds : aDataSeriesSeq)
+ {
+ uno::Reference<chart2::data::XDataSource> xDSrc(ds, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xDSrc.is());
+ const uno::Sequence<Reference<chart2::data::XLabeledDataSequence> > aDataSeqs = xDSrc->getDataSequences();
+ for (auto const & lds : aDataSeqs)
+ {
+ Reference<chart2::data::XDataSequence> xValues = lds->getValues();
+ CPPUNIT_ASSERT(xValues.is());
+ Reference<beans::XPropertySet> xPropSet(xValues, uno::UNO_QUERY);
+ if (!xPropSet.is())
+ continue;
+
+ OUString aRoleName;
+ xPropSet->getPropertyValue("Role") >>= aRoleName;
+ if (aRoleName == aLabelRole)
+ {
+ Reference<chart2::data::XLabeledDataSequence> xLabel = lds;
+ CPPUNIT_ASSERT(xLabel.is());
+ Reference<chart2::data::XDataSequence> xDS2 = xLabel->getLabel();
+ CPPUNIT_ASSERT(xDS2.is());
+ uno::Sequence<uno::Any> aData = xDS2->getData();
+ aRet.push_back(aData);
+ }
+ }
+ }
+
+ return aRet;
+}
+
+uno::Reference<chart::XChartDocument> ChartTest::getChartDocFromDrawImpress(
+ sal_Int32 nPage, sal_Int32 nShape )
+{
+ uno::Reference<chart::XChartDocument> xEmpty;
+
+ uno::Reference<drawing::XDrawPagesSupplier> xPages(mxComponent, uno::UNO_QUERY);
+ if (!xPages.is())
+ return xEmpty;
+
+ uno::Reference<drawing::XDrawPage> xPage(
+ xPages->getDrawPages()->getByIndex(nPage), uno::UNO_QUERY_THROW);
+
+ uno::Reference<beans::XPropertySet> xShapeProps(xPage->getByIndex(nShape), uno::UNO_QUERY);
+ if (!xShapeProps.is())
+ return xEmpty;
+
+ uno::Reference<frame::XModel> xDocModel;
+ xShapeProps->getPropertyValue("Model") >>= xDocModel;
+ if (!xDocModel.is())
+ return xEmpty;
+
+ uno::Reference<chart::XChartDocument> xChartDoc(xDocModel, uno::UNO_QUERY);
+ return xChartDoc;
+}
+
+uno::Reference<chart::XChartDocument> ChartTest::getChartDocFromDrawImpressNamed(sal_Int32 nPage, std::u16string_view rName)
+{
+ uno::Reference<chart::XChartDocument> xChart;
+
+ uno::Reference<drawing::XDrawPagesSupplier> xPages(mxComponent, uno::UNO_QUERY);
+ if (!xPages.is())
+ return xChart;
+
+ uno::Reference<drawing::XDrawPage> xPage(xPages->getDrawPages()->getByIndex(nPage), uno::UNO_QUERY);
+ if (!xPage.is())
+ return xChart;
+
+ for (sal_Int32 i=0; i < xPage->getCount(); ++i)
+ {
+ uno::Reference<container::XNamed> xNamedShape(xPage->getByIndex(i), uno::UNO_QUERY);
+ if (!xNamedShape.is())
+ continue;
+
+ if (xNamedShape->getName() != rName)
+ continue;
+
+ uno::Reference<beans::XPropertySet> xShapeProps(xNamedShape, uno::UNO_QUERY);
+ if (!xShapeProps.is())
+ continue;
+
+ uno::Reference<frame::XModel> xDocModel;
+ xShapeProps->getPropertyValue("Model") >>= xDocModel;
+ if (!xDocModel.is())
+ continue;
+
+ return uno::Reference<chart::XChartDocument>(xDocModel, uno::UNO_QUERY);
+ }
+
+ return xChart;
+}
+
+uno::Reference<chart::XChartDocument> ChartTest::getChartDocFromWriter( sal_Int32 nShape )
+{
+ // DO NOT use XDrawPageSupplier since SwVirtFlyDrawObj are not created
+ // during import, only in layout!
+ Reference<text::XTextEmbeddedObjectsSupplier> xEOS(mxComponent, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xEOS.is());
+ Reference<container::XIndexAccess> xEmbeddeds(xEOS->getEmbeddedObjects(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xEmbeddeds.is());
+
+ Reference<beans::XPropertySet> xShapeProps(xEmbeddeds->getByIndex(nShape), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xShapeProps.is());
+
+ Reference<frame::XModel> xDocModel;
+ xShapeProps->getPropertyValue("Model") >>= xDocModel;
+ CPPUNIT_ASSERT(xDocModel.is());
+
+ uno::Reference<chart::XChartDocument> xChartDoc(xDocModel, uno::UNO_QUERY);
+ return xChartDoc;
+}
+
+uno::Sequence < OUString > ChartTest::getImpressChartColumnDescriptions(sal_Int32 nPage, sal_Int32 nShape)
+{
+ uno::Reference< chart::XChartDocument > xChartDoc = getChartDocFromDrawImpress( nPage, nShape );
+ uno::Reference< chart::XChartDataArray > xChartData ( xChartDoc->getData(), uno::UNO_QUERY_THROW);
+ uno::Sequence < OUString > seriesList = xChartData->getColumnDescriptions();
+ return seriesList;
+}
+
+OUString getTitleString( const Reference<chart2::XTitled>& xTitled )
+{
+ uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+ CPPUNIT_ASSERT(xTitle.is());
+ const uno::Sequence<uno::Reference<chart2::XFormattedString> > aFSSeq = xTitle->getText();
+ OUString aText;
+ for (auto const & fs : aFSSeq)
+ aText += fs->getString();
+
+ return aText;
+}
+
+sal_Int32 getNumberFormat( const Reference<chart2::XChartDocument>& xChartDoc, const OUString& sFormat )
+{
+ Reference<util::XNumberFormatsSupplier> xNFS(xChartDoc, uno::UNO_QUERY_THROW);
+ Reference<util::XNumberFormats> xNumberFormats = xNFS->getNumberFormats();
+ CPPUNIT_ASSERT(xNumberFormats.is());
+
+ return xNumberFormats->queryKey(sFormat, css::lang::Locale(), false);
+}
+
+sal_Int32 getNumberFormatFromAxis( const Reference<chart2::XAxis>& xAxis )
+{
+ Reference<beans::XPropertySet> xPS(xAxis, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPS.is());
+ sal_Int32 nNumberFormat = -1;
+ bool bSuccess = xPS->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormat;
+ CPPUNIT_ASSERT(bSuccess);
+
+ return nNumberFormat;
+}
+
+sal_Int16 getNumberFormatType( const Reference<chart2::XChartDocument>& xChartDoc, sal_Int32 nNumberFormat )
+{
+ Reference<util::XNumberFormatsSupplier> xNFS(xChartDoc, uno::UNO_QUERY_THROW);
+ Reference<util::XNumberFormats> xNumberFormats = xNFS->getNumberFormats();
+ CPPUNIT_ASSERT(xNumberFormats.is());
+
+ Reference<beans::XPropertySet> xNumPS = xNumberFormats->getByKey(nNumberFormat);
+ CPPUNIT_ASSERT(xNumPS.is());
+
+ sal_Int16 nType = util::NumberFormat::UNDEFINED;
+ xNumPS->getPropertyValue("Type") >>= nType;
+
+ return nType;
+}
+
+Sequence< double > getDateCategories(const Reference<chart2::XChartDocument>& xChartDoc)
+{
+ CPPUNIT_ASSERT(xChartDoc->hasInternalDataProvider());
+ uno::Reference< chart2::XInternalDataProvider > xDataProvider( xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW );
+ uno::Reference< chart::XDateCategories > xDateCategories( xDataProvider, uno::UNO_QUERY_THROW );
+ CPPUNIT_ASSERT(xDateCategories.is());
+ return xDateCategories->getDateCategories();
+}
+
+Sequence< OUString > ChartTest::getFormattedDateCategories( const Reference<chart2::XChartDocument>& xChartDoc )
+{
+ Reference<util::XNumberFormatsSupplier> xNFS(xChartDoc, uno::UNO_QUERY_THROW);
+ Reference< util::XNumberFormatter > xNumFormatter(
+ util::NumberFormatter::create(comphelper::getComponentContext(m_xSFactory)), uno::UNO_QUERY_THROW );
+ xNumFormatter->attachNumberFormatsSupplier(xNFS);
+
+ Reference<chart2::XAxis> xAxisX = getAxisFromDoc(xChartDoc, 0, 0, 0);
+ chart2::ScaleData aScaleData = xAxisX->getScaleData();
+ CPPUNIT_ASSERT_EQUAL(chart2::AxisType::DATE, aScaleData.AxisType);
+
+ sal_Int32 nNumFmt = getNumberFormatFromAxis(xAxisX);
+
+ Sequence<double> aDateSeq = getDateCategories(xChartDoc);
+ const sal_Int32 nNumCategories = aDateSeq.getLength();
+ Sequence<OUString> aFormattedDates(nNumCategories);
+ auto aFormattedDatesRange = asNonConstRange(aFormattedDates);
+
+ for (sal_Int32 nIdx = 0; nIdx < nNumCategories; ++nIdx)
+ aFormattedDatesRange[nIdx] = xNumFormatter->convertNumberToString(nNumFmt, aDateSeq[nIdx]);
+
+ return aFormattedDates;
+}
+
+awt::Size ChartTest::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc )
+{
+ awt::Size aSize( 0, 0 );
+ uno::Reference< com::sun::star::embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY );
+ CPPUNIT_ASSERT( xVisualObject.is() );
+ aSize = xVisualObject->getVisualAreaSize( com::sun::star::embed::Aspects::MSOLE_CONTENT );
+ return aSize;
+}
+
+awt::Size ChartTest::getSize(css::uno::Reference<chart2::XDiagram> xDiagram, const awt::Size& rPageSize)
+{
+ Reference< beans::XPropertySet > xProp(xDiagram, uno::UNO_QUERY);
+ chart2::RelativeSize aRelativeSize;
+ xProp->getPropertyValue( "RelativeSize" ) >>= aRelativeSize;
+ double fX = aRelativeSize.Primary * rPageSize.Width;
+ double fY = aRelativeSize.Secondary * rPageSize.Height;
+ awt::Size aSize;
+ aSize.Width = static_cast< sal_Int32 >( ::rtl::math::round( fX ) );
+ aSize.Height = static_cast< sal_Int32 >( ::rtl::math::round( fY ) );
+ return aSize;
+}
+
+uno::Reference<drawing::XShape>
+getShapeByName(const uno::Reference<drawing::XShapes>& rShapes, const OUString& rName,
+ const std::function<bool(const uno::Reference<drawing::XShape>&)>& pCondition
+ = nullptr)
+{
+ for (sal_Int32 i = 0; i < rShapes->getCount(); ++i)
+ {
+ uno::Reference<drawing::XShapes> xShapes(rShapes->getByIndex(i), uno::UNO_QUERY);
+ if (xShapes.is())
+ {
+ uno::Reference<drawing::XShape> xRet = getShapeByName(xShapes, rName, pCondition);
+ if (xRet.is())
+ return xRet;
+ }
+ uno::Reference<container::XNamed> xNamedShape(rShapes->getByIndex(i), uno::UNO_QUERY);
+ if (xNamedShape->getName() == rName)
+ {
+ uno::Reference<drawing::XShape> xShape(xNamedShape, uno::UNO_QUERY);
+ if (pCondition == nullptr || pCondition(xShape))
+ return xShape;
+ }
+ }
+ return uno::Reference<drawing::XShape>();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/data/doc/chart.doc b/chart2/qa/extras/data/doc/chart.doc
new file mode 100644
index 0000000000..2bfa5aed2c
--- /dev/null
+++ b/chart2/qa/extras/data/doc/chart.doc
Binary files differ
diff --git a/chart2/qa/extras/data/docx/3d-bar-label.docx b/chart2/qa/extras/data/docx/3d-bar-label.docx
new file mode 100644
index 0000000000..69cab8e719
--- /dev/null
+++ b/chart2/qa/extras/data/docx/3d-bar-label.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/Bar_horizontal_cone.docx b/chart2/qa/extras/data/docx/Bar_horizontal_cone.docx
new file mode 100644
index 0000000000..2280d89fc1
--- /dev/null
+++ b/chart2/qa/extras/data/docx/Bar_horizontal_cone.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/DisplayUnits.docx b/chart2/qa/extras/data/docx/DisplayUnits.docx
new file mode 100644
index 0000000000..97092a3ed6
--- /dev/null
+++ b/chart2/qa/extras/data/docx/DisplayUnits.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/FDO74430.docx b/chart2/qa/extras/data/docx/FDO74430.docx
new file mode 100644
index 0000000000..f4a68b519d
--- /dev/null
+++ b/chart2/qa/extras/data/docx/FDO74430.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/FDO75975.docx b/chart2/qa/extras/data/docx/FDO75975.docx
new file mode 100644
index 0000000000..30f251014b
--- /dev/null
+++ b/chart2/qa/extras/data/docx/FDO75975.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/MSO_Custom_Leader_Line.docx b/chart2/qa/extras/data/docx/MSO_Custom_Leader_Line.docx
new file mode 100644
index 0000000000..c158a0d765
--- /dev/null
+++ b/chart2/qa/extras/data/docx/MSO_Custom_Leader_Line.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/MSO_axis_position.docx b/chart2/qa/extras/data/docx/MSO_axis_position.docx
new file mode 100644
index 0000000000..a9955b7b1a
--- /dev/null
+++ b/chart2/qa/extras/data/docx/MSO_axis_position.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/PieChartDataLabels.docx b/chart2/qa/extras/data/docx/PieChartDataLabels.docx
new file mode 100644
index 0000000000..99a72c0f29
--- /dev/null
+++ b/chart2/qa/extras/data/docx/PieChartDataLabels.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/TableOnPage3.docx b/chart2/qa/extras/data/docx/TableOnPage3.docx
new file mode 100644
index 0000000000..79763bd352
--- /dev/null
+++ b/chart2/qa/extras/data/docx/TableOnPage3.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/UpDownBars.docx b/chart2/qa/extras/data/docx/UpDownBars.docx
new file mode 100644
index 0000000000..755f814996
--- /dev/null
+++ b/chart2/qa/extras/data/docx/UpDownBars.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/area-chart-labels.docx b/chart2/qa/extras/data/docx/area-chart-labels.docx
new file mode 100644
index 0000000000..4db844112d
--- /dev/null
+++ b/chart2/qa/extras/data/docx/area-chart-labels.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/bar-chart-labels.docx b/chart2/qa/extras/data/docx/bar-chart-labels.docx
new file mode 100644
index 0000000000..9ff8b4fd17
--- /dev/null
+++ b/chart2/qa/extras/data/docx/bar-chart-labels.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/barChartRotation.docx b/chart2/qa/extras/data/docx/barChartRotation.docx
new file mode 100644
index 0000000000..bf4be47b34
--- /dev/null
+++ b/chart2/qa/extras/data/docx/barChartRotation.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/bubblechart.docx b/chart2/qa/extras/data/docx/bubblechart.docx
new file mode 100644
index 0000000000..c2040730cf
--- /dev/null
+++ b/chart2/qa/extras/data/docx/bubblechart.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/chart.docx b/chart2/qa/extras/data/docx/chart.docx
new file mode 100644
index 0000000000..f9cddd4949
--- /dev/null
+++ b/chart2/qa/extras/data/docx/chart.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/clustered-bar-chart-labels.docx b/chart2/qa/extras/data/docx/clustered-bar-chart-labels.docx
new file mode 100644
index 0000000000..3b9941cc1e
--- /dev/null
+++ b/chart2/qa/extras/data/docx/clustered-bar-chart-labels.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/data-label-borders.docx b/chart2/qa/extras/data/docx/data-label-borders.docx
new file mode 100644
index 0000000000..6f2b94d98e
--- /dev/null
+++ b/chart2/qa/extras/data/docx/data-label-borders.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/data_point_inherited_color.docx b/chart2/qa/extras/data/docx/data_point_inherited_color.docx
new file mode 100644
index 0000000000..70de8b2188
--- /dev/null
+++ b/chart2/qa/extras/data/docx/data_point_inherited_color.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/doughnut-chart-labels.docx b/chart2/qa/extras/data/docx/doughnut-chart-labels.docx
new file mode 100644
index 0000000000..559208578f
--- /dev/null
+++ b/chart2/qa/extras/data/docx/doughnut-chart-labels.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/doughnutChart.docx b/chart2/qa/extras/data/docx/doughnutChart.docx
new file mode 100644
index 0000000000..f0642d4d5c
--- /dev/null
+++ b/chart2/qa/extras/data/docx/doughnutChart.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/fdo74115_WallBitmapFill.docx b/chart2/qa/extras/data/docx/fdo74115_WallBitmapFill.docx
new file mode 100644
index 0000000000..15f42b0cf3
--- /dev/null
+++ b/chart2/qa/extras/data/docx/fdo74115_WallBitmapFill.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/fdo74115_WallGradientFill.docx b/chart2/qa/extras/data/docx/fdo74115_WallGradientFill.docx
new file mode 100644
index 0000000000..e10334bd9a
--- /dev/null
+++ b/chart2/qa/extras/data/docx/fdo74115_WallGradientFill.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/fdo78290_Combination_Chart_Marker_x.docx b/chart2/qa/extras/data/docx/fdo78290_Combination_Chart_Marker_x.docx
new file mode 100644
index 0000000000..ee2489d21a
--- /dev/null
+++ b/chart2/qa/extras/data/docx/fdo78290_Combination_Chart_Marker_x.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/fdo78290_Line_Chart_Marker_x.docx b/chart2/qa/extras/data/docx/fdo78290_Line_Chart_Marker_x.docx
new file mode 100644
index 0000000000..7e4b096b83
--- /dev/null
+++ b/chart2/qa/extras/data/docx/fdo78290_Line_Chart_Marker_x.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/fdo78290_Scatter_Chart_Marker_x.docx b/chart2/qa/extras/data/docx/fdo78290_Scatter_Chart_Marker_x.docx
new file mode 100644
index 0000000000..2edc8f0862
--- /dev/null
+++ b/chart2/qa/extras/data/docx/fdo78290_Scatter_Chart_Marker_x.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/fdo83058_dlblPos.docx b/chart2/qa/extras/data/docx/fdo83058_dlblPos.docx
new file mode 100644
index 0000000000..721a717897
--- /dev/null
+++ b/chart2/qa/extras/data/docx/fdo83058_dlblPos.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/line-chart-label-default-placement.docx b/chart2/qa/extras/data/docx/line-chart-label-default-placement.docx
new file mode 100644
index 0000000000..ab9548d59c
--- /dev/null
+++ b/chart2/qa/extras/data/docx/line-chart-label-default-placement.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/pieChartRotation.docx b/chart2/qa/extras/data/docx/pieChartRotation.docx
new file mode 100644
index 0000000000..f76f602374
--- /dev/null
+++ b/chart2/qa/extras/data/docx/pieChartRotation.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/piechart_deleted_legend_entry.docx b/chart2/qa/extras/data/docx/piechart_deleted_legend_entry.docx
new file mode 100644
index 0000000000..da6b2fa19a
--- /dev/null
+++ b/chart2/qa/extras/data/docx/piechart_deleted_legend_entry.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/radar-chart-labels.docx b/chart2/qa/extras/data/docx/radar-chart-labels.docx
new file mode 100644
index 0000000000..2cb876dd26
--- /dev/null
+++ b/chart2/qa/extras/data/docx/radar-chart-labels.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/scatter-chart-text-x-values.docx b/chart2/qa/extras/data/docx/scatter-chart-text-x-values.docx
new file mode 100644
index 0000000000..b741bbce21
--- /dev/null
+++ b/chart2/qa/extras/data/docx/scatter-chart-text-x-values.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf121744.docx b/chart2/qa/extras/data/docx/tdf121744.docx
new file mode 100644
index 0000000000..b5ff10098c
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf121744.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf123206.docx b/chart2/qa/extras/data/docx/tdf123206.docx
new file mode 100644
index 0000000000..f47089fe3b
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf123206.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf124083.docx b/chart2/qa/extras/data/docx/tdf124083.docx
new file mode 100644
index 0000000000..b8030ca9a8
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf124083.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf124243.docx b/chart2/qa/extras/data/docx/tdf124243.docx
new file mode 100644
index 0000000000..e58ef6a02e
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf124243.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf125337.docx b/chart2/qa/extras/data/docx/tdf125337.docx
new file mode 100644
index 0000000000..811f12d898
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf125337.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf128794.docx b/chart2/qa/extras/data/docx/tdf128794.docx
new file mode 100644
index 0000000000..098c0a00e3
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf128794.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf132174.docx b/chart2/qa/extras/data/docx/tdf132174.docx
new file mode 100644
index 0000000000..4f43695784
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf132174.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf133632.docx b/chart2/qa/extras/data/docx/tdf133632.docx
new file mode 100644
index 0000000000..b970e73f4c
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf133632.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf134111.docx b/chart2/qa/extras/data/docx/tdf134111.docx
new file mode 100644
index 0000000000..26e3a03e0b
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf134111.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf134255.docx b/chart2/qa/extras/data/docx/tdf134255.docx
new file mode 100644
index 0000000000..ff3cd8b67b
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf134255.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf136650.docx b/chart2/qa/extras/data/docx/tdf136650.docx
new file mode 100644
index 0000000000..cd095ec631
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf136650.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf139658.docx b/chart2/qa/extras/data/docx/tdf139658.docx
new file mode 100644
index 0000000000..59deda9f83
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf139658.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf143130.docx b/chart2/qa/extras/data/docx/tdf143130.docx
new file mode 100644
index 0000000000..a364f4811a
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf143130.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/tdf91250.docx b/chart2/qa/extras/data/docx/tdf91250.docx
new file mode 100644
index 0000000000..4cb199b457
--- /dev/null
+++ b/chart2/qa/extras/data/docx/tdf91250.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testAreaChartLoad.docx b/chart2/qa/extras/data/docx/testAreaChartLoad.docx
new file mode 100644
index 0000000000..9383f75cde
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testAreaChartLoad.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testAxisTitlePosition.docx b/chart2/qa/extras/data/docx/testAxisTitlePosition.docx
new file mode 100644
index 0000000000..6abd37eec5
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testAxisTitlePosition.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testBarChart.docx b/chart2/qa/extras/data/docx/testBarChart.docx
new file mode 100644
index 0000000000..b92260f718
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testBarChart.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testBarChartDataPointPropDOCX.docx b/chart2/qa/extras/data/docx/testBarChartDataPointPropDOCX.docx
new file mode 100644
index 0000000000..66df9153d3
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testBarChartDataPointPropDOCX.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testChartDataTable.docx b/chart2/qa/extras/data/docx/testChartDataTable.docx
new file mode 100644
index 0000000000..8663e8937e
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testChartDataTable.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testChartTitlePropertiesBitmapFill.docx b/chart2/qa/extras/data/docx/testChartTitlePropertiesBitmapFill.docx
new file mode 100644
index 0000000000..462c15976a
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testChartTitlePropertiesBitmapFill.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testChartTitlePropertiesColorFill.docx b/chart2/qa/extras/data/docx/testChartTitlePropertiesColorFill.docx
new file mode 100644
index 0000000000..d86928d615
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testChartTitlePropertiesColorFill.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testChartTitlePropertiesGradientFill.docx b/chart2/qa/extras/data/docx/testChartTitlePropertiesGradientFill.docx
new file mode 100644
index 0000000000..a72600d09e
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testChartTitlePropertiesGradientFill.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testColorGradientWithTransparency.docx b/chart2/qa/extras/data/docx/testColorGradientWithTransparency.docx
new file mode 100644
index 0000000000..adc2aff042
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testColorGradientWithTransparency.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testCustomlabeltext.docx b/chart2/qa/extras/data/docx/testCustomlabeltext.docx
new file mode 100644
index 0000000000..db28209c9c
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testCustomlabeltext.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testLabelSeparator.docx b/chart2/qa/extras/data/docx/testLabelSeparator.docx
new file mode 100644
index 0000000000..452fdccc94
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testLabelSeparator.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx b/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx
new file mode 100644
index 0000000000..75605de72f
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testMultipleChart.docx b/chart2/qa/extras/data/docx/testMultipleChart.docx
new file mode 100644
index 0000000000..28d8bbcfe1
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testMultipleChart.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testMultiplechartembeddings.docx b/chart2/qa/extras/data/docx/testMultiplechartembeddings.docx
new file mode 100644
index 0000000000..28d8bbcfe1
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testMultiplechartembeddings.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testSeriesIdxOrder.docx b/chart2/qa/extras/data/docx/testSeriesIdxOrder.docx
new file mode 100644
index 0000000000..9274e2c2c2
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testSeriesIdxOrder.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testSimpleCategoryAxis.docx b/chart2/qa/extras/data/docx/testSimpleCategoryAxis.docx
new file mode 100644
index 0000000000..de511664a5
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testSimpleCategoryAxis.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testStockChart.docx b/chart2/qa/extras/data/docx/testStockChart.docx
new file mode 100644
index 0000000000..a804e7df2d
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testStockChart.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testTdf108110.docx b/chart2/qa/extras/data/docx/testTdf108110.docx
new file mode 100644
index 0000000000..769360c152
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testTdf108110.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testTdf114179.docx b/chart2/qa/extras/data/docx/testTdf114179.docx
new file mode 100644
index 0000000000..36fb11e170
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testTdf114179.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testTdf122226.docx b/chart2/qa/extras/data/docx/testTdf122226.docx
new file mode 100644
index 0000000000..7205525a76
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testTdf122226.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testchartoleobjectembeddings.docx b/chart2/qa/extras/data/docx/testchartoleobjectembeddings.docx
new file mode 100644
index 0000000000..8167de7a35
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testchartoleobjectembeddings.docx
Binary files differ
diff --git a/chart2/qa/extras/data/docx/testcustomshapepos.docx b/chart2/qa/extras/data/docx/testcustomshapepos.docx
new file mode 100644
index 0000000000..640c48ea46
--- /dev/null
+++ b/chart2/qa/extras/data/docx/testcustomshapepos.docx
Binary files differ
diff --git a/chart2/qa/extras/data/fods/stacked-column-chart.fods b/chart2/qa/extras/data/fods/stacked-column-chart.fods
new file mode 100644
index 0000000000..8a142120ba
--- /dev/null
+++ b/chart2/qa/extras/data/fods/stacked-column-chart.fods
@@ -0,0 +1,861 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
+ <office:meta><meta:initial-creator>Michael Meeks</meta:initial-creator><meta:creation-date>2014-06-05T11:25:47.346574464</meta:creation-date><dc:date>2014-06-05T11:32:25.317381922</dc:date><dc:creator>Michael Meeks</dc:creator><meta:editing-duration>PT3M51S</meta:editing-duration><meta:editing-cycles>6</meta:editing-cycles><meta:generator>LibreOffice/3.5$Linux_X86_64 LibreOffice_project/f647884-246edd6</meta:generator><meta:document-statistic meta:table-count="2" meta:cell-count="27" meta:object-count="1"/></office:meta>
+ <office:settings>
+ <config:config-item-set config:name="ooo:view-settings">
+ <config:config-item config:name="VisibleAreaTop" config:type="int">0</config:config-item>
+ <config:config-item config:name="VisibleAreaLeft" config:type="int">0</config:config-item>
+ <config:config-item config:name="VisibleAreaWidth" config:type="int">27093</config:config-item>
+ <config:config-item config:name="VisibleAreaHeight" config:type="int">9934</config:config-item>
+ <config:config-item-map-indexed config:name="Views">
+ <config:config-item-map-entry>
+ <config:config-item config:name="ViewId" config:type="string">view1</config:config-item>
+ <config:config-item-map-named config:name="Tables">
+ <config:config-item-map-entry config:name="Data">
+ <config:config-item config:name="CursorPositionX" config:type="int">1</config:config-item>
+ <config:config-item config:name="CursorPositionY" config:type="int">0</config:config-item>
+ <config:config-item config:name="HorizontalSplitMode" config:type="short">0</config:config-item>
+ <config:config-item config:name="VerticalSplitMode" config:type="short">0</config:config-item>
+ <config:config-item config:name="HorizontalSplitPosition" config:type="int">0</config:config-item>
+ <config:config-item config:name="VerticalSplitPosition" config:type="int">0</config:config-item>
+ <config:config-item config:name="ActiveSplitRange" config:type="short">2</config:config-item>
+ <config:config-item config:name="PositionLeft" config:type="int">0</config:config-item>
+ <config:config-item config:name="PositionRight" config:type="int">0</config:config-item>
+ <config:config-item config:name="PositionTop" config:type="int">0</config:config-item>
+ <config:config-item config:name="PositionBottom" config:type="int">0</config:config-item>
+ <config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
+ <config:config-item config:name="ZoomValue" config:type="int">130</config:config-item>
+ <config:config-item config:name="PageViewZoomValue" config:type="int">60</config:config-item>
+ <config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item>
+ </config:config-item-map-entry>
+ <config:config-item-map-entry config:name="Summary">
+ <config:config-item config:name="CursorPositionX" config:type="int">1</config:config-item>
+ <config:config-item config:name="CursorPositionY" config:type="int">16</config:config-item>
+ <config:config-item config:name="HorizontalSplitMode" config:type="short">0</config:config-item>
+ <config:config-item config:name="VerticalSplitMode" config:type="short">0</config:config-item>
+ <config:config-item config:name="HorizontalSplitPosition" config:type="int">0</config:config-item>
+ <config:config-item config:name="VerticalSplitPosition" config:type="int">0</config:config-item>
+ <config:config-item config:name="ActiveSplitRange" config:type="short">2</config:config-item>
+ <config:config-item config:name="PositionLeft" config:type="int">0</config:config-item>
+ <config:config-item config:name="PositionRight" config:type="int">0</config:config-item>
+ <config:config-item config:name="PositionTop" config:type="int">0</config:config-item>
+ <config:config-item config:name="PositionBottom" config:type="int">0</config:config-item>
+ <config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
+ <config:config-item config:name="ZoomValue" config:type="int">130</config:config-item>
+ <config:config-item config:name="PageViewZoomValue" config:type="int">60</config:config-item>
+ <config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item>
+ </config:config-item-map-entry>
+ </config:config-item-map-named>
+ <config:config-item config:name="ActiveTable" config:type="string">Summary</config:config-item>
+ <config:config-item config:name="HorizontalScrollbarWidth" config:type="int">270</config:config-item>
+ <config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
+ <config:config-item config:name="ZoomValue" config:type="int">130</config:config-item>
+ <config:config-item config:name="PageViewZoomValue" config:type="int">60</config:config-item>
+ <config:config-item config:name="ShowPageBreakPreview" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ShowZeroValues" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="ShowNotes" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="GridColor" config:type="long">12632256</config:config-item>
+ <config:config-item config:name="ShowPageBreaks" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="HasColumnRowHeaders" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="HasSheetTabs" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsOutlineSymbolsSet" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToRaster" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="RasterIsVisible" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="RasterResolutionX" config:type="int">1000</config:config-item>
+ <config:config-item config:name="RasterResolutionY" config:type="int">1000</config:config-item>
+ <config:config-item config:name="RasterSubdivisionX" config:type="int">1</config:config-item>
+ <config:config-item config:name="RasterSubdivisionY" config:type="int">1</config:config-item>
+ <config:config-item config:name="IsRasterAxisSynchronized" config:type="boolean">true</config:config-item>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ </config:config-item-set>
+ <config:config-item-set config:name="ooo:configuration-settings">
+ <config:config-item config:name="ShowZeroValues" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="GridColor" config:type="long">12632256</config:config-item>
+ <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToRaster" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="RasterSubdivisionX" config:type="int">1</config:config-item>
+ <config:config-item config:name="RasterSubdivisionY" config:type="int">1</config:config-item>
+ <config:config-item-map-indexed config:name="ForbiddenCharacters">
+ <config:config-item-map-entry>
+ <config:config-item config:name="Language" config:type="string">en</config:config-item>
+ <config:config-item config:name="Country" config:type="string">GB</config:config-item>
+ <config:config-item config:name="Variant" config:type="string"/>
+ <config:config-item config:name="BeginLine" config:type="string"/>
+ <config:config-item config:name="EndLine" config:type="string"/>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ <config:config-item config:name="AutoCalculate" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="PrinterSetup" config:type="base64Binary">fwH+/0Nhbm9uLTg2MGkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ1VQUzpDYW5vbi04NjBpAAAAAAAAAAAAAAAAAAAAAAAWAAMApQAAAAAAAAAIAFZUAAAkbQAASm9iRGF0YSAxCnByaW50ZXI9Q2Fub24tODYwaQpvcmllbnRhdGlvbj1Qb3J0cmFpdApjb3BpZXM9MQptYXJnaW5kYWp1c3RtZW50PTAsMCwwLDAKY29sb3JkZXB0aD0yNApwc2xldmVsPTAKcGRmZGV2aWNlPTEKY29sb3JkZXZpY2U9MApQUERDb250ZXhEYXRhClBhZ2VTaXplOkxldHRlcgAAEgBDT01QQVRfRFVQTEVYX01PREUKAERVUExFWF9PRkY=</config:config-item>
+ <config:config-item config:name="ShowNotes" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsDocumentShared" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="HasSheetTabs" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="PrinterName" config:type="string">Canon-860i</config:config-item>
+ <config:config-item config:name="LinkUpdateMode" config:type="short">3</config:config-item>
+ <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="RasterIsVisible" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="RasterResolutionX" config:type="int">1000</config:config-item>
+ <config:config-item config:name="RasterResolutionY" config:type="int">1000</config:config-item>
+ <config:config-item config:name="IsOutlineSymbolsSet" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="ShowPageBreaks" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item>
+ <config:config-item config:name="IsRasterAxisSynchronized" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="HasColumnRowHeaders" config:type="boolean">true</config:config-item>
+ </config:config-item-set>
+ </office:settings>
+ <office:scripts>
+ <office:script script:language="ooo:Basic">
+ <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/>
+ </office:script>
+ </office:scripts>
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Sans" svg:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="swiss" style:font-pitch="variable"/>
+ <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="DejaVu Sans" svg:font-family="&apos;DejaVu Sans&apos;" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Droid Sans Devanagari" svg:font-family="&apos;Droid Sans Devanagari&apos;" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Tahoma" svg:font-family="Tahoma" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="table-cell">
+ <style:paragraph-properties style:tab-stop-distance="0.4921in"/>
+ <style:text-properties style:font-name="Liberation Sans" fo:language="en" fo:country="GB" style:font-name-asian="Arial" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Tahoma" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.1181in" draw:shadow-offset-y="0.1181in"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:punctuation-wrap="simple" style:line-break="strict" style:writing-mode="page" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" fo:font-family="&apos;Liberation Serif&apos;" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="12pt" fo:language="en" fo:country="GB" style:letter-kerning="true" style:font-size-asian="24pt" style:language-asian="zh" style:country-asian="CN" style:font-size-complex="24pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <number:number-style style:name="N0">
+ <number:number number:min-integer-digits="1"/>
+ </number:number-style>
+ <number:currency-style style:name="N121P0" style:volatile="true">
+ <number:currency-symbol number:language="en" number:country="GB">£</number:currency-symbol>
+ <number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
+ </number:currency-style>
+ <number:currency-style style:name="N121">
+ <style:text-properties fo:color="#ff0000"/>
+ <number:text>-</number:text>
+ <number:currency-symbol number:language="en" number:country="GB">£</number:currency-symbol>
+ <number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
+ <style:map style:condition="value()&gt;=0" style:apply-style-name="N121P0"/>
+ </number:currency-style>
+ <number:currency-style style:name="N123P0" style:volatile="true">
+ <number:currency-symbol number:language="en" number:country="GB">£</number:currency-symbol>
+ <number:number number:decimal-places="0" number:min-integer-digits="1" number:grouping="true"/>
+ </number:currency-style>
+ <number:currency-style style:name="N123">
+ <style:text-properties fo:color="#ff0000"/>
+ <number:text>-</number:text>
+ <number:currency-symbol number:language="en" number:country="GB">£</number:currency-symbol>
+ <number:number number:decimal-places="0" number:min-integer-digits="1" number:grouping="true"/>
+ <style:map style:condition="value()&gt;=0" style:apply-style-name="N123P0"/>
+ </number:currency-style>
+ <style:style style:name="Default" style:family="table-cell">
+ <style:text-properties style:font-name-complex="Droid Sans Devanagari"/>
+ </style:style>
+ <style:style style:name="Result" style:family="table-cell" style:parent-style-name="Default">
+ <style:text-properties fo:font-style="italic" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="Result2" style:family="table-cell" style:parent-style-name="Result" style:data-style-name="N121"/>
+ <style:style style:name="Heading" style:family="table-cell" style:parent-style-name="Default">
+ <style:table-cell-properties style:text-align-source="fix" style:repeat-content="false"/>
+ <style:paragraph-properties fo:text-align="center"/>
+ <style:text-properties fo:font-size="16pt" fo:font-style="italic" fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="Heading1" style:family="table-cell" style:parent-style-name="Heading">
+ <style:table-cell-properties style:rotation-angle="90"/>
+ </style:style>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="co1" style:family="table-column">
+ <style:table-column-properties fo:break-before="auto" style:column-width="0.889in"/>
+ </style:style>
+ <style:style style:name="ro1" style:family="table-row">
+ <style:table-row-properties style:row-height="0.178in" fo:break-before="auto" style:use-optimal-row-height="true"/>
+ </style:style>
+ <style:style style:name="ta1" style:family="table" style:master-page-name="Default">
+ <style:table-properties table:display="true" style:writing-mode="lr-tb"/>
+ </style:style>
+ <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default">
+ <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="ce2" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N123"/>
+ <style:style style:name="gr1" style:family="graphic">
+ <style:graphic-properties draw:ole-draw-aspect="1"/>
+ </style:style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties style:writing-mode="lr-tb"/>
+ <style:header-style>
+ <style:header-footer-properties fo:min-height="0.2953in" fo:margin-left="0in" fo:margin-right="0in" fo:margin-bottom="0.0984in"/>
+ </style:header-style>
+ <style:footer-style>
+ <style:header-footer-properties fo:min-height="0.2953in" fo:margin-left="0in" fo:margin-right="0in" fo:margin-top="0.0984in"/>
+ </style:footer-style>
+ </style:page-layout>
+ <style:page-layout style:name="pm2">
+ <style:page-layout-properties style:writing-mode="lr-tb"/>
+ <style:header-style>
+ <style:header-footer-properties fo:min-height="0.2953in" fo:margin-left="0in" fo:margin-right="0in" fo:margin-bottom="0.0984in" fo:border="2.49pt solid #000000" fo:padding="0.0071in" fo:background-color="#c0c0c0">
+ <style:background-image/>
+ </style:header-footer-properties>
+ </style:header-style>
+ <style:footer-style>
+ <style:header-footer-properties fo:min-height="0.2953in" fo:margin-left="0in" fo:margin-right="0in" fo:margin-top="0.0984in" fo:border="2.49pt solid #000000" fo:padding="0.0071in" fo:background-color="#c0c0c0">
+ <style:background-image/>
+ </style:header-footer-properties>
+ </style:footer-style>
+ </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Default" style:page-layout-name="pm1">
+ <style:header>
+ <text:p><text:sheet-name>???</text:sheet-name></text:p>
+ </style:header>
+ <style:header-left style:display="false"/>
+ <style:footer>
+ <text:p>Page <text:page-number>1</text:page-number></text:p>
+ </style:footer>
+ <style:footer-left style:display="false"/>
+ </style:master-page>
+ <style:master-page style:name="Report" style:page-layout-name="pm2">
+ <style:header>
+ <style:region-left>
+ <text:p><text:sheet-name>???</text:sheet-name> (<text:title>???</text:title>)</text:p>
+ </style:region-left>
+ <style:region-right>
+ <text:p><text:date style:data-style-name="N2" text:date-value="2014-06-06">00/00/0000</text:date>, <text:time>00:00:00</text:time></text:p>
+ </style:region-right>
+ </style:header>
+ <style:header-left style:display="false"/>
+ <style:footer>
+ <text:p>Page <text:page-number>1</text:page-number> / <text:page-count>99</text:page-count></text:p>
+ </style:footer>
+ <style:footer-left style:display="false"/>
+ </style:master-page>
+ </office:master-styles>
+ <office:body>
+ <office:spreadsheet>
+ <table:table table:name="Summary" table:style-name="ta1">
+ <table:shapes>
+ <draw:frame draw:z-index="0" draw:style-name="gr1" svg:width="6.2988in" svg:height="3.5429in" svg:x="3.5118in" svg:y="0.25in">
+ <draw:object draw:notify-on-update-of-ranges="Summary.B1:Summary.B1 Summary.A2:Summary.A2 Summary.B2:Summary.B2 Summary.A3:Summary.A3 Summary.B3:Summary.B3 Summary.A4:Summary.A4 Summary.B4:Summary.B4 Summary.A5:Summary.A5 Summary.B5:Summary.B5 Summary.A6:Summary.A6 Summary.B6:Summary.B6">
+ <office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:chartooo="http://openoffice.org/2010/chart" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.chart">
+ <office:meta><meta:generator>LibreOffice/3.5$Linux_X86_64 LibreOffice_project/f647884-246edd6</meta:generator></office:meta>
+ <office:styles/>
+ <office:automatic-styles>
+ <number:number-style style:name="N0">
+ <number:number number:min-integer-digits="1"/>
+ </number:number-style>
+ <number:currency-style style:name="N123P0" style:volatile="true">
+ <number:currency-symbol number:language="en" number:country="GB">£</number:currency-symbol>
+ <number:number number:decimal-places="0" number:min-integer-digits="1" number:grouping="true"/>
+ </number:currency-style>
+ <number:currency-style style:name="N123">
+ <style:text-properties fo:color="#ff0000"/>
+ <number:text>-</number:text>
+ <number:currency-symbol number:language="en" number:country="GB">£</number:currency-symbol>
+ <number:number number:decimal-places="0" number:min-integer-digits="1" number:grouping="true"/>
+ <style:map style:condition="value()&gt;=0" style:apply-style-name="N123P0"/>
+ </number:currency-style>
+ <style:style style:name="ch1" style:family="chart">
+ <style:graphic-properties draw:stroke="none"/>
+ </style:style>
+ <style:style style:name="ch2" style:family="chart">
+ <style:chart-properties chart:auto-position="true"/>
+ <style:graphic-properties draw:stroke="none" svg:stroke-color="#b3b3b3" draw:fill="none" draw:fill-color="#e6e6e6"/>
+ <style:text-properties fo:font-size="10pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/>
+ </style:style>
+ <style:style style:name="ch3" style:family="chart">
+ <style:chart-properties chart:stacked="true" chart:include-hidden-cells="false" chart:auto-position="true" chart:auto-size="true" chart:treat-empty-cells="leave-gap" chart:series-source="rows" chart:right-angled-axes="true"/>
+ </style:style>
+ <style:style style:name="ch4" style:family="chart" style:data-style-name="N0">
+ <style:chart-properties chart:display-label="true" chart:logarithmic="false" chart:reverse-direction="false" text:line-break="false" chart:axis-position="0"/>
+ <style:graphic-properties svg:stroke-color="#b3b3b3"/>
+ <style:text-properties fo:font-size="10pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/>
+ </style:style>
+ <style:style style:name="ch5" style:family="chart" style:data-style-name="N123">
+ <style:chart-properties chart:display-label="true" chart:logarithmic="false" chart:reverse-direction="false" text:line-break="false" chart:axis-position="0"/>
+ <style:graphic-properties svg:stroke-color="#b3b3b3"/>
+ <style:text-properties fo:font-size="10pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/>
+ </style:style>
+ <style:style style:name="ch6" style:family="chart">
+ <style:graphic-properties svg:stroke-color="#b3b3b3"/>
+ </style:style>
+ <style:style style:name="ch7" style:family="chart" style:data-style-name="N123">
+ <style:graphic-properties draw:stroke="none" draw:fill-color="#004586" dr3d:edge-rounding="5%"/>
+ <style:text-properties fo:font-size="10pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/>
+ </style:style>
+ <style:style style:name="ch8" style:family="chart" style:data-style-name="N123">
+ <style:graphic-properties draw:stroke="none" draw:fill-color="#ff420e" dr3d:edge-rounding="5%"/>
+ <style:text-properties fo:font-size="10pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/>
+ </style:style>
+ <style:style style:name="ch9" style:family="chart" style:data-style-name="N123">
+ <style:graphic-properties draw:stroke="none" draw:fill-color="#ffd320" dr3d:edge-rounding="5%"/>
+ <style:text-properties fo:font-size="10pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/>
+ </style:style>
+ <style:style style:name="ch10" style:family="chart" style:data-style-name="N123">
+ <style:graphic-properties draw:stroke="none" draw:fill-color="#579d1c" dr3d:edge-rounding="5%"/>
+ <style:text-properties fo:font-size="10pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/>
+ </style:style>
+ <style:style style:name="ch11" style:family="chart" style:data-style-name="N123">
+ <style:graphic-properties draw:stroke="none" draw:fill-color="#7e0021" dr3d:edge-rounding="5%"/>
+ <style:text-properties fo:font-size="10pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/>
+ </style:style>
+ <style:style style:name="ch12" style:family="chart">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-color="#b3b3b3" draw:fill="none" draw:fill-color="#e6e6e6"/>
+ </style:style>
+ <style:style style:name="ch13" style:family="chart">
+ <style:graphic-properties svg:stroke-color="#b3b3b3" draw:fill-color="#cccccc"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:chart>
+ <chart:chart svg:width="16cm" svg:height="9cm" xlink:href=".." xlink:type="simple" chart:class="chart:bar" chart:style-name="ch1">
+ <chart:legend chart:legend-position="end" svg:x="14.372cm" svg:y="3.205cm" style:legend-expansion="high" chart:style-name="ch2"/>
+ <chart:plot-area chart:style-name="ch3" table:cell-range-address="Summary.B1:Summary.B6 Summary.A2:Summary.A6" chart:data-source-has-labels="both" svg:x="0.77cm" svg:y="0.855cm" svg:width="12.962cm" svg:height="7.545cm">
+ <chartooo:coordinate-region svg:x="2.053cm" svg:y="1.054cm" svg:width="11.679cm" svg:height="6.699cm"/>
+ <chart:axis chart:dimension="x" chart:name="primary-x" chart:style-name="ch4" chartooo:axis-type="auto">
+ <chartooo:date-scale/>
+ <chart:categories table:cell-range-address="Summary.B1:Summary.B1"/>
+ </chart:axis>
+ <chart:axis chart:dimension="y" chart:name="primary-y" chart:style-name="ch5">
+ <chart:grid chart:style-name="ch6" chart:class="major"/>
+ </chart:axis>
+ <chart:series chart:style-name="ch7" chart:values-cell-range-address="Summary.B2:Summary.B2" chart:label-cell-address="Summary.A2:Summary.A2" chart:class="chart:bar">
+ <chart:data-point/>
+ </chart:series>
+ <chart:series chart:style-name="ch8" chart:values-cell-range-address="Summary.B3:Summary.B3" chart:label-cell-address="Summary.A3:Summary.A3" chart:class="chart:bar">
+ <chart:data-point/>
+ </chart:series>
+ <chart:series chart:style-name="ch9" chart:values-cell-range-address="Summary.B4:Summary.B4" chart:label-cell-address="Summary.A4:Summary.A4" chart:class="chart:bar">
+ <chart:data-point/>
+ </chart:series>
+ <chart:series chart:style-name="ch10" chart:values-cell-range-address="Summary.B5:Summary.B5" chart:label-cell-address="Summary.A5:Summary.A5" chart:class="chart:bar">
+ <chart:data-point/>
+ </chart:series>
+ <chart:series chart:style-name="ch11" chart:values-cell-range-address="Summary.B6:Summary.B6" chart:label-cell-address="Summary.A6:Summary.A6" chart:class="chart:bar">
+ <chart:data-point/>
+ </chart:series>
+ <chart:wall chart:style-name="ch12"/>
+ <chart:floor chart:style-name="ch13"/>
+ </chart:plot-area>
+ <table:table table:name="local-table">
+ <table:table-header-columns>
+ <table:table-column/>
+ </table:table-header-columns>
+ <table:table-columns>
+ <table:table-column/>
+ </table:table-columns>
+ <table:table-header-rows>
+ <table:table-row>
+ <table:table-cell>
+ <text:p/>
+ </table:table-cell>
+ <table:table-cell office:value-type="string">
+ <text:p>Some</text:p>
+ <draw:g>
+ <svg:desc>Summary.B1:Summary.B1</svg:desc></draw:g>
+ </table:table-cell>
+ </table:table-row>
+ </table:table-header-rows>
+ <table:table-rows>
+ <table:table-row>
+ <table:table-cell office:value-type="string">
+ <text:p>One</text:p>
+ <draw:g>
+ <svg:desc>Summary.A2:Summary.A2</svg:desc></draw:g>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="956.594173563644">
+ <text:p>956.594173563644</text:p>
+ <draw:g>
+ <svg:desc>Summary.B2:Summary.B2</svg:desc></draw:g>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row>
+ <table:table-cell office:value-type="string">
+ <text:p>Two</text:p>
+ <draw:g>
+ <svg:desc>Summary.A3:Summary.A3</svg:desc></draw:g>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="207.425649510697">
+ <text:p>207.425649510697</text:p>
+ <draw:g>
+ <svg:desc>Summary.B3:Summary.B3</svg:desc></draw:g>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row>
+ <table:table-cell office:value-type="string">
+ <text:p>Three</text:p>
+ <draw:g>
+ <svg:desc>Summary.A4:Summary.A4</svg:desc></draw:g>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="689.508363604546">
+ <text:p>689.508363604546</text:p>
+ <draw:g>
+ <svg:desc>Summary.B4:Summary.B4</svg:desc></draw:g>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row>
+ <table:table-cell office:value-type="string">
+ <text:p>Four</text:p>
+ <draw:g>
+ <svg:desc>Summary.A5:Summary.A5</svg:desc></draw:g>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="346.062566153705">
+ <text:p>346.062566153705</text:p>
+ <draw:g>
+ <svg:desc>Summary.B5:Summary.B5</svg:desc></draw:g>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row>
+ <table:table-cell office:value-type="string">
+ <text:p>Five</text:p>
+ <draw:g>
+ <svg:desc>Summary.A6:Summary.A6</svg:desc></draw:g>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="893.98120646365">
+ <text:p>893.98120646365</text:p>
+ <draw:g>
+ <svg:desc>Summary.B6:Summary.B6</svg:desc></draw:g>
+ </table:table-cell>
+ </table:table-row>
+ </table:table-rows>
+ </table:table>
+ </chart:chart>
+ </office:chart>
+ </office:body>
+ </office:document>
+ </draw:object><draw:image>
+ <office:binary-data>VkNMTVRGAQAxAAAAAAAAAAEAGwAAAAAAAAAAAAAAAAA7EwAAoA8AAPsIAAAIBwAAAIA+AAAo
+ IwAArQEAAIsAAQACAAAA//+BAAEAEAAAAAAAAAAAAAAAfz4AACcjAACLAAEAAgAAACAAggAB
+ ACEAAAACABsAAAACAAIAAAAAAAAAJyMAAAEAAAAAAH8+AAACAACVAAEABAAAAAAAAACWAAEA
+ AgAAAAkAhQABAAUAAAD///8AAYQAAQAFAAAAAAAAAABvAAIANgAAAAEABgBAHwAAKCMAAAAA
+ AAAoIwAAAAAAAAAAAACAPgAAAAAAAIA+AAAoIwAAQB8AACgjAAAAAIQAAQAFAAAAs7OzAAEA
+ AgEAjgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAG8AAAABAGkAAAABADMAAAAGAOEe
+ AABNHgAA+gcAAE0eAAD6BwAAHAQAAMc1AAAcBAAAxzUAAE0eAADhHgAATR4AAAABAAIAAAAA
+ AAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswAB
+ hQABAAUAAAAAAAAAAG0AAwBTAAAABgDhHgAATR4AAPoHAABNHgAA+gcAABwEAADHNQAAHAQA
+ AMc1AABNHgAA4R4AAE0eAAAEABoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAgEA
+ HQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAhAABAAUAAACzs7MAAQACAQBuAAAA
+ FQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAxzUAAEweAAD6
+ BwAATB4AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA
+ AACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwAzAAAAAgDHNQAATB4AAPoHAABMHgAA
+ BAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tF
+ X1NFUV9FTkQAAAAAAAAAAIQAAQAFAAAAs7OzAAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VR
+ X0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAMc1AACOGgAA+gcAAI4aAAAAAQACAAAAAAAB
+ AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAhAABAAUAAACzs7MAAYUA
+ AQAFAAAAAAAAAABtAAMAMwAAAAIAxzUAAI4aAAD6BwAAjhoAAAQAGgAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAEAAAAAAACAQAdAAAAEwBYUEFUSFNUUk9LRV9TRVFfRU5EAAAAAAAAAACE
+ AAEABQAAALOzswABAAIBAG4AAAAVAFhQQVRIU1RST0tFX1NFUV9CRUdJTgAAAABPAAAAAQBJ
+ AAAAAQATAAAAAgDHNQAA0BYAAPoHAADQFgAAAAEAAgAAAAAAAQACAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAABAAAAAAAAAAAAAAAAAIQAAQAFAAAAs7OzAAGFAAEABQAAAAAAAAAAbQADADMA
+ AAACAMc1AADQFgAA+gcAANAWAAAEABoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAA
+ AgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAhAABAAUAAACzs7MAAQACAQBu
+ AAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAxzUAABIT
+ AAD6BwAAEhMAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA
+ AAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwAzAAAAAgDHNQAAEhMAAPoHAAAS
+ EwAABAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAIBAB0AAAATAFhQQVRIU1RS
+ T0tFX1NFUV9FTkQAAAAAAAAAAIQAAQAFAAAAs7OzAAEAAgEAbgAAABUAWFBBVEhTVFJPS0Vf
+ U0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAMc1AABUDwAA+gcAAFQPAAAAAQACAAAA
+ AAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAhAABAAUAAACzs7MA
+ AYUAAQAFAAAAAAAAAABtAAMAMwAAAAIAxzUAAFQPAAD6BwAAVA8AAAQAGgAAAAEAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAEAAAAAAACAQAdAAAAEwBYUEFUSFNUUk9LRV9TRVFfRU5EAAAAAAAA
+ AACEAAEABQAAALOzswABAAIBAG4AAAAVAFhQQVRIU1RST0tFX1NFUV9CRUdJTgAAAABPAAAA
+ AQBJAAAAAQATAAAAAgDHNQAAlgsAAPoHAACWCwAAAAEAAgAAAAAAAQACAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAIQAAQAFAAAAs7OzAAGFAAEABQAAAAAAAAAAbQAD
+ ADMAAAACAMc1AACWCwAA+gcAAJYLAAAEABoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA
+ AAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAhAABAAUAAACzs7MAAQAC
+ AQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIAxzUA
+ ANgHAAD6BwAA2AcAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAA
+ AAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwAzAAAAAgDHNQAA2AcAAPoH
+ AADYBwAABAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAIBAB0AAAATAFhQQVRI
+ U1RST0tFX1NFUV9FTkQAAAAAAAAAAIQAAQAFAAAAs7OzAAEAAgEAbgAAABUAWFBBVEhTVFJP
+ S0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAMc1AAAbBAAA+gcAABsEAAAAAQAC
+ AAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAhAABAAUAAACz
+ s7MAAYUAAQAFAAAAAAAAAABtAAMAMwAAAAIAxzUAABsEAAD6BwAAGwQAAAQAGgAAAAEAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAEAAAAAAACAQAdAAAAEwBYUEFUSFNUUk9LRV9TRVFfRU5EAAAA
+ AAAAAACEAAEABQAAALOzswABAAIBAG4AAAAVAFhQQVRIU1RST0tFX1NFUV9CRUdJTgAAAABP
+ AAAAAQBJAAAAAQATAAAAAgD6BwAA4h4AAPoHAABMHgAAAAEAAgAAAAAAAQACAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAIQAAQAFAAAAs7OzAAGFAAEABQAAAAAAAAAA
+ bQADADMAAAACAPoHAADiHgAA+gcAAEweAAAEABoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ BAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAhAABAAUAAACzs7MA
+ AQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAAAAIA
+ +gcAAOIeAAD6BwAATB4AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwAzAAAAAgD6BwAA4h4A
+ APoHAABMHgAABAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAIBAB0AAAATAFhQ
+ QVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIQAAQAFAAAAs7OzAAEAAgEAbgAAABUAWFBBVEhT
+ VFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAMc1AADiHgAAxzUAAEweAAAA
+ AQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAhAABAAUA
+ AACzs7MAAYUAAQAFAAAAAAAAAABtAAMAMwAAAAIAxzUAAOIeAADHNQAATB4AAAQAGgAAAAEA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAACAQAdAAAAEwBYUEFUSFNUUk9LRV9TRVFfRU5E
+ AAAAAAAAAACEAAEABQAAALOzswABAAIBAG4AAAAVAFhQQVRIU1RST0tFX1NFUV9CRUdJTgAA
+ AABPAAAAAQBJAAAAAQATAAAAAgDHNQAA4h4AAMc1AABMHgAAAAEAAgAAAAAAAQACAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAIQAAQAFAAAAs7OzAAGFAAEABQAAAAAA
+ AAAAbQADADMAAAACAMc1AADiHgAAxzUAAEweAAAEABoAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAABAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAhAABAAUAAACz
+ s7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEAEwAA
+ AAIA+gcAAEweAADHNQAATB4AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwAzAAAAAgD6BwAA
+ TB4AAMc1AABMHgAABAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAIBAB0AAAAT
+ AFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIQAAQAFAAAAs7OzAAEAAgEAbgAAABUAWFBB
+ VEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAGQHAABMHgAA+gcAAEwe
+ AAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAhAAB
+ AAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAMwAAAAIAZAcAAEweAAD6BwAATB4AAAQAGgAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAACAQAdAAAAEwBYUEFUSFNUUk9LRV9TRVFf
+ RU5EAAAAAAAAAACEAAEABQAAALOzswABAAIBAG4AAAAVAFhQQVRIU1RST0tFX1NFUV9CRUdJ
+ TgAAAABPAAAAAQBJAAAAAQATAAAAAgBkBwAATB4AAPoHAABMHgAAAAEAAgAAAAAAAQACAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAIQAAQAFAAAAs7OzAAGFAAEABQAA
+ AAAAAAAAbQADADMAAAACAGQHAABMHgAA+gcAAEweAAAEABoAAAABAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAABAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAhAABAAUA
+ AACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAAAAEA
+ EwAAAAIAZAcAAI4aAAD6BwAAjhoAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwAzAAAAAgBk
+ BwAAjhoAAPoHAACOGgAABAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAIBAB0A
+ AAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIQAAQAFAAAAs7OzAAEAAgEAbgAAABUA
+ WFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAGQHAACOGgAA+gcA
+ AI4aAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAA
+ hAABAAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAMwAAAAIAZAcAAI4aAAD6BwAAjhoAAAQA
+ GgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAACAQAdAAAAEwBYUEFUSFNUUk9LRV9T
+ RVFfRU5EAAAAAAAAAACEAAEABQAAALOzswABAAIBAG4AAAAVAFhQQVRIU1RST0tFX1NFUV9C
+ RUdJTgAAAABPAAAAAQBJAAAAAQATAAAAAgBkBwAA0BYAAPoHAADQFgAAAAEAAgAAAAAAAQAC
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAIQAAQAFAAAAs7OzAAGFAAEA
+ BQAAAAAAAAAAbQADADMAAAACAGQHAADQFgAA+gcAANAWAAAEABoAAAABAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAABAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAAhAAB
+ AAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEASQAA
+ AAEAEwAAAAIAZAcAANAWAAD6BwAA0BYAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwAzAAAA
+ AgBkBwAA0BYAAPoHAADQFgAABAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAIB
+ AB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIQAAQAFAAAAs7OzAAEAAgEAbgAA
+ ABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAGQHAAASEwAA
+ +gcAABITAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAA
+ AAAAhAABAAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAMwAAAAIAZAcAABITAAD6BwAAEhMA
+ AAQAGgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAACAQAdAAAAEwBYUEFUSFNUUk9L
+ RV9TRVFfRU5EAAAAAAAAAACEAAEABQAAALOzswABAAIBAG4AAAAVAFhQQVRIU1RST0tFX1NF
+ UV9CRUdJTgAAAABPAAAAAQBJAAAAAQATAAAAAgBkBwAAEhMAAPoHAAASEwAAAAEAAgAAAAAA
+ AQACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAIQAAQAFAAAAs7OzAAGF
+ AAEABQAAAAAAAAAAbQADADMAAAACAGQHAAASEwAA+gcAABITAAAEABoAAAABAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAABAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAAAAAA
+ hAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAAAAEA
+ SQAAAAEAEwAAAAIAZAcAAFQPAAD6BwAAVA8AAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0AAwAz
+ AAAAAgBkBwAAVA8AAPoHAABUDwAABAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA
+ AAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIQAAQAFAAAAs7OzAAEAAgEA
+ bgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAGQHAABU
+ DwAA+gcAAFQPAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAA
+ AAAAAAAAhAABAAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAMwAAAAIAZAcAAFQPAAD6BwAA
+ VA8AAAQAGgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAACAQAdAAAAEwBYUEFUSFNU
+ Uk9LRV9TRVFfRU5EAAAAAAAAAACEAAEABQAAALOzswABAAIBAG4AAAAVAFhQQVRIU1RST0tF
+ X1NFUV9CRUdJTgAAAABPAAAAAQBJAAAAAQATAAAAAgBkBwAAlgsAAPoHAACWCwAAAAEAAgAA
+ AAAAAQACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAIQAAQAFAAAAs7Oz
+ AAGFAAEABQAAAAAAAAAAbQADADMAAAACAGQHAACWCwAA+gcAAJYLAAAEABoAAAABAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAABAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAAAAAA
+ AAAAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAATwAA
+ AAEASQAAAAEAEwAAAAIAZAcAAJYLAAD6BwAAlgsAAAABAAIAAAAAAAEAAgAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAAAG0A
+ AwAzAAAAAgBkBwAAlgsAAPoHAACWCwAABAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA
+ AAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIQAAQAFAAAAs7OzAAEA
+ AgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAACAGQH
+ AADYBwAA+gcAANgHAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAA
+ AAAAAAAAAAAAhAABAAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAMwAAAAIAZAcAANgHAAD6
+ BwAA2AcAAAQAGgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAACAQAdAAAAEwBYUEFU
+ SFNUUk9LRV9TRVFfRU5EAAAAAAAAAACEAAEABQAAALOzswABAAIBAG4AAAAVAFhQQVRIU1RS
+ T0tFX1NFUV9CRUdJTgAAAABPAAAAAQBJAAAAAQATAAAAAgBkBwAA2AcAAPoHAADYBwAAAAEA
+ AgAAAAAAAQACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAIQAAQAFAAAA
+ s7OzAAGFAAEABQAAAAAAAAAAbQADADMAAAACAGQHAADYBwAA+gcAANgHAAAEABoAAAABAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VORAAA
+ AAAAAAAAhAABAAUAAACzs7MAAQACAQBuAAAAFQBYUEFUSFNUUk9LRV9TRVFfQkVHSU4AAAAA
+ TwAAAAEASQAAAAEAEwAAAAIAZAcAABsEAAD6BwAAGwQAAAABAAIAAAAAAAEAAgAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAACEAAEABQAAALOzswABhQABAAUAAAAAAAAA
+ AG0AAwAzAAAAAgBkBwAAGwQAAPoHAAAbBAAABAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAQAAAAAAAIBAB0AAAATAFhQQVRIU1RST0tFX1NFUV9FTkQAAAAAAAAAAIQAAQAFAAAAs7Oz
+ AAEAAgEAbgAAABUAWFBBVEhTVFJPS0VfU0VRX0JFR0lOAAAAAE8AAAABAEkAAAABABMAAAAC
+ AGQHAAAbBAAA+gcAABsEAAAAAQACAAAAAAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA
+ AAAAAAAAAAAAAAAAhAABAAUAAACzs7MAAYUAAQAFAAAAAAAAAABtAAMAMwAAAAIAZAcAABsE
+ AAD6BwAAGwQAAAQAGgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAACAQAdAAAAEwBY
+ UEFUSFNUUk9LRV9TRVFfRU5EAAAAAAAAAACEAAEABQAAALOzswABAAIBAG4AAAAVAFhQQVRI
+ U1RST0tFX1NFUV9CRUdJTgAAAABPAAAAAQBJAAAAAQATAAAAAgD6BwAATB4AAPoHAAAbBAAA
+ AAEAAgAAAAAAAQACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAIQAAQAF
+ AAAAs7OzAAGFAAEABQAAAAAAAAAAbQADADMAAAACAPoHAABMHgAA+gcAABsEAAAEABoAAAAB
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAgEAHQAAABMAWFBBVEhTVFJPS0VfU0VRX0VO
+ RAAAAAAAAAAAhQABAAUAAACGRQAAAYQAAQAFAAAAAAAAAABvAAIALgAAAAEABQBtEwAATB4A
+ AFMqAABMHgAAUyoAACMXAABtEwAAIxcAAG0TAABMHgAAAACFAAEABQAAAA5C/wABhAABAAUA
+ AAAAAAAAAG8AAgAuAAAAAQAFAG0TAAAjFwAAUyoAACMXAABTKgAAlhUAAG0TAACWFQAAbRMA
+ ACMXAAAAAIUAAQAFAAAAINP/AAGEAAEABQAAAAAAAAAAbwACAC4AAAABAAUAbRMAAJYVAABT
+ KgAAlhUAAFMqAABtEAAAbRMAAG0QAABtEwAAlhUAAAAAhQABAAUAAAAcnVcAAYQAAQAFAAAA
+ AAAAAABvAAIALgAAAAEABQBtEwAAbRAAAFMqAABtEAAAUyoAANYNAABtEwAA1g0AAG0TAABt
+ EAAAAACFAAEABQAAACEAfgABhAABAAUAAAAAAAAAAG8AAgAuAAAAAQAFAG0TAADWDQAAUyoA
+ ANYNAABTKgAAJQcAAG0TAAAlBwAAbRMAANYNAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlOVFNI
+ QVBFX0JFR0lOAAAAAAAAAACKAAEAQQAAAAMAOwAAAA8ATGliZXJhdGlvbiBTYW5zAAAAAAAA
+ YQEAAP//AAACAAUAAAAAAAAACQgAAAAAAAAAAAD/AwAAAAAAiAABAAIAAAABAIcAAQAFAAAA
+ /////wCGAAEABAAAAAAAAABxAAIANgAAACQdAACAIAAABAAAAFMAbwBtAGUAAAAEAAQAAADs
+ AAAAowEAAMMCAAB6AwAABABTAG8AbQBlAAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAAC
+ AQATAAAACQBYVEVYVF9FT0MBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MCAAAAAAAAAAAC
+ AQATAAAACQBYVEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAAC
+ AQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VO
+ RAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAIoAAQBB
+ AAAAAwA7AAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJCAAA
+ AAAAAAAAAP8DAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEAAgAm
+ AAAAkQUAAMMeAAACAAAAowAwAAAAAgACAAAAtwAAAG8BAAACAKMAMAAAAgEAEwAAAAkAWFRF
+ WFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRF
+ WFRfRU9XAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRF
+ WFRfRU9QAAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAAAC
+ AQAgAAAAFgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lOAAAAAAAAAACKAAEAQQAAAAMAOwAAAA8A
+ TGliZXJhdGlvbiBTYW5zAAAAAAAAYQEAAP//AAACAAUAAAAAAAAACQgAAAAAAAAAAAD/AwAA
+ AAAAiAABAAIAAAABAIcAAQAFAAAA/////wCGAAEABAAAAAAAAABxAAIANgAAACMEAAAFGwAA
+ BAAAAKMANQAwADAAAAAEAAQAAAC3AAAAbwEAACYCAADdAgAABACjADUAMAAwAAACAQATAAAA
+ CQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MBAAAAAAAAAAACAQATAAAA
+ CQBYVEVYVF9FT1cBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MCAAAAAAAAAAACAQATAAAA
+ CQBYVEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAA
+ CQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAA
+ AAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAIoAAQBBAAAAAwA7
+ AAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJCAAAAAAAAAAA
+ AP8DAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEAAgBGAAAAAwMA
+ AEcXAAAGAAAAowAxACwAMAAwADAAAAAGAAYAAAC3AAAAbwEAANcBAACPAgAARgMAAP0DAAAG
+ AKMAMQAsADAAMAAwAAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVY
+ VF9FT0MBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1cBAAAAAAAAAAACAQATAAAACQBYVEVY
+ VF9FT0MCAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVY
+ VF9FT0MEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MFAAAAAAAAAAACAQATAAAACQBYVEVY
+ VF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVY
+ VF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVH
+ SU4AAAAAAAAAAIoAAQBBAAAAAwA7AAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8A
+ AAIABQAAAAAAAAAJCAAAAAAAAAAAAP8DAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYA
+ AQAEAAAAAAAAAHEAAgBGAAAAAwMAAIkTAAAGAAAAowAxACwANQAwADAAAAAGAAYAAAC3AAAA
+ bwEAANcBAACPAgAARgMAAP0DAAAGAKMAMQAsADUAMAAwAAACAQATAAAACQBYVEVYVF9FT0MA
+ AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1cB
+ AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MCAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MD
+ AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MF
+ AAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AA
+ AAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAAAAAW
+ AFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAIoAAQBBAAAAAwA7AAAADwBMaWJlcmF0
+ aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJCAAAAAAAAAAAAP8DAAAAAACIAAEA
+ AgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEAAgBGAAAAAwMAAMsPAAAGAAAAowAy
+ ACwAMAAwADAAAAAGAAYAAAC3AAAAbwEAANcBAACPAgAARgMAAP0DAAAGAKMAMgAsADAAMAAw
+ AAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MBAAAAAAAA
+ AAACAQATAAAACQBYVEVYVF9FT1cBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MCAAAAAAAA
+ AAACAQATAAAACQBYVEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MEAAAAAAAA
+ AAACAQATAAAACQBYVEVYVF9FT0MFAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAA
+ AAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBF
+ X0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAIoA
+ AQBBAAAAAwA7AAAADwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJ
+ CAAAAAAAAAAAAP8DAAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEA
+ AgBGAAAAAwMAAA0MAAAGAAAAowAyACwANQAwADAAAAAGAAYAAAC3AAAAbwEAANcBAACPAgAA
+ RgMAAP0DAAAGAKMAMgAsADUAMAAwAAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQAT
+ AAAACQBYVEVYVF9FT0MBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1cBAAAAAAAAAAACAQAT
+ AAAACQBYVEVYVF9FT0MCAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MDAAAAAAAAAAACAQAT
+ AAAACQBYVEVYVF9FT0MEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MFAAAAAAAAAAACAQAT
+ AAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAe
+ AAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhUX1BBSU5U
+ U0hBUEVfQkVHSU4AAAAAAAAAAIoAAQBBAAAAAwA7AAAADwBMaWJlcmF0aW9uIFNhbnMAAAAA
+ AABhAQAA//8AAAIABQAAAAAAAAAJCAAAAAAAAAAAAP8DAAAAAACIAAEAAgAAAAEAhwABAAUA
+ AAD/////AIYAAQAEAAAAAAAAAHEAAgBGAAAAAwMAAE8IAAAGAAAAowAzACwAMAAwADAAAAAG
+ AAYAAAC3AAAAbwEAANcBAACPAgAARgMAAP0DAAAGAKMAMwAsADAAMAAwAAACAQATAAAACQBY
+ VEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MBAAAAAAAAAAACAQATAAAACQBY
+ VEVYVF9FT1cBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MCAAAAAAAAAAACAQATAAAACQBY
+ VEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MEAAAAAAAAAAACAQATAAAACQBY
+ VEVYVF9FT0MFAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBY
+ VEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAA
+ AAIBACAAAAAWAFhURVhUX1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAIoAAQBBAAAAAwA7AAAA
+ DwBMaWJlcmF0aW9uIFNhbnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJCAAAAAAAAAAAAP8D
+ AAAAAACIAAEAAgAAAAEAhwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEAAgBGAAAAAwMAAJIE
+ AAAGAAAAowAzACwANQAwADAAAAAGAAYAAAC3AAAAbwEAANcBAACPAgAARgMAAP0DAAAGAKMA
+ MwAsADUAMAAwAAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9F
+ T0MBAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1cBAAAAAAAAAAACAQATAAAACQBYVEVYVF9F
+ T0MCAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MDAAAAAAAAAAACAQATAAAACQBYVEVYVF9F
+ T0MEAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MFAAAAAAAAAAACAQATAAAACQBYVEVYVF9F
+ T0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAAAAACAQAeAAAAFABYVEVYVF9Q
+ QUlOVFNIQVBFX0VORAAAAAAAAAAAhQABAAUAAACGRQAAAYQAAQAFAAAAAAAAAABvAAIANgAA
+ AAEABgAlOQAA2RUAALs4AADZFQAAuzgAAAYVAACOOQAABhUAAI45AADZFQAAJTkAANkVAAAA
+ AIUAAQAFAAAADkL/AAGEAAEABQAAAAAAAAAAbwACADYAAAABAAYAJTkAAOsTAAC7OAAA6xMA
+ ALs4AAAYEwAAjjkAABgTAACOOQAA6xMAACU5AADrEwAAAACFAAEABQAAACDT/wABhAABAAUA
+ AAAAAAAAAG8AAgA2AAAAAQAGACU5AAD9EQAAuzgAAP0RAAC7OAAAKhEAAI45AAAqEQAAjjkA
+ AP0RAAAlOQAA/REAAAAAhQABAAUAAAAcnVcAAYQAAQAFAAAAAAAAAABvAAIANgAAAAEABgAl
+ OQAADxAAALs4AAAPEAAAuzgAADwPAACOOQAAPA8AAI45AAAPEAAAJTkAAA8QAAAAAIUAAQAF
+ AAAAIQB+AAGEAAEABQAAAAAAAAAAbwACADYAAAABAAYAJTkAACEOAAC7OAAAIQ4AALs4AABO
+ DQAAjjkAAE4NAACOOQAAIQ4AACU5AAAhDgAAAAAAAgEAIAAAABYAWFRFWFRfUEFJTlRTSEFQ
+ RV9CRUdJTgAAAAAAAAAAigABAEEAAAADADsAAAAPAExpYmVyYXRpb24gU2FucwAAAAAAAGEB
+ AAD//wAAAgAFAAAAAAAAAAkIAAAAAAAAAAAA/wMAAAAAAIgAAQACAAAAAQCHAAEABQAAAP//
+ //8AhgABAAQAAAAAAAAAcQACADYAAADyOQAALQ4AAAQAAABGAGkAdgBlAAAABAAEAAAA0QAA
+ ACABAACjAQAAWgIAAAQARgBpAHYAZQAAAgEAEwAAAAkAWFRFWFRfRU9DAAAAAAAAAAAAAgEA
+ EwAAAAkAWFRFWFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAgAAAAAAAAAAAgEA
+ EwAAAAkAWFRFWFRfRU9DAwAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAAAgEA
+ EwAAAAkAWFRFWFRfRU9QAAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJTlRTSEFQRV9FTkQA
+ AAAAAAAAAAACAQAgAAAAFgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lOAAAAAAAAAACKAAEAQQAA
+ AAMAOwAAAA8ATGliZXJhdGlvbiBTYW5zAAAAAAAAYQEAAP//AAACAAUAAAAAAAAACQgAAAAA
+ AAAAAAD/AwAAAAAAiAABAAIAAAABAIcAAQAFAAAA/////wCGAAEABAAAAAAAAABxAAIANgAA
+ API5AAAbEAAABAAAAEYAbwB1AHIAAAAEAAQAAADRAAAAiQEAAEACAACpAgAABABGAG8AdQBy
+ AAACAQATAAAACQBYVEVYVF9FT0MAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MBAAAAAAAA
+ AAACAQATAAAACQBYVEVYVF9FT0MCAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT0MDAAAAAAAA
+ AAACAQATAAAACQBYVEVYVF9FT0wAAAAAAAAAAAACAQATAAAACQBYVEVYVF9FT1AAAAAAAAAA
+ AAACAQAeAAAAFABYVEVYVF9QQUlOVFNIQVBFX0VORAAAAAAAAAAAAAIBACAAAAAWAFhURVhU
+ X1BBSU5UU0hBUEVfQkVHSU4AAAAAAAAAAIoAAQBBAAAAAwA7AAAADwBMaWJlcmF0aW9uIFNh
+ bnMAAAAAAABhAQAA//8AAAIABQAAAAAAAAAJCAAAAAAAAAAAAP8DAAAAAACIAAEAAgAAAAEA
+ hwABAAUAAAD/////AIYAAQAEAAAAAAAAAHEAAgA+AAAA8jkAAAkSAAAFAAAAVABoAHIAZQBl
+ AAAABQAFAAAAtwAAAG8BAADXAQAAjwIAAEYDAAAFAFQAaAByAGUAZQAAAgEAEwAAAAkAWFRF
+ WFRfRU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRF
+ WFRfRU9DAgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAwAAAAAAAAAAAgEAEwAAAAkAWFRF
+ WFRfRU9DBAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRF
+ WFRfRU9QAAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAAAC
+ AQAgAAAAFgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lOAAAAAAAAAACKAAEAQQAAAAMAOwAAAA8A
+ TGliZXJhdGlvbiBTYW5zAAAAAAAAYQEAAP//AAACAAUAAAAAAAAACQgAAAAAAAAAAAD/AwAA
+ AAAAiAABAAIAAAABAIcAAQAFAAAA/////wCGAAEABAAAAAAAAABxAAIALgAAAPI5AAD3EwAA
+ AwAAAFQAdwBvAAAAAwADAAAAnQAAAIkBAABAAgAAAwBUAHcAbwAAAgEAEwAAAAkAWFRFWFRf
+ RU9DAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRf
+ RU9DAgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRf
+ RU9QAAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAAACAQAg
+ AAAAFgBYVEVYVF9QQUlOVFNIQVBFX0JFR0lOAAAAAAAAAACKAAEAQQAAAAMAOwAAAA8ATGli
+ ZXJhdGlvbiBTYW5zAAAAAAAAYQEAAP//AAACAAUAAAAAAAAACQgAAAAAAAAAAAD/AwAAAAAA
+ iAABAAIAAAABAIcAAQAFAAAA/////wCGAAEABAAAAAAAAABxAAIALgAAAPI5AADlFQAAAwAA
+ AE8AbgBlAAAAAwADAAAABgEAAL0BAAB0AgAAAwBPAG4AZQAAAgEAEwAAAAkAWFRFWFRfRU9D
+ AAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9DAQAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9D
+ AgAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9MAAAAAAAAAAAAAgEAEwAAAAkAWFRFWFRfRU9Q
+ AAAAAAAAAAAAAgEAHgAAABQAWFRFWFRfUEFJTlRTSEFQRV9FTkQAAAAAAAAAAIwAAQAAAAAA
+ iwABAAIAAAAgAIIAAQAhAAAAAgAbAAAAAgACAAAAAAAAACcjAAABAAAAAAB/PgAAAgAAjAAB
+ AAAAAACMAAEAAAAAAA==
+ </office:binary-data>
+ </draw:image>
+ </draw:frame></table:shapes>
+ <table:table-column table:style-name="co1" table:default-cell-style-name="Default"/>
+ <table:table-column table:style-name="co1" table:number-columns-repeated="2" table:default-cell-style-name="ce2"/>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell table:style-name="ce1" office:value-type="string">
+ <text:p>Summary</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="ce1" office:value-type="string">
+ <text:p>Some</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="ce1"/>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="string">
+ <text:p>One</text:p>
+ </table:table-cell>
+ <table:table-cell table:formula="of:=[Data.A1]" office:value-type="currency" office:currency="GBP" office:value="956.594173563644">
+ <text:p>£957</text:p>
+ </table:table-cell>
+ <table:table-cell/>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="string">
+ <text:p>Two</text:p>
+ </table:table-cell>
+ <table:table-cell table:formula="of:=[Data.A2]" office:value-type="currency" office:currency="GBP" office:value="207.425649510697">
+ <text:p>£207</text:p>
+ </table:table-cell>
+ <table:table-cell/>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="string">
+ <text:p>Three</text:p>
+ </table:table-cell>
+ <table:table-cell table:formula="of:=[Data.A3]" office:value-type="currency" office:currency="GBP" office:value="689.508363604546">
+ <text:p>£690</text:p>
+ </table:table-cell>
+ <table:table-cell/>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="string">
+ <text:p>Four</text:p>
+ </table:table-cell>
+ <table:table-cell table:formula="of:=[Data.A4]" office:value-type="currency" office:currency="GBP" office:value="346.062566153705">
+ <text:p>£346</text:p>
+ </table:table-cell>
+ <table:table-cell/>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="string">
+ <text:p>Five</text:p>
+ </table:table-cell>
+ <table:table-cell table:formula="of:=[Data.A5]" office:value-type="currency" office:currency="GBP" office:value="893.98120646365">
+ <text:p>£894</text:p>
+ </table:table-cell>
+ <table:table-cell/>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell/>
+ <table:table-cell table:style-name="Default" table:number-columns-repeated="2"/>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell table:style-name="ce1" office:value-type="string">
+ <text:p>To reproduce bug:</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Default" table:number-columns-repeated="2"/>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell/>
+ <table:table-cell table:style-name="Default" office:value-type="string">
+ <text:p>Save as Flat ODS: extension &apos;.fods&apos;</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Default"/>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell/>
+ <table:table-cell table:style-name="Default" office:value-type="string">
+ <text:p>Reload … bingo …</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="Default"/>
+ </table:table-row>
+ </table:table>
+ <table:table table:name="Data" table:style-name="ta1">
+ <table:table-column table:style-name="co1" table:number-columns-repeated="2" table:default-cell-style-name="Default"/>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="float" office:value="956.594173563644">
+ <text:p>956.5941735636</text:p>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="573.410327779129">
+ <text:p>573.4103277791</text:p>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="float" office:value="207.425649510697">
+ <text:p>207.4256495107</text:p>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="604.592139367014">
+ <text:p>604.592139367</text:p>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="float" office:value="689.508363604546">
+ <text:p>689.5083636045</text:p>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="44.302029768005">
+ <text:p>44.302029768</text:p>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="float" office:value="346.062566153705">
+ <text:p>346.0625661537</text:p>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="835.630784509704">
+ <text:p>835.6307845097</text:p>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="float" office:value="893.98120646365">
+ <text:p>893.9812064637</text:p>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="220.445565413684">
+ <text:p>220.4455654137</text:p>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell office:value-type="float" office:value="140.184764517471">
+ <text:p>140.1847645175</text:p>
+ </table:table-cell>
+ <table:table-cell office:value-type="float" office:value="130.774514051154">
+ <text:p>130.7745140512</text:p>
+ </table:table-cell>
+ </table:table-row>
+ </table:table>
+ <table:named-expressions/>
+ </office:spreadsheet>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/chart2/qa/extras/data/odp/BarChartVeryLongLabel.odp b/chart2/qa/extras/data/odp/BarChartVeryLongLabel.odp
new file mode 100644
index 0000000000..c627af79e4
--- /dev/null
+++ b/chart2/qa/extras/data/odp/BarChartVeryLongLabel.odp
Binary files differ
diff --git a/chart2/qa/extras/data/odp/chart.odp b/chart2/qa/extras/data/odp/chart.odp
new file mode 100644
index 0000000000..81a5f56b27
--- /dev/null
+++ b/chart2/qa/extras/data/odp/chart.odp
Binary files differ
diff --git a/chart2/qa/extras/data/odp/ellipticalGradientFill.odp b/chart2/qa/extras/data/odp/ellipticalGradientFill.odp
new file mode 100644
index 0000000000..754f439e58
--- /dev/null
+++ b/chart2/qa/extras/data/odp/ellipticalGradientFill.odp
Binary files differ
diff --git a/chart2/qa/extras/data/odp/tdf119029.odp b/chart2/qa/extras/data/odp/tdf119029.odp
new file mode 100644
index 0000000000..87e4a03c84
--- /dev/null
+++ b/chart2/qa/extras/data/odp/tdf119029.odp
Binary files differ
diff --git a/chart2/qa/extras/data/odp/tdf121189.odp b/chart2/qa/extras/data/odp/tdf121189.odp
new file mode 100644
index 0000000000..6f99e00549
--- /dev/null
+++ b/chart2/qa/extras/data/odp/tdf121189.odp
Binary files differ
diff --git a/chart2/qa/extras/data/odp/tdf123206.odp b/chart2/qa/extras/data/odp/tdf123206.odp
new file mode 100644
index 0000000000..1975756bce
--- /dev/null
+++ b/chart2/qa/extras/data/odp/tdf123206.odp
Binary files differ
diff --git a/chart2/qa/extras/data/odp/tdf128345_ChartArea_CG_TS.odp b/chart2/qa/extras/data/odp/tdf128345_ChartArea_CG_TS.odp
new file mode 100644
index 0000000000..754e71d512
--- /dev/null
+++ b/chart2/qa/extras/data/odp/tdf128345_ChartArea_CG_TS.odp
Binary files differ
diff --git a/chart2/qa/extras/data/odp/tdf128345_ChartWall_CS_TG.odp b/chart2/qa/extras/data/odp/tdf128345_ChartWall_CS_TG.odp
new file mode 100644
index 0000000000..4c09ebb7bb
--- /dev/null
+++ b/chart2/qa/extras/data/odp/tdf128345_ChartWall_CS_TG.odp
Binary files differ
diff --git a/chart2/qa/extras/data/odp/tdf128345_Legend_CS_TG_axial.odp b/chart2/qa/extras/data/odp/tdf128345_Legend_CS_TG_axial.odp
new file mode 100644
index 0000000000..bfcd8a5dd5
--- /dev/null
+++ b/chart2/qa/extras/data/odp/tdf128345_Legend_CS_TG_axial.odp
Binary files differ
diff --git a/chart2/qa/extras/data/ods/ErrorBarRange.ods b/chart2/qa/extras/data/ods/ErrorBarRange.ods
new file mode 100644
index 0000000000..28e6aeeddb
--- /dev/null
+++ b/chart2/qa/extras/data/ods/ErrorBarRange.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/PivotChartRoundTrip.ods b/chart2/qa/extras/data/ods/PivotChartRoundTrip.ods
new file mode 100644
index 0000000000..c34521e0bc
--- /dev/null
+++ b/chart2/qa/extras/data/ods/PivotChartRoundTrip.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/PivotTableExample.ods b/chart2/qa/extras/data/ods/PivotTableExample.ods
new file mode 100644
index 0000000000..bc8df81702
--- /dev/null
+++ b/chart2/qa/extras/data/ods/PivotTableExample.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/axis-numformats-linked.ods b/chart2/qa/extras/data/ods/axis-numformats-linked.ods
new file mode 100644
index 0000000000..ddaa9c9014
--- /dev/null
+++ b/chart2/qa/extras/data/ods/axis-numformats-linked.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/axis_number_format.ods b/chart2/qa/extras/data/ods/axis_number_format.ods
new file mode 100644
index 0000000000..52e979a490
--- /dev/null
+++ b/chart2/qa/extras/data/ods/axis_number_format.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/chart.ods b/chart2/qa/extras/data/ods/chart.ods
new file mode 100644
index 0000000000..2a9916aca0
--- /dev/null
+++ b/chart2/qa/extras/data/ods/chart.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/chartWithDotInSheetName.ods b/chart2/qa/extras/data/ods/chartWithDotInSheetName.ods
new file mode 100644
index 0000000000..873d45f4be
--- /dev/null
+++ b/chart2/qa/extras/data/ods/chartWithDotInSheetName.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/combined_chart_secondary_axis.ods b/chart2/qa/extras/data/ods/combined_chart_secondary_axis.ods
new file mode 100644
index 0000000000..d125bc23d3
--- /dev/null
+++ b/chart2/qa/extras/data/ods/combined_chart_secondary_axis.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/error_bar.ods b/chart2/qa/extras/data/ods/error_bar.ods
new file mode 100644
index 0000000000..9c3adbbca8
--- /dev/null
+++ b/chart2/qa/extras/data/ods/error_bar.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/error_bar_properties.ods b/chart2/qa/extras/data/ods/error_bar_properties.ods
new file mode 100644
index 0000000000..056be88b22
--- /dev/null
+++ b/chart2/qa/extras/data/ods/error_bar_properties.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/error_bar_range.ods b/chart2/qa/extras/data/ods/error_bar_range.ods
new file mode 100644
index 0000000000..27a0103e57
--- /dev/null
+++ b/chart2/qa/extras/data/ods/error_bar_range.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/fdo60083.ods b/chart2/qa/extras/data/ods/fdo60083.ods
new file mode 100644
index 0000000000..74704f6185
--- /dev/null
+++ b/chart2/qa/extras/data/ods/fdo60083.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/labelString.ods b/chart2/qa/extras/data/ods/labelString.ods
new file mode 100644
index 0000000000..2b7e03c8eb
--- /dev/null
+++ b/chart2/qa/extras/data/ods/labelString.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/legend_overlay.ods b/chart2/qa/extras/data/ods/legend_overlay.ods
new file mode 100644
index 0000000000..fade626405
--- /dev/null
+++ b/chart2/qa/extras/data/ods/legend_overlay.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/moving-type.ods b/chart2/qa/extras/data/ods/moving-type.ods
new file mode 100644
index 0000000000..8a8568cfa7
--- /dev/null
+++ b/chart2/qa/extras/data/ods/moving-type.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/multilevelcat.ods b/chart2/qa/extras/data/ods/multilevelcat.ods
new file mode 100644
index 0000000000..76b140a879
--- /dev/null
+++ b/chart2/qa/extras/data/ods/multilevelcat.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/multiple_axis.ods b/chart2/qa/extras/data/ods/multiple_axis.ods
new file mode 100644
index 0000000000..7e2a505ccb
--- /dev/null
+++ b/chart2/qa/extras/data/ods/multiple_axis.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/pie_chart_100_and_0.ods b/chart2/qa/extras/data/ods/pie_chart_100_and_0.ods
new file mode 100644
index 0000000000..a6ff5d6aa0
--- /dev/null
+++ b/chart2/qa/extras/data/ods/pie_chart_100_and_0.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/secondary_axis.ods b/chart2/qa/extras/data/ods/secondary_axis.ods
new file mode 100644
index 0000000000..3f8f269c0f
--- /dev/null
+++ b/chart2/qa/extras/data/ods/secondary_axis.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/ser_labels.ods b/chart2/qa/extras/data/ods/ser_labels.ods
new file mode 100644
index 0000000000..c7bd966382
--- /dev/null
+++ b/chart2/qa/extras/data/ods/ser_labels.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/smoothedLines.ods b/chart2/qa/extras/data/ods/smoothedLines.ods
new file mode 100644
index 0000000000..725827e639
--- /dev/null
+++ b/chart2/qa/extras/data/ods/smoothedLines.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/stepped_lines.ods b/chart2/qa/extras/data/ods/stepped_lines.ods
new file mode 100644
index 0000000000..23d443ab5d
--- /dev/null
+++ b/chart2/qa/extras/data/ods/stepped_lines.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf101894.ods b/chart2/qa/extras/data/ods/tdf101894.ods
new file mode 100644
index 0000000000..70d8b3a0dd
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf101894.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf107097.ods b/chart2/qa/extras/data/ods/tdf107097.ods
new file mode 100644
index 0000000000..efa9f1c013
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf107097.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf108021.ods b/chart2/qa/extras/data/ods/tdf108021.ods
new file mode 100644
index 0000000000..ebbc5e56f2
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf108021.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf120348.ods b/chart2/qa/extras/data/ods/tdf120348.ods
new file mode 100644
index 0000000000..7a593c1bff
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf120348.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf123774.ods b/chart2/qa/extras/data/ods/tdf123774.ods
new file mode 100644
index 0000000000..5c422b58c3
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf123774.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf128432.ods b/chart2/qa/extras/data/ods/tdf128432.ods
new file mode 100644
index 0000000000..a93822fc9b
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf128432.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf131115.ods b/chart2/qa/extras/data/ods/tdf131115.ods
new file mode 100644
index 0000000000..76a87c2c22
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf131115.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf131979.ods b/chart2/qa/extras/data/ods/tdf131979.ods
new file mode 100644
index 0000000000..3dfcf6b699
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf131979.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf132076.ods b/chart2/qa/extras/data/ods/tdf132076.ods
new file mode 100644
index 0000000000..348dd0d71f
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf132076.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf135366_data_label_series.ods b/chart2/qa/extras/data/ods/tdf135366_data_label_series.ods
new file mode 100644
index 0000000000..e7c1f7d89d
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf135366_data_label_series.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf136011.ods b/chart2/qa/extras/data/ods/tdf136011.ods
new file mode 100644
index 0000000000..03a0a7dd63
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf136011.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf136024.ods b/chart2/qa/extras/data/ods/tdf136024.ods
new file mode 100644
index 0000000000..c8d004f544
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf136024.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf146066.ods b/chart2/qa/extras/data/ods/tdf146066.ods
new file mode 100644
index 0000000000..03abe9ae68
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf146066.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf146463.ods b/chart2/qa/extras/data/ods/tdf146463.ods
new file mode 100644
index 0000000000..6214f4a500
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf146463.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf148142.ods b/chart2/qa/extras/data/ods/tdf148142.ods
new file mode 100644
index 0000000000..9b736a06d1
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf148142.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf151091.ods b/chart2/qa/extras/data/ods/tdf151091.ods
new file mode 100644
index 0000000000..b3a43b3cea
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf151091.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf158223.ods b/chart2/qa/extras/data/ods/tdf158223.ods
new file mode 100644
index 0000000000..33a7169744
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf158223.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf59857.ods b/chart2/qa/extras/data/ods/tdf59857.ods
new file mode 100644
index 0000000000..e60e9c4c12
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf59857.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf62057.ods b/chart2/qa/extras/data/ods/tdf62057.ods
new file mode 100644
index 0000000000..3945c41d03
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf62057.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf64224.ods b/chart2/qa/extras/data/ods/tdf64224.ods
new file mode 100644
index 0000000000..e60e9c4c12
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf64224.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf72776.ods b/chart2/qa/extras/data/ods/tdf72776.ods
new file mode 100644
index 0000000000..4ddad64a5e
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf72776.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf86624.ods b/chart2/qa/extras/data/ods/tdf86624.ods
new file mode 100644
index 0000000000..05702371a1
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf86624.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/tdf96161.ods b/chart2/qa/extras/data/ods/tdf96161.ods
new file mode 100644
index 0000000000..797a712a74
--- /dev/null
+++ b/chart2/qa/extras/data/ods/tdf96161.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/testChartMainWithSubTitle.ods b/chart2/qa/extras/data/ods/testChartMainWithSubTitle.ods
new file mode 100644
index 0000000000..5ae4fa7d99
--- /dev/null
+++ b/chart2/qa/extras/data/ods/testChartMainWithSubTitle.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/testChartSubTitle.ods b/chart2/qa/extras/data/ods/testChartSubTitle.ods
new file mode 100644
index 0000000000..1c7814195d
--- /dev/null
+++ b/chart2/qa/extras/data/ods/testChartSubTitle.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/testColorGradientWithTransparency.ods b/chart2/qa/extras/data/ods/testColorGradientWithTransparency.ods
new file mode 100644
index 0000000000..d8a41c02c1
--- /dev/null
+++ b/chart2/qa/extras/data/ods/testColorGradientWithTransparency.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/test_CrossBetween.ods b/chart2/qa/extras/data/ods/test_CrossBetween.ods
new file mode 100644
index 0000000000..e59546b3d0
--- /dev/null
+++ b/chart2/qa/extras/data/ods/test_CrossBetween.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/trend_calculators.ods b/chart2/qa/extras/data/ods/trend_calculators.ods
new file mode 100644
index 0000000000..fdc5ea42dc
--- /dev/null
+++ b/chart2/qa/extras/data/ods/trend_calculators.ods
Binary files differ
diff --git a/chart2/qa/extras/data/ods/trendline.ods b/chart2/qa/extras/data/ods/trendline.ods
new file mode 100644
index 0000000000..707d510203
--- /dev/null
+++ b/chart2/qa/extras/data/ods/trendline.ods
Binary files differ
diff --git a/chart2/qa/extras/data/odt/axis-position.odt b/chart2/qa/extras/data/odt/axis-position.odt
new file mode 100644
index 0000000000..35ea152aa0
--- /dev/null
+++ b/chart2/qa/extras/data/odt/axis-position.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/chart.odt b/chart2/qa/extras/data/odt/chart.odt
new file mode 100644
index 0000000000..5f2dd34d2a
--- /dev/null
+++ b/chart2/qa/extras/data/odt/chart.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/multilevelcat.odt b/chart2/qa/extras/data/odt/multilevelcat.odt
new file mode 100644
index 0000000000..8148e1be10
--- /dev/null
+++ b/chart2/qa/extras/data/odt/multilevelcat.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/scatter-plot-labels.odt b/chart2/qa/extras/data/odt/scatter-plot-labels.odt
new file mode 100644
index 0000000000..ab8f243242
--- /dev/null
+++ b/chart2/qa/extras/data/odt/scatter-plot-labels.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/stock_chart_LO_6_2.odt b/chart2/qa/extras/data/odt/stock_chart_LO_6_2.odt
new file mode 100644
index 0000000000..06e15a6b0d
--- /dev/null
+++ b/chart2/qa/extras/data/odt/stock_chart_LO_6_2.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/tdf108022.odt b/chart2/qa/extras/data/odt/tdf108022.odt
new file mode 100644
index 0000000000..b8659ec32c
--- /dev/null
+++ b/chart2/qa/extras/data/odt/tdf108022.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/tdf114657.odt b/chart2/qa/extras/data/odt/tdf114657.odt
new file mode 100644
index 0000000000..4c99963b0d
--- /dev/null
+++ b/chart2/qa/extras/data/odt/tdf114657.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/tdf128733.odt b/chart2/qa/extras/data/odt/tdf128733.odt
new file mode 100644
index 0000000000..18aace26c0
--- /dev/null
+++ b/chart2/qa/extras/data/odt/tdf128733.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/tdf131143.odt b/chart2/qa/extras/data/odt/tdf131143.odt
new file mode 100644
index 0000000000..e8ffeaf5a9
--- /dev/null
+++ b/chart2/qa/extras/data/odt/tdf131143.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/tdf135366_data_label_export.odt b/chart2/qa/extras/data/odt/tdf135366_data_label_export.odt
new file mode 100644
index 0000000000..85759f2ade
--- /dev/null
+++ b/chart2/qa/extras/data/odt/tdf135366_data_label_export.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/tdf135366_data_label_point.odt b/chart2/qa/extras/data/odt/tdf135366_data_label_point.odt
new file mode 100644
index 0000000000..3c176a37ad
--- /dev/null
+++ b/chart2/qa/extras/data/odt/tdf135366_data_label_point.odt
Binary files differ
diff --git a/chart2/qa/extras/data/odt/testPieChartWallLineStyle.odt b/chart2/qa/extras/data/odt/testPieChartWallLineStyle.odt
new file mode 100644
index 0000000000..0e1ab533b1
--- /dev/null
+++ b/chart2/qa/extras/data/odt/testPieChartWallLineStyle.odt
Binary files differ
diff --git a/chart2/qa/extras/data/ppt/chart.ppt b/chart2/qa/extras/data/ppt/chart.ppt
new file mode 100644
index 0000000000..0efffaf36a
--- /dev/null
+++ b/chart2/qa/extras/data/ppt/chart.ppt
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/PieChartWithAutomaticLayout_SizeAndPosition.pptx b/chart2/qa/extras/data/pptx/PieChartWithAutomaticLayout_SizeAndPosition.pptx
new file mode 100644
index 0000000000..3f95e932b1
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/PieChartWithAutomaticLayout_SizeAndPosition.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/bnc864396.pptx b/chart2/qa/extras/data/pptx/bnc864396.pptx
new file mode 100644
index 0000000000..e2e05c5161
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/bnc864396.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/bnc882383.pptx b/chart2/qa/extras/data/pptx/bnc882383.pptx
new file mode 100644
index 0000000000..18b44f0c1b
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/bnc882383.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/bnc889755.pptx b/chart2/qa/extras/data/pptx/bnc889755.pptx
new file mode 100644
index 0000000000..f3af677656
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/bnc889755.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/chart.pptx b/chart2/qa/extras/data/pptx/chart.pptx
new file mode 100644
index 0000000000..8f11ea53d0
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/chart.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/percentage-number-formats.pptx b/chart2/qa/extras/data/pptx/percentage-number-formats.pptx
new file mode 100644
index 0000000000..280c7ef291
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/percentage-number-formats.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/sparse-chart.pptx b/chart2/qa/extras/data/pptx/sparse-chart.pptx
new file mode 100644
index 0000000000..d91e8f52f4
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/sparse-chart.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/stacked-bar-chart-hidden-series.pptx b/chart2/qa/extras/data/pptx/stacked-bar-chart-hidden-series.pptx
new file mode 100644
index 0000000000..20ba89a0b7
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/stacked-bar-chart-hidden-series.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/stacked-non-stacked-mix-y-axis.pptx b/chart2/qa/extras/data/pptx/stacked-non-stacked-mix-y-axis.pptx
new file mode 100644
index 0000000000..27d099d40f
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/stacked-non-stacked-mix-y-axis.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf105517.pptx b/chart2/qa/extras/data/pptx/tdf105517.pptx
new file mode 100644
index 0000000000..ff9d747f03
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf105517.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf106217.pptx b/chart2/qa/extras/data/pptx/tdf106217.pptx
new file mode 100644
index 0000000000..64fb968b8a
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf106217.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf115107-2.pptx b/chart2/qa/extras/data/pptx/tdf115107-2.pptx
new file mode 100644
index 0000000000..629056ecc8
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf115107-2.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf115107.pptx b/chart2/qa/extras/data/pptx/tdf115107.pptx
new file mode 100644
index 0000000000..2ec5c2cd22
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf115107.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf115859.pptx b/chart2/qa/extras/data/pptx/tdf115859.pptx
new file mode 100644
index 0000000000..07943041be
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf115859.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf116163.pptx b/chart2/qa/extras/data/pptx/tdf116163.pptx
new file mode 100644
index 0000000000..5fbee8304a
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf116163.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf121205.pptx b/chart2/qa/extras/data/pptx/tdf121205.pptx
new file mode 100644
index 0000000000..e60849ec02
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf121205.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf122765.pptx b/chart2/qa/extras/data/pptx/tdf122765.pptx
new file mode 100644
index 0000000000..948190c30b
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf122765.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf125444.pptx b/chart2/qa/extras/data/pptx/tdf125444.pptx
new file mode 100644
index 0000000000..e78efecd65
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf125444.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf127393.pptx b/chart2/qa/extras/data/pptx/tdf127393.pptx
new file mode 100644
index 0000000000..7c4047817a
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf127393.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf127720.pptx b/chart2/qa/extras/data/pptx/tdf127720.pptx
new file mode 100644
index 0000000000..b10a4c5ab4
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf127720.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf127811.pptx b/chart2/qa/extras/data/pptx/tdf127811.pptx
new file mode 100644
index 0000000000..cf3fdee606
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf127811.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf128345_ChartArea_CG_TS.pptx b/chart2/qa/extras/data/pptx/tdf128345_ChartArea_CG_TS.pptx
new file mode 100644
index 0000000000..986dbe0dfd
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf128345_ChartArea_CG_TS.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf128345_ChartWall_CS_TG.pptx b/chart2/qa/extras/data/pptx/tdf128345_ChartWall_CS_TG.pptx
new file mode 100644
index 0000000000..63d126b78d
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf128345_ChartWall_CS_TG.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf128345_Legend_CS_TG_axial.pptx b/chart2/qa/extras/data/pptx/tdf128345_Legend_CS_TG_axial.pptx
new file mode 100644
index 0000000000..67e383cfb1
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf128345_Legend_CS_TG_axial.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf135366_CustomLabelText.pptx b/chart2/qa/extras/data/pptx/tdf135366_CustomLabelText.pptx
new file mode 100644
index 0000000000..58d73fcd26
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf135366_CustomLabelText.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf137691_dataTable.pptx b/chart2/qa/extras/data/pptx/tdf137691_dataTable.pptx
new file mode 100644
index 0000000000..edb465d729
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf137691_dataTable.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf150176.pptx b/chart2/qa/extras/data/pptx/tdf150176.pptx
new file mode 100644
index 0000000000..fa217f92c8
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf150176.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf48041.pptx b/chart2/qa/extras/data/pptx/tdf48041.pptx
new file mode 100644
index 0000000000..b0872f84f2
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf48041.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/tdf60316.pptx b/chart2/qa/extras/data/pptx/tdf60316.pptx
new file mode 100644
index 0000000000..d1da03e5fa
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/tdf60316.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/testChartTitlePropertiesBitmapFill.pptx b/chart2/qa/extras/data/pptx/testChartTitlePropertiesBitmapFill.pptx
new file mode 100644
index 0000000000..395546edb4
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/testChartTitlePropertiesBitmapFill.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/testChartTitlePropertiesColorFill.pptx b/chart2/qa/extras/data/pptx/testChartTitlePropertiesColorFill.pptx
new file mode 100644
index 0000000000..361bdd643c
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/testChartTitlePropertiesColorFill.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/pptx/testChartTitlePropertiesGradientFill.pptx b/chart2/qa/extras/data/pptx/testChartTitlePropertiesGradientFill.pptx
new file mode 100644
index 0000000000..a77896dcdf
--- /dev/null
+++ b/chart2/qa/extras/data/pptx/testChartTitlePropertiesGradientFill.pptx
Binary files differ
diff --git a/chart2/qa/extras/data/xls/axis_sourceformatting.xls b/chart2/qa/extras/data/xls/axis_sourceformatting.xls
new file mode 100644
index 0000000000..2ee38b7208
--- /dev/null
+++ b/chart2/qa/extras/data/xls/axis_sourceformatting.xls
Binary files differ
diff --git a/chart2/qa/extras/data/xls/chart.xls b/chart2/qa/extras/data/xls/chart.xls
new file mode 100644
index 0000000000..7c81d7f49e
--- /dev/null
+++ b/chart2/qa/extras/data/xls/chart.xls
Binary files differ
diff --git a/chart2/qa/extras/data/xls/piechart_outside.xls b/chart2/qa/extras/data/xls/piechart_outside.xls
new file mode 100644
index 0000000000..02a4f7b855
--- /dev/null
+++ b/chart2/qa/extras/data/xls/piechart_outside.xls
Binary files differ
diff --git a/chart2/qa/extras/data/xls/source_number_format_axis.xls b/chart2/qa/extras/data/xls/source_number_format_axis.xls
new file mode 100644
index 0000000000..bc54593ac1
--- /dev/null
+++ b/chart2/qa/extras/data/xls/source_number_format_axis.xls
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/ChartDataTable.xlsx b/chart2/qa/extras/data/xlsx/ChartDataTable.xlsx
new file mode 100644
index 0000000000..fff4f00aea
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/ChartDataTable.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/DataTable-MultipleLegendEntriesForOneDataSeries.xlsx b/chart2/qa/extras/data/xlsx/DataTable-MultipleLegendEntriesForOneDataSeries.xlsx
new file mode 100644
index 0000000000..b077fd2e03
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/DataTable-MultipleLegendEntriesForOneDataSeries.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/add_series_secondary_axis.xlsx b/chart2/qa/extras/data/xlsx/add_series_secondary_axis.xlsx
new file mode 100644
index 0000000000..03d7a47f6c
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/add_series_secondary_axis.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/auto_marker_excel10.xlsx b/chart2/qa/extras/data/xlsx/auto_marker_excel10.xlsx
new file mode 100644
index 0000000000..c157562572
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/auto_marker_excel10.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/autotitledel_2007.xlsx b/chart2/qa/extras/data/xlsx/autotitledel_2007.xlsx
new file mode 100644
index 0000000000..9ce71cf4e0
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/autotitledel_2007.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/autotitledel_2013.xlsx b/chart2/qa/extras/data/xlsx/autotitledel_2013.xlsx
new file mode 100644
index 0000000000..a5070273a8
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/autotitledel_2013.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/axis-label-rotation.xlsx b/chart2/qa/extras/data/xlsx/axis-label-rotation.xlsx
new file mode 100644
index 0000000000..cc3b1df8a4
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/axis-label-rotation.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/axis_character_properties.xlsx b/chart2/qa/extras/data/xlsx/axis_character_properties.xlsx
new file mode 100644
index 0000000000..635aafe81b
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/axis_character_properties.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/axis_title_default_rotation.xlsx b/chart2/qa/extras/data/xlsx/axis_title_default_rotation.xlsx
new file mode 100644
index 0000000000..5cda3af37e
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/axis_title_default_rotation.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/axis_title_rotated.xlsx b/chart2/qa/extras/data/xlsx/axis_title_rotated.xlsx
new file mode 100644
index 0000000000..29e42d8a47
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/axis_title_rotated.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/axis_title_rotation.xlsx b/chart2/qa/extras/data/xlsx/axis_title_rotation.xlsx
new file mode 100644
index 0000000000..fc90e2bf4c
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/axis_title_rotation.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/bar_chart_simple.xlsx b/chart2/qa/extras/data/xlsx/bar_chart_simple.xlsx
new file mode 100644
index 0000000000..52040bf2cd
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/bar_chart_simple.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/barchart_outend.xlsx b/chart2/qa/extras/data/xlsx/barchart_outend.xlsx
new file mode 100644
index 0000000000..621c0c2844
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/barchart_outend.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/barchart_totalsrow.xlsx b/chart2/qa/extras/data/xlsx/barchart_totalsrow.xlsx
new file mode 100644
index 0000000000..c87b2b3186
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/barchart_totalsrow.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/bubble_chart_simple.xlsx b/chart2/qa/extras/data/xlsx/bubble_chart_simple.xlsx
new file mode 100644
index 0000000000..d13fe5ef48
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/bubble_chart_simple.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/chart-area-style-background.xlsx b/chart2/qa/extras/data/xlsx/chart-area-style-background.xlsx
new file mode 100644
index 0000000000..2baf1e2063
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/chart-area-style-background.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/chart-area-style-border.xlsx b/chart2/qa/extras/data/xlsx/chart-area-style-border.xlsx
new file mode 100644
index 0000000000..81a6a6e606
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/chart-area-style-border.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/chart-auto-background.xlsx b/chart2/qa/extras/data/xlsx/chart-auto-background.xlsx
new file mode 100644
index 0000000000..a4594ad4fc
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/chart-auto-background.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/chart-hatch-fill.xlsx b/chart2/qa/extras/data/xlsx/chart-hatch-fill.xlsx
new file mode 100644
index 0000000000..4e3394c8ef
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/chart-hatch-fill.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/chart-text-can-overlap.xlsx b/chart2/qa/extras/data/xlsx/chart-text-can-overlap.xlsx
new file mode 100644
index 0000000000..59f907dffe
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/chart-text-can-overlap.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/chart.xlsx b/chart2/qa/extras/data/xlsx/chart.xlsx
new file mode 100644
index 0000000000..193bfc49d5
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/chart.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/chart_label_text_break.xlsx b/chart2/qa/extras/data/xlsx/chart_label_text_break.xlsx
new file mode 100644
index 0000000000..81c4958604
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/chart_label_text_break.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/chart_pie2007.xlsx b/chart2/qa/extras/data/xlsx/chart_pie2007.xlsx
new file mode 100644
index 0000000000..583c6720a4
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/chart_pie2007.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/chart_title.xlsx b/chart2/qa/extras/data/xlsx/chart_title.xlsx
new file mode 100644
index 0000000000..0b79855462
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/chart_title.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/chart_with_name_range.xlsx b/chart2/qa/extras/data/xlsx/chart_with_name_range.xlsx
new file mode 100644
index 0000000000..2f2b814011
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/chart_with_name_range.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/combined_chart_secondary_axis.xlsx b/chart2/qa/extras/data/xlsx/combined_chart_secondary_axis.xlsx
new file mode 100644
index 0000000000..e922d4df4a
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/combined_chart_secondary_axis.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/custom_data_label.xlsx b/chart2/qa/extras/data/xlsx/custom_data_label.xlsx
new file mode 100644
index 0000000000..cc69aaf0dc
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/custom_data_label.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/data_label.xlsx b/chart2/qa/extras/data/xlsx/data_label.xlsx
new file mode 100644
index 0000000000..1ccf9b6987
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/data_label.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/data_labels_fill_color.xlsx b/chart2/qa/extras/data/xlsx/data_labels_fill_color.xlsx
new file mode 100644
index 0000000000..1a55f5b868
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/data_labels_fill_color.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/deleted_data_labels.xlsx b/chart2/qa/extras/data/xlsx/deleted_data_labels.xlsx
new file mode 100644
index 0000000000..587c956082
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/deleted_data_labels.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/deleted_legend_entry.xlsx b/chart2/qa/extras/data/xlsx/deleted_legend_entry.xlsx
new file mode 100644
index 0000000000..06a052646f
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/deleted_legend_entry.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/deleted_legend_entry2.xlsx b/chart2/qa/extras/data/xlsx/deleted_legend_entry2.xlsx
new file mode 100644
index 0000000000..ea02464b1c
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/deleted_legend_entry2.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/dispBlanksAs_2007.xlsx b/chart2/qa/extras/data/xlsx/dispBlanksAs_2007.xlsx
new file mode 100644
index 0000000000..64e673e7c7
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/dispBlanksAs_2007.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/dispBlanksAs_2013.xlsx b/chart2/qa/extras/data/xlsx/dispBlanksAs_2013.xlsx
new file mode 100644
index 0000000000..86a0a35961
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/dispBlanksAs_2013.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/empty_chart.xlsx b/chart2/qa/extras/data/xlsx/empty_chart.xlsx
new file mode 100644
index 0000000000..449902146a
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/empty_chart.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/external_str_ref.xlsx b/chart2/qa/extras/data/xlsx/external_str_ref.xlsx
new file mode 100644
index 0000000000..f2dde80e1f
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/external_str_ref.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/fdo54361-1.xlsx b/chart2/qa/extras/data/xlsx/fdo54361-1.xlsx
new file mode 100644
index 0000000000..dba79ef9cf
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/fdo54361-1.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/fdo54361.xlsx b/chart2/qa/extras/data/xlsx/fdo54361.xlsx
new file mode 100644
index 0000000000..2c49802a05
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/fdo54361.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/fdo70609.xlsx b/chart2/qa/extras/data/xlsx/fdo70609.xlsx
new file mode 100644
index 0000000000..261ef88058
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/fdo70609.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/fdo78080.xlsx b/chart2/qa/extras/data/xlsx/fdo78080.xlsx
new file mode 100644
index 0000000000..c4a4e3e003
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/fdo78080.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/gapWidth.xlsx b/chart2/qa/extras/data/xlsx/gapWidth.xlsx
new file mode 100644
index 0000000000..0e9c0eec08
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/gapWidth.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/hidden_cells.xlsx b/chart2/qa/extras/data/xlsx/hidden_cells.xlsx
new file mode 100644
index 0000000000..da3e2da77e
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/hidden_cells.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/incorrect_label_position.xlsx b/chart2/qa/extras/data/xlsx/incorrect_label_position.xlsx
new file mode 100644
index 0000000000..4f133b5581
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/incorrect_label_position.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/legend_manual_layout.xlsx b/chart2/qa/extras/data/xlsx/legend_manual_layout.xlsx
new file mode 100644
index 0000000000..16ea01142e
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/legend_manual_layout.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/majorTickMark.xlsx b/chart2/qa/extras/data/xlsx/majorTickMark.xlsx
new file mode 100644
index 0000000000..2b6cdcfb36
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/majorTickMark.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/markerColor.xlsx b/chart2/qa/extras/data/xlsx/markerColor.xlsx
new file mode 100644
index 0000000000..65e87ff38d
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/markerColor.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/minorTickMark.xlsx b/chart2/qa/extras/data/xlsx/minorTickMark.xlsx
new file mode 100644
index 0000000000..2d68792474
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/minorTickMark.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/no_marker.xlsx b/chart2/qa/extras/data/xlsx/no_marker.xlsx
new file mode 100644
index 0000000000..228c4590fa
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/no_marker.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/number-formats.xlsx b/chart2/qa/extras/data/xlsx/number-formats.xlsx
new file mode 100644
index 0000000000..f5250c52ec
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/number-formats.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/pie_chart_datapoint_explosion.xlsx b/chart2/qa/extras/data/xlsx/pie_chart_datapoint_explosion.xlsx
new file mode 100644
index 0000000000..273ebeb82e
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/pie_chart_datapoint_explosion.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/piechart_deleted_legendentry.xlsx b/chart2/qa/extras/data/xlsx/piechart_deleted_legendentry.xlsx
new file mode 100644
index 0000000000..8428686ff6
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/piechart_deleted_legendentry.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/piechart_legend.xlsx b/chart2/qa/extras/data/xlsx/piechart_legend.xlsx
new file mode 100644
index 0000000000..baea1de9b0
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/piechart_legend.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/piechart_outside.xlsx b/chart2/qa/extras/data/xlsx/piechart_outside.xlsx
new file mode 100644
index 0000000000..e90eab1e90
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/piechart_outside.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/plotVisOnly.xlsx b/chart2/qa/extras/data/xlsx/plotVisOnly.xlsx
new file mode 100644
index 0000000000..8e4fcbd5ea
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/plotVisOnly.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/plot_area_manual_layout.xlsx b/chart2/qa/extras/data/xlsx/plot_area_manual_layout.xlsx
new file mode 100644
index 0000000000..f0bc588134
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/plot_area_manual_layout.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/rAngAx.xlsx b/chart2/qa/extras/data/xlsx/rAngAx.xlsx
new file mode 100644
index 0000000000..f6d521a3ed
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/rAngAx.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/secondary_axis_title_default_rotation.xlsx b/chart2/qa/extras/data/xlsx/secondary_axis_title_default_rotation.xlsx
new file mode 100644
index 0000000000..de5d0391d2
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/secondary_axis_title_default_rotation.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/ser_labels.xlsx b/chart2/qa/extras/data/xlsx/ser_labels.xlsx
new file mode 100644
index 0000000000..ba2315666e
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/ser_labels.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/smoothed_series.xlsx b/chart2/qa/extras/data/xlsx/smoothed_series.xlsx
new file mode 100644
index 0000000000..bab00ce139
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/smoothed_series.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/smoothed_series2007.xlsx b/chart2/qa/extras/data/xlsx/smoothed_series2007.xlsx
new file mode 100644
index 0000000000..3c8f0cc460
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/smoothed_series2007.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/strict_chart.xlsx b/chart2/qa/extras/data/xlsx/strict_chart.xlsx
new file mode 100644
index 0000000000..43789331a5
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/strict_chart.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf100084.xlsx b/chart2/qa/extras/data/xlsx/tdf100084.xlsx
new file mode 100644
index 0000000000..5f03f39244
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf100084.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf108107.xlsx b/chart2/qa/extras/data/xlsx/tdf108107.xlsx
new file mode 100644
index 0000000000..3f86326fa2
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf108107.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf111173.xlsx b/chart2/qa/extras/data/xlsx/tdf111173.xlsx
new file mode 100644
index 0000000000..e62c6747b5
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf111173.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf111824.xlsx b/chart2/qa/extras/data/xlsx/tdf111824.xlsx
new file mode 100644
index 0000000000..ae86756c47
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf111824.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf114139.xlsx b/chart2/qa/extras/data/xlsx/tdf114139.xlsx
new file mode 100644
index 0000000000..ef09575c1f
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf114139.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf115012.xlsx b/chart2/qa/extras/data/xlsx/tdf115012.xlsx
new file mode 100644
index 0000000000..cf8ac7d81e
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf115012.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf119138-missing-autotitledeleted.xlsx b/chart2/qa/extras/data/xlsx/tdf119138-missing-autotitledeleted.xlsx
new file mode 100644
index 0000000000..a20aa0bb1b
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf119138-missing-autotitledeleted.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf122031.xlsx b/chart2/qa/extras/data/xlsx/tdf122031.xlsx
new file mode 100644
index 0000000000..ac937a8c7a
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf122031.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf122915.xlsx b/chart2/qa/extras/data/xlsx/tdf122915.xlsx
new file mode 100644
index 0000000000..ff20e04baf
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf122915.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf124817.xlsx b/chart2/qa/extras/data/xlsx/tdf124817.xlsx
new file mode 100644
index 0000000000..d9b09644e4
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf124817.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf126033.xlsx b/chart2/qa/extras/data/xlsx/tdf126033.xlsx
new file mode 100644
index 0000000000..ee60103c98
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf126033.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf126115.xlsx b/chart2/qa/extras/data/xlsx/tdf126115.xlsx
new file mode 100644
index 0000000000..f845c06e31
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf126115.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf127777.xlsx b/chart2/qa/extras/data/xlsx/tdf127777.xlsx
new file mode 100644
index 0000000000..c04de30fc8
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf127777.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf128619.xlsx b/chart2/qa/extras/data/xlsx/tdf128619.xlsx
new file mode 100644
index 0000000000..e6eb142593
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf128619.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf128621.xlsx b/chart2/qa/extras/data/xlsx/tdf128621.xlsx
new file mode 100644
index 0000000000..93a6822da9
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf128621.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf128627.xlsx b/chart2/qa/extras/data/xlsx/tdf128627.xlsx
new file mode 100644
index 0000000000..419c1ad2f9
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf128627.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf128633.xlsx b/chart2/qa/extras/data/xlsx/tdf128633.xlsx
new file mode 100644
index 0000000000..fa186895d6
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf128633.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf128634.xlsx b/chart2/qa/extras/data/xlsx/tdf128634.xlsx
new file mode 100644
index 0000000000..91baa780ce
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf128634.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf128732.xlsx b/chart2/qa/extras/data/xlsx/tdf128732.xlsx
new file mode 100644
index 0000000000..b92afb1ed6
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf128732.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf130657.xlsx b/chart2/qa/extras/data/xlsx/tdf130657.xlsx
new file mode 100644
index 0000000000..036da200ab
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf130657.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf130986.xlsx b/chart2/qa/extras/data/xlsx/tdf130986.xlsx
new file mode 100644
index 0000000000..9674fd1ab1
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf130986.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf132076.xlsx b/chart2/qa/extras/data/xlsx/tdf132076.xlsx
new file mode 100644
index 0000000000..799ef9c855
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf132076.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf133190_tdf133191.xlsx b/chart2/qa/extras/data/xlsx/tdf133190_tdf133191.xlsx
new file mode 100644
index 0000000000..f8cad0e8cf
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf133190_tdf133191.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf133376.xlsx b/chart2/qa/extras/data/xlsx/tdf133376.xlsx
new file mode 100644
index 0000000000..2000733ec8
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf133376.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf134118.xlsx b/chart2/qa/extras/data/xlsx/tdf134118.xlsx
new file mode 100644
index 0000000000..ca86fb8cf1
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf134118.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf134225.xlsx b/chart2/qa/extras/data/xlsx/tdf134225.xlsx
new file mode 100644
index 0000000000..ae7bdc66e3
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf134225.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf134978.xlsx b/chart2/qa/extras/data/xlsx/tdf134978.xlsx
new file mode 100644
index 0000000000..ad5522a914
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf134978.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap.xlsx b/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap.xlsx
new file mode 100644
index 0000000000..69cad0d671
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap2.xlsx b/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap2.xlsx
new file mode 100644
index 0000000000..ced797258a
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf135184RoundLineCap2.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf136105.xlsx b/chart2/qa/extras/data/xlsx/tdf136105.xlsx
new file mode 100644
index 0000000000..bc3a909224
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf136105.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf136267.xlsx b/chart2/qa/extras/data/xlsx/tdf136267.xlsx
new file mode 100644
index 0000000000..741a33c429
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf136267.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf136752.xlsx b/chart2/qa/extras/data/xlsx/tdf136752.xlsx
new file mode 100644
index 0000000000..05fad58cff
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf136752.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf137505.xlsx b/chart2/qa/extras/data/xlsx/tdf137505.xlsx
new file mode 100644
index 0000000000..08fa6778bb
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf137505.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf137734.xlsx b/chart2/qa/extras/data/xlsx/tdf137734.xlsx
new file mode 100644
index 0000000000..8c177becc3
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf137734.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf137917.xlsx b/chart2/qa/extras/data/xlsx/tdf137917.xlsx
new file mode 100644
index 0000000000..4d08a23acd
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf137917.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf138204.xlsx b/chart2/qa/extras/data/xlsx/tdf138204.xlsx
new file mode 100644
index 0000000000..04c2e50d79
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf138204.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf140489.xlsx b/chart2/qa/extras/data/xlsx/tdf140489.xlsx
new file mode 100644
index 0000000000..bd24f40be7
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf140489.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf142351.xlsx b/chart2/qa/extras/data/xlsx/tdf142351.xlsx
new file mode 100644
index 0000000000..0414bb3f16
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf142351.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf143127.xlsx b/chart2/qa/extras/data/xlsx/tdf143127.xlsx
new file mode 100644
index 0000000000..116a00b60c
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf143127.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf143942.xlsx b/chart2/qa/extras/data/xlsx/tdf143942.xlsx
new file mode 100644
index 0000000000..33ff6696b7
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf143942.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf150434.xlsx b/chart2/qa/extras/data/xlsx/tdf150434.xlsx
new file mode 100644
index 0000000000..309a0c4c25
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf150434.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf81396.xlsx b/chart2/qa/extras/data/xlsx/tdf81396.xlsx
new file mode 100644
index 0000000000..2a557262a2
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf81396.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf90876.xlsx b/chart2/qa/extras/data/xlsx/tdf90876.xlsx
new file mode 100644
index 0000000000..3cf60e8168
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf90876.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdf98690.xlsx b/chart2/qa/extras/data/xlsx/tdf98690.xlsx
new file mode 100644
index 0000000000..4269afa9ea
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdf98690.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/tdfPieNumFormat.xlsx b/chart2/qa/extras/data/xlsx/tdfPieNumFormat.xlsx
new file mode 100644
index 0000000000..0835cb3332
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/tdfPieNumFormat.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/test3DAreaChartZAxis.xlsx b/chart2/qa/extras/data/xlsx/test3DAreaChartZAxis.xlsx
new file mode 100644
index 0000000000..01c6fe56f1
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/test3DAreaChartZAxis.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testAutoTitleDeleted.xlsx b/chart2/qa/extras/data/xlsx/testAutoTitleDeleted.xlsx
new file mode 100644
index 0000000000..409389e23b
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testAutoTitleDeleted.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testBarChartDataPointPropXLSX.xlsx b/chart2/qa/extras/data/xlsx/testBarChartDataPointPropXLSX.xlsx
new file mode 100644
index 0000000000..e73d16bd2d
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testBarChartDataPointPropXLSX.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testChartTitlePropertiesBitmapFill.xlsx b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesBitmapFill.xlsx
new file mode 100644
index 0000000000..9d2dff9b3e
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesBitmapFill.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testChartTitlePropertiesColorFill.xlsx b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesColorFill.xlsx
new file mode 100644
index 0000000000..9e9aa0beaf
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesColorFill.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testChartTitlePropertiesGradientFill.xlsx b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesGradientFill.xlsx
new file mode 100644
index 0000000000..b5b6177543
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testChartTitlePropertiesGradientFill.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testCombinedChartAxis.xlsx b/chart2/qa/extras/data/xlsx/testCombinedChartAxis.xlsx
new file mode 100644
index 0000000000..47f8246e23
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testCombinedChartAxis.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testCustomPosDataLabels.xlsx b/chart2/qa/extras/data/xlsx/testCustomPosDataLabels.xlsx
new file mode 100644
index 0000000000..caa08956cd
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testCustomPosDataLabels.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testDataPointLabelCustomPos.xlsx b/chart2/qa/extras/data/xlsx/testDataPointLabelCustomPos.xlsx
new file mode 100644
index 0000000000..69f89ec0e4
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testDataPointLabelCustomPos.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testDataseriesOverlapStackedChart.xlsx b/chart2/qa/extras/data/xlsx/testDataseriesOverlapStackedChart.xlsx
new file mode 100644
index 0000000000..ba1c526b41
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testDataseriesOverlapStackedChart.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testErrorBarProp.xlsx b/chart2/qa/extras/data/xlsx/testErrorBarProp.xlsx
new file mode 100644
index 0000000000..ac9dde9b79
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testErrorBarProp.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testSecondaryAxis.xlsx b/chart2/qa/extras/data/xlsx/testSecondaryAxis.xlsx
new file mode 100644
index 0000000000..6faa39b294
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testSecondaryAxis.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testTdf130032.xlsx b/chart2/qa/extras/data/xlsx/testTdf130032.xlsx
new file mode 100644
index 0000000000..03a3dbf403
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testTdf130032.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/testTdf90749.xlsx b/chart2/qa/extras/data/xlsx/testTdf90749.xlsx
new file mode 100644
index 0000000000..ca3bc806c0
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/testTdf90749.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/title_character_properties.xlsx b/chart2/qa/extras/data/xlsx/title_character_properties.xlsx
new file mode 100644
index 0000000000..2a239936ca
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/title_character_properties.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/title_manual_layout.xlsx b/chart2/qa/extras/data/xlsx/title_manual_layout.xlsx
new file mode 100644
index 0000000000..c89b2af4dc
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/title_manual_layout.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/trendline.xlsx b/chart2/qa/extras/data/xlsx/trendline.xlsx
new file mode 100644
index 0000000000..701fcfd012
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/trendline.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/trendline2007.xlsx b/chart2/qa/extras/data/xlsx/trendline2007.xlsx
new file mode 100644
index 0000000000..87d4d5a9cf
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/trendline2007.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/vary_color.xlsx b/chart2/qa/extras/data/xlsx/vary_color.xlsx
new file mode 100644
index 0000000000..980cdda341
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/vary_color.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/vary_color2007.xlsx b/chart2/qa/extras/data/xlsx/vary_color2007.xlsx
new file mode 100644
index 0000000000..657c2176d6
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/vary_color2007.xlsx
Binary files differ
diff --git a/chart2/qa/extras/data/xlsx/xAxisLabelsRotation.xlsx b/chart2/qa/extras/data/xlsx/xAxisLabelsRotation.xlsx
new file mode 100644
index 0000000000..cf511dfaf2
--- /dev/null
+++ b/chart2/qa/extras/data/xlsx/xAxisLabelsRotation.xlsx
Binary files differ
diff --git a/chart2/qa/extras/uichart.cxx b/chart2/qa/extras/uichart.cxx
new file mode 100644
index 0000000000..84b8658d29
--- /dev/null
+++ b/chart2/qa/extras/uichart.cxx
@@ -0,0 +1,441 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "charttest.hxx"
+
+#include <comphelper/propertyvalue.hxx>
+#include <vcl/scheduler.hxx>
+
+using namespace ::com::sun::star;
+
+class Chart2UiChartTest : public ChartTest
+{
+public:
+ Chart2UiChartTest()
+ : ChartTest("/chart2/qa/extras/data/")
+ {
+ }
+
+ void testCopyPasteToNewSheet(uno::Reference<chart::XChartDocument> xChartDoc,
+ OUString aObjectName, sal_Int32 nColumns, sal_Int32 nRows);
+};
+
+void Chart2UiChartTest::testCopyPasteToNewSheet(uno::Reference<chart::XChartDocument> xChartDoc,
+ OUString aObjectName, sal_Int32 nColumns,
+ sal_Int32 nRows)
+{
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference<chart::XChartDataArray> xChartData(xChartDoc->getData(), uno::UNO_QUERY_THROW);
+
+ uno::Sequence<OUString> aExpectedColumnDescriptions = xChartData->getColumnDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of columns in origin file", nColumns,
+ aExpectedColumnDescriptions.getLength());
+
+ uno::Sequence<OUString> aExpectedRowDescriptions = xChartData->getRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of rows in origin file", nRows,
+ aExpectedRowDescriptions.getLength());
+
+ Sequence<Sequence<double>> aExpectedData = xChartData->getData();
+
+ uno::Sequence<beans::PropertyValue> aPropertyValues = {
+ comphelper::makePropertyValue("ToObject", aObjectName),
+ };
+ dispatchCommand(mxComponent, ".uno:GoToObject", aPropertyValues);
+
+ dispatchCommand(mxComponent, ".uno:Copy", {});
+
+ // create a new document
+ load("private:factory/scalc");
+
+ dispatchCommand(mxComponent, ".uno:Paste", {});
+
+ uno::Reference<chart2::XChartDocument> xChartDoc2 = getChartDocFromSheet(0, mxComponent);
+ CPPUNIT_ASSERT(xChartDoc2.is());
+
+ uno::Reference<chart::XChartDataArray> xDataArray(xChartDoc2->getDataProvider(),
+ UNO_QUERY_THROW);
+
+ Sequence<OUString> aColumnDesc = xDataArray->getColumnDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of columns in destination file", nColumns,
+ aColumnDesc.getLength());
+ for (sal_Int32 i = 0; i < nColumns; ++i)
+ {
+ OString sMessage("Incorrect description in column: " + OString::number(i));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sMessage.getStr(), aExpectedColumnDescriptions[i],
+ aColumnDesc[i]);
+ }
+
+ Sequence<OUString> aRowDesc = xDataArray->getRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of rows in destination file", nRows,
+ aRowDesc.getLength());
+ for (sal_Int32 i = 0; i < nRows; ++i)
+ {
+ OString sMessage("Incorrect description in row: " + OString::number(i));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sMessage.getStr(), aExpectedRowDescriptions[i], aRowDesc[i]);
+ }
+
+ Sequence<Sequence<double>> aData = xDataArray->getData();
+
+ for (sal_Int32 nRowIdx = 0; nRowIdx < nRows; ++nRowIdx)
+ {
+ for (sal_Int32 nColIdx = 0; nColIdx < nColumns; ++nColIdx)
+ {
+ double nValue = aData[nRowIdx][nColIdx];
+ double nExpected = aExpectedData[nRowIdx][nColIdx];
+ OString sMessage("Incorrect value in Col: " + OString::number(nColIdx)
+ + " Row: " + OString::number(nRowIdx));
+
+ if (std::isnan(nValue))
+ {
+ // On paste, 0 becomes NaN, check whether it's expected
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(sMessage.getStr(), 0.0, nExpected, 1e-1);
+ }
+ else
+ {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(sMessage.getStr(), nExpected, nValue, 1e-1);
+ }
+ }
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2UiChartTest, testTdf120348)
+{
+ loadFromFile(u"ods/tdf120348.ods");
+ uno::Reference<chart::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ uno::UNO_QUERY_THROW);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 0
+ // - Actual : 3.33625955201419
+ // - Incorrect value in Col: 2 Row: 51
+ testCopyPasteToNewSheet(xChartDoc, "Object 2", 4, 158);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2UiChartTest, testTdf151091)
+{
+ std::vector<OUString> aExpected
+ = { u"Ωφέλιμο"_ustr, u"Επικίνδυνο"_ustr, u"Απόσταση"_ustr, u"Μάσκα"_ustr, u"Εμβόλιο"_ustr };
+
+ loadFromFile(u"ods/tdf151091.ods");
+ uno::Reference<chart::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference<chart::XChartDataArray> xChartData(xChartDoc->getData(), uno::UNO_QUERY_THROW);
+ uno::Sequence<OUString> aSeriesList = xChartData->getColumnDescriptions();
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5), aSeriesList.getLength());
+
+ for (size_t i = 0; i < 5; ++i)
+ CPPUNIT_ASSERT_EQUAL(aExpected[i], aSeriesList[i]);
+
+ uno::Sequence<beans::PropertyValue> aPropertyValues = {
+ comphelper::makePropertyValue("ToObject", OUString("Object 1")),
+ };
+ dispatchCommand(mxComponent, ".uno:GoToObject", aPropertyValues);
+
+ dispatchCommand(mxComponent, ".uno:Copy", {});
+
+ // create a new writer document
+ load("private:factory/swriter");
+
+ dispatchCommand(mxComponent, ".uno:Paste", {});
+
+ aSeriesList = getWriterChartColumnDescriptions(mxComponent);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 5
+ // - Actual : 1
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5), aSeriesList.getLength());
+
+ for (size_t i = 0; i < 5; ++i)
+ CPPUNIT_ASSERT_EQUAL(aExpected[i], aSeriesList[i]);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2UiChartTest, testTdf107097)
+{
+ loadFromFile(u"ods/tdf107097.ods");
+ uno::Reference<chart::XChartDocument> xChartDoc(getPivotChartDocFromSheet(1, mxComponent),
+ uno::UNO_QUERY_THROW);
+ testCopyPasteToNewSheet(xChartDoc, "Object 1", 4, 12);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2UiChartTest, testTdf136011)
+{
+ loadFromFile(u"ods/tdf136011.ods");
+ uno::Reference<chart::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ uno::UNO_QUERY_THROW);
+ testCopyPasteToNewSheet(xChartDoc, "Object 1", 3, 9);
+
+ loadFromFile(u"ods/tdf136011.ods");
+ uno::Reference<chart::XChartDocument> xChartDoc2(getChartCompFromSheet(0, 1, mxComponent),
+ uno::UNO_QUERY_THROW);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: Test 1 1
+ // - Actual : Test 1
+ // - Incorrect description in row: 0
+ testCopyPasteToNewSheet(xChartDoc2, "Object 2", 3, 9);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2UiChartTest, testTdf62057)
+{
+ loadFromFile(u"ods/tdf62057.ods");
+ uno::Reference<chart::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ uno::UNO_QUERY_THROW);
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 2
+ // - Actual : 7
+ // - Incorrect number of columns in destination file
+ testCopyPasteToNewSheet(xChartDoc, "Object 1", 2, 6);
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2UiChartTest, testTdf98690)
+{
+ loadFromFile(u"xlsx/tdf98690.xlsx");
+ uno::Reference<chart::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ uno::UNO_QUERY_THROW);
+
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference<chart::XChartDataArray> xChartData(xChartDoc->getData(), uno::UNO_QUERY_THROW);
+ uno::Sequence<OUString> aSeriesList = xChartData->getColumnDescriptions();
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(6), aSeriesList.getLength());
+
+ uno::Sequence<beans::PropertyValue> aPropertyValues = {
+ comphelper::makePropertyValue("ToObject", OUString("Chart 2")),
+ };
+ dispatchCommand(mxComponent, ".uno:GoToObject", aPropertyValues);
+
+ dispatchCommand(mxComponent, ".uno:Copy", {});
+
+ // create a new document
+ load("private:factory/scalc");
+
+ dispatchCommand(mxComponent, ".uno:Paste", {});
+
+ uno::Reference<chart::XChartDocument> xChartDoc2(getChartCompFromSheet(0, 0, mxComponent),
+ uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xChartDoc2.is());
+ uno::Reference<chart::XChartDataArray> xChartData2(xChartDoc2->getData(), uno::UNO_QUERY_THROW);
+ uno::Sequence<OUString> aSeriesList2 = xChartData2->getColumnDescriptions();
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 12
+ // - Actual : 0
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(12), aSeriesList2.getLength());
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2UiChartTest, testTdf101894)
+{
+ loadFromFile(u"ods/tdf101894.ods");
+ uno::Reference<chart::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ uno::UNO_QUERY_THROW);
+
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference<chart::XChartDataArray> xChartData(xChartDoc->getData(), uno::UNO_QUERY_THROW);
+
+ uno::Sequence<OUString> aExpectedColumnDescriptions = xChartData->getColumnDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of columns in origin file",
+ static_cast<sal_Int32>(12),
+ aExpectedColumnDescriptions.getLength());
+
+ uno::Sequence<OUString> aExpectedRowDescriptions = xChartData->getRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of rows in origin file",
+ static_cast<sal_Int32>(8), aExpectedRowDescriptions.getLength());
+
+ Sequence<Sequence<double>> aExpectedData = xChartData->getData();
+
+ // Create a copy of the sheet and move to the end
+ uno::Sequence<beans::PropertyValue> aArgs(
+ comphelper::InitPropertySequence({ { "DocName", uno::Any(OUString("tdf101894")) },
+ { "Index", uno::Any(sal_uInt16(32767)) },
+ { "Copy", uno::Any(true) } }));
+ dispatchCommand(mxComponent, ".uno:Move", aArgs);
+
+ uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW);
+ uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xIA->getCount());
+
+ for (sal_Int32 sheetIndex = 0; sheetIndex < 2; ++sheetIndex)
+ {
+ uno::Reference<chart::XChartDocument> xChartDoc2(
+ getChartCompFromSheet(sheetIndex, 0, mxComponent), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xChartDoc2.is());
+ uno::Reference<chart::XChartDataArray> xChartData2(xChartDoc2->getData(),
+ uno::UNO_QUERY_THROW);
+
+ uno::Sequence<OUString> aColumnDescriptions = xChartData2->getColumnDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of columns in origin file",
+ static_cast<sal_Int32>(12), aColumnDescriptions.getLength());
+ for (sal_Int32 i = 0; i < 12; ++i)
+ {
+ OString sMessage("Incorrect description in column: " + OString::number(i));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sMessage.getStr(), aExpectedColumnDescriptions[i],
+ aColumnDescriptions[i]);
+ }
+
+ uno::Sequence<OUString> aRowDescriptions = xChartData2->getRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of rows in origin file",
+ static_cast<sal_Int32>(8), aRowDescriptions.getLength());
+ for (sal_Int32 i = 0; i < 8; ++i)
+ {
+ OString sMessage("Incorrect description in row: " + OString::number(i));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sMessage.getStr(), aExpectedRowDescriptions[i],
+ aRowDescriptions[i]);
+ }
+
+ Sequence<Sequence<double>> aData = xChartData2->getData();
+
+ for (sal_Int32 nRowIdx = 0; nRowIdx < 8; ++nRowIdx)
+ {
+ for (sal_Int32 nColIdx = 0; nColIdx < 12; ++nColIdx)
+ {
+ double nValue = aData[nRowIdx][nColIdx];
+ double nExpected = aExpectedData[nRowIdx][nColIdx];
+ OString sMessage("Incorrect value in Col: " + OString::number(nColIdx)
+ + " Row: " + OString::number(nRowIdx));
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 1
+ // - Actual : 2.2250738585072e-308
+ // - Incorrect value in Col: 0 Row: 0
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(sMessage.getStr(), nExpected, nValue, 1e-1);
+ }
+ }
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2UiChartTest, testCopyPasteChartWithDotInSheetName)
+{
+ loadFromFile(u"ods/chartWithDotInSheetName.ods");
+ uno::Reference<chart::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ uno::UNO_QUERY_THROW);
+
+ CPPUNIT_ASSERT(xChartDoc.is());
+ uno::Reference<chart::XChartDataArray> xChartData(xChartDoc->getData(), uno::UNO_QUERY_THROW);
+
+ uno::Sequence<OUString> aExpectedColumnDescriptions = xChartData->getColumnDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of columns in origin file",
+ static_cast<sal_Int32>(4),
+ aExpectedColumnDescriptions.getLength());
+
+ uno::Sequence<OUString> aExpectedRowDescriptions = xChartData->getRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of rows in origin file",
+ static_cast<sal_Int32>(7), aExpectedRowDescriptions.getLength());
+
+ Sequence<Sequence<double>> aExpectedData = xChartData->getData();
+
+ dispatchCommand(mxComponent, ".uno:SelectAll", {});
+ dispatchCommand(mxComponent, ".uno:Copy", {});
+
+ uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
+ { { "Name", uno::Any(OUString("NewTab")) }, { "Index", uno::Any(sal_uInt16(2)) } }));
+ dispatchCommand(mxComponent, ".uno:Insert", aArgs);
+
+ uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW);
+ uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xIA->getCount());
+
+ dispatchCommand(mxComponent, ".uno:Paste", {});
+
+ for (sal_Int32 sheetIndex = 0; sheetIndex < 2; ++sheetIndex)
+ {
+ uno::Reference<chart::XChartDocument> xChartDoc2(
+ getChartCompFromSheet(sheetIndex, 0, mxComponent), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT(xChartDoc2.is());
+ uno::Reference<chart::XChartDataArray> xChartData2(xChartDoc2->getData(),
+ uno::UNO_QUERY_THROW);
+
+ uno::Sequence<OUString> aColumnDescriptions = xChartData2->getColumnDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of columns in origin file",
+ static_cast<sal_Int32>(4), aColumnDescriptions.getLength());
+ for (sal_Int32 i = 0; i < 4; ++i)
+ {
+ OString sMessage("Incorrect description in column: " + OString::number(i));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sMessage.getStr(), aExpectedColumnDescriptions[i],
+ aColumnDescriptions[i]);
+ }
+
+ uno::Sequence<OUString> aRowDescriptions = xChartData2->getRowDescriptions();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Incorrect number of rows in origin file",
+ static_cast<sal_Int32>(7), aRowDescriptions.getLength());
+ for (sal_Int32 i = 0; i < 7; ++i)
+ {
+ OString sMessage("Incorrect description in row: " + OString::number(i));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sMessage.getStr(), aExpectedRowDescriptions[i],
+ aRowDescriptions[i]);
+ }
+
+ Sequence<Sequence<double>> aData = xChartData2->getData();
+
+ for (sal_Int32 nRowIdx = 0; nRowIdx < 7; ++nRowIdx)
+ {
+ for (sal_Int32 nColIdx = 0; nColIdx < 4; ++nColIdx)
+ {
+ double nValue = aData[nRowIdx][nColIdx];
+ double nExpected = aExpectedData[nRowIdx][nColIdx];
+ OString sMessage("Incorrect value in Col: " + OString::number(nColIdx)
+ + " Row: " + OString::number(nRowIdx));
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(sMessage.getStr(), nExpected, nValue, 1e-1);
+ }
+ }
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Chart2UiChartTest, testTdf158223)
+{
+ loadFromFile(u"ods/tdf158223.ods");
+
+ uno::Reference<sheet::XSpreadsheetDocument> xDoc(mxComponent, UNO_QUERY_THROW);
+ uno::Reference<container::XIndexAccess> xIA(xDoc->getSheets(), UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), xIA->getCount());
+
+ for (sal_Int32 sheetIndex = 0; sheetIndex < 2; ++sheetIndex)
+ {
+ OUString sExpectedValuesX("$Tabelle" + OUString::number(sheetIndex + 1) + ".$A$2:$A$11");
+ OUString sExpectedValuesY("$Tabelle" + OUString::number(sheetIndex + 1) + ".$B$2:$B$11");
+ uno::Reference<chart2::XChartDocument> xChartDoc
+ = getChartDocFromSheet(sheetIndex, mxComponent);
+ Reference<chart2::data::XDataSequence> xValuesX
+ = getDataSequenceFromDocByRole(xChartDoc, u"values-x");
+ CPPUNIT_ASSERT_EQUAL(sExpectedValuesX, xValuesX->getSourceRangeRepresentation());
+ Reference<chart2::data::XDataSequence> xValuesY
+ = getDataSequenceFromDocByRole(xChartDoc, u"values-y");
+ CPPUNIT_ASSERT_EQUAL(sExpectedValuesY, xValuesY->getSourceRangeRepresentation());
+ }
+
+ // Remove last sheet
+ uno::Sequence<beans::PropertyValue> aArgs(
+ comphelper::InitPropertySequence({ { "Index", uno::Any(sal_uInt16(3)) } }));
+ dispatchCommand(mxComponent, ".uno:Remove", aArgs);
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xIA->getCount());
+
+ for (sal_Int32 sheetIndex = 0; sheetIndex < 2; ++sheetIndex)
+ {
+ OUString sExpectedValuesX("$Tabelle" + OUString::number(sheetIndex + 1) + ".$A$2:$A$11");
+ OUString sExpectedValuesY("$Tabelle" + OUString::number(sheetIndex + 1) + ".$B$2:$B$11");
+ uno::Reference<chart2::XChartDocument> xChartDoc
+ = getChartDocFromSheet(sheetIndex, mxComponent);
+ Reference<chart2::data::XDataSequence> xValuesX
+ = getDataSequenceFromDocByRole(xChartDoc, u"values-x");
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: $Tabelle2.$A$2:$A$11
+ // - Actual : $Tabelle2.$A$2:$Tabelle1.$A$11
+ CPPUNIT_ASSERT_EQUAL(sExpectedValuesX, xValuesX->getSourceRangeRepresentation());
+ Reference<chart2::data::XDataSequence> xValuesY
+ = getDataSequenceFromDocByRole(xChartDoc, u"values-y");
+ CPPUNIT_ASSERT_EQUAL(sExpectedValuesY, xValuesY->getSourceRangeRepresentation());
+ }
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/xshape/chart2xshape.cxx b/chart2/qa/extras/xshape/chart2xshape.cxx
new file mode 100644
index 0000000000..f247b7507a
--- /dev/null
+++ b/chart2/qa/extras/xshape/chart2xshape.cxx
@@ -0,0 +1,322 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <charttest.hxx>
+#include <com/sun/star/chart/XChartDocument.hpp>
+
+#include <com/sun/star/qa/XDumper.hpp>
+
+#include <test/xmldiff.hxx>
+#include <test/xmltesttools.hxx>
+
+#include <fstream>
+#include <string_view>
+
+class Chart2XShapeTest : public ChartTest
+{
+public:
+ Chart2XShapeTest()
+ : ChartTest("/chart2/qa/extras/xshape/data/")
+ {
+ }
+
+ void testTdf150832();
+ void testTdf149204();
+ void testTdf151424();
+ void testFdo75075();
+ void testPropertyMappingBarChart();
+ void testPieChartLabels1();
+ void testPieChartLabels2();
+ void testPieChartLabels3();
+ void testPieChartLabels4();
+ void testChart();
+ void testTdf76649TrendLineBug();
+ void testTdf88154LabelRotatedLayout();
+
+ CPPUNIT_TEST_SUITE(Chart2XShapeTest);
+ CPPUNIT_TEST(testTdf150832);
+ CPPUNIT_TEST(testTdf149204);
+ CPPUNIT_TEST(testTdf151424);
+ CPPUNIT_TEST(testFdo75075);
+ CPPUNIT_TEST(testPropertyMappingBarChart);
+ CPPUNIT_TEST(testPieChartLabels1);
+ CPPUNIT_TEST(testPieChartLabels2);
+ CPPUNIT_TEST(testPieChartLabels3);
+ CPPUNIT_TEST(testPieChartLabels4);
+ CPPUNIT_TEST(testChart);
+ CPPUNIT_TEST(testTdf76649TrendLineBug);
+ CPPUNIT_TEST(testTdf88154LabelRotatedLayout);
+
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ void compareAgainstReference(std::u16string_view rDump, std::u16string_view rReferenceFile);
+ OUString getXShapeDumpString();
+ xmlDocUniquePtr getXShapeDumpXmlDoc();
+};
+
+namespace
+{
+OUString getShapeDump(css::uno::Reference<css::chart::XChartDocument> const& doc)
+{
+ return css::uno::Reference<css::qa::XDumper>(doc, css::uno::UNO_QUERY_THROW)->dump("shapes");
+}
+
+bool checkDumpAgainstFile(std::u16string_view rDump, std::u16string_view aFilePath,
+ char const* toleranceFile)
+{
+ OString aOFile = OUStringToOString(aFilePath, RTL_TEXTENCODING_UTF8);
+
+ CPPUNIT_ASSERT_MESSAGE("dump is empty", !rDump.empty());
+
+ OString aDump = OUStringToOString(rDump, RTL_TEXTENCODING_UTF8);
+ return doXMLDiff(aOFile.getStr(), aDump.getStr(), static_cast<int>(rDump.size()),
+ toleranceFile);
+}
+}
+
+OUString Chart2XShapeTest::getXShapeDumpString()
+{
+ uno::Reference<chart::XChartDocument> xChartDoc(getChartCompFromSheet(0, 0, mxComponent),
+ UNO_QUERY_THROW);
+ return getShapeDump(xChartDoc);
+}
+
+xmlDocUniquePtr Chart2XShapeTest::getXShapeDumpXmlDoc()
+{
+ OUString rDump = getXShapeDumpString();
+ OString aXmlDump = OUStringToOString(rDump, RTL_TEXTENCODING_UTF8);
+ return xmlDocUniquePtr(xmlParseDoc(reinterpret_cast<const xmlChar*>(aXmlDump.getStr())));
+}
+
+void Chart2XShapeTest::compareAgainstReference(std::u16string_view rDump,
+ std::u16string_view rReferenceFile)
+{
+ checkDumpAgainstFile(
+ rDump,
+ Concat2View(m_directories.getPathFromSrc(u"/chart2/qa/extras/xshape/data/reference/")
+ + rReferenceFile),
+ OUStringToOString(
+ m_directories.getPathFromSrc(u"/chart2/qa/extras/xshape/data/reference/tolerance.xml"),
+ RTL_TEXTENCODING_UTF8)
+ .getStr());
+}
+
+void Chart2XShapeTest::testTdf150832()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 319
+ // - Actual : 0
+ loadFromFile(u"xls/tdf150832.xls");
+ compareAgainstReference(getXShapeDumpString(), u"tdf150832.xml");
+}
+
+void Chart2XShapeTest::testTdf149204()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 12230
+ // - Actual : 12940
+ // - Node: /XShapes/XShape[2]
+ // - Attr: sizeX
+ loadFromFile(u"pptx/tdf149204.pptx");
+ uno::Reference<chart::XChartDocument> xChartDoc = getChartDocFromDrawImpress(0, 0);
+ compareAgainstReference(getShapeDump(xChartDoc), u"tdf149204.xml");
+}
+
+void Chart2XShapeTest::testTdf151424()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 3717
+ // - Actual : 3530
+ // - Node: /XShapes/XShape[2]/XShapes/XShape[1]
+ // - Attr: positionX
+ loadFromFile(u"ods/tdf151424.ods");
+ compareAgainstReference(getXShapeDumpString(), u"tdf151424.xml");
+}
+
+void Chart2XShapeTest::testFdo75075()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ loadFromFile(u"ods/fdo75075.ods");
+ compareAgainstReference(getXShapeDumpString(), u"fdo75075.xml");
+}
+
+void Chart2XShapeTest::testPropertyMappingBarChart()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ loadFromFile(u"ods/property-mapping-bar.ods");
+ compareAgainstReference(getXShapeDumpString(), u"property-mapping-bar.xml");
+}
+
+void Chart2XShapeTest::testPieChartLabels1()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ // inside placement for the best fit case
+ loadFromFile(u"xlsx/tdf90839-1.xlsx");
+ compareAgainstReference(getXShapeDumpString(), u"tdf90839-1.xml");
+}
+
+void Chart2XShapeTest::testPieChartLabels2()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ // text wrap: wrap all text labels except one
+ loadFromFile(u"xlsx/tdf90839-2.xlsx");
+ compareAgainstReference(getXShapeDumpString(), u"tdf90839-2.xml");
+}
+
+void Chart2XShapeTest::testPieChartLabels3()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ // text wrap: wrap no text label except one
+ loadFromFile(u"xlsx/tdf90839-3.xlsx");
+ compareAgainstReference(getXShapeDumpString(), u"tdf90839-3.xml");
+}
+
+void Chart2XShapeTest::testPieChartLabels4()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ // data value and percent value are centered horizontally
+ loadFromFile(u"ods/tdf90839-4.ods");
+ compareAgainstReference(getXShapeDumpString(), u"tdf90839-4.xml");
+}
+
+void Chart2XShapeTest::testChart()
+{
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+
+ loadFromFile(u"ods/testChart.ods");
+ compareAgainstReference(getXShapeDumpString(), u"testChart.xml");
+}
+
+void Chart2XShapeTest::testTdf76649TrendLineBug()
+{
+ // This bug prevents that the trendline (regression curve) is drawn
+ // if the first cell is empty. See tdf#76649 for details.
+
+ loadFromFile(u"ods/tdf76649_TrendLineBug.ods");
+
+ xmlDocUniquePtr pXmlDoc = getXShapeDumpXmlDoc();
+
+ // Check if the regression curve exists (which means a XShape with a certain
+ // name should exist in the dump)
+ assertXPath(pXmlDoc, "//XShape[@name='CID/D=0:CS=0:CT=0:Series=0:Curve=0']"_ostr, 1);
+}
+
+void Chart2XShapeTest::testTdf88154LabelRotatedLayout()
+{
+ loadFromFile(u"pptx/tdf88154_LabelRotatedLayout.pptx");
+ uno::Reference<chart::XChartDocument> xChartDoc = getChartDocFromDrawImpress(0, 5);
+ OUString rDump = getShapeDump(xChartDoc);
+ OString aXmlDump = OUStringToOString(rDump, RTL_TEXTENCODING_UTF8);
+ xmlDocUniquePtr pXmlDoc(xmlParseDoc(reinterpret_cast<const xmlChar*>(aXmlDump.getStr())));
+
+ {
+ OString aPath("//XShape[@text='Oct-12']/Transformation"_ostr);
+ assertXPath(pXmlDoc, aPath, 1);
+ double fT11 = getXPath(pXmlDoc, aPath + "/Line1", "column1"_ostr).toDouble();
+ double fT12 = getXPath(pXmlDoc, aPath + "/Line1", "column2"_ostr).toDouble();
+ double fT21 = getXPath(pXmlDoc, aPath + "/Line2", "column1"_ostr).toDouble();
+ double fT22 = getXPath(pXmlDoc, aPath + "/Line2", "column2"_ostr).toDouble();
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(fT11, -fT21, 1e-8);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(fT12, fT22, 1e-8);
+ }
+ {
+ OString aPath("//XShape[@text='Nov-12']/Transformation"_ostr);
+ assertXPath(pXmlDoc, aPath, 1);
+ double fT11 = getXPath(pXmlDoc, aPath + "/Line1", "column1"_ostr).toDouble();
+ double fT12 = getXPath(pXmlDoc, aPath + "/Line1", "column2"_ostr).toDouble();
+ double fT21 = getXPath(pXmlDoc, aPath + "/Line2", "column1"_ostr).toDouble();
+ double fT22 = getXPath(pXmlDoc, aPath + "/Line2", "column2"_ostr).toDouble();
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(fT11, -fT21, 1e-8);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(fT12, fT22, 1e-8);
+ }
+ {
+ OString aPath("//XShape[@text='Dec-12']/Transformation"_ostr);
+ assertXPath(pXmlDoc, aPath, 1);
+ double fT11 = getXPath(pXmlDoc, aPath + "/Line1", "column1"_ostr).toDouble();
+ double fT12 = getXPath(pXmlDoc, aPath + "/Line1", "column2"_ostr).toDouble();
+ double fT21 = getXPath(pXmlDoc, aPath + "/Line2", "column1"_ostr).toDouble();
+ double fT22 = getXPath(pXmlDoc, aPath + "/Line2", "column2"_ostr).toDouble();
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(fT11, -fT21, 1e-8);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(fT12, fT22, 1e-8);
+ }
+ {
+ OString aPath("//XShape[@text='May-13']/Transformation"_ostr);
+ assertXPath(pXmlDoc, aPath, 1);
+ double fT11 = getXPath(pXmlDoc, aPath + "/Line1", "column1"_ostr).toDouble();
+ double fT12 = getXPath(pXmlDoc, aPath + "/Line1", "column2"_ostr).toDouble();
+ double fT21 = getXPath(pXmlDoc, aPath + "/Line2", "column1"_ostr).toDouble();
+ double fT22 = getXPath(pXmlDoc, aPath + "/Line2", "column2"_ostr).toDouble();
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(fT11, -fT21, 1e-8);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(fT12, fT22, 1e-8);
+ }
+ {
+ OString aPath("//XShape[@text='Jan-14']/Transformation"_ostr);
+ assertXPath(pXmlDoc, aPath, 1);
+ double fT11 = getXPath(pXmlDoc, aPath + "/Line1", "column1"_ostr).toDouble();
+ double fT12 = getXPath(pXmlDoc, aPath + "/Line1", "column2"_ostr).toDouble();
+ double fT21 = getXPath(pXmlDoc, aPath + "/Line2", "column1"_ostr).toDouble();
+ double fT22 = getXPath(pXmlDoc, aPath + "/Line2", "column2"_ostr).toDouble();
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(fT11, -fT21, 1e-8);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(fT12, fT22, 1e-8);
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Chart2XShapeTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/extras/xshape/data/ods/fdo75075.ods b/chart2/qa/extras/xshape/data/ods/fdo75075.ods
new file mode 100644
index 0000000000..d2a1be49bf
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/ods/fdo75075.ods
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/ods/property-mapping-bar.ods b/chart2/qa/extras/xshape/data/ods/property-mapping-bar.ods
new file mode 100644
index 0000000000..1a4e826dfb
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/ods/property-mapping-bar.ods
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/ods/tdf151424.ods b/chart2/qa/extras/xshape/data/ods/tdf151424.ods
new file mode 100644
index 0000000000..d1f6adcc24
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/ods/tdf151424.ods
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/ods/tdf76649_TrendLineBug.ods b/chart2/qa/extras/xshape/data/ods/tdf76649_TrendLineBug.ods
new file mode 100644
index 0000000000..1032e960b9
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/ods/tdf76649_TrendLineBug.ods
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/ods/tdf90839-4.ods b/chart2/qa/extras/xshape/data/ods/tdf90839-4.ods
new file mode 100644
index 0000000000..3126ac1759
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/ods/tdf90839-4.ods
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/ods/testChart.ods b/chart2/qa/extras/xshape/data/ods/testChart.ods
new file mode 100644
index 0000000000..956f57d525
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/ods/testChart.ods
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/pptx/tdf149204.pptx b/chart2/qa/extras/xshape/data/pptx/tdf149204.pptx
new file mode 100644
index 0000000000..60d006547a
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/pptx/tdf149204.pptx
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/pptx/tdf88154_LabelRotatedLayout.pptx b/chart2/qa/extras/xshape/data/pptx/tdf88154_LabelRotatedLayout.pptx
new file mode 100644
index 0000000000..f3af677656
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/pptx/tdf88154_LabelRotatedLayout.pptx
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/reference/fdo75075.xml b/chart2/qa/extras/xshape/data/reference/fdo75075.xml
new file mode 100644
index 0000000000..fe8cb00cf1
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/fdo75075.xml
@@ -0,0 +1,1692 @@
+<?xml version="1.0"?>
+<XShapes>
+ <XShape positionX="0" positionY="0" sizeX="16000" sizeY="9000" type="com.sun.star.drawing.RectangleShape" name="CID/Page=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="16001.000000" column2="0.000000" column3="0.000000"/>
+ <Line2 column1="0.000000" column2="9001.000000" column3="0.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="12852" sizeY="8640" type="com.sun.star.drawing.GroupShape" name="CID/D=0">
+ <XShapes>
+ <XShape positionX="1524" positionY="379" sizeX="10364" sizeY="7794" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="10365.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="379.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="12852" sizeY="8640" type="com.sun.star.drawing.RectangleShape" name="PlotAreaIncludingAxes" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="12853.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="12852" sizeY="8640" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1374" positionY="378" sizeX="10664" sizeY="7944" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1524" positionY="379" sizeX="10364" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="PlotAreaExcludingAxes">
+ <XShapes>
+ <XShape positionX="1524" positionY="379" sizeX="10364" sizeY="7794" type="com.sun.star.drawing.RectangleShape" name="CID/DiagramWall=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="e6e6e6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="10365.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="379.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10365.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="379.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1374" positionY="378" sizeX="10664" sizeY="7944" type="com.sun.star.drawing.GroupShape" name="testonly;CooContainer=XXX_CID">
+ <XShapes>
+ <XShape positionX="1524" positionY="378" sizeX="10364" sizeY="7794" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1524" positionY="378" sizeX="10364" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0:Grid=0">
+ <XShapes>
+ <XShape positionX="1524" positionY="378" sizeX="10364" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="11888" positionY="8172"/>
+ <point positionX="1524" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11888" positionY="7197"/>
+ <point positionX="1524" positionY="7197"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11888" positionY="6223"/>
+ <point positionX="1524" positionY="6223"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11888" positionY="5249"/>
+ <point positionX="1524" positionY="5249"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11888" positionY="4275"/>
+ <point positionX="1524" positionY="4275"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11888" positionY="3300"/>
+ <point positionX="1524" positionY="3300"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11888" positionY="2326"/>
+ <point positionX="1524" positionY="2326"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11888" positionY="1352"/>
+ <point positionX="1524" positionY="1352"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11888" positionY="378"/>
+ <point positionX="1524" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="10364" positionY="7794"/>
+ <point positionX="0" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10364" positionY="6819"/>
+ <point positionX="0" positionY="6819"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10364" positionY="5845"/>
+ <point positionX="0" positionY="5845"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10364" positionY="4871"/>
+ <point positionX="0" positionY="4871"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10364" positionY="3897"/>
+ <point positionX="0" positionY="3897"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10364" positionY="2922"/>
+ <point positionX="0" positionY="2922"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10364" positionY="1948"/>
+ <point positionX="0" positionY="1948"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10364" positionY="974"/>
+ <point positionX="0" positionY="974"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10364" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="10364.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1524" positionY="378" sizeX="0" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" name="HandlesOnly" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="NONE">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="1524" positionY="8172"/>
+ <point positionX="1524" positionY="7197"/>
+ <point positionX="1524" positionY="6223"/>
+ <point positionX="1524" positionY="5249"/>
+ <point positionX="1524" positionY="4275"/>
+ <point positionX="1524" positionY="3300"/>
+ <point positionX="1524" positionY="2326"/>
+ <point positionX="1524" positionY="1352"/>
+ <point positionX="1524" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="0" positionY="6819"/>
+ <point positionX="0" positionY="5845"/>
+ <point positionX="0" positionY="4871"/>
+ <point positionX="0" positionY="3897"/>
+ <point positionX="0" positionY="2922"/>
+ <point positionX="0" positionY="1948"/>
+ <point positionX="0" positionY="974"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10365.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10365.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1374" positionY="378" sizeX="10664" sizeY="7944" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1524" positionY="8172" sizeX="10364" sizeY="150" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=0,0">
+ <XShapes>
+ <XShape positionX="1524" positionY="8172" sizeX="10364" sizeY="150" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="1524" positionY="8322"/>
+ <point positionX="1524" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1524" positionY="8322"/>
+ <point positionX="1524" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="3596" positionY="8322"/>
+ <point positionX="3596" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="3596" positionY="8322"/>
+ <point positionX="3596" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="5669" positionY="8322"/>
+ <point positionX="5669" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="5669" positionY="8322"/>
+ <point positionX="5669" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7742" positionY="8322"/>
+ <point positionX="7742" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7742" positionY="8322"/>
+ <point positionX="7742" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="9815" positionY="8322"/>
+ <point positionX="9815" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="9815" positionY="8322"/>
+ <point positionX="9815" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11888" positionY="8322"/>
+ <point positionX="11888" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11888" positionY="8322"/>
+ <point positionX="11888" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="150"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="150"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="2072" positionY="150"/>
+ <point positionX="2072" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="2072" positionY="150"/>
+ <point positionX="2072" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="4145" positionY="150"/>
+ <point positionX="4145" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="4145" positionY="150"/>
+ <point positionX="4145" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="6218" positionY="150"/>
+ <point positionX="6218" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="6218" positionY="150"/>
+ <point positionX="6218" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="8291" positionY="150"/>
+ <point positionX="8291" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="8291" positionY="150"/>
+ <point positionX="8291" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10364" positionY="150"/>
+ <point positionX="10364" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10364" positionY="150"/>
+ <point positionX="10364" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="10364.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="150.000000" column3="8172.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1524" positionY="8172" sizeX="10364" sizeY="0" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="1524" positionY="8172"/>
+ <point positionX="11888" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="10364" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="10364.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="0.000000" column3="8172.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10365.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="151.000000" column3="8172.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1374" positionY="378" sizeX="150" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="1374" positionY="378" sizeX="150" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="1374" positionY="8172"/>
+ <point positionX="1524" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="8172"/>
+ <point positionX="1524" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="7197"/>
+ <point positionX="1524" positionY="7197"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="7197"/>
+ <point positionX="1524" positionY="7197"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="6223"/>
+ <point positionX="1524" positionY="6223"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="6223"/>
+ <point positionX="1524" positionY="6223"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="5249"/>
+ <point positionX="1524" positionY="5249"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="5249"/>
+ <point positionX="1524" positionY="5249"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="4275"/>
+ <point positionX="1524" positionY="4275"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="4275"/>
+ <point positionX="1524" positionY="4275"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="3300"/>
+ <point positionX="1524" positionY="3300"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="3300"/>
+ <point positionX="1524" positionY="3300"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="2326"/>
+ <point positionX="1524" positionY="2326"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="2326"/>
+ <point positionX="1524" positionY="2326"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="1352"/>
+ <point positionX="1524" positionY="1352"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="1352"/>
+ <point positionX="1524" positionY="1352"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="378"/>
+ <point positionX="1524" positionY="378"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="1374" positionY="378"/>
+ <point positionX="1524" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="150" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="150" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="6819"/>
+ <point positionX="150" positionY="6819"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="6819"/>
+ <point positionX="150" positionY="6819"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="5845"/>
+ <point positionX="150" positionY="5845"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="5845"/>
+ <point positionX="150" positionY="5845"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="4871"/>
+ <point positionX="150" positionY="4871"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="4871"/>
+ <point positionX="150" positionY="4871"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="3897"/>
+ <point positionX="150" positionY="3897"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="3897"/>
+ <point positionX="150" positionY="3897"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="2922"/>
+ <point positionX="150" positionY="2922"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="2922"/>
+ <point positionX="150" positionY="2922"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="1948"/>
+ <point positionX="150" positionY="1948"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="1948"/>
+ <point positionX="150" positionY="1948"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="974"/>
+ <point positionX="150" positionY="974"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="974"/>
+ <point positionX="150" positionY="974"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="150" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="150" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="150.000000" column2="0.000000" column3="1374.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1524" positionY="378" sizeX="0" sizeY="7794" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="1524" positionY="8172"/>
+ <point positionX="1524" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="1524.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="151.000000" column2="0.000000" column3="1374.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="11888" positionY="378" sizeX="150" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,1">
+ <XShapes>
+ <XShape positionX="11888" positionY="378" sizeX="150" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="12038" positionY="8172"/>
+ <point positionX="11888" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="8172"/>
+ <point positionX="11888" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="7058"/>
+ <point positionX="11888" positionY="7058"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="7058"/>
+ <point positionX="11888" positionY="7058"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="5945"/>
+ <point positionX="11888" positionY="5945"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="5945"/>
+ <point positionX="11888" positionY="5945"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="4831"/>
+ <point positionX="11888" positionY="4831"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="4831"/>
+ <point positionX="11888" positionY="4831"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="3718"/>
+ <point positionX="11888" positionY="3718"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="3718"/>
+ <point positionX="11888" positionY="3718"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="2604"/>
+ <point positionX="11888" positionY="2604"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="2604"/>
+ <point positionX="11888" positionY="2604"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="1491"/>
+ <point positionX="11888" positionY="1491"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="1491"/>
+ <point positionX="11888" positionY="1491"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="378"/>
+ <point positionX="11888" positionY="378"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12038" positionY="378"/>
+ <point positionX="11888" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="150" positionY="7794"/>
+ <point positionX="0" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="7794"/>
+ <point positionX="0" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="6680"/>
+ <point positionX="0" positionY="6680"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="6680"/>
+ <point positionX="0" positionY="6680"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="5567"/>
+ <point positionX="0" positionY="5567"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="5567"/>
+ <point positionX="0" positionY="5567"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="4453"/>
+ <point positionX="0" positionY="4453"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="4453"/>
+ <point positionX="0" positionY="4453"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="3340"/>
+ <point positionX="0" positionY="3340"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="3340"/>
+ <point positionX="0" positionY="3340"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="2226"/>
+ <point positionX="0" positionY="2226"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="2226"/>
+ <point positionX="0" positionY="2226"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="1113"/>
+ <point positionX="0" positionY="1113"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="1113"/>
+ <point positionX="0" positionY="1113"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="150.000000" column2="0.000000" column3="11888.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="11888" positionY="378" sizeX="0" sizeY="7794" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="11888" positionY="8172"/>
+ <point positionX="11888" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="11888.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="151.000000" column2="0.000000" column3="11888.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10665.000000" column2="0.000000" column3="1374.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2042" positionY="1250" sizeX="9327" sizeY="6922" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="2042" positionY="1250" sizeX="9327" sizeY="6922" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0">
+ <XShapes>
+ <XShape positionX="2042" positionY="3765" sizeX="1036" sizeY="4407" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="2042" positionY="8172"/>
+ <point positionX="3078" positionY="8172"/>
+ <point positionX="3078" positionY="3765"/>
+ <point positionX="2042" positionY="3765"/>
+ <point positionX="2042" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="4407"/>
+ <point positionX="1036" positionY="4407"/>
+ <point positionX="1036" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="4407"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1036.000000" column2="0.000000" column3="2042.000000"/>
+ <Line2 column1="0.000000" column2="4407.000000" column3="3765.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4115" positionY="1993" sizeX="1036" sizeY="6179" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="4115" positionY="8172"/>
+ <point positionX="5151" positionY="8172"/>
+ <point positionX="5151" positionY="1993"/>
+ <point positionX="4115" positionY="1993"/>
+ <point positionX="4115" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="6179"/>
+ <point positionX="1036" positionY="6179"/>
+ <point positionX="1036" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="6179"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1036.000000" column2="0.000000" column3="4115.000000"/>
+ <Line2 column1="0.000000" column2="6179.000000" column3="1993.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6187" positionY="1250" sizeX="1037" sizeY="6922" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="6187" positionY="8172"/>
+ <point positionX="7224" positionY="8172"/>
+ <point positionX="7224" positionY="1250"/>
+ <point positionX="6187" positionY="1250"/>
+ <point positionX="6187" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="6922"/>
+ <point positionX="1037" positionY="6922"/>
+ <point positionX="1037" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="6922"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1037.000000" column2="0.000000" column3="6187.000000"/>
+ <Line2 column1="0.000000" column2="6922.000000" column3="1250.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8260" positionY="1524" sizeX="1037" sizeY="6648" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=3" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="8260" positionY="8172"/>
+ <point positionX="9297" positionY="8172"/>
+ <point positionX="9297" positionY="1524"/>
+ <point positionX="8260" positionY="1524"/>
+ <point positionX="8260" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="6648"/>
+ <point positionX="1037" positionY="6648"/>
+ <point positionX="1037" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="6648"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1037.000000" column2="0.000000" column3="8260.000000"/>
+ <Line2 column1="0.000000" column2="6648.000000" column3="1524.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="10333" positionY="2603" sizeX="1036" sizeY="5569" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=4" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="10333" positionY="8172"/>
+ <point positionX="11369" positionY="8172"/>
+ <point positionX="11369" positionY="2603"/>
+ <point positionX="10333" positionY="2603"/>
+ <point positionX="10333" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="5569"/>
+ <point positionX="1036" positionY="5569"/>
+ <point positionX="1036" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="5569"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1036.000000" column2="0.000000" column3="10333.000000"/>
+ <Line2 column1="0.000000" column2="5569.000000" column3="2603.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9328.000000" column2="0.000000" column3="2042.000000"/>
+ <Line2 column1="0.000000" column2="6923.000000" column3="1250.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9328.000000" column2="0.000000" column3="2042.000000"/>
+ <Line2 column1="0.000000" column2="6923.000000" column3="1250.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2560" positionY="880" sizeX="8291" sizeY="4152" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="2560" positionY="880" sizeX="8291" sizeY="4152" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=1:Series=0">
+ <XShapes>
+ <XShape positionX="2560" positionY="4541" sizeX="0" sizeY="491" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=1:Series=0:Point=0">
+ <XShapes>
+ <XShape positionX="2560" positionY="4541" sizeX="0" sizeY="491" type="com.sun.star.drawing.LineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="2560" positionY="5032"/>
+ <point positionX="2560" positionY="4541"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="491"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="2560.000000"/>
+ <Line2 column1="0.000000" column2="491.000000" column3="4541.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1.000000" column2="0.000000" column3="2560.000000"/>
+ <Line2 column1="0.000000" column2="492.000000" column3="4541.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4633" positionY="3871" sizeX="0" sizeY="1060" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=1:Series=0:Point=1">
+ <XShapes>
+ <XShape positionX="4633" positionY="3871" sizeX="0" sizeY="1060" type="com.sun.star.drawing.LineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="4633" positionY="4931"/>
+ <point positionX="4633" positionY="3871"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="1060"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="4633.000000"/>
+ <Line2 column1="0.000000" column2="1060.000000" column3="3871.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1.000000" column2="0.000000" column3="4633.000000"/>
+ <Line2 column1="0.000000" column2="1061.000000" column3="3871.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6706" positionY="2620" sizeX="0" sizeY="1938" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=1:Series=0:Point=2">
+ <XShapes>
+ <XShape positionX="6706" positionY="2620" sizeX="0" sizeY="1938" type="com.sun.star.drawing.LineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="6706" positionY="4558"/>
+ <point positionX="6706" positionY="2620"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="1938"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="6706.000000"/>
+ <Line2 column1="0.000000" column2="1938.000000" column3="2620.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1.000000" column2="0.000000" column3="6706.000000"/>
+ <Line2 column1="0.000000" column2="1939.000000" column3="2620.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8778" positionY="1799" sizeX="0" sizeY="899" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=1:Series=0:Point=3">
+ <XShapes>
+ <XShape positionX="8778" positionY="1799" sizeX="0" sizeY="899" type="com.sun.star.drawing.LineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="8778" positionY="2698"/>
+ <point positionX="8778" positionY="1799"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="899"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="8778.000000"/>
+ <Line2 column1="0.000000" column2="899.000000" column3="1799.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1.000000" column2="0.000000" column3="8778.000000"/>
+ <Line2 column1="0.000000" column2="900.000000" column3="1799.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="10851" positionY="880" sizeX="0" sizeY="1241" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=1:Series=0:Point=4">
+ <XShapes>
+ <XShape positionX="10851" positionY="880" sizeX="0" sizeY="1241" type="com.sun.star.drawing.LineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="10851" positionY="2121"/>
+ <point positionX="10851" positionY="880"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="1241"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="10851.000000"/>
+ <Line2 column1="0.000000" column2="1241.000000" column3="880.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1.000000" column2="0.000000" column3="10851.000000"/>
+ <Line2 column1="0.000000" column2="1242.000000" column3="880.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="8292.000000" column2="0.000000" column3="2560.000000"/>
+ <Line2 column1="0.000000" column2="4153.000000" column3="880.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="8292.000000" column2="0.000000" column3="2560.000000"/>
+ <Line2 column1="0.000000" column2="4153.000000" column3="880.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2042" positionY="4728" sizeX="1036" sizeY="94" type="com.sun.star.drawing.GroupShape" name="CID/StockLoss=">
+ <XShapes>
+ <XShape positionX="2042" positionY="4728" sizeX="1036" sizeY="94" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="000000" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1037.000000" column2="0.000000" column3="2042.000000"/>
+ <Line2 column1="0.000000" column2="95.000000" column3="4728.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1037.000000" column2="0.000000" column3="2042.000000"/>
+ <Line2 column1="0.000000" column2="95.000000" column3="4728.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4115" positionY="972" sizeX="7254" sizeY="3850" type="com.sun.star.drawing.GroupShape" name="CID/StockGain=">
+ <XShapes>
+ <XShape positionX="4115" positionY="4288" sizeX="1036" sizeY="534" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1037.000000" column2="0.000000" column3="4115.000000"/>
+ <Line2 column1="0.000000" column2="535.000000" column3="4288.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6187" positionY="2671" sizeX="1036" sizeY="1617" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1037.000000" column2="0.000000" column3="6187.000000"/>
+ <Line2 column1="0.000000" column2="1618.000000" column3="2671.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8260" positionY="1978" sizeX="1036" sizeY="692" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1037.000000" column2="0.000000" column3="8260.000000"/>
+ <Line2 column1="0.000000" column2="693.000000" column3="1978.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="10333" positionY="972" sizeX="1036" sizeY="1005" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1037.000000" column2="0.000000" column3="10333.000000"/>
+ <Line2 column1="0.000000" column2="1006.000000" column3="972.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="7255.000000" column2="0.000000" column3="4115.000000"/>
+ <Line2 column1="0.000000" column2="3851.000000" column3="972.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10665.000000" column2="0.000000" column3="1374.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10665.000000" column2="0.000000" column3="1374.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="12852" sizeY="8640" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1700" positionY="8422" sizeX="10013" sizeY="398" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=0,0">
+ <XShapes>
+ <XShape positionX="1700" positionY="8422" sizeX="1722" sizeY="398" type="com.sun.star.drawing.TextShape" text="2014.02.10" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1723.000000" column2="0.000000" column3="1700.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="3773" positionY="8422" sizeX="1722" sizeY="398" type="com.sun.star.drawing.TextShape" text="2014.02.11" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1723.000000" column2="0.000000" column3="3773.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="5846" positionY="8422" sizeX="1722" sizeY="398" type="com.sun.star.drawing.TextShape" text="2014.02.12" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1723.000000" column2="0.000000" column3="5846.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7918" positionY="8422" sizeX="1722" sizeY="398" type="com.sun.star.drawing.TextShape" text="2014.02.13" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1723.000000" column2="0.000000" column3="7918.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9991" positionY="8422" sizeX="1722" sizeY="398" type="com.sun.star.drawing.TextShape" text="2014.02.14" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1723.000000" column2="0.000000" column3="9991.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10014.000000" column2="0.000000" column3="1700.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="955" sizeY="8192" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="1088" positionY="7974" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="0" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="1088.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="7974.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="6999" sizeX="955" sizeY="398" type="com.sun.star.drawing.TextShape" text="10000" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="956.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="6999.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="6025" sizeX="955" sizeY="398" type="com.sun.star.drawing.TextShape" text="20000" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="956.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="6025.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="5051" sizeX="955" sizeY="398" type="com.sun.star.drawing.TextShape" text="30000" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="956.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="5051.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="4077" sizeX="955" sizeY="398" type="com.sun.star.drawing.TextShape" text="40000" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="956.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4077.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="3102" sizeX="955" sizeY="398" type="com.sun.star.drawing.TextShape" text="50000" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="956.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="3102.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="2128" sizeX="955" sizeY="398" type="com.sun.star.drawing.TextShape" text="60000" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="956.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="2128.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="1154" sizeX="955" sizeY="398" type="com.sun.star.drawing.TextShape" text="70000" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="956.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="1154.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="955" sizeY="398" type="com.sun.star.drawing.TextShape" text="80000" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="956.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="956.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8193.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12138" positionY="180" sizeX="1034" sizeY="8192" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,1">
+ <XShapes>
+ <XShape positionX="12138" positionY="7974" sizeX="1034" sizeY="398" type="com.sun.star.drawing.TextShape" text="1.6100" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="12138.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="7974.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12138" positionY="6860" sizeX="1034" sizeY="398" type="com.sun.star.drawing.TextShape" text="1.6200" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="12138.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="6860.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12138" positionY="5747" sizeX="1034" sizeY="398" type="com.sun.star.drawing.TextShape" text="1.6300" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="12138.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="5747.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12138" positionY="4633" sizeX="1034" sizeY="398" type="com.sun.star.drawing.TextShape" text="1.6400" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="12138.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4633.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12138" positionY="3520" sizeX="1034" sizeY="398" type="com.sun.star.drawing.TextShape" text="1.6500" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="12138.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="3520.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12138" positionY="2406" sizeX="1034" sizeY="398" type="com.sun.star.drawing.TextShape" text="1.6600" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="12138.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="2406.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12138" positionY="1293" sizeX="1034" sizeY="398" type="com.sun.star.drawing.TextShape" text="1.6700" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="12138.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="1293.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12138" positionY="180" sizeX="1034" sizeY="398" type="com.sun.star.drawing.TextShape" text="1.6800" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="12138.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="12138.000000"/>
+ <Line2 column1="0.000000" column2="8193.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12853.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12853.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12853.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="13492" positionY="3952" sizeX="2298" sizeY="1096" type="com.sun.star.drawing.GroupShape" name="CID/D=0:Legend=">
+ <XShapes>
+ <XShape positionX="13492" positionY="3952" sizeX="2298" sizeY="1096" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="e6e6e6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="2299.000000" column2="0.000000" column3="13492.000000"/>
+ <Line2 column1="0.000000" column2="1097.000000" column3="3952.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="13608" positionY="4145" sizeX="800" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="13608" positionY="4145" sizeX="800" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="13608" positionY="4145" sizeX="800" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="13608.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="13608" positionY="4145" sizeX="800" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="13608.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="13608.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="13608.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="13608" positionY="4643" sizeX="800" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="13608" positionY="4643" sizeX="800" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=1:Series=0:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="13608" positionY="4643" sizeX="800" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="13608.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="13608" positionY="4748" sizeX="800" sizeY="0" type="com.sun.star.drawing.LineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="13608" positionY="4748"/>
+ <point positionX="14408" positionY="4748"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="800" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="800.000000" column2="0.000000" column3="13608.000000"/>
+ <Line2 column1="0.000000" column2="0.000000" column3="4748.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="13608.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="13608.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14508" positionY="4052" sizeX="1166" sizeY="398" type="com.sun.star.drawing.TextShape" text="Volume" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="4800" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1167.000000" column2="0.000000" column3="14508.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4052.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14508" positionY="4550" sizeX="875" sizeY="398" type="com.sun.star.drawing.TextShape" text="Close" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="4800" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="876.000000" column2="0.000000" column3="14508.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4550.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="2299.000000" column2="0.000000" column3="13492.000000"/>
+ <Line2 column1="0.000000" column2="1097.000000" column3="3952.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+</XShapes>
+
+
diff --git a/chart2/qa/extras/xshape/data/reference/property-mapping-bar.xml b/chart2/qa/extras/xshape/data/reference/property-mapping-bar.xml
new file mode 100644
index 0000000000..6e28467c19
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/property-mapping-bar.xml
@@ -0,0 +1,1164 @@
+<?xml version="1.0"?>
+<XShapes>
+ <XShape positionX="0" positionY="0" sizeX="16000" sizeY="9000" type="com.sun.star.drawing.RectangleShape" name="CID/Page=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="16001.000000" column2="0.000000" column3="0.000000"/>
+ <Line2 column1="0.000000" column2="9001.000000" column3="0.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="13996" sizeY="8640" type="com.sun.star.drawing.GroupShape" name="CID/D=0">
+ <XShapes>
+ <XShape positionX="756" positionY="380" sizeX="13560" sizeY="7793" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="13561.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="380.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="13996" sizeY="8640" type="com.sun.star.drawing.RectangleShape" name="PlotAreaIncludingAxes" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="13997.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="13996" sizeY="8640" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="606" positionY="378" sizeX="13710" sizeY="7944" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="756" positionY="380" sizeX="13560" sizeY="7793" type="com.sun.star.drawing.GroupShape" name="PlotAreaExcludingAxes">
+ <XShapes>
+ <XShape positionX="756" positionY="380" sizeX="13560" sizeY="7793" type="com.sun.star.drawing.RectangleShape" name="CID/DiagramWall=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="e6e6e6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="13561.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="380.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13561.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="380.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="606" positionY="378" sizeX="13710" sizeY="7944" type="com.sun.star.drawing.GroupShape" name="testonly;CooContainer=XXX_CID">
+ <XShapes>
+ <XShape positionX="756" positionY="378" sizeX="13560" sizeY="7794" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="756" positionY="378" sizeX="13560" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0:Grid=0">
+ <XShapes>
+ <XShape positionX="756" positionY="378" sizeX="13560" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="14316" positionY="8172"/>
+ <point positionX="756" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14316" positionY="7058"/>
+ <point positionX="756" positionY="7058"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14316" positionY="5945"/>
+ <point positionX="756" positionY="5945"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14316" positionY="4832"/>
+ <point positionX="756" positionY="4832"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14316" positionY="3718"/>
+ <point positionX="756" positionY="3718"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14316" positionY="2605"/>
+ <point positionX="756" positionY="2605"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14316" positionY="1492"/>
+ <point positionX="756" positionY="1492"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14316" positionY="378"/>
+ <point positionX="756" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="13560" positionY="7794"/>
+ <point positionX="0" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13560" positionY="6680"/>
+ <point positionX="0" positionY="6680"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13560" positionY="5567"/>
+ <point positionX="0" positionY="5567"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13560" positionY="4454"/>
+ <point positionX="0" positionY="4454"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13560" positionY="3340"/>
+ <point positionX="0" positionY="3340"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13560" positionY="2227"/>
+ <point positionX="0" positionY="2227"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13560" positionY="1114"/>
+ <point positionX="0" positionY="1114"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13560" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="13560.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="756" positionY="378" sizeX="0" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" name="HandlesOnly" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="NONE">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="756" positionY="8172"/>
+ <point positionX="756" positionY="7058"/>
+ <point positionX="756" positionY="5945"/>
+ <point positionX="756" positionY="4832"/>
+ <point positionX="756" positionY="3718"/>
+ <point positionX="756" positionY="2605"/>
+ <point positionX="756" positionY="1492"/>
+ <point positionX="756" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="0" positionY="6680"/>
+ <point positionX="0" positionY="5567"/>
+ <point positionX="0" positionY="4454"/>
+ <point positionX="0" positionY="3340"/>
+ <point positionX="0" positionY="2227"/>
+ <point positionX="0" positionY="1114"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13561.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13561.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="606" positionY="378" sizeX="13710" sizeY="7944" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="756" positionY="8172" sizeX="13560" sizeY="150" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=0,0">
+ <XShapes>
+ <XShape positionX="756" positionY="8172" sizeX="13560" sizeY="150" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="756" positionY="8322"/>
+ <point positionX="756" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="756" positionY="8322"/>
+ <point positionX="756" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="4146" positionY="8322"/>
+ <point positionX="4146" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="4146" positionY="8322"/>
+ <point positionX="4146" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7536" positionY="8322"/>
+ <point positionX="7536" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7536" positionY="8322"/>
+ <point positionX="7536" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10926" positionY="8322"/>
+ <point positionX="10926" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10926" positionY="8322"/>
+ <point positionX="10926" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14316" positionY="8322"/>
+ <point positionX="14316" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14316" positionY="8322"/>
+ <point positionX="14316" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="150"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="150"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="3390" positionY="150"/>
+ <point positionX="3390" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="3390" positionY="150"/>
+ <point positionX="3390" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="6780" positionY="150"/>
+ <point positionX="6780" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="6780" positionY="150"/>
+ <point positionX="6780" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10170" positionY="150"/>
+ <point positionX="10170" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10170" positionY="150"/>
+ <point positionX="10170" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13560" positionY="150"/>
+ <point positionX="13560" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13560" positionY="150"/>
+ <point positionX="13560" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="13560.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="150.000000" column3="8172.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="756" positionY="8172" sizeX="13560" sizeY="0" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="756" positionY="8172"/>
+ <point positionX="14316" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="13560" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="13560.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="0.000000" column3="8172.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13561.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="151.000000" column3="8172.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="606" positionY="378" sizeX="150" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="606" positionY="378" sizeX="150" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="606" positionY="8172"/>
+ <point positionX="756" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="8172"/>
+ <point positionX="756" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="7058"/>
+ <point positionX="756" positionY="7058"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="7058"/>
+ <point positionX="756" positionY="7058"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="5945"/>
+ <point positionX="756" positionY="5945"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="5945"/>
+ <point positionX="756" positionY="5945"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="4832"/>
+ <point positionX="756" positionY="4832"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="4832"/>
+ <point positionX="756" positionY="4832"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="3718"/>
+ <point positionX="756" positionY="3718"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="3718"/>
+ <point positionX="756" positionY="3718"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="2605"/>
+ <point positionX="756" positionY="2605"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="2605"/>
+ <point positionX="756" positionY="2605"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="1492"/>
+ <point positionX="756" positionY="1492"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="1492"/>
+ <point positionX="756" positionY="1492"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="378"/>
+ <point positionX="756" positionY="378"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="378"/>
+ <point positionX="756" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="150" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="150" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="6680"/>
+ <point positionX="150" positionY="6680"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="6680"/>
+ <point positionX="150" positionY="6680"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="5567"/>
+ <point positionX="150" positionY="5567"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="5567"/>
+ <point positionX="150" positionY="5567"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="4454"/>
+ <point positionX="150" positionY="4454"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="4454"/>
+ <point positionX="150" positionY="4454"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="3340"/>
+ <point positionX="150" positionY="3340"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="3340"/>
+ <point positionX="150" positionY="3340"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="2227"/>
+ <point positionX="150" positionY="2227"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="2227"/>
+ <point positionX="150" positionY="2227"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="1114"/>
+ <point positionX="150" positionY="1114"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="1114"/>
+ <point positionX="150" positionY="1114"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="150" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="150" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="150.000000" column2="0.000000" column3="606.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="756" positionY="378" sizeX="0" sizeY="7794" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="756" positionY="8172"/>
+ <point positionX="756" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="151.000000" column2="0.000000" column3="606.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13711.000000" column2="0.000000" column3="606.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1321" positionY="1492" sizeX="12430" sizeY="6680" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1321" positionY="3718" sizeX="11300" sizeY="4454" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0">
+ <XShapes>
+ <XShape positionX="1321" positionY="7058" sizeX="1130" sizeY="1114" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff0000" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="1321" positionY="8172"/>
+ <point positionX="2451" positionY="8172"/>
+ <point positionX="2451" positionY="7058"/>
+ <point positionX="1321" positionY="7058"/>
+ <point positionX="1321" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="1114"/>
+ <point positionX="1130" positionY="1114"/>
+ <point positionX="1130" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="1114"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1130.000000" column2="0.000000" column3="1321.000000"/>
+ <Line2 column1="0.000000" column2="1114.000000" column3="7058.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4711" positionY="5945" sizeX="1130" sizeY="2227" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="00ff00" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="4711" positionY="8172"/>
+ <point positionX="5841" positionY="8172"/>
+ <point positionX="5841" positionY="5945"/>
+ <point positionX="4711" positionY="5945"/>
+ <point positionX="4711" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="2227"/>
+ <point positionX="1130" positionY="2227"/>
+ <point positionX="1130" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="2227"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1130.000000" column2="0.000000" column3="4711.000000"/>
+ <Line2 column1="0.000000" column2="2227.000000" column3="5945.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8101" positionY="4832" sizeX="1130" sizeY="3340" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="0000ff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="8101" positionY="8172"/>
+ <point positionX="9231" positionY="8172"/>
+ <point positionX="9231" positionY="4832"/>
+ <point positionX="8101" positionY="4832"/>
+ <point positionX="8101" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="3340"/>
+ <point positionX="1130" positionY="3340"/>
+ <point positionX="1130" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="3340"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1130.000000" column2="0.000000" column3="8101.000000"/>
+ <Line2 column1="0.000000" column2="3340.000000" column3="4832.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="11491" positionY="3718" sizeX="1130" sizeY="4454" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=3" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="11491" positionY="8172"/>
+ <point positionX="12621" positionY="8172"/>
+ <point positionX="12621" positionY="3718"/>
+ <point positionX="11491" positionY="3718"/>
+ <point positionX="11491" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="4454"/>
+ <point positionX="1130" positionY="4454"/>
+ <point positionX="1130" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="4454"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1130.000000" column2="0.000000" column3="11491.000000"/>
+ <Line2 column1="0.000000" column2="4454.000000" column3="3718.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="11301.000000" column2="0.000000" column3="1321.000000"/>
+ <Line2 column1="0.000000" column2="4455.000000" column3="3718.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2451" positionY="1492" sizeX="11300" sizeY="6680" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=1">
+ <XShapes>
+ <XShape positionX="2451" positionY="4832" sizeX="1130" sizeY="3340" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="2451" positionY="8172"/>
+ <point positionX="3581" positionY="8172"/>
+ <point positionX="3581" positionY="4832"/>
+ <point positionX="2451" positionY="4832"/>
+ <point positionX="2451" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="3340"/>
+ <point positionX="1130" positionY="3340"/>
+ <point positionX="1130" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="3340"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1130.000000" column2="0.000000" column3="2451.000000"/>
+ <Line2 column1="0.000000" column2="3340.000000" column3="4832.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="5841" positionY="3718" sizeX="1130" sizeY="4454" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="5841" positionY="8172"/>
+ <point positionX="6971" positionY="8172"/>
+ <point positionX="6971" positionY="3718"/>
+ <point positionX="5841" positionY="3718"/>
+ <point positionX="5841" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="4454"/>
+ <point positionX="1130" positionY="4454"/>
+ <point positionX="1130" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="4454"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1130.000000" column2="0.000000" column3="5841.000000"/>
+ <Line2 column1="0.000000" column2="4454.000000" column3="3718.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9231" positionY="2605" sizeX="1130" sizeY="5567" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="9231" positionY="8172"/>
+ <point positionX="10361" positionY="8172"/>
+ <point positionX="10361" positionY="2605"/>
+ <point positionX="9231" positionY="2605"/>
+ <point positionX="9231" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="5567"/>
+ <point positionX="1130" positionY="5567"/>
+ <point positionX="1130" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="5567"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1130.000000" column2="0.000000" column3="9231.000000"/>
+ <Line2 column1="0.000000" column2="5567.000000" column3="2605.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12621" positionY="1492" sizeX="1130" sizeY="6680" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=3" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="12621" positionY="8172"/>
+ <point positionX="13751" positionY="8172"/>
+ <point positionX="13751" positionY="1492"/>
+ <point positionX="12621" positionY="1492"/>
+ <point positionX="12621" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="6680"/>
+ <point positionX="1130" positionY="6680"/>
+ <point positionX="1130" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="6680"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1130.000000" column2="0.000000" column3="12621.000000"/>
+ <Line2 column1="0.000000" column2="6680.000000" column3="1492.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="11301.000000" column2="0.000000" column3="2451.000000"/>
+ <Line2 column1="0.000000" column2="6681.000000" column3="1492.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12431.000000" column2="0.000000" column3="1321.000000"/>
+ <Line2 column1="0.000000" column2="6681.000000" column3="1492.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13711.000000" column2="0.000000" column3="606.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13711.000000" column2="0.000000" column3="606.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="12395" sizeY="8640" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="2358" positionY="8422" sizeX="10357" sizeY="398" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=0,0">
+ <XShapes>
+ <XShape positionX="2358" positionY="8422" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="1" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="2358.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="5748" positionY="8422" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="2" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="5748.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9138" positionY="8422" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="3" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="9138.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12528" positionY="8422" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="4" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="12528.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10358.000000" column2="0.000000" column3="2358.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="187" sizeY="8192" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="320" positionY="7974" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="0" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="7974.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="6860" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="1" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="6860.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="5747" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="2" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="5747.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="4634" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="3" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4634.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="3520" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="4" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="3520.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="2407" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="5" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="2407.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="1294" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="6" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="1294.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="7" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8193.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12396.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13997.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13997.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14636" positionY="3952" sizeX="1154" sizeY="1096" type="com.sun.star.drawing.GroupShape" name="CID/D=0:Legend=">
+ <XShapes>
+ <XShape positionX="14636" positionY="3952" sizeX="1154" sizeY="1096" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="e6e6e6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1155.000000" column2="0.000000" column3="14636.000000"/>
+ <Line2 column1="0.000000" column2="1097.000000" column3="3952.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14752" positionY="4145" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="14752" positionY="4145" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="14752" positionY="4145" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14752.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14752" positionY="4145" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14752.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14752.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14752.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14752" positionY="4643" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="14752" positionY="4643" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="14752" positionY="4643" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14752.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14752" positionY="4643" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14752.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14752.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14752.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="15063" positionY="4052" sizeX="611" sizeY="398" type="com.sun.star.drawing.TextShape" text="col1" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="4800" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="612.000000" column2="0.000000" column3="15063.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4052.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="15063" positionY="4550" sizeX="611" sizeY="398" type="com.sun.star.drawing.TextShape" text="col2" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="4800" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="612.000000" column2="0.000000" column3="15063.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4550.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1155.000000" column2="0.000000" column3="14636.000000"/>
+ <Line2 column1="0.000000" column2="1097.000000" column3="3952.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+</XShapes>
+
+
diff --git a/chart2/qa/extras/xshape/data/reference/tdf149204.xml b/chart2/qa/extras/xshape/data/reference/tdf149204.xml
new file mode 100644
index 0000000000..5e157983d0
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/tdf149204.xml
@@ -0,0 +1,397 @@
+<?xml version="1.0"?>
+<XShapes>
+ <XShape positionX="0" positionY="0" sizeX="14277" sizeY="10471" type="com.sun.star.drawing.RectangleShape" name="CID/Page=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="14278.000000" column2="0.000000" column3="0.000000"/>
+ <Line2 column1="0.000000" column2="10472.000000" column3="0.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1741" positionY="1996" sizeX="12230" sizeY="7836" type="com.sun.star.drawing.GroupShape" name="CID/D=0">
+ <XShapes>
+ <XShape positionX="1741" positionY="1996" sizeX="12230" sizeY="7836" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="12231.000000" column2="0.000000" column3="1741.000000"/>
+ <Line2 column1="0.000000" column2="7837.000000" column3="1996.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1741" positionY="2023" sizeX="12230" sizeY="7782" type="com.sun.star.drawing.RectangleShape" name="PlotAreaIncludingAxes" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="12231.000000" column2="0.000000" column3="1741.000000"/>
+ <Line2 column1="0.000000" column2="7783.000000" column3="2023.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1741" positionY="2023" sizeX="12230" sizeY="7782" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1741" positionY="2023" sizeX="12230" sizeY="7782" type="com.sun.star.drawing.Shape3DSceneObject" name="PlotAreaExcludingAxes"/>
+ <XShape positionX="3838" positionY="3445" sizeX="9322" sizeY="5248" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="3838" positionY="3445" sizeX="9322" sizeY="5248" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="12788" positionY="8216" sizeX="372" sizeY="477" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0:DataLabels=">
+ <XShapes>
+ <XShape positionX="12788" positionY="8216" sizeX="372" sizeY="477" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0">
+ <XShapes>
+ <XShape positionX="12788" positionY="8216" sizeX="372" sizeY="477" type="com.sun.star.drawing.TextShape" text="13" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="3490" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="373.000000" column2="0.000000" column3="12788.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="8216.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="373.000000" column2="0.000000" column3="12788.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="8216.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="373.000000" column2="0.000000" column3="12788.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="8216.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7092" positionY="5831" sizeX="187" sizeY="477" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=1:DataLabels=">
+ <XShapes>
+ <XShape positionX="7092" positionY="5831" sizeX="187" sizeY="477" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=1:DataLabels=:DataLabel=0">
+ <XShapes>
+ <XShape positionX="7092" positionY="5831" sizeX="187" sizeY="477" type="com.sun.star.drawing.TextShape" text="6" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="3490" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="7092.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="5831.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="7092.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="5831.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="7092.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="5831.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="3838" positionY="3445" sizeX="187" sizeY="477" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=2:DataLabels=">
+ <XShapes>
+ <XShape positionX="3838" positionY="3445" sizeX="187" sizeY="477" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=2:DataLabels=:DataLabel=0">
+ <XShapes>
+ <XShape positionX="3838" positionY="3445" sizeX="187" sizeY="477" type="com.sun.star.drawing.TextShape" text="2" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="3490" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="3838.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="3445.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="3838.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="3445.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="3838.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="3445.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9323.000000" column2="0.000000" column3="3838.000000"/>
+ <Line2 column1="0.000000" column2="5249.000000" column3="3445.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9323.000000" column2="0.000000" column3="3838.000000"/>
+ <Line2 column1="0.000000" column2="5249.000000" column3="3445.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12231.000000" column2="0.000000" column3="1741.000000"/>
+ <Line2 column1="0.000000" column2="7783.000000" column3="2023.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12231.000000" column2="0.000000" column3="1741.000000"/>
+ <Line2 column1="0.000000" column2="7837.000000" column3="1996.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4074" positionY="985" sizeX="9260" sizeY="1295" type="com.sun.star.drawing.TextShape" name="CID/Title=" text="Gr&#xE1;fico de Colunas ou Barras" fontHeight="18.600000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="118" textRightDistance="118" textUpperDistance="197" textLowerDistance="197" textMaximumFrameHeight="0" textMaximumFrameWidth="11421" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="d9d9d9" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="9261.000000" column2="0.000000" column3="4074.000000"/>
+ <Line2 column1="0.000000" column2="1296.000000" column3="985.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4958" positionY="9793" sizeX="4360" sizeY="677" type="com.sun.star.drawing.GroupShape" name="CID/D=0:Legend=">
+ <XShapes>
+ <XShape positionX="4958" positionY="9793" sizeX="4360" sizeY="677" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="d9d9d9" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4361.000000" column2="0.000000" column3="4958.000000"/>
+ <Line2 column1="0.000000" column2="678.000000" column3="9793.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7910" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="7910" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="7910" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="7910.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7910" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="5b9bd5" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="7910.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="7910.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="7910.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6439" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="6439" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="6439" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="6439.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6439" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ed7d31" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="6439.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="6439.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="6439.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="5074" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="5074" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=2:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="5074" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="5074.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="5074" positionY="10026" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="a5a5a5" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="5074.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="5074.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="5074.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="10026.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="5385" positionY="9893" sizeX="822" sizeY="477" type="com.sun.star.drawing.TextShape" text="Cupe" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="13966" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="823.000000" column2="0.000000" column3="5385.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="9893.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6750" positionY="9893" sizeX="928" sizeY="477" type="com.sun.star.drawing.TextShape" text="Hatch" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="13966" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="929.000000" column2="0.000000" column3="6750.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="9893.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8221" positionY="9893" sizeX="981" sizeY="477" type="com.sun.star.drawing.TextShape" text="Sedan" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="13966" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="982.000000" column2="0.000000" column3="8221.000000"/>
+ <Line2 column1="0.000000" column2="478.000000" column3="9893.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="4361.000000" column2="0.000000" column3="4958.000000"/>
+ <Line2 column1="0.000000" column2="678.000000" column3="9793.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+</XShapes>
+
+
diff --git a/chart2/qa/extras/xshape/data/reference/tdf150832.xml b/chart2/qa/extras/xshape/data/reference/tdf150832.xml
new file mode 100644
index 0000000000..66730ab850
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/tdf150832.xml
@@ -0,0 +1,974 @@
+<?xml version="1.0"?>
+<XShapes>
+ <XShape positionX="0" positionY="0" sizeX="15990" sizeY="8998" type="com.sun.star.drawing.RectangleShape" name="CID/Page=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="15991.000000" column2="0.000000" column3="0.000000"/>
+ <Line2 column1="0.000000" column2="8999.000000" column3="0.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="179" sizeX="13089" sizeY="8640" type="com.sun.star.drawing.GroupShape" name="CID/D=0">
+ <XShapes>
+ <XShape positionX="755" positionY="379" sizeX="12653" sizeY="7793" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="12654.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="379.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="179" sizeX="13089" sizeY="8640" type="com.sun.star.drawing.RectangleShape" name="PlotAreaIncludingAxes" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="13090.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="179.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="179" sizeX="13089" sizeY="8640" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="605" positionY="377" sizeX="12803" sizeY="7944" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="755" positionY="379" sizeX="12653" sizeY="7793" type="com.sun.star.drawing.GroupShape" name="PlotAreaExcludingAxes">
+ <XShapes>
+ <XShape positionX="755" positionY="379" sizeX="12653" sizeY="7793" type="com.sun.star.drawing.RectangleShape" name="CID/DiagramWall=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="000000" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="12654.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="379.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12654.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="379.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="605" positionY="377" sizeX="12803" sizeY="7944" type="com.sun.star.drawing.GroupShape" name="testonly;CooContainer=XXX_CID">
+ <XShapes>
+ <XShape positionX="755" positionY="377" sizeX="12653" sizeY="7794" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="755" positionY="377" sizeX="12653" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0:Grid=0">
+ <XShapes>
+ <XShape positionX="755" positionY="377" sizeX="12653" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="13408" positionY="8171"/>
+ <point positionX="755" positionY="8171"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13408" positionY="7057"/>
+ <point positionX="755" positionY="7057"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13408" positionY="5944"/>
+ <point positionX="755" positionY="5944"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13408" positionY="4831"/>
+ <point positionX="755" positionY="4831"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13408" positionY="3717"/>
+ <point positionX="755" positionY="3717"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13408" positionY="2604"/>
+ <point positionX="755" positionY="2604"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13408" positionY="1491"/>
+ <point positionX="755" positionY="1491"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13408" positionY="377"/>
+ <point positionX="755" positionY="377"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="12653" positionY="7794"/>
+ <point positionX="0" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12653" positionY="6680"/>
+ <point positionX="0" positionY="6680"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12653" positionY="5567"/>
+ <point positionX="0" positionY="5567"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12653" positionY="4454"/>
+ <point positionX="0" positionY="4454"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12653" positionY="3340"/>
+ <point positionX="0" positionY="3340"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12653" positionY="2227"/>
+ <point positionX="0" positionY="2227"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12653" positionY="1114"/>
+ <point positionX="0" positionY="1114"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12653" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="12653.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="377.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="755" positionY="377" sizeX="0" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" name="HandlesOnly" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="NONE">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="755" positionY="8171"/>
+ <point positionX="755" positionY="7057"/>
+ <point positionX="755" positionY="5944"/>
+ <point positionX="755" positionY="4831"/>
+ <point positionX="755" positionY="3717"/>
+ <point positionX="755" positionY="2604"/>
+ <point positionX="755" positionY="1491"/>
+ <point positionX="755" positionY="377"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="0" positionY="6680"/>
+ <point positionX="0" positionY="5567"/>
+ <point positionX="0" positionY="4454"/>
+ <point positionX="0" positionY="3340"/>
+ <point positionX="0" positionY="2227"/>
+ <point positionX="0" positionY="1114"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="377.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12654.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="377.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12654.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="377.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="605" positionY="377" sizeX="12803" sizeY="7944" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="755" positionY="8171" sizeX="12653" sizeY="150" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=0,0">
+ <XShapes>
+ <XShape positionX="755" positionY="8171" sizeX="12653" sizeY="150" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="755" positionY="8321"/>
+ <point positionX="755" positionY="8171"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="4972" positionY="8321"/>
+ <point positionX="4972" positionY="8171"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="9190" positionY="8321"/>
+ <point positionX="9190" positionY="8171"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13408" positionY="8321"/>
+ <point positionX="13408" positionY="8171"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="150"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="4217" positionY="150"/>
+ <point positionX="4217" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="8435" positionY="150"/>
+ <point positionX="8435" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="12653" positionY="150"/>
+ <point positionX="12653" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="12653.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="150.000000" column3="8171.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="755" positionY="8171" sizeX="12653" sizeY="0" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="755" positionY="8171"/>
+ <point positionX="13408" positionY="8171"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="12653" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="12653.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="0.000000" column3="8171.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12654.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="151.000000" column3="8171.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="605" positionY="377" sizeX="150" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="605" positionY="377" sizeX="150" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="605" positionY="8171"/>
+ <point positionX="755" positionY="8171"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="605" positionY="7057"/>
+ <point positionX="755" positionY="7057"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="605" positionY="5944"/>
+ <point positionX="755" positionY="5944"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="605" positionY="4831"/>
+ <point positionX="755" positionY="4831"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="605" positionY="3717"/>
+ <point positionX="755" positionY="3717"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="605" positionY="2604"/>
+ <point positionX="755" positionY="2604"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="605" positionY="1491"/>
+ <point positionX="755" positionY="1491"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="605" positionY="377"/>
+ <point positionX="755" positionY="377"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="150" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="6680"/>
+ <point positionX="150" positionY="6680"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="5567"/>
+ <point positionX="150" positionY="5567"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="4454"/>
+ <point positionX="150" positionY="4454"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="3340"/>
+ <point positionX="150" positionY="3340"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="2227"/>
+ <point positionX="150" positionY="2227"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="1114"/>
+ <point positionX="150" positionY="1114"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="150" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="150.000000" column2="0.000000" column3="605.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="377.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="755" positionY="377" sizeX="0" sizeY="7794" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="755" positionY="8171"/>
+ <point positionX="755" positionY="377"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="755.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="377.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="151.000000" column2="0.000000" column3="605.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="377.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12804.000000" column2="0.000000" column3="605.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="377.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1457" positionY="1491" sizeX="11248" sizeY="6680" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1457" positionY="2604" sizeX="9842" sizeY="5567" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0">
+ <XShapes>
+ <XShape positionX="1457" positionY="7057" sizeX="1406" sizeY="1114" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="1457" positionY="8171"/>
+ <point positionX="2863" positionY="8171"/>
+ <point positionX="2863" positionY="7057"/>
+ <point positionX="1457" positionY="7057"/>
+ <point positionX="1457" positionY="8171"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="1114"/>
+ <point positionX="1406" positionY="1114"/>
+ <point positionX="1406" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="1114"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1406.000000" column2="0.000000" column3="1457.000000"/>
+ <Line2 column1="0.000000" column2="1114.000000" column3="7057.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="5675" positionY="4831" sizeX="1406" sizeY="3340" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="5675" positionY="8171"/>
+ <point positionX="7081" positionY="8171"/>
+ <point positionX="7081" positionY="4831"/>
+ <point positionX="5675" positionY="4831"/>
+ <point positionX="5675" positionY="8171"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="3340"/>
+ <point positionX="1406" positionY="3340"/>
+ <point positionX="1406" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="3340"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1406.000000" column2="0.000000" column3="5675.000000"/>
+ <Line2 column1="0.000000" column2="3340.000000" column3="4831.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9893" positionY="2604" sizeX="1406" sizeY="5567" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="9893" positionY="8171"/>
+ <point positionX="11299" positionY="8171"/>
+ <point positionX="11299" positionY="2604"/>
+ <point positionX="9893" positionY="2604"/>
+ <point positionX="9893" positionY="8171"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="5567"/>
+ <point positionX="1406" positionY="5567"/>
+ <point positionX="1406" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="5567"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1406.000000" column2="0.000000" column3="9893.000000"/>
+ <Line2 column1="0.000000" column2="5567.000000" column3="2604.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9843.000000" column2="0.000000" column3="1457.000000"/>
+ <Line2 column1="0.000000" column2="5568.000000" column3="2604.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2863" positionY="1491" sizeX="9842" sizeY="6680" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=1">
+ <XShapes>
+ <XShape positionX="2863" positionY="5944" sizeX="1406" sizeY="2227" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="2863" positionY="8171"/>
+ <point positionX="4269" positionY="8171"/>
+ <point positionX="4269" positionY="5944"/>
+ <point positionX="2863" positionY="5944"/>
+ <point positionX="2863" positionY="8171"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="2227"/>
+ <point positionX="1406" positionY="2227"/>
+ <point positionX="1406" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="2227"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1406.000000" column2="0.000000" column3="2863.000000"/>
+ <Line2 column1="0.000000" column2="2227.000000" column3="5944.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7081" positionY="3717" sizeX="1406" sizeY="4454" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="8171"/>
+ <point positionX="8487" positionY="8171"/>
+ <point positionX="8487" positionY="3717"/>
+ <point positionX="7081" positionY="3717"/>
+ <point positionX="7081" positionY="8171"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="4454"/>
+ <point positionX="1406" positionY="4454"/>
+ <point positionX="1406" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="4454"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1406.000000" column2="0.000000" column3="7081.000000"/>
+ <Line2 column1="0.000000" column2="4454.000000" column3="3717.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="11299" positionY="1491" sizeX="1406" sizeY="6680" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="11299" positionY="8171"/>
+ <point positionX="12705" positionY="8171"/>
+ <point positionX="12705" positionY="1491"/>
+ <point positionX="11299" positionY="1491"/>
+ <point positionX="11299" positionY="8171"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="6680"/>
+ <point positionX="1406" positionY="6680"/>
+ <point positionX="1406" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="6680"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="1406.000000" column2="0.000000" column3="11299.000000"/>
+ <Line2 column1="0.000000" column2="6680.000000" column3="1491.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9843.000000" column2="0.000000" column3="2863.000000"/>
+ <Line2 column1="0.000000" column2="6681.000000" column3="1491.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="11249.000000" column2="0.000000" column3="1457.000000"/>
+ <Line2 column1="0.000000" column2="6681.000000" column3="1491.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12804.000000" column2="0.000000" column3="605.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="377.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12804.000000" column2="0.000000" column3="605.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="377.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="179" sizeX="11074" sizeY="8640" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="2770" positionY="8421" sizeX="8623" sizeY="398" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=0,0">
+ <XShapes>
+ <XShape positionX="2770" positionY="8421" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="1" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="2770.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8421.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6988" positionY="8421" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="2" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="6988.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8421.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="11206" positionY="8421" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="3" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="11206.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8421.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="8624.000000" column2="0.000000" column3="2770.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8421.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="179" sizeX="187" sizeY="8192" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="319" positionY="7973" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="0" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="7973.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="6859" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="1" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="6859.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="5746" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="2" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="5746.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="4633" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="3" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4633.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="3519" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="4" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="3519.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="2406" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="5" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="2406.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="1293" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="6" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="1293.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="319" positionY="179" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="7" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="179.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="8193.000000" column3="179.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="11075.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="179.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13090.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="179.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13090.000000" column2="0.000000" column3="319.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="179.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="13727" positionY="3951" sizeX="2053" sizeY="1096" type="com.sun.star.drawing.GroupShape" name="CID/D=0:Legend=">
+ <XShapes>
+ <XShape positionX="13727" positionY="3951" sizeX="2053" sizeY="1096" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="000000" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="2054.000000" column2="0.000000" column3="13727.000000"/>
+ <Line2 column1="0.000000" column2="1097.000000" column3="3951.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="13843" positionY="4144" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="13843" positionY="4144" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="13843" positionY="4144" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="13843.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4144.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="13843" positionY="4144" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="13843.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4144.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="13843.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4144.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="13843.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4144.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="13843" positionY="4642" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="13843" positionY="4642" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="13843" positionY="4642" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="13843.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4642.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="13843" positionY="4642" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="13843.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4642.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="13843.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4642.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="13843.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4642.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14154" positionY="4051" sizeX="1510" sizeY="398" type="com.sun.star.drawing.TextShape" text="Column A" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="4797" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1511.000000" column2="0.000000" column3="14154.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4051.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14154" positionY="4549" sizeX="1510" sizeY="398" type="com.sun.star.drawing.TextShape" text="Column B" fontHeight="10.000000" fontColor="000000" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="4797" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1511.000000" column2="0.000000" column3="14154.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4549.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="2054.000000" column2="0.000000" column3="13727.000000"/>
+ <Line2 column1="0.000000" column2="1097.000000" column3="3951.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+</XShapes>
+
+
diff --git a/chart2/qa/extras/xshape/data/reference/tdf151424.xml b/chart2/qa/extras/xshape/data/reference/tdf151424.xml
new file mode 100644
index 0000000000..c1aafbbd6a
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/tdf151424.xml
@@ -0,0 +1,1160 @@
+<?xml version="1.0"?>
+<XShapes>
+ <XShape positionX="0" positionY="0" sizeX="16011" sizeY="9010" type="com.sun.star.drawing.RectangleShape" name="CID/Page=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="16012.000000" column2="0.000000" column3="0.000000"/>
+ <Line2 column1="0.000000" column2="9011.000000" column3="0.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="13524" sizeY="8650" type="com.sun.star.drawing.GroupShape" name="CID/D=0">
+ <XShapes>
+ <XShape positionX="3730" positionY="1154" sizeX="6703" sizeY="6703" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6704.000000" column2="0.000000" column3="3730.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1154.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="13524" sizeY="8650" type="com.sun.star.drawing.RectangleShape" name="PlotAreaIncludingAxes" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="13525.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8651.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2991" positionY="180" sizeX="8181" sizeY="8650" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="3730" positionY="1153" sizeX="6703" sizeY="6704" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="3730" positionY="1154" sizeX="6703" sizeY="6703" type="com.sun.star.drawing.GroupShape" name="PlotAreaExcludingAxes">
+ <XShapes>
+ <XShape positionX="3730" positionY="1154" sizeX="6703" sizeY="6703" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="e6e6e6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6704.000000" column2="0.000000" column3="3730.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1154.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="6704.000000" column2="0.000000" column3="3730.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1154.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4104" positionY="1153" sizeX="5954" sizeY="6703" type="com.sun.star.drawing.GroupShape" name="testonly;CooContainer=XXX_CID">
+ <XShapes>
+ <XShape positionX="4179" positionY="1153" sizeX="5804" sizeY="6703" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="4179" positionY="1153" sizeX="5804" sizeY="6703" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0:Grid=0">
+ <XShapes>
+ <XShape positionX="4179" positionY="1153" sizeX="5804" sizeY="6703" type="com.sun.star.drawing.PolyLineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="4504"/>
+ <point positionX="7081" positionY="4504"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7081" positionY="1153"/>
+ <point positionX="4179" positionY="2828"/>
+ <point positionX="4179" positionY="6180"/>
+ <point positionX="7081" positionY="7856"/>
+ <point positionX="9983" positionY="6180"/>
+ <point positionX="9983" positionY="2828"/>
+ <point positionX="7081" positionY="1153"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="2902" positionY="3351"/>
+ <point positionX="2902" positionY="3351"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="2902" positionY="0"/>
+ <point positionX="0" positionY="1675"/>
+ <point positionX="0" positionY="5027"/>
+ <point positionX="2902" positionY="6703"/>
+ <point positionX="5804" positionY="5027"/>
+ <point positionX="5804" positionY="1675"/>
+ <point positionX="2902" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="5804.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="6703.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5805.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5805.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4104" positionY="1153" sizeX="5954" sizeY="6703" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="4179" positionY="1153" sizeX="5804" sizeY="6703" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=0,0">
+ <XShapes>
+ <XShape positionX="4179" positionY="1153" sizeX="5804" sizeY="6703" type="com.sun.star.drawing.PolyLineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="1153"/>
+ <point positionX="4179" positionY="2828"/>
+ <point positionX="4179" positionY="6180"/>
+ <point positionX="7081" positionY="7856"/>
+ <point positionX="9983" positionY="6180"/>
+ <point positionX="9983" positionY="2828"/>
+ <point positionX="7081" positionY="1153"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="2902" positionY="0"/>
+ <point positionX="0" positionY="1675"/>
+ <point positionX="0" positionY="5027"/>
+ <point positionX="2902" positionY="6703"/>
+ <point positionX="5804" positionY="5027"/>
+ <point positionX="5804" positionY="1675"/>
+ <point positionX="2902" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="5804.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="6703.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5805.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6931" positionY="1153" sizeX="300" sizeY="3351" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="6931" positionY="1153" sizeX="300" sizeY="3351" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7231" positionY="4504"/>
+ <point positionX="6931" positionY="4504"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7231" positionY="4504"/>
+ <point positionX="6931" positionY="4504"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7231" positionY="1153"/>
+ <point positionX="6931" positionY="1153"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7231" positionY="1153"/>
+ <point positionX="6931" positionY="1153"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="300" positionY="3351"/>
+ <point positionX="0" positionY="3351"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="300" positionY="3351"/>
+ <point positionX="0" positionY="3351"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="300" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="300" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="300.000000" column2="0.000000" column3="6931.000000"/>
+ <Line2 column1="0.000000" column2="3351.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7081" positionY="1153" sizeX="0" sizeY="3351" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="4504"/>
+ <point positionX="7081" positionY="1153"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="3351"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="7081.000000"/>
+ <Line2 column1="0.000000" column2="3351.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="301.000000" column2="0.000000" column3="6931.000000"/>
+ <Line2 column1="0.000000" column2="3352.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4104" positionY="2698" sizeX="3052" sizeY="1936" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="4104" positionY="2698" sizeX="3052" sizeY="1936" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7156" positionY="4374"/>
+ <point positionX="7006" positionY="4634"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7156" positionY="4374"/>
+ <point positionX="7006" positionY="4634"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="4254" positionY="2698"/>
+ <point positionX="4104" positionY="2958"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="4254" positionY="2698"/>
+ <point positionX="4104" positionY="2958"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="3052" positionY="1676"/>
+ <point positionX="2902" positionY="1936"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="3052" positionY="1676"/>
+ <point positionX="2902" positionY="1936"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="0"/>
+ <point positionX="0" positionY="260"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="0"/>
+ <point positionX="0" positionY="260"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="3052.000000" column2="0.000000" column3="4104.000000"/>
+ <Line2 column1="0.000000" column2="1936.000000" column3="2698.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4179" positionY="2828" sizeX="2902" sizeY="1676" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="4504"/>
+ <point positionX="4179" positionY="2828"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="2902" positionY="1676"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="2902.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="1676.000000" column3="2828.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="3053.000000" column2="0.000000" column3="4104.000000"/>
+ <Line2 column1="0.000000" column2="1937.000000" column3="2698.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4104" positionY="4374" sizeX="3052" sizeY="1936" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="4104" positionY="4374" sizeX="3052" sizeY="1936" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7006" positionY="4374"/>
+ <point positionX="7156" positionY="4634"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7006" positionY="4374"/>
+ <point positionX="7156" positionY="4634"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="4104" positionY="6050"/>
+ <point positionX="4254" positionY="6310"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="4104" positionY="6050"/>
+ <point positionX="4254" positionY="6310"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="2902" positionY="0"/>
+ <point positionX="3052" positionY="260"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="2902" positionY="0"/>
+ <point positionX="3052" positionY="260"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="1676"/>
+ <point positionX="150" positionY="1936"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="1676"/>
+ <point positionX="150" positionY="1936"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="3052.000000" column2="0.000000" column3="4104.000000"/>
+ <Line2 column1="0.000000" column2="1936.000000" column3="4374.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4179" positionY="4504" sizeX="2902" sizeY="1676" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="4504"/>
+ <point positionX="4179" positionY="6180"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="2902" positionY="0"/>
+ <point positionX="0" positionY="1676"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="2902.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="1676.000000" column3="4504.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="3053.000000" column2="0.000000" column3="4104.000000"/>
+ <Line2 column1="0.000000" column2="1937.000000" column3="4374.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6931" positionY="4504" sizeX="300" sizeY="3352" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="6931" positionY="4504" sizeX="300" sizeY="3352" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="6931" positionY="4504"/>
+ <point positionX="7231" positionY="4504"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="6931" positionY="4504"/>
+ <point positionX="7231" positionY="4504"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="6931" positionY="7856"/>
+ <point positionX="7231" positionY="7856"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="6931" positionY="7856"/>
+ <point positionX="7231" positionY="7856"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="300" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="300" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="3352"/>
+ <point positionX="300" positionY="3352"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="3352"/>
+ <point positionX="300" positionY="3352"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="300.000000" column2="0.000000" column3="6931.000000"/>
+ <Line2 column1="0.000000" column2="3352.000000" column3="4504.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7081" positionY="4504" sizeX="0" sizeY="3352" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="4504"/>
+ <point positionX="7081" positionY="7856"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="3352"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="7081.000000"/>
+ <Line2 column1="0.000000" column2="3352.000000" column3="4504.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="301.000000" column2="0.000000" column3="6931.000000"/>
+ <Line2 column1="0.000000" column2="3353.000000" column3="4504.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7006" positionY="4374" sizeX="3052" sizeY="1936" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="7006" positionY="4374" sizeX="3052" sizeY="1936" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7006" positionY="4634"/>
+ <point positionX="7156" positionY="4374"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7006" positionY="4634"/>
+ <point positionX="7156" positionY="4374"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="9908" positionY="6310"/>
+ <point positionX="10058" positionY="6050"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="9908" positionY="6310"/>
+ <point positionX="10058" positionY="6050"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="260"/>
+ <point positionX="150" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="260"/>
+ <point positionX="150" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="2902" positionY="1936"/>
+ <point positionX="3052" positionY="1676"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="2902" positionY="1936"/>
+ <point positionX="3052" positionY="1676"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="3052.000000" column2="0.000000" column3="7006.000000"/>
+ <Line2 column1="0.000000" column2="1936.000000" column3="4374.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7081" positionY="4504" sizeX="2902" sizeY="1676" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="4504"/>
+ <point positionX="9983" positionY="6180"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="2902" positionY="1676"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="2902.000000" column2="0.000000" column3="7081.000000"/>
+ <Line2 column1="0.000000" column2="1676.000000" column3="4504.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="3053.000000" column2="0.000000" column3="7006.000000"/>
+ <Line2 column1="0.000000" column2="1937.000000" column3="4374.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7006" positionY="2698" sizeX="3052" sizeY="1936" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="7006" positionY="2698" sizeX="3052" sizeY="1936" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7156" positionY="4634"/>
+ <point positionX="7006" positionY="4374"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7156" positionY="4634"/>
+ <point positionX="7006" positionY="4374"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10058" positionY="2958"/>
+ <point positionX="9908" positionY="2698"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10058" positionY="2958"/>
+ <point positionX="9908" positionY="2698"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="150" positionY="1936"/>
+ <point positionX="0" positionY="1676"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="150" positionY="1936"/>
+ <point positionX="0" positionY="1676"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="3052" positionY="260"/>
+ <point positionX="2902" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="3052" positionY="260"/>
+ <point positionX="2902" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="3052.000000" column2="0.000000" column3="7006.000000"/>
+ <Line2 column1="0.000000" column2="1936.000000" column3="2698.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7081" positionY="2828" sizeX="2902" sizeY="1676" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="4504"/>
+ <point positionX="9983" positionY="2828"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="1676"/>
+ <point positionX="2902" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="2902.000000" column2="0.000000" column3="7081.000000"/>
+ <Line2 column1="0.000000" column2="1676.000000" column3="2828.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="3053.000000" column2="0.000000" column3="7006.000000"/>
+ <Line2 column1="0.000000" column2="1937.000000" column3="2698.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6931" positionY="1153" sizeX="300" sizeY="3351" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="6931" positionY="1153" sizeX="300" sizeY="3351" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7231" positionY="4504"/>
+ <point positionX="6931" positionY="4504"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7231" positionY="4504"/>
+ <point positionX="6931" positionY="4504"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7231" positionY="1153"/>
+ <point positionX="6931" positionY="1153"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="7231" positionY="1153"/>
+ <point positionX="6931" positionY="1153"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="300" positionY="3351"/>
+ <point positionX="0" positionY="3351"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="300" positionY="3351"/>
+ <point positionX="0" positionY="3351"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="300" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="300" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="300.000000" column2="0.000000" column3="6931.000000"/>
+ <Line2 column1="0.000000" column2="3351.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7081" positionY="1153" sizeX="0" sizeY="3351" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="4504"/>
+ <point positionX="7081" positionY="1153"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="3351"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="7081.000000"/>
+ <Line2 column1="0.000000" column2="3351.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="301.000000" column2="0.000000" column3="6931.000000"/>
+ <Line2 column1="0.000000" column2="3352.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5955.000000" column2="0.000000" column3="4104.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4179" positionY="1153" sizeX="5804" sizeY="6703" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="5340" positionY="3163" sizeX="3482" sizeY="4022" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0">
+ <XShapes>
+ <XShape positionX="5340" positionY="3163" sizeX="3482" sizeY="4022" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="5340" positionY="3163" sizeX="3482" sizeY="4022" type="com.sun.star.drawing.PolyLineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="40" textRightDistance="40" textUpperDistance="40" textLowerDistance="40" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="3163"/>
+ <point positionX="5340" positionY="3499"/>
+ <point positionX="6501" positionY="4839"/>
+ <point positionX="7081" positionY="7185"/>
+ <point positionX="8822" positionY="5509"/>
+ <point positionX="7661" positionY="4169"/>
+ <point positionX="7081" positionY="3163"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="1741" positionY="0"/>
+ <point positionX="0" positionY="336"/>
+ <point positionX="1161" positionY="1676"/>
+ <point positionX="1741" positionY="4022"/>
+ <point positionX="3482" positionY="2346"/>
+ <point positionX="2321" positionY="1006"/>
+ <point positionX="1741" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="3482.000000" column2="0.000000" column3="5340.000000"/>
+ <Line2 column1="0.000000" column2="4022.000000" column3="3163.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="3483.000000" column2="0.000000" column3="5340.000000"/>
+ <Line2 column1="0.000000" column2="4023.000000" column3="3163.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="3483.000000" column2="0.000000" column3="5340.000000"/>
+ <Line2 column1="0.000000" column2="4023.000000" column3="3163.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4179" positionY="1153" sizeX="5804" sizeY="6703" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=1">
+ <XShapes>
+ <XShape positionX="4179" positionY="1153" sizeX="5804" sizeY="6703" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="4179" positionY="1153" sizeX="5804" sizeY="6703" type="com.sun.star.drawing.PolyLineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="40" textRightDistance="40" textUpperDistance="40" textLowerDistance="40" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7081" positionY="1153"/>
+ <point positionX="4179" positionY="2828"/>
+ <point positionX="4179" positionY="6180"/>
+ <point positionX="7081" positionY="7856"/>
+ <point positionX="9983" positionY="6180"/>
+ <point positionX="9983" positionY="2828"/>
+ <point positionX="7081" positionY="1153"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="2902" positionY="0"/>
+ <point positionX="0" positionY="1675"/>
+ <point positionX="0" positionY="5027"/>
+ <point positionX="2902" positionY="6703"/>
+ <point positionX="5804" positionY="5027"/>
+ <point positionX="5804" positionY="1675"/>
+ <point positionX="2902" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="5804.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="6703.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5805.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5805.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5805.000000" column2="0.000000" column3="4179.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5955.000000" column2="0.000000" column3="4104.000000"/>
+ <Line2 column1="0.000000" column2="6704.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="6704.000000" column2="0.000000" column3="3730.000000"/>
+ <Line2 column1="0.000000" column2="6705.000000" column3="1153.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2991" positionY="180" sizeX="8181" sizeY="8650" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="2991" positionY="180" sizeX="8181" sizeY="8650" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=0,0">
+ <XShapes>
+ <XShape positionX="6737" positionY="180" sizeX="690" sizeY="398" type="com.sun.star.drawing.TextShape" text="Bla1" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="BOTTOM" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="691.000000" column2="0.000000" column3="6737.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2991" positionY="2143" sizeX="690" sizeY="398" type="com.sun.star.drawing.TextShape" text="Bla2" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="BOTTOM" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="691.000000" column2="0.000000" column3="2991.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="2143.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2991" positionY="6468" sizeX="690" sizeY="398" type="com.sun.star.drawing.TextShape" text="Bla3" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="691.000000" column2="0.000000" column3="2991.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="6468.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6737" positionY="8432" sizeX="690" sizeY="398" type="com.sun.star.drawing.TextShape" text="Bla4" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="691.000000" column2="0.000000" column3="6737.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8432.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="10482" positionY="6468" sizeX="690" sizeY="398" type="com.sun.star.drawing.TextShape" text="Bla5" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="691.000000" column2="0.000000" column3="10482.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="6468.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="10482" positionY="2143" sizeX="690" sizeY="398" type="com.sun.star.drawing.TextShape" text="Bla6" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="BOTTOM" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="691.000000" column2="0.000000" column3="10482.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="2143.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="8182.000000" column2="0.000000" column3="2991.000000"/>
+ <Line2 column1="0.000000" column2="8651.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7331" positionY="955" sizeX="187" sizeY="3749" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="7331" positionY="4306" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="0" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="7331.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4306.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7331" positionY="955" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="5" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="7331.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="955.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="7331.000000"/>
+ <Line2 column1="0.000000" column2="3750.000000" column3="955.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="8182.000000" column2="0.000000" column3="2991.000000"/>
+ <Line2 column1="0.000000" column2="8651.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="8182.000000" column2="0.000000" column3="2991.000000"/>
+ <Line2 column1="0.000000" column2="8651.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13525.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8651.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14164" positionY="3957" sizeX="1637" sizeY="1096" type="com.sun.star.drawing.GroupShape" name="CID/D=0:Legend=">
+ <XShapes>
+ <XShape positionX="14164" positionY="3957" sizeX="1637" sizeY="1096" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="e6e6e6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1638.000000" column2="0.000000" column3="14164.000000"/>
+ <Line2 column1="0.000000" column2="1097.000000" column3="3957.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14280" positionY="4150" sizeX="800" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="14280" positionY="4150" sizeX="800" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="14280" positionY="4150" sizeX="800" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="14280.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4150.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14280" positionY="4255" sizeX="800" sizeY="0" type="com.sun.star.drawing.LineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="40" textRightDistance="40" textUpperDistance="40" textLowerDistance="40" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="14280" positionY="4255"/>
+ <point positionX="15080" positionY="4255"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="800" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="800.000000" column2="0.000000" column3="14280.000000"/>
+ <Line2 column1="0.000000" column2="0.000000" column3="4255.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="14280.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4150.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="14280.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4150.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14280" positionY="4648" sizeX="800" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="14280" positionY="4648" sizeX="800" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="14280" positionY="4648" sizeX="800" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="14280.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4648.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14280" positionY="4753" sizeX="800" sizeY="0" type="com.sun.star.drawing.LineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="40" textRightDistance="40" textUpperDistance="40" textLowerDistance="40" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="14280" positionY="4753"/>
+ <point positionX="15080" positionY="4753"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="800" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="800.000000" column2="0.000000" column3="14280.000000"/>
+ <Line2 column1="0.000000" column2="0.000000" column3="4753.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="14280.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4648.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="801.000000" column2="0.000000" column3="14280.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4648.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="15180" positionY="4057" sizeX="346" sizeY="398" type="com.sun.star.drawing.TextShape" text="ist" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="4803" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="347.000000" column2="0.000000" column3="15180.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4057.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="15180" positionY="4555" sizeX="505" sizeY="398" type="com.sun.star.drawing.TextShape" text="soll" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="4803" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="506.000000" column2="0.000000" column3="15180.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4555.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1638.000000" column2="0.000000" column3="14164.000000"/>
+ <Line2 column1="0.000000" column2="1097.000000" column3="3957.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+</XShapes>
+
+
diff --git a/chart2/qa/extras/xshape/data/reference/tdf90839-1.xml b/chart2/qa/extras/xshape/data/reference/tdf90839-1.xml
new file mode 100644
index 0000000000..222e595157
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/tdf90839-1.xml
@@ -0,0 +1,336 @@
+<?xml version="1.0"?>
+<XShapes>
+ <XShape positionX="0" positionY="0" sizeX="29642" sizeY="18368" type="com.sun.star.drawing.RectangleShape" name="CID/Page=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="29643.000000" column2="0.000000" column3="0.000000"/>
+ <Line2 column1="0.000000" column2="18369.000000" column3="0.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8412" positionY="3819" sizeX="11070" sizeY="9723" type="com.sun.star.drawing.GroupShape" name="CID/D=0">
+ <XShapes>
+ <XShape positionX="9761" positionY="3821" sizeX="9721" sizeY="9721" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9722.000000" column3="3821.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8412" positionY="3819" sizeX="11070" sizeY="9723" type="com.sun.star.drawing.RectangleShape" name="PlotAreaIncludingAxes" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="11071.000000" column2="0.000000" column3="8412.000000"/>
+ <Line2 column1="0.000000" column2="9724.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8412" positionY="3819" sizeX="11070" sizeY="9723" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="9761" positionY="3819" sizeX="9721" sizeY="9723" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="9761" positionY="3821" sizeX="9721" sizeY="9721" type="com.sun.star.drawing.GroupShape" name="PlotAreaExcludingAxes">
+ <XShapes>
+ <XShape positionX="9761" positionY="3821" sizeX="9721" sizeY="9721" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="d9d9d9" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9722.000000" column3="3821.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9722.000000" column3="3821.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9761" positionY="3819" sizeX="9721" sizeY="9722" type="com.sun.star.drawing.GroupShape" name="testonly;CooContainer=XXX_CID">
+ <XShapes>
+ <XShape positionX="9761" positionY="3819" sizeX="9721" sizeY="9722" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="9761" positionY="3819" sizeX="9721" sizeY="9722" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0">
+ <XShapes>
+ <XShape positionX="14621" positionY="5243" sizeX="4861" sizeY="8132" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,19316,9938,24011,11196/D=0:CS=0:CT=0:Series=0:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="4f81bd" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4861.000000" column2="0.000000" column3="14621.000000"/>
+ <Line2 column1="0.000000" column2="8132.000000" column3="5243.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9779" positionY="8680" sizeX="6100" sizeY="4861" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,11833,12661,9045,16643/D=0:CS=0:CT=0:Series=0:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="c0504d" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6100.000000" column2="0.000000" column3="9779.000000"/>
+ <Line2 column1="0.000000" column2="4861.000000" column3="8680.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9761" positionY="7422" sizeX="4860" sizeY="1682" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,9779,8256,4937,7833/D=0:CS=0:CT=0:Series=0:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="9bbb59" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4860.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="1682.000000" column3="7422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9926" positionY="3838" sizeX="4695" sizeY="4842" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,11497,4957,8372,1233/D=0:CS=0:CT=0:Series=0:Point=3" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="8064a2" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4695.000000" column2="0.000000" column3="9926.000000"/>
+ <Line2 column1="0.000000" column2="4842.000000" column3="3838.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14197" positionY="3819" sizeX="3861" sizeY="4861" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,16283,4113,17946,-454/D=0:CS=0:CT=0:Series=0:Point=4" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="4bacc6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="3861.000000" column2="0.000000" column3="14197.000000"/>
+ <Line2 column1="0.000000" column2="4861.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9723.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9723.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9723.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9724.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8412" positionY="4371" sizeX="10660" sizeY="8143" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="8412" positionY="4371" sizeX="10660" sizeY="8143" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="8412" positionY="4371" sizeX="10660" sizeY="8143" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0:DataLabels=">
+ <XShapes>
+ <XShape positionX="17800" positionY="9144" sizeX="1272" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0">
+ <XShapes>
+ <XShape positionX="17800" positionY="9144" sizeX="1272" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Yellow&#10;33%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="3889" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1273.000000" column2="0.000000" column3="17800.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="9144.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1273.000000" column2="0.000000" column3="17800.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="9144.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="11835" positionY="11349" sizeX="1034" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=1">
+ <XShapes>
+ <XShape positionX="11835" positionY="11349" sizeX="1034" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Black&#10;28%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="3889" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="11835.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="11349.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1035.000000" column2="0.000000" column3="11835.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="11349.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8412" positionY="7661" sizeX="1219" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=2">
+ <XShapes>
+ <XShape positionX="8412" positionY="7661" sizeX="1219" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Green&#10;6%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="8466" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1220.000000" column2="0.000000" column3="8412.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="7661.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1220.000000" column2="0.000000" column3="8412.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="7661.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="11695" positionY="4954" sizeX="822" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=3">
+ <XShapes>
+ <XShape positionX="11695" positionY="4954" sizeX="822" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Red&#10;19%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="3889" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="823.000000" column2="0.000000" column3="11695.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="4954.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="823.000000" column2="0.000000" column3="11695.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="4954.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="15450" positionY="4371" sizeX="1140" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=4">
+ <XShapes>
+ <XShape positionX="15450" positionY="4371" sizeX="1140" sizeY="1165" type="com.sun.star.drawing.TextShape" text="White&#10;14%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="3889" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1141.000000" column2="0.000000" column3="15450.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="4371.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1141.000000" column2="0.000000" column3="15450.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="4371.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10661.000000" column2="0.000000" column3="8412.000000"/>
+ <Line2 column1="0.000000" column2="8144.000000" column3="4371.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10661.000000" column2="0.000000" column3="8412.000000"/>
+ <Line2 column1="0.000000" column2="8144.000000" column3="4371.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10661.000000" column2="0.000000" column3="8412.000000"/>
+ <Line2 column1="0.000000" column2="8144.000000" column3="4371.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="11071.000000" column2="0.000000" column3="8412.000000"/>
+ <Line2 column1="0.000000" column2="9724.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="11071.000000" column2="0.000000" column3="8412.000000"/>
+ <Line2 column1="0.000000" column2="9724.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+</XShapes>
+
+
diff --git a/chart2/qa/extras/xshape/data/reference/tdf90839-2.xml b/chart2/qa/extras/xshape/data/reference/tdf90839-2.xml
new file mode 100644
index 0000000000..9ea3f9c16c
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/tdf90839-2.xml
@@ -0,0 +1,336 @@
+<?xml version="1.0"?>
+<XShapes>
+ <XShape positionX="0" positionY="0" sizeX="29643" sizeY="18368" type="com.sun.star.drawing.RectangleShape" name="CID/Page=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="29644.000000" column2="0.000000" column3="0.000000"/>
+ <Line2 column1="0.000000" column2="18369.000000" column3="0.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2513" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.GroupShape" name="CID/D=0">
+ <XShapes>
+ <XShape positionX="9762" positionY="3821" sizeX="9721" sizeY="9721" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9762.000000"/>
+ <Line2 column1="0.000000" column2="9722.000000" column3="3821.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2513" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.RectangleShape" name="PlotAreaIncludingAxes" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2513.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2513" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="9762" positionY="3819" sizeX="9721" sizeY="9723" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="9762" positionY="3821" sizeX="9721" sizeY="9721" type="com.sun.star.drawing.GroupShape" name="PlotAreaExcludingAxes">
+ <XShapes>
+ <XShape positionX="9762" positionY="3821" sizeX="9721" sizeY="9721" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="d9d9d9" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9762.000000"/>
+ <Line2 column1="0.000000" column2="9722.000000" column3="3821.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9762.000000"/>
+ <Line2 column1="0.000000" column2="9722.000000" column3="3821.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9762" positionY="3819" sizeX="9721" sizeY="9722" type="com.sun.star.drawing.GroupShape" name="testonly;CooContainer=XXX_CID">
+ <XShapes>
+ <XShape positionX="9762" positionY="3819" sizeX="9721" sizeY="9722" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="9762" positionY="3819" sizeX="9721" sizeY="9722" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0">
+ <XShapes>
+ <XShape positionX="14622" positionY="5243" sizeX="4861" sizeY="8132" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,19317,9938,24012,11196/D=0:CS=0:CT=0:Series=0:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="4f81bd" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4861.000000" column2="0.000000" column3="14622.000000"/>
+ <Line2 column1="0.000000" column2="8132.000000" column3="5243.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9780" positionY="8680" sizeX="6100" sizeY="4861" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,11834,12661,9046,16643/D=0:CS=0:CT=0:Series=0:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="c0504d" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6100.000000" column2="0.000000" column3="9780.000000"/>
+ <Line2 column1="0.000000" column2="4861.000000" column3="8680.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9762" positionY="7422" sizeX="4860" sizeY="1682" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,9780,8256,4938,7833/D=0:CS=0:CT=0:Series=0:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="9bbb59" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4860.000000" column2="0.000000" column3="9762.000000"/>
+ <Line2 column1="0.000000" column2="1682.000000" column3="7422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9927" positionY="3838" sizeX="4695" sizeY="4842" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,11498,4957,8373,1233/D=0:CS=0:CT=0:Series=0:Point=3" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="8064a2" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4695.000000" column2="0.000000" column3="9927.000000"/>
+ <Line2 column1="0.000000" column2="4842.000000" column3="3838.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14198" positionY="3819" sizeX="3861" sizeY="4861" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,16284,4113,17947,-454/D=0:CS=0:CT=0:Series=0:Point=4" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="4bacc6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="3861.000000" column2="0.000000" column3="14198.000000"/>
+ <Line2 column1="0.000000" column2="4861.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9762.000000"/>
+ <Line2 column1="0.000000" column2="9723.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9762.000000"/>
+ <Line2 column1="0.000000" column2="9723.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9762.000000"/>
+ <Line2 column1="0.000000" column2="9723.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9762.000000"/>
+ <Line2 column1="0.000000" column2="9724.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2513" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="2513" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="2513" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0:DataLabels=">
+ <XShapes>
+ <XShape positionX="19462" positionY="9977" sizeX="7040" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0">
+ <XShapes>
+ <XShape positionX="19462" positionY="9977" sizeX="7040" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Yellow - The color of sun and honey&#10;33%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="7041.000000" column2="0.000000" column3="19462.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="9977.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="7041.000000" column2="0.000000" column3="19462.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="9977.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4630" positionY="12784" sizeX="7119" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=1">
+ <XShapes>
+ <XShape positionX="4630" positionY="12784" sizeX="7119" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Black - The color of night and coffee&#10;28%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="8467" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="7120.000000" column2="0.000000" column3="4630.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="12784.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="7120.000000" column2="0.000000" column3="4630.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="12784.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2513" positionY="7661" sizeX="7119" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=2">
+ <XShapes>
+ <XShape positionX="2513" positionY="7661" sizeX="7119" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Green - The color of grass and hope&#10;6%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="8467" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="7120.000000" column2="0.000000" column3="2513.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="7661.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="7120.000000" column2="0.000000" column3="2513.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="7661.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4442" positionY="3678" sizeX="6961" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=3">
+ <XShapes>
+ <XShape positionX="4442" positionY="3678" sizeX="6961" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Red - The color of rose and passion&#10;19%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="BOTTOM" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="8467" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="4442.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="3678.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="4442.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="3678.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="16335" positionY="2808" sizeX="6961" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=4">
+ <XShapes>
+ <XShape positionX="16335" positionY="2808" sizeX="6961" sizeY="1165" type="com.sun.star.drawing.TextShape" text="White - The color of milk and purity&#10;14%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="BOTTOM" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="9881" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="16335.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="16335.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2513.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2513.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2513.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2513.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2513.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+</XShapes>
+
+
diff --git a/chart2/qa/extras/xshape/data/reference/tdf90839-3.xml b/chart2/qa/extras/xshape/data/reference/tdf90839-3.xml
new file mode 100644
index 0000000000..a042916da8
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/tdf90839-3.xml
@@ -0,0 +1,336 @@
+<?xml version="1.0"?>
+<XShapes>
+ <XShape positionX="0" positionY="0" sizeX="29642" sizeY="18368" type="com.sun.star.drawing.RectangleShape" name="CID/Page=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="29643.000000" column2="0.000000" column3="0.000000"/>
+ <Line2 column1="0.000000" column2="18369.000000" column3="0.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2512" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.GroupShape" name="CID/D=0">
+ <XShapes>
+ <XShape positionX="9761" positionY="3821" sizeX="9721" sizeY="9721" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9722.000000" column3="3821.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2512" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.RectangleShape" name="PlotAreaIncludingAxes" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2512.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2512" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="9761" positionY="3819" sizeX="9721" sizeY="9723" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="9761" positionY="3821" sizeX="9721" sizeY="9721" type="com.sun.star.drawing.GroupShape" name="PlotAreaExcludingAxes">
+ <XShapes>
+ <XShape positionX="9761" positionY="3821" sizeX="9721" sizeY="9721" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="d9d9d9" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9722.000000" column3="3821.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9722.000000" column3="3821.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9761" positionY="3819" sizeX="9721" sizeY="9722" type="com.sun.star.drawing.GroupShape" name="testonly;CooContainer=XXX_CID">
+ <XShapes>
+ <XShape positionX="9761" positionY="3819" sizeX="9721" sizeY="9722" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="9761" positionY="3819" sizeX="9721" sizeY="9722" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0">
+ <XShapes>
+ <XShape positionX="14621" positionY="5243" sizeX="4861" sizeY="8132" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,19316,9938,24011,11196/D=0:CS=0:CT=0:Series=0:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="4f81bd" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4861.000000" column2="0.000000" column3="14621.000000"/>
+ <Line2 column1="0.000000" column2="8132.000000" column3="5243.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9779" positionY="8680" sizeX="6100" sizeY="4861" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,11833,12661,9045,16643/D=0:CS=0:CT=0:Series=0:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="c0504d" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6100.000000" column2="0.000000" column3="9779.000000"/>
+ <Line2 column1="0.000000" column2="4861.000000" column3="8680.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9761" positionY="7422" sizeX="4860" sizeY="1682" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,9779,8256,4937,7833/D=0:CS=0:CT=0:Series=0:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="9bbb59" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4860.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="1682.000000" column3="7422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9926" positionY="3838" sizeX="4695" sizeY="4842" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,11497,4957,8372,1233/D=0:CS=0:CT=0:Series=0:Point=3" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="8064a2" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4695.000000" column2="0.000000" column3="9926.000000"/>
+ <Line2 column1="0.000000" column2="4842.000000" column3="3838.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14197" positionY="3819" sizeX="3861" sizeY="4861" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,16283,4113,17946,-454/D=0:CS=0:CT=0:Series=0:Point=4" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="4bacc6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="3861.000000" column2="0.000000" column3="14197.000000"/>
+ <Line2 column1="0.000000" column2="4861.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9723.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9723.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9723.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9722.000000" column2="0.000000" column3="9761.000000"/>
+ <Line2 column1="0.000000" column2="9724.000000" column3="3819.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2512" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="2512" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="2512" positionY="2808" sizeX="23989" sizeY="11141" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0:DataLabels=">
+ <XShapes>
+ <XShape positionX="19461" positionY="9977" sizeX="7040" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0">
+ <XShapes>
+ <XShape positionX="19461" positionY="9977" sizeX="7040" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Yellow - The color of sun and honey&#10;33%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="8466" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="7041.000000" column2="0.000000" column3="19461.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="9977.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="7041.000000" column2="0.000000" column3="19461.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="9977.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4629" positionY="12784" sizeX="7119" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=1">
+ <XShapes>
+ <XShape positionX="4629" positionY="12784" sizeX="7119" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Black - The color of night and coffee&#10;28%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="7120.000000" column2="0.000000" column3="4629.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="12784.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="7120.000000" column2="0.000000" column3="4629.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="12784.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2512" positionY="7661" sizeX="7119" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=2">
+ <XShapes>
+ <XShape positionX="2512" positionY="7661" sizeX="7119" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Green - The color of grass and hope&#10;6%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="7120.000000" column2="0.000000" column3="2512.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="7661.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="7120.000000" column2="0.000000" column3="2512.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="7661.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4441" positionY="3678" sizeX="6961" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=3">
+ <XShapes>
+ <XShape positionX="4441" positionY="3678" sizeX="6961" sizeY="1165" type="com.sun.star.drawing.TextShape" text="Red - The color of rose and passion&#10;19%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="BOTTOM" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="4441.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="3678.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="4441.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="3678.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="16334" positionY="2808" sizeX="6961" sizeY="1165" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=4">
+ <XShapes>
+ <XShape positionX="16334" positionY="2808" sizeX="6961" sizeY="1165" type="com.sun.star.drawing.TextShape" text="White - The color of milk and purity&#10;14%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="BOTTOM" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="16334.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="16334.000000"/>
+ <Line2 column1="0.000000" column2="1166.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2512.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2512.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2512.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2512.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="23990.000000" column2="0.000000" column3="2512.000000"/>
+ <Line2 column1="0.000000" column2="11142.000000" column3="2808.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+</XShapes>
+
+
diff --git a/chart2/qa/extras/xshape/data/reference/tdf90839-4.xml b/chart2/qa/extras/xshape/data/reference/tdf90839-4.xml
new file mode 100644
index 0000000000..83d7217861
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/tdf90839-4.xml
@@ -0,0 +1,336 @@
+<?xml version="1.0"?>
+<XShapes>
+ <XShape positionX="0" positionY="0" sizeX="25991" sizeY="18367" type="com.sun.star.drawing.RectangleShape" name="CID/Page=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="25992.000000" column2="0.000000" column3="0.000000"/>
+ <Line2 column1="0.000000" column2="18368.000000" column3="0.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1922" positionY="2294" sizeX="21359" sizeY="12760" type="com.sun.star.drawing.GroupShape" name="CID/D=0">
+ <XShapes>
+ <XShape positionX="8034" positionY="3894" sizeX="9575" sizeY="9575" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="9576.000000" column2="0.000000" column3="8034.000000"/>
+ <Line2 column1="0.000000" column2="9576.000000" column3="3894.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1922" positionY="2294" sizeX="21359" sizeY="12760" type="com.sun.star.drawing.RectangleShape" name="PlotAreaIncludingAxes" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="21360.000000" column2="0.000000" column3="1922.000000"/>
+ <Line2 column1="0.000000" column2="12761.000000" column3="2294.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1922" positionY="2294" sizeX="21359" sizeY="12760" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="8034" positionY="3892" sizeX="9575" sizeY="9577" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="8034" positionY="3894" sizeX="9575" sizeY="9575" type="com.sun.star.drawing.GroupShape" name="PlotAreaExcludingAxes">
+ <XShapes>
+ <XShape positionX="8034" positionY="3894" sizeX="9575" sizeY="9575" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="d9d9d9" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="9576.000000" column2="0.000000" column3="8034.000000"/>
+ <Line2 column1="0.000000" column2="9576.000000" column3="3894.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9576.000000" column2="0.000000" column3="8034.000000"/>
+ <Line2 column1="0.000000" column2="9576.000000" column3="3894.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8034" positionY="3892" sizeX="9575" sizeY="9576" type="com.sun.star.drawing.GroupShape" name="testonly;CooContainer=XXX_CID">
+ <XShapes>
+ <XShape positionX="8034" positionY="3892" sizeX="9575" sizeY="9576" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="8034" positionY="3892" sizeX="9575" sizeY="9576" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0">
+ <XShapes>
+ <XShape positionX="12821" positionY="5295" sizeX="4788" sizeY="8009" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,17445,9919,22070,11158/D=0:CS=0:CT=0:Series=0:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="4f81bd" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4788.000000" column2="0.000000" column3="12821.000000"/>
+ <Line2 column1="0.000000" column2="8009.000000" column3="5295.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8052" positionY="8680" sizeX="6008" sizeY="4788" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,10075,12602,7329,16523/D=0:CS=0:CT=0:Series=0:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="c0504d" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6008.000000" column2="0.000000" column3="8052.000000"/>
+ <Line2 column1="0.000000" column2="4788.000000" column3="8680.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8034" positionY="7441" sizeX="4787" sizeY="1656" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,8052,8263,3282,7845/D=0:CS=0:CT=0:Series=0:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="9bbb59" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4787.000000" column2="0.000000" column3="8034.000000"/>
+ <Line2 column1="0.000000" column2="1656.000000" column3="7441.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="8197" positionY="3911" sizeX="4624" sizeY="4769" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,9744,5013,6666,1345/D=0:CS=0:CT=0:Series=0:Point=3" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="8064a2" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="4624.000000" column2="0.000000" column3="8197.000000"/>
+ <Line2 column1="0.000000" column2="4769.000000" column3="3911.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12404" positionY="3892" sizeX="3802" sizeY="4788" type="com.sun.star.drawing.ClosedBezierShape" name="CID/MultiClick:DragMethod=PieSegmentDragging:DragParameter=0,14458,4181,16096,-317/D=0:CS=0:CT=0:Series=0:Point=4" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="26" textRightDistance="26" textUpperDistance="26" textLowerDistance="26" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="4bacc6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="3802.000000" column2="0.000000" column3="12404.000000"/>
+ <Line2 column1="0.000000" column2="4788.000000" column3="3892.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9576.000000" column2="0.000000" column3="8034.000000"/>
+ <Line2 column1="0.000000" column2="9577.000000" column3="3892.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9576.000000" column2="0.000000" column3="8034.000000"/>
+ <Line2 column1="0.000000" column2="9577.000000" column3="3892.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9576.000000" column2="0.000000" column3="8034.000000"/>
+ <Line2 column1="0.000000" column2="9577.000000" column3="3892.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="9576.000000" column2="0.000000" column3="8034.000000"/>
+ <Line2 column1="0.000000" column2="9578.000000" column3="3892.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1922" positionY="2294" sizeX="21359" sizeY="12760" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1922" positionY="2294" sizeX="21359" sizeY="12760" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1922" positionY="2294" sizeX="21359" sizeY="12760" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0:DataLabels=">
+ <XShapes>
+ <XShape positionX="17590" positionY="9958" sizeX="5691" sizeY="2329" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=0">
+ <XShapes>
+ <XShape positionX="17590" positionY="9958" sizeX="5691" sizeY="2329" type="com.sun.star.drawing.TextShape" text="Yellow - The color of sun and honey&#10;120&#10;33%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="6977" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="5692.000000" column2="0.000000" column3="17590.000000"/>
+ <Line2 column1="0.000000" column2="2330.000000" column3="9958.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5692.000000" column2="0.000000" column3="17590.000000"/>
+ <Line2 column1="0.000000" column2="2330.000000" column3="9958.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4220" positionY="12725" sizeX="5770" sizeY="2329" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=1">
+ <XShapes>
+ <XShape positionX="4220" positionY="12725" sizeX="5770" sizeY="2329" type="com.sun.star.drawing.TextShape" text="Black - The color of night and coffee&#10;100&#10;28%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="6977" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="5771.000000" column2="0.000000" column3="4220.000000"/>
+ <Line2 column1="0.000000" column2="2330.000000" column3="12725.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5771.000000" column2="0.000000" column3="4220.000000"/>
+ <Line2 column1="0.000000" column2="2330.000000" column3="12725.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1922" positionY="7086" sizeX="5982" sizeY="2329" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=2">
+ <XShapes>
+ <XShape positionX="1922" positionY="7086" sizeX="5982" sizeY="2329" type="com.sun.star.drawing.TextShape" text="Green - The color of grass and hope&#10;20&#10;6%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="6977" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="5983.000000" column2="0.000000" column3="1922.000000"/>
+ <Line2 column1="0.000000" column2="2330.000000" column3="7086.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="5983.000000" column2="0.000000" column3="1922.000000"/>
+ <Line2 column1="0.000000" column2="2330.000000" column3="7086.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2688" positionY="3152" sizeX="6961" sizeY="1747" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=3">
+ <XShapes>
+ <XShape positionX="2688" positionY="3152" sizeX="6961" sizeY="1747" type="com.sun.star.drawing.TextShape" text="Red - The color of rose and passion&#10;70&#10;19%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="BOTTOM" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="6977" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="2688.000000"/>
+ <Line2 column1="0.000000" column2="1748.000000" column3="3152.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="2688.000000"/>
+ <Line2 column1="0.000000" column2="1748.000000" column3="3152.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14509" positionY="2294" sizeX="6961" sizeY="1747" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/CID/D=0:CS=0:CT=0:Series=0:DataLabels=:DataLabel=4">
+ <XShapes>
+ <XShape positionX="14509" positionY="2294" sizeX="6961" sizeY="1747" type="com.sun.star.drawing.TextShape" text="White - The color of milk and purity&#10;50&#10;14%" fontHeight="12.000000" fontColor="595959" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="BOTTOM" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="8664" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="14509.000000"/>
+ <Line2 column1="0.000000" column2="1748.000000" column3="2294.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="6962.000000" column2="0.000000" column3="14509.000000"/>
+ <Line2 column1="0.000000" column2="1748.000000" column3="2294.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="21360.000000" column2="0.000000" column3="1922.000000"/>
+ <Line2 column1="0.000000" column2="12761.000000" column3="2294.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="21360.000000" column2="0.000000" column3="1922.000000"/>
+ <Line2 column1="0.000000" column2="12761.000000" column3="2294.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="21360.000000" column2="0.000000" column3="1922.000000"/>
+ <Line2 column1="0.000000" column2="12761.000000" column3="2294.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="21360.000000" column2="0.000000" column3="1922.000000"/>
+ <Line2 column1="0.000000" column2="12761.000000" column3="2294.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="21360.000000" column2="0.000000" column3="1922.000000"/>
+ <Line2 column1="0.000000" column2="12761.000000" column3="2294.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+</XShapes>
+
+
diff --git a/chart2/qa/extras/xshape/data/reference/testChart.xml b/chart2/qa/extras/xshape/data/reference/testChart.xml
new file mode 100644
index 0000000000..ad64e5f3b6
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/testChart.xml
@@ -0,0 +1,1218 @@
+<?xml version="1.0"?>
+<XShapes>
+ <XShape positionX="0" positionY="0" sizeX="16000" sizeY="9000" type="com.sun.star.drawing.RectangleShape" name="CID/Page=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="16001.000000" column2="0.000000" column3="0.000000"/>
+ <Line2 column1="0.000000" column2="9001.000000" column3="0.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="13864" sizeY="8640" type="com.sun.star.drawing.GroupShape" name="CID/D=0">
+ <XShapes>
+ <XShape positionX="756" positionY="379" sizeX="13428" sizeY="7794" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="13429.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="379.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="13864" sizeY="8640" type="com.sun.star.drawing.RectangleShape" name="PlotAreaIncludingAxes" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="13865.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="13864" sizeY="8640" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="606" positionY="378" sizeX="13578" sizeY="7944" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="756" positionY="379" sizeX="13428" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="PlotAreaExcludingAxes">
+ <XShapes>
+ <XShape positionX="756" positionY="379" sizeX="13428" sizeY="7794" type="com.sun.star.drawing.RectangleShape" name="CID/DiagramWall=" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="e6e6e6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="13429.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="379.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13429.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="379.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="606" positionY="378" sizeX="13577" sizeY="7944" type="com.sun.star.drawing.GroupShape" name="testonly;CooContainer=XXX_CID">
+ <XShapes>
+ <XShape positionX="756" positionY="378" sizeX="13427" sizeY="7794" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="756" positionY="378" sizeX="13427" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0:Grid=0">
+ <XShapes>
+ <XShape positionX="756" positionY="378" sizeX="13427" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="14183" positionY="8172"/>
+ <point positionX="756" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14183" positionY="6873"/>
+ <point positionX="756" positionY="6873"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14183" positionY="5574"/>
+ <point positionX="756" positionY="5574"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14183" positionY="4275"/>
+ <point positionX="756" positionY="4275"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14183" positionY="2976"/>
+ <point positionX="756" positionY="2976"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14183" positionY="1677"/>
+ <point positionX="756" positionY="1677"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14183" positionY="378"/>
+ <point positionX="756" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="13427" positionY="7794"/>
+ <point positionX="0" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13427" positionY="6495"/>
+ <point positionX="0" positionY="6495"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13427" positionY="5196"/>
+ <point positionX="0" positionY="5196"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13427" positionY="3897"/>
+ <point positionX="0" positionY="3897"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13427" positionY="2598"/>
+ <point positionX="0" positionY="2598"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13427" positionY="1299"/>
+ <point positionX="0" positionY="1299"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13427" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="13427.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="756" positionY="378" sizeX="0" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" name="HandlesOnly" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="NONE">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="756" positionY="8172"/>
+ <point positionX="756" positionY="6873"/>
+ <point positionX="756" positionY="5574"/>
+ <point positionX="756" positionY="4275"/>
+ <point positionX="756" positionY="2976"/>
+ <point positionX="756" positionY="1677"/>
+ <point positionX="756" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="0" positionY="6495"/>
+ <point positionX="0" positionY="5196"/>
+ <point positionX="0" positionY="3897"/>
+ <point positionX="0" positionY="2598"/>
+ <point positionX="0" positionY="1299"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13428.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13428.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="606" positionY="378" sizeX="13577" sizeY="7944" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="756" positionY="8172" sizeX="13427" sizeY="150" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=0,0">
+ <XShapes>
+ <XShape positionX="756" positionY="8172" sizeX="13427" sizeY="150" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="756" positionY="8322"/>
+ <point positionX="756" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="756" positionY="8322"/>
+ <point positionX="756" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="3441" positionY="8322"/>
+ <point positionX="3441" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="3441" positionY="8322"/>
+ <point positionX="3441" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="6127" positionY="8322"/>
+ <point positionX="6127" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="6127" positionY="8322"/>
+ <point positionX="6127" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="8812" positionY="8322"/>
+ <point positionX="8812" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="8812" positionY="8322"/>
+ <point positionX="8812" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11498" positionY="8322"/>
+ <point positionX="11498" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="11498" positionY="8322"/>
+ <point positionX="11498" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14183" positionY="8322"/>
+ <point positionX="14183" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="14183" positionY="8322"/>
+ <point positionX="14183" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="150"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="150"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="2685" positionY="150"/>
+ <point positionX="2685" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="2685" positionY="150"/>
+ <point positionX="2685" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="5371" positionY="150"/>
+ <point positionX="5371" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="5371" positionY="150"/>
+ <point positionX="5371" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="8056" positionY="150"/>
+ <point positionX="8056" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="8056" positionY="150"/>
+ <point positionX="8056" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10742" positionY="150"/>
+ <point positionX="10742" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="10742" positionY="150"/>
+ <point positionX="10742" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13427" positionY="150"/>
+ <point positionX="13427" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="13427" positionY="150"/>
+ <point positionX="13427" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="13427.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="150.000000" column3="8172.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="756" positionY="8172" sizeX="13427" sizeY="0" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="756" positionY="8172"/>
+ <point positionX="14183" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="13427" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="13427.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="0.000000" column3="8172.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13428.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="151.000000" column3="8172.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="606" positionY="378" sizeX="150" sizeY="7794" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="606" positionY="378" sizeX="150" sizeY="7794" type="com.sun.star.drawing.PolyLineShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="606" positionY="8172"/>
+ <point positionX="756" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="8172"/>
+ <point positionX="756" positionY="8172"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="6873"/>
+ <point positionX="756" positionY="6873"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="6873"/>
+ <point positionX="756" positionY="6873"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="5574"/>
+ <point positionX="756" positionY="5574"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="5574"/>
+ <point positionX="756" positionY="5574"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="4275"/>
+ <point positionX="756" positionY="4275"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="4275"/>
+ <point positionX="756" positionY="4275"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="2976"/>
+ <point positionX="756" positionY="2976"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="2976"/>
+ <point positionX="756" positionY="2976"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="1677"/>
+ <point positionX="756" positionY="1677"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="1677"/>
+ <point positionX="756" positionY="1677"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="378"/>
+ <point positionX="756" positionY="378"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="606" positionY="378"/>
+ <point positionX="756" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="150" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="150" positionY="7794"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="6495"/>
+ <point positionX="150" positionY="6495"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="6495"/>
+ <point positionX="150" positionY="6495"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="5196"/>
+ <point positionX="150" positionY="5196"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="5196"/>
+ <point positionX="150" positionY="5196"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="3897"/>
+ <point positionX="150" positionY="3897"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="3897"/>
+ <point positionX="150" positionY="3897"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="2598"/>
+ <point positionX="150" positionY="2598"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="2598"/>
+ <point positionX="150" positionY="2598"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="1299"/>
+ <point positionX="150" positionY="1299"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="1299"/>
+ <point positionX="150" positionY="1299"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="150" positionY="0"/>
+ </pointSequence>
+ <pointSequence>
+ <point positionX="0" positionY="0"/>
+ <point positionX="150" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="150.000000" column2="0.000000" column3="606.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="756" positionY="378" sizeX="0" sizeY="7794" type="com.sun.star.drawing.LineShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" lineStyle="SOLID">
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="756" positionY="8172"/>
+ <point positionX="756" positionY="378"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="7794"/>
+ <point positionX="0" positionY="0"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="0.000000" column2="0.000000" column3="756.000000"/>
+ <Line2 column1="0.000000" column2="7794.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="151.000000" column2="0.000000" column3="606.000000"/>
+ <Line2 column1="0.000000" column2="7795.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13578.000000" column2="0.000000" column3="606.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="1203" positionY="1677" sizeX="12533" sizeY="6495" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="1203" positionY="1677" sizeX="11638" sizeY="6495" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=0">
+ <XShapes>
+ <XShape positionX="1203" positionY="6873" sizeX="895" sizeY="1299" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="1203" positionY="8172"/>
+ <point positionX="2098" positionY="8172"/>
+ <point positionX="2098" positionY="6873"/>
+ <point positionX="1203" positionY="6873"/>
+ <point positionX="1203" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="1299"/>
+ <point positionX="895" positionY="1299"/>
+ <point positionX="895" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="1299"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="895.000000" column2="0.000000" column3="1203.000000"/>
+ <Line2 column1="0.000000" column2="1299.000000" column3="6873.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="3889" positionY="5574" sizeX="895" sizeY="2598" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="3889" positionY="8172"/>
+ <point positionX="4784" positionY="8172"/>
+ <point positionX="4784" positionY="5574"/>
+ <point positionX="3889" positionY="5574"/>
+ <point positionX="3889" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="2598"/>
+ <point positionX="895" positionY="2598"/>
+ <point positionX="895" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="2598"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="895.000000" column2="0.000000" column3="3889.000000"/>
+ <Line2 column1="0.000000" column2="2598.000000" column3="5574.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="6574" positionY="4275" sizeX="895" sizeY="3897" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="6574" positionY="8172"/>
+ <point positionX="7469" positionY="8172"/>
+ <point positionX="7469" positionY="4275"/>
+ <point positionX="6574" positionY="4275"/>
+ <point positionX="6574" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="3897"/>
+ <point positionX="895" positionY="3897"/>
+ <point positionX="895" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="3897"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="895.000000" column2="0.000000" column3="6574.000000"/>
+ <Line2 column1="0.000000" column2="3897.000000" column3="4275.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="9260" positionY="2976" sizeX="895" sizeY="5196" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=3" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="9260" positionY="8172"/>
+ <point positionX="10155" positionY="8172"/>
+ <point positionX="10155" positionY="2976"/>
+ <point positionX="9260" positionY="2976"/>
+ <point positionX="9260" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="5196"/>
+ <point positionX="895" positionY="5196"/>
+ <point positionX="895" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="5196"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="895.000000" column2="0.000000" column3="9260.000000"/>
+ <Line2 column1="0.000000" column2="5196.000000" column3="2976.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="11946" positionY="1677" sizeX="895" sizeY="6495" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:Point=4" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="11946" positionY="8172"/>
+ <point positionX="12841" positionY="8172"/>
+ <point positionX="12841" positionY="1677"/>
+ <point positionX="11946" positionY="1677"/>
+ <point positionX="11946" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="6495"/>
+ <point positionX="895" positionY="6495"/>
+ <point positionX="895" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="6495"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="895.000000" column2="0.000000" column3="11946.000000"/>
+ <Line2 column1="0.000000" column2="6495.000000" column3="1677.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="11639.000000" column2="0.000000" column3="1203.000000"/>
+ <Line2 column1="0.000000" column2="6496.000000" column3="1677.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="2098" positionY="2976" sizeX="11638" sizeY="5196" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:CT=0:Series=1">
+ <XShapes>
+ <XShape positionX="2098" positionY="5574" sizeX="896" sizeY="2598" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=0" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="2098" positionY="8172"/>
+ <point positionX="2994" positionY="8172"/>
+ <point positionX="2994" positionY="5574"/>
+ <point positionX="2098" positionY="5574"/>
+ <point positionX="2098" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="2598"/>
+ <point positionX="896" positionY="2598"/>
+ <point positionX="896" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="2598"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="896.000000" column2="0.000000" column3="2098.000000"/>
+ <Line2 column1="0.000000" column2="2598.000000" column3="5574.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4784" positionY="6873" sizeX="895" sizeY="1299" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=1" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="4784" positionY="8172"/>
+ <point positionX="5679" positionY="8172"/>
+ <point positionX="5679" positionY="6873"/>
+ <point positionX="4784" positionY="6873"/>
+ <point positionX="4784" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="1299"/>
+ <point positionX="895" positionY="1299"/>
+ <point positionX="895" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="1299"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="895.000000" column2="0.000000" column3="4784.000000"/>
+ <Line2 column1="0.000000" column2="1299.000000" column3="6873.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7470" positionY="4275" sizeX="895" sizeY="3897" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=2" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="7470" positionY="8172"/>
+ <point positionX="8365" positionY="8172"/>
+ <point positionX="8365" positionY="4275"/>
+ <point positionX="7470" positionY="4275"/>
+ <point positionX="7470" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="3897"/>
+ <point positionX="895" positionY="3897"/>
+ <point positionX="895" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="3897"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="895.000000" column2="0.000000" column3="7470.000000"/>
+ <Line2 column1="0.000000" column2="3897.000000" column3="4275.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="10155" positionY="2976" sizeX="895" sizeY="5196" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=3" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="10155" positionY="8172"/>
+ <point positionX="11050" positionY="8172"/>
+ <point positionX="11050" positionY="2976"/>
+ <point positionX="10155" positionY="2976"/>
+ <point positionX="10155" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="5196"/>
+ <point positionX="895" positionY="5196"/>
+ <point positionX="895" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="5196"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="895.000000" column2="0.000000" column3="10155.000000"/>
+ <Line2 column1="0.000000" column2="5196.000000" column3="2976.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12841" positionY="5574" sizeX="895" sizeY="2598" type="com.sun.star.drawing.PolyPolygonShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:Point=4" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <PolyPolygon>
+ <pointSequence>
+ <point positionX="12841" positionY="8172"/>
+ <point positionX="13736" positionY="8172"/>
+ <point positionX="13736" positionY="5574"/>
+ <point positionX="12841" positionY="5574"/>
+ <point positionX="12841" positionY="8172"/>
+ </pointSequence>
+ </PolyPolygon>
+ <Geometry>
+ <pointSequence>
+ <point positionX="0" positionY="2598"/>
+ <point positionX="895" positionY="2598"/>
+ <point positionX="895" positionY="0"/>
+ <point positionX="0" positionY="0"/>
+ <point positionX="0" positionY="2598"/>
+ </pointSequence>
+ </Geometry>
+ <Transformation>
+ <Line1 column1="895.000000" column2="0.000000" column3="12841.000000"/>
+ <Line2 column1="0.000000" column2="2598.000000" column3="5574.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="11639.000000" column2="0.000000" column3="2098.000000"/>
+ <Line2 column1="0.000000" column2="5197.000000" column3="2976.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12534.000000" column2="0.000000" column3="1203.000000"/>
+ <Line2 column1="0.000000" column2="6496.000000" column3="1677.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13578.000000" column2="0.000000" column3="606.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13579.000000" column2="0.000000" column3="606.000000"/>
+ <Line2 column1="0.000000" column2="7945.000000" column3="378.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="12615" sizeY="8640" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="2005" positionY="8422" sizeX="10930" sizeY="398" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=0,0">
+ <XShapes>
+ <XShape positionX="2005" positionY="8422" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="1" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="2005.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="4691" positionY="8422" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="2" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="4691.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="7376" positionY="8422" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="3" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="7376.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="10062" positionY="8422" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="4" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="10062.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="12748" positionY="8422" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="5" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="12748.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="10931.000000" column2="0.000000" column3="2005.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="8422.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="187" sizeY="8192" type="com.sun.star.drawing.GroupShape" name="CID/D=0:CS=0:Axis=1,0">
+ <XShapes>
+ <XShape positionX="320" positionY="7974" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="0" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="7974.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="6675" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="1" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="6675.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="5376" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="2" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="5376.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="4077" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="3" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4077.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="2778" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="4" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="2778.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="1479" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="5" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="1479.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="320" positionY="180" sizeX="187" sizeY="398" type="com.sun.star.drawing.TextShape" text="6" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="RIGHT" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="1" textMinimumFrameWidth="1" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="188.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8193.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="12616.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13865.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="13865.000000" column2="0.000000" column3="320.000000"/>
+ <Line2 column1="0.000000" column2="8641.000000" column3="180.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14504" positionY="3952" sizeX="1286" sizeY="1096" type="com.sun.star.drawing.GroupShape" name="CID/D=0:Legend=">
+ <XShapes>
+ <XShape positionX="14504" positionY="3952" sizeX="1286" sizeY="1096" type="com.sun.star.drawing.RectangleShape" name="MarkHandles" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="e6e6e6" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="1287.000000" column2="0.000000" column3="14504.000000"/>
+ <Line2 column1="0.000000" column2="1097.000000" column3="3952.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14620" positionY="4145" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="14620" positionY="4145" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=0:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="14620" positionY="4145" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14620.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14620" positionY="4145" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="004586" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14620.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14620.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14620.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4145.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14620" positionY="4643" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape">
+ <XShapes>
+ <XShape positionX="14620" positionY="4643" sizeX="211" sizeY="211" type="com.sun.star.drawing.GroupShape" name="CID/MultiClick/D=0:CS=0:CT=0:Series=1:LegendEntry=0">
+ <XShapes>
+ <XShape positionX="14620" positionY="4643" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14620.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14620" positionY="4643" sizeX="211" sizeY="211" type="com.sun.star.drawing.RectangleShape" fontHeight="12.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="CENTER" textVerticalAdjust="CENTER" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="ff420e" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14620.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14620.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="212.000000" column2="0.000000" column3="14620.000000"/>
+ <Line2 column1="0.000000" column2="212.000000" column3="4643.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14931" positionY="4052" sizeX="743" sizeY="398" type="com.sun.star.drawing.TextShape" text="test1" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="4800" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="744.000000" column2="0.000000" column3="14931.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4052.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ <XShape positionX="14931" positionY="4550" sizeX="743" sizeY="398" type="com.sun.star.drawing.TextShape" text="test2" fontHeight="10.000000" fontColor="ffffffff" textAutoGrowHeight="true" textAutoGrowWidth="true" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="LEFT" textVerticalAdjust="TOP" textLeftDistance="0" textRightDistance="0" textUpperDistance="0" textLowerDistance="0" textMaximumFrameHeight="0" textMaximumFrameWidth="4800" textMinimumFrameHeight="100" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="NONE" fillColor="ffffff" fillTransparence="0" fillTransparenceGradientName="">
+ <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
+ <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
+ <FillBitmap/>
+ <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
+ <LineStart/>
+ <LineEnd/>
+ <Transformation>
+ <Line1 column1="744.000000" column2="0.000000" column3="14931.000000"/>
+ <Line2 column1="0.000000" column2="399.000000" column3="4550.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+ </XShapes>
+ <Transformation>
+ <Line1 column1="1287.000000" column2="0.000000" column3="14504.000000"/>
+ <Line2 column1="0.000000" column2="1097.000000" column3="3952.000000"/>
+ <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
+ </Transformation>
+ </XShape>
+</XShapes>
+
+
diff --git a/chart2/qa/extras/xshape/data/reference/tolerance.xml b/chart2/qa/extras/xshape/data/reference/tolerance.xml
new file mode 100644
index 0000000000..17ec7220fc
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/reference/tolerance.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<tolerances>
+ <tolerance elementName="Line2" attribName="column2" value="1"/>
+ <tolerance elementName="Line2" attribName="column3" value="1"/>
+ <tolerance elementName="XShape" attribName="positionY" value="1"/>
+ <tolerance elementName="XShape" attribName="sizeY" value="1"/>
+</tolerances>
diff --git a/chart2/qa/extras/xshape/data/xls/tdf150832.xls b/chart2/qa/extras/xshape/data/xls/tdf150832.xls
new file mode 100644
index 0000000000..1044345619
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/xls/tdf150832.xls
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/xlsx/tdf90839-1.xlsx b/chart2/qa/extras/xshape/data/xlsx/tdf90839-1.xlsx
new file mode 100644
index 0000000000..05db435f60
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/xlsx/tdf90839-1.xlsx
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/xlsx/tdf90839-2.xlsx b/chart2/qa/extras/xshape/data/xlsx/tdf90839-2.xlsx
new file mode 100644
index 0000000000..d3922f7f20
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/xlsx/tdf90839-2.xlsx
Binary files differ
diff --git a/chart2/qa/extras/xshape/data/xlsx/tdf90839-3.xlsx b/chart2/qa/extras/xshape/data/xlsx/tdf90839-3.xlsx
new file mode 100644
index 0000000000..5a3ee4cf49
--- /dev/null
+++ b/chart2/qa/extras/xshape/data/xlsx/tdf90839-3.xlsx
Binary files differ
diff --git a/chart2/qa/unit/chart2-dialogs-test.cxx b/chart2/qa/unit/chart2-dialogs-test.cxx
new file mode 100644
index 0000000000..00bb9179df
--- /dev/null
+++ b/chart2/qa/unit/chart2-dialogs-test.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <test/screenshot_test.hxx>
+#include <vcl/abstdlg.hxx>
+
+using namespace ::com::sun::star;
+
+/// Test opening a dialog in chart2
+class Chart2DialogsTest : public ScreenshotTest
+{
+private:
+ /// helper method to populate KnownDialogs, called in setUp(). Needs to be
+ /// written and has to add entries to KnownDialogs
+ virtual void registerKnownDialogsByID(mapType& rKnownDialogs) override;
+
+ /// dialog creation for known dialogs by ID. Has to be implemented for
+ /// each registered known dialog
+ virtual VclPtr<VclAbstractDialog> createDialogByID(sal_uInt32 nID) override;
+
+public:
+ Chart2DialogsTest();
+
+ // try to open a dialog
+ void openAnyDialog();
+
+ CPPUNIT_TEST_SUITE(Chart2DialogsTest);
+ CPPUNIT_TEST(openAnyDialog);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+Chart2DialogsTest::Chart2DialogsTest() {}
+
+void Chart2DialogsTest::registerKnownDialogsByID(mapType& /*rKnownDialogs*/)
+{
+ // fill map of known dialogs
+}
+
+VclPtr<VclAbstractDialog> Chart2DialogsTest::createDialogByID(sal_uInt32 /*nID*/)
+{
+ return nullptr;
+}
+
+void Chart2DialogsTest::openAnyDialog()
+{
+ /// process input file containing the UXMLDescriptions of the dialogs to dump
+ processDialogBatchFile(u"chart2/qa/unit/data/chart2-dialogs-test.txt");
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Chart2DialogsTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/unit/common_functor_test.cxx b/chart2/qa/unit/common_functor_test.cxx
new file mode 100644
index 0000000000..b2e404e135
--- /dev/null
+++ b/chart2/qa/unit/common_functor_test.cxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <com/sun/star/uno/Any.h>
+#include <rtl/ustring.hxx>
+
+#include <iterator>
+#include <vector>
+
+#include <CommonFunctors.hxx>
+
+
+class CommonFunctorsTest : public CppUnit::TestFixture
+{
+public:
+ CPPUNIT_TEST_SUITE(CommonFunctorsTest);
+ CPPUNIT_TEST(testAnyToString);
+ CPPUNIT_TEST(testDoubleToString);
+ CPPUNIT_TEST_SUITE_END();
+
+ void testAnyToString();
+ void testDoubleToString();
+
+private:
+};
+
+void CommonFunctorsTest::testAnyToString()
+{
+ std::vector<css::uno::Any> aInput;
+ aInput.emplace_back(2.0);
+ aInput.emplace_back(10.0);
+ aInput.emplace_back(12.0);
+ aInput.emplace_back(15.0);
+ aInput.emplace_back(25.234);
+ aInput.emplace_back(123.456);
+ aInput.emplace_back(0.123450);
+
+ std::vector<OUString> aOutput;
+ std::transform(aInput.begin(), aInput.end(),
+ std::back_inserter(aOutput), chart::CommonFunctors::AnyToString());
+
+ CPPUNIT_ASSERT_EQUAL(OUString("2"), aOutput[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("10"), aOutput[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("12"), aOutput[2]);
+ CPPUNIT_ASSERT_EQUAL(OUString("15"), aOutput[3]);
+ CPPUNIT_ASSERT_EQUAL(OUString("25.234"), aOutput[4]);
+ CPPUNIT_ASSERT_EQUAL(OUString("123.456"), aOutput[5]);
+ CPPUNIT_ASSERT_EQUAL(OUString("0.12345"), aOutput[6]);
+}
+
+void CommonFunctorsTest::testDoubleToString()
+{
+ std::vector<double> aInput { 2.0, 10.0, 12.0, 15.0, 25.234, 123.456, 0.123450 };
+
+ std::vector<OUString> aOutput;
+ std::transform(aInput.begin(), aInput.end(),
+ std::back_inserter(aOutput), chart::CommonFunctors::DoubleToOUString());
+
+ CPPUNIT_ASSERT_EQUAL(OUString("2"), aOutput[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("10"), aOutput[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("12"), aOutput[2]);
+ CPPUNIT_ASSERT_EQUAL(OUString("15"), aOutput[3]);
+ CPPUNIT_ASSERT_EQUAL(OUString("25.234"), aOutput[4]);
+ CPPUNIT_ASSERT_EQUAL(OUString("123.456"), aOutput[5]);
+ CPPUNIT_ASSERT_EQUAL(OUString("0.12345"), aOutput[6]);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(CommonFunctorsTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/qa/unit/data/chart2-dialogs-test.txt b/chart2/qa/unit/data/chart2-dialogs-test.txt
new file mode 100644
index 0000000000..92cc0880b0
--- /dev/null
+++ b/chart2/qa/unit/data/chart2-dialogs-test.txt
@@ -0,0 +1,69 @@
+# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+# This file contains all dialogs that the unit tests in the module
+# will work on if it is in script mode. It will read one-by-one,
+# try to open it and create a screenshot that will be saved in
+# workdir/screenshots using the pattern of the ui-file name.
+#
+# Syntax:
+# - empty lines are allowed
+# - lines starting with '#' are treated as comment
+# - all other lines should contain a *.ui filename in the same
+# notation as in the dialog constructors (see code)
+
+#
+# The 'known' dialogs which have a hard-coded representation
+# in registerKnownDialogsByID/createDialogByID
+#
+
+# No known dialogs in chart2 for now
+
+#
+# Dialogs without a hard-coded representation. These will
+# be visualized using a fallback based on weld::Builder
+#
+
+# currently deactivated, leads to problems and the test to not work
+# This is typically a hint that these should be hard-coded in the
+# test case since they need some document and model data to work
+
+modules/schart/ui/datarangedialog.ui
+modules/schart/ui/attributedialog.ui
+modules/schart/ui/chardialog.ui
+modules/schart/ui/paradialog.ui
+modules/schart/ui/3dviewdialog.ui
+modules/schart/ui/tp_3D_SceneAppearance.ui
+modules/schart/ui/tp_3D_SceneGeometry.ui
+modules/schart/ui/tp_3D_SceneIllumination.ui
+modules/schart/ui/tp_axisLabel.ui
+modules/schart/ui/tp_AxisPositions.ui
+modules/schart/ui/tp_DataLabel.ui
+modules/schart/ui/tp_ErrorBars.ui
+modules/schart/ui/tp_LegendPosition.ui
+modules/schart/ui/tp_ChartType.ui
+modules/schart/ui/tp_PolarOptions.ui
+modules/schart/ui/tp_Scale.ui
+modules/schart/ui/tp_SeriesToAxis.ui
+modules/schart/ui/titlerotationtabpage.ui
+modules/schart/ui/tp_Trendline.ui
+modules/schart/ui/tp_ChartType.ui
+modules/schart/ui/tp_DataSource.ui
+modules/schart/ui/tp_RangeChooser.ui
+modules/schart/ui/wizelementspage.ui
+modules/schart/ui/charttypedialog.ui
+modules/schart/ui/chartdatadialog.ui
+modules/schart/ui/insertaxisdlg.ui
+modules/schart/ui/insertgriddlg.ui
+modules/schart/ui/dlg_DataLabel.ui
+modules/schart/ui/dlg_InsertErrorBars.ui
+modules/schart/ui/dlg_InsertLegend.ui
+modules/schart/ui/inserttitledlg.ui
+modules/schart/ui/smoothlinesdlg.ui
+modules/schart/ui/steppedlinesdlg.ui
diff --git a/chart2/qa/unit/data/tolerance.xml b/chart2/qa/unit/data/tolerance.xml
new file mode 100644
index 0000000000..b73b0ff155
--- /dev/null
+++ b/chart2/qa/unit/data/tolerance.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<tolerances>
+ <tolerance elementName="XShape" attribName="positionX" value="1.2" relative="true"/>
+ <tolerance elementName="XShape" attribName="positionY" value="1.2" relative="true"/>
+ <tolerance elementName="XShape" attribName="sizeX" value="1.2" relative="true"/>
+ <tolerance elementName="XShape" attribName="sizeY" value="1.2" relative="true"/>
+</tolerances>
diff --git a/chart2/qa/unoapi/knownissues.xcl b/chart2/qa/unoapi/knownissues.xcl
new file mode 100644
index 0000000000..8321f45d00
--- /dev/null
+++ b/chart2/qa/unoapi/knownissues.xcl
@@ -0,0 +1,58 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+#i83851
+sch.ChXChartDocument::com::sun::star::frame::XModel
+#i83833
+sch.ChXChartDocument::com::sun::star::chart::XChartDocument
+#i83834
+sch.ChXChartDocument::com::sun::star::chart::ChartTableAddressSupplier
+
+#i83852
+sch.ChXChartView::com::sun::star::view::XSelectionSupplier
+
+#i83855
+sch.ChXDiagram::com::sun::star::chart::LineDiagram
+#i83853
+sch.ChXDiagram::com::sun::star::beans::XPropertySet
+#i83854
+sch.ChXDiagram::com::sun::star::chart::ChartAxisXSupplier
+sch.ChXDiagram::com::sun::star::chart::ChartAxisYSupplier
+sch.ChXDiagram::com::sun::star::chart::ChartAxisZSupplier
+#i83856
+sch.ChXDiagram::com::sun::star::chart::StockDiagram
+
+sch.ChartLegend::com::sun::star::drawing::XShape
+#i83830
+sch.ChartTitle::com::sun::star::drawing::XShape
+
+#i78867
+sch.ChXChartDocument::com::sun::star::xml::UserDefinedAttributesSupplier
+sch.ChXChartAxis::com::sun::star::xml::UserDefinedAttributesSupplier
+sch.ChXDiagram::com::sun::star::xml::UserDefinedAttributesSupplier
+sch.ChartArea::com::sun::star::xml::UserDefinedAttributesSupplier
+sch.ChartGrid::com::sun::star::xml::UserDefinedAttributesSupplier
+sch.ChartLegend::com::sun::star::xml::UserDefinedAttributesSupplier
+sch.ChartLine::com::sun::star::xml::UserDefinedAttributesSupplier
+sch.ChartTitle::com::sun::star::xml::UserDefinedAttributesSupplier
+sch.ChXDataPoint::com::sun::star::xml::UserDefinedAttributesSupplier
+
+#i83865
+sch.ChXDataPoint::com::sun::star::drawing::LineProperties
+#112078
+sch.ChartLegend::com::sun::star::beans::XPropertySet
diff --git a/chart2/qa/unoapi/sch.sce b/chart2/qa/unoapi/sch.sce
new file mode 100644
index 0000000000..54842bfd7e
--- /dev/null
+++ b/chart2/qa/unoapi/sch.sce
@@ -0,0 +1,42 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+-o sch.ChXChartDocument
+#i79073 -o sch.AccArea
+#i79073 -o sch.AccAxis
+#i79073 -o sch.AccDataPoint
+#i79073 -o sch.AccDataSeries
+#i79073 -o sch.AccDiagram
+#i79073 -o sch.AccFloor
+#i79073 -o sch.AccGrid
+#i79073 -o sch.AccLegend
+#i79073 -o sch.AccLegendEntry
+#i79073 -o sch.AccTitle
+#i79073 -o sch.AccWall
+#i79073 -o sch.AccessibleDocumentView
+-o sch.ChXChartAxis
+-o sch.ChXChartData
+-o sch.ChXChartDataArray
+-o sch.ChXChartView
+-o sch.ChXDataPoint
+#i83868 -o sch.ChXDataRow
+-o sch.ChXDiagram
+-o sch.ChartArea
+-o sch.ChartGrid
+-o sch.ChartLegend
+-o sch.ChartLine
+-o sch.ChartTitle
diff --git a/chart2/qa/unoapi/testdocuments/TransparencyChart.sxs b/chart2/qa/unoapi/testdocuments/TransparencyChart.sxs
new file mode 100644
index 0000000000..c3a5833ae2
--- /dev/null
+++ b/chart2/qa/unoapi/testdocuments/TransparencyChart.sxs
Binary files differ
diff --git a/chart2/qa/unoapi/testdocuments/emptyChart.sds b/chart2/qa/unoapi/testdocuments/emptyChart.sds
new file mode 100644
index 0000000000..853a44a12c
--- /dev/null
+++ b/chart2/qa/unoapi/testdocuments/emptyChart.sds
Binary files differ
diff --git a/chart2/qa/unoapi/testdocuments/space-metal.jpg b/chart2/qa/unoapi/testdocuments/space-metal.jpg
new file mode 100644
index 0000000000..d233443890
--- /dev/null
+++ b/chart2/qa/unoapi/testdocuments/space-metal.jpg
Binary files differ
diff --git a/chart2/source/chartcore.component b/chart2/source/chartcore.component
new file mode 100644
index 0000000000..d15c808919
--- /dev/null
+++ b/chart2/source/chartcore.component
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.chart2.ExponentialScaling"
+ constructor="com_sun_star_chart2_ExponentialScaling_get_implementation">
+ <service name="com.sun.star.chart2.ExponentialScaling"/>
+ </implementation>
+ <implementation name="com.sun.star.chart2.LinearScaling"
+ constructor="com_sun_star_chart2_LinearScaling_get_implementation">
+ <service name="com.sun.star.chart2.LinearScaling"/>
+ </implementation>
+ <implementation name="com.sun.star.chart2.LogarithmicScaling"
+ constructor="com_sun_star_chart2_LogarithmicScaling_get_implementation">
+ <service name="com.sun.star.chart2.LogarithmicScaling"/>
+ </implementation>
+ <implementation name="com.sun.star.chart2.PowerScaling"
+ constructor="com_sun_star_chart2_PowerScaling_get_implementation">
+ <service name="com.sun.star.chart2.PowerScaling"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.CachedDataSequence"
+ constructor="com_sun_star_comp_chart_CachedDataSequence_get_implementation">
+ <service name="com.sun.star.chart2.data.DataSequence"/>
+ <service name="com.sun.star.chart2.data.NumericalDataSequence"/>
+ <service name="com.sun.star.chart2.data.TextualDataSequence"/>
+ <service name="com.sun.star.comp.chart.CachedDataSequence"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.DataSource"
+ constructor="com_sun_star_comp_chart_DataSource_get_implementation">
+ <service name="com.sun.star.chart2.data.DataSource"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.InternalDataProvider"
+ constructor="com_sun_star_comp_chart_InternalDataProvider_get_implementation">
+ <service name="com.sun.star.chart2.data.DataProvider"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.ConfigDefaultColorScheme"
+ constructor="com_sun_star_comp_chart2_ConfigDefaultColorScheme_get_implementation">
+ <service name="com.sun.star.chart2.ColorScheme"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.ErrorBar"
+ constructor="com_sun_star_comp_chart2_ErrorBar_get_implementation">
+ <service name="com.sun.star.chart2.ErrorBar"/>
+ <service name="com.sun.star.comp.chart2.ErrorBar"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.ExponentialRegressionCurve"
+ constructor="com_sun_star_comp_chart2_ExponentialRegressionCurve_get_implementation">
+ <service name="com.sun.star.chart2.ExponentialRegressionCurve"/>
+ <service name="com.sun.star.chart2.RegressionCurve"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.LabeledDataSequence"
+ constructor="com_sun_star_comp_chart2_LabeledDataSequence_get_implementation">
+ <service name="com.sun.star.chart2.data.LabeledDataSequence"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.LinearRegressionCurve"
+ constructor="com_sun_star_comp_chart2_LinearRegressionCurve_get_implementation">
+ <service name="com.sun.star.chart2.LinearRegressionCurve"/>
+ <service name="com.sun.star.chart2.RegressionCurve"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.LogarithmicRegressionCurve"
+ constructor="com_sun_star_comp_chart2_LogarithmicRegressionCurve_get_implementation">
+ <service name="com.sun.star.chart2.LogarithmicRegressionCurve"/>
+ <service name="com.sun.star.chart2.RegressionCurve"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.MeanValueRegressionCurve"
+ constructor="com_sun_star_comp_chart2_MeanValueRegressionCurve_get_implementation">
+ <service name="com.sun.star.chart2.MeanValueRegressionCurve"/>
+ <service name="com.sun.star.chart2.RegressionCurve"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.PotentialRegressionCurve"
+ constructor="com_sun_star_comp_chart2_PotentialRegressionCurve_get_implementation">
+ <service name="com.sun.star.chart2.PotentialRegressionCurve"/>
+ <service name="com.sun.star.chart2.RegressionCurve"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.PolynomialRegressionCurve"
+ constructor="com_sun_star_comp_chart2_PolynomialRegressionCurve_get_implementation">
+ <service name="com.sun.star.chart2.PolynomialRegressionCurve"/>
+ <service name="com.sun.star.chart2.RegressionCurve"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.MovingAverageRegressionCurve"
+ constructor="com_sun_star_comp_chart2_MovingAverageRegressionCurve_get_implementation">
+ <service name="com.sun.star.chart2.MovingAverageRegressionCurve"/>
+ <service name="com.sun.star.chart2.RegressionCurve"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.RegressionEquation"
+ constructor="com_sun_star_comp_chart2_RegressionEquation_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.RegressionEquation"/>
+ <service name="com.sun.star.drawing.FillProperties"/>
+ <service name="com.sun.star.drawing.LineProperties"/>
+ <service name="com.sun.star.style.CharacterProperties"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.AreaChartType"
+ constructor="com_sun_star_comp_chart_AreaChartType_get_implementation">
+ <service name="com.sun.star.chart2.AreaChartType"/>
+ <service name="com.sun.star.chart2.ChartType"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.BarChartType"
+ constructor="com_sun_star_comp_chart_BarChartType_get_implementation">
+ <service name="com.sun.star.chart2.BarChartType"/>
+ <service name="com.sun.star.chart2.ChartType"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.BubbleChartType"
+ constructor="com_sun_star_comp_chart_BubbleChartType_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.BubbleChartType"/>
+ <service name="com.sun.star.chart2.ChartType"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.CandleStickChartType"
+ constructor="com_sun_star_comp_chart_CandleStickChartType_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.CandleStickChartType"/>
+ <service name="com.sun.star.chart2.ChartType"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.ChartTypeManager"
+ constructor="com_sun_star_comp_chart_ChartTypeManager_get_implementation">
+ <service name="com.sun.star.chart2.ChartTypeManager"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.ColumnChartType"
+ constructor="com_sun_star_comp_chart_ColumnChartType_get_implementation">
+ <service name="com.sun.star.chart2.ChartType"/>
+ <service name="com.sun.star.chart2.ColumnChartType"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.DataSeries"
+ constructor="com_sun_star_comp_chart_DataSeries_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.DataPointProperties"/>
+ <service name="com.sun.star.chart2.DataSeries"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.FilledNetChartType"
+ constructor="com_sun_star_comp_chart_FilledNetChartType_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.ChartType"/>
+ <service name="com.sun.star.chart2.FilledNetChartType"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.FormattedString"
+ constructor="com_sun_star_comp_chart_FormattedString_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.FormattedString"/>
+ <service name="com.sun.star.chart2.DataPointCustomLabelField"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.LineChartType"
+ constructor="com_sun_star_comp_chart_LineChartType_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.ChartType"/>
+ <service name="com.sun.star.chart2.LineChartType"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.NetChartType"
+ constructor="com_sun_star_comp_chart_NetChartType_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.ChartType"/>
+ <service name="com.sun.star.chart2.NetChartType"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.PieChartType"
+ constructor="com_sun_star_comp_chart_PieChartType_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.ChartType"/>
+ <service name="com.sun.star.chart2.PieChartType"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart.ScatterChartType"
+ constructor="com_sun_star_comp_chart_ScatterChartType_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.ChartType"/>
+ <service name="com.sun.star.chart2.ScatterChartType"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.Axis"
+ constructor="com_sun_star_comp_chart2_Axis_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.Axis"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.CartesianCoordinateSystem2d"
+ constructor="com_sun_star_comp_chart2_CartesianCoordinateSystem2d_get_implementation">
+ <service name="com.sun.star.chart2.CartesianCoordinateSystem2d"/>
+ <service name="com.sun.star.chart2.CoordinateSystems.Cartesian"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.CartesianCoordinateSystem3d"
+ constructor="com_sun_star_comp_chart2_CartesianCoordinateSystem3d_get_implementation">
+ <service name="com.sun.star.chart2.CartesianCoordinateSystem3d"/>
+ <service name="com.sun.star.chart2.CoordinateSystems.Cartesian"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.ChartModel"
+ constructor="com_sun_star_comp_chart2_ChartModel_get_implementation">
+ <service name="com.sun.star.chart.ChartDocument"/>
+ <service name="com.sun.star.chart2.ChartDocument"/>
+ <service name="com.sun.star.document.OfficeDocument"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.Diagram"
+ constructor="com_sun_star_comp_chart2_Diagram_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.Diagram"/>
+ <service name="com.sun.star.layout.LayoutElement"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.GridProperties"
+ constructor="com_sun_star_comp_chart2_GridProperties_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.GridProperties"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.Legend"
+ constructor="com_sun_star_comp_chart2_Legend_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.Legend"/>
+ <service name="com.sun.star.drawing.FillProperties"/>
+ <service name="com.sun.star.drawing.LineProperties"/>
+ <service name="com.sun.star.layout.LayoutElement"/>
+ <service name="com.sun.star.style.CharacterProperties"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.DataTable"
+ constructor="com_sun_star_comp_chart2_DataTable_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.DataTable"/>
+ <service name="com.sun.star.drawing.FillProperties"/>
+ <service name="com.sun.star.drawing.LineProperties"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.PageBackground"
+ constructor="com_sun_star_comp_chart2_PageBackground_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.PageBackground"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.PolarCoordinateSystem2d"
+ constructor="com_sun_star_comp_chart2_PolarCoordinateSystem2d_get_implementation">
+ <service name="com.sun.star.chart2.CoordinateSystems.Polar"/>
+ <service name="com.sun.star.chart2.PolarCoordinateSystem2d"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.PolarCoordinateSystem3d"
+ constructor="com_sun_star_comp_chart2_PolarCoordinateSystem3d_get_implementation">
+ <service name="com.sun.star.chart2.CoordinateSystems.Polar"/>
+ <service name="com.sun.star.chart2.PolarCoordinateSystem3d"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.Title"
+ constructor="com_sun_star_comp_chart2_Title_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart2.Title"/>
+ <service name="com.sun.star.layout.LayoutElement"/>
+ <service name="com.sun.star.style.ParagraphProperties"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.XMLFilter"
+ constructor="com_sun_star_comp_chart2_XMLFilter_get_implementation">
+ <service name="com.sun.star.document.ExportFilter"/>
+ <service name="com.sun.star.document.ImportFilter"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.report.XMLFilter"
+ constructor="com_sun_star_comp_chart2_report_XMLFilter_get_implementation">
+ <service name="com.sun.star.document.ExportFilter"/>
+ <service name="com.sun.star.document.ImportFilter"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.ChartView"
+ constructor="com_sun_star_comp_chart2_ChartView_get_implementation">
+ <service name="com.sun.star.chart2.ChartView"/>
+ </implementation>
+</component>
diff --git a/chart2/source/controller/accessibility/AccessibleBase.cxx b/chart2/source/controller/accessibility/AccessibleBase.cxx
new file mode 100644
index 0000000000..905c7f8969
--- /dev/null
+++ b/chart2/source/controller/accessibility/AccessibleBase.cxx
@@ -0,0 +1,848 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <AccessibleBase.hxx>
+#include "AccessibleChartShape.hxx"
+#include <ObjectHierarchy.hxx>
+#include <ObjectIdentifier.hxx>
+#include <ChartView.hxx>
+#include <ChartController.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleEventObject.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <sal/log.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/window.hxx>
+#include <vcl/settings.hxx>
+#include <o3tl/functional.hxx>
+#include <o3tl/safeint.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+#include <iterator>
+
+#include "ChartElementFactory.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::Reference;
+using ::osl::MutexGuard;
+using ::osl::ClearableMutexGuard;
+using ::com::sun::star::uno::Any;
+
+namespace chart
+{
+
+/** @param bMayHaveChildren is false per default
+ */
+AccessibleBase::AccessibleBase(
+ AccessibleElementInfo aAccInfo,
+ bool bMayHaveChildren,
+ bool bAlwaysTransparent /* default: false */ ) :
+ impl::AccessibleBase_Base( m_aMutex ),
+ m_bIsDisposed( false ),
+ m_bMayHaveChildren( bMayHaveChildren ),
+ m_bChildrenInitialized( false ),
+ m_nEventNotifierId(0),
+ m_nStateSet( 0 ),
+ m_aAccInfo(std::move( aAccInfo )),
+ m_bAlwaysTransparent( bAlwaysTransparent ),
+ m_bStateSetInitialized( false )
+{
+ // initialize some states
+ m_nStateSet |= AccessibleStateType::ENABLED;
+ m_nStateSet |= AccessibleStateType::SHOWING;
+ m_nStateSet |= AccessibleStateType::VISIBLE;
+ m_nStateSet |= AccessibleStateType::SELECTABLE;
+ m_nStateSet |= AccessibleStateType::FOCUSABLE;
+}
+
+AccessibleBase::~AccessibleBase()
+{
+ OSL_ASSERT( m_bIsDisposed );
+}
+
+bool AccessibleBase::CheckDisposeState( bool bThrowException /* default: true */ ) const
+{
+ if( bThrowException &&
+ m_bIsDisposed )
+ {
+ throw lang::DisposedException("component has state DEFUNC",
+ static_cast< uno::XWeak * >( const_cast< AccessibleBase * >( this )));
+ }
+ return m_bIsDisposed;
+}
+
+bool AccessibleBase::NotifyEvent( EventType eEventType, const AccessibleUniqueId & rId )
+{
+ if( GetId() == rId )
+ {
+ // event is addressed to this object
+
+ css::uno::Any aEmpty;
+ css::uno::Any aSelected;
+ aSelected <<= AccessibleStateType::SELECTED;
+ switch( eEventType )
+ {
+ case EventType::GOT_SELECTION:
+ {
+ AddState( AccessibleStateType::SELECTED );
+ BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aSelected, aEmpty );
+
+ AddState( AccessibleStateType::FOCUSED );
+ aSelected <<= AccessibleStateType::FOCUSED;
+ BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aSelected, aEmpty );
+
+ SAL_INFO("chart2.accessibility", "Selection acquired by: " << getAccessibleName());
+ }
+ break;
+
+ case EventType::LOST_SELECTION:
+ {
+ RemoveState( AccessibleStateType::SELECTED );
+ BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aEmpty, aSelected );
+
+ AddState( AccessibleStateType::FOCUSED );
+ aSelected <<= AccessibleStateType::FOCUSED;
+ BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aEmpty, aSelected );
+ SAL_INFO("chart2.accessibility", "Selection lost by: " << getAccessibleName());
+ }
+ break;
+ }
+ return true;
+ }
+ else if( m_bMayHaveChildren )
+ {
+ bool bStop = false;
+
+ ClearableMutexGuard aGuard( m_aMutex );
+ // make local copy for notification
+ ChildListVectorType aLocalChildList( m_aChildList );
+ aGuard.clear();
+
+ for (auto const& localChild : aLocalChildList)
+ {
+ // Note: at this place we must be sure to have an AccessibleBase
+ // object in the UNO reference to XAccessible !
+ bStop = (*static_cast< AccessibleBase * >
+ ( localChild.get() )).NotifyEvent( eEventType, rId );
+ if (bStop)
+ break;
+ }
+ return bStop;
+ }
+
+ return false;
+}
+
+void AccessibleBase::AddState( sal_Int64 aState )
+{
+ CheckDisposeState();
+ m_nStateSet |= aState;
+}
+
+void AccessibleBase::RemoveState( sal_Int64 aState )
+{
+ CheckDisposeState();
+ m_nStateSet &= ~aState;
+}
+
+bool AccessibleBase::UpdateChildren()
+{
+ bool bMustUpdateChildren = false;
+ {
+ MutexGuard aGuard( m_aMutex );
+ if( ! m_bMayHaveChildren ||
+ m_bIsDisposed )
+ return false;
+
+ bMustUpdateChildren = ( m_bMayHaveChildren &&
+ ! m_bChildrenInitialized );
+ }
+
+ // update unguarded
+ if( bMustUpdateChildren )
+ m_bChildrenInitialized = ImplUpdateChildren();
+
+ return m_bChildrenInitialized;
+}
+
+bool AccessibleBase::ImplUpdateChildren()
+{
+ bool bResult = false;
+
+ if( m_aAccInfo.m_spObjectHierarchy )
+ {
+ ObjectHierarchy::tChildContainer aModelChildren(
+ m_aAccInfo.m_spObjectHierarchy->getChildren( GetId() ));
+ std::vector< ChildOIDMap::key_type > aAccChildren;
+ aAccChildren.reserve( aModelChildren.size());
+ std::transform( m_aChildOIDMap.begin(), m_aChildOIDMap.end(),
+ std::back_inserter( aAccChildren ),
+ ::o3tl::select1st< ChildOIDMap::value_type >() );
+
+ std::sort( aModelChildren.begin(), aModelChildren.end());
+
+ std::vector< ObjectIdentifier > aChildrenToRemove, aChildrenToAdd;
+ std::set_difference( aModelChildren.begin(), aModelChildren.end(),
+ aAccChildren.begin(), aAccChildren.end(),
+ std::back_inserter( aChildrenToAdd ));
+ std::set_difference( aAccChildren.begin(), aAccChildren.end(),
+ aModelChildren.begin(), aModelChildren.end(),
+ std::back_inserter( aChildrenToRemove ));
+
+ for (auto const& childToRemove : aChildrenToRemove)
+ {
+ RemoveChildByOId(childToRemove);
+ }
+
+ AccessibleElementInfo aAccInfo( GetInfo());
+ aAccInfo.m_pParent = this;
+
+ for (auto const& childToAdd : aChildrenToAdd)
+ {
+ aAccInfo.m_aOID = childToAdd;
+ if ( childToAdd.isAutoGeneratedObject() )
+ {
+ AddChild( ChartElementFactory::CreateChartElement( aAccInfo ).get() );
+ }
+ else if ( childToAdd.isAdditionalShape() )
+ {
+ AddChild( new AccessibleChartShape( aAccInfo ) );
+ }
+ }
+ bResult = true;
+ }
+
+ return bResult;
+}
+
+void AccessibleBase::AddChild( AccessibleBase * pChild )
+{
+ OSL_ENSURE( pChild != nullptr, "Invalid Child" );
+ if( !pChild )
+ return;
+
+ ClearableMutexGuard aGuard( m_aMutex );
+
+ Reference< XAccessible > xChild( pChild );
+ m_aChildList.push_back( xChild );
+
+ m_aChildOIDMap[ pChild->GetId() ] = xChild;
+
+ // inform listeners of new child
+ if( m_bChildrenInitialized )
+ {
+ Any aEmpty, aNew;
+ aNew <<= xChild;
+
+ aGuard.clear();
+ BroadcastAccEvent( AccessibleEventId::CHILD, aNew, aEmpty );
+ }
+}
+
+/** in this method we imply that the Reference< XAccessible > elements in the
+ vector are AccessibleBase objects !
+ */
+void AccessibleBase::RemoveChildByOId( const ObjectIdentifier& rOId )
+{
+ ClearableMutexGuard aGuard( m_aMutex );
+
+ ChildOIDMap::iterator aIt( m_aChildOIDMap.find( rOId ));
+ if( aIt == m_aChildOIDMap.end())
+ return;
+
+ Reference< XAccessible > xChild( aIt->second );
+
+ // remove from map
+ m_aChildOIDMap.erase( aIt );
+
+ // search child in vector
+ ChildListVectorType::iterator aVecIter =
+ std::find( m_aChildList.begin(), m_aChildList.end(), xChild );
+
+ OSL_ENSURE( aVecIter != m_aChildList.end(),
+ "Inconsistent ChildMap" );
+
+ // remove child from vector
+ m_aChildList.erase( aVecIter );
+ bool bInitialized = m_bChildrenInitialized;
+
+ // call listeners unguarded
+ aGuard.clear();
+
+ // inform listeners of removed child
+ if( bInitialized )
+ {
+ Any aEmpty, aOld;
+ aOld <<= xChild;
+
+ BroadcastAccEvent( AccessibleEventId::CHILD, aEmpty, aOld );
+ }
+
+ // dispose the child
+ Reference< lang::XComponent > xComp( xChild, UNO_QUERY );
+ if( xComp.is())
+ xComp->dispose();
+}
+
+awt::Point AccessibleBase::GetUpperLeftOnScreen() const
+{
+ awt::Point aResult;
+ if( m_aAccInfo.m_pParent )
+ {
+ ClearableMutexGuard aGuard( m_aMutex );
+ AccessibleBase * pParent = m_aAccInfo.m_pParent;
+ aGuard.clear();
+
+ if( pParent )
+ {
+ aResult = pParent->GetUpperLeftOnScreen();
+ }
+ else
+ OSL_FAIL( "Default position used is probably incorrect." );
+ }
+
+ return aResult;
+}
+
+void AccessibleBase::BroadcastAccEvent(
+ sal_Int16 nId,
+ const Any & rNew,
+ const Any & rOld ) const
+{
+ ClearableMutexGuard aGuard( m_aMutex );
+
+ if ( !m_nEventNotifierId )
+ return;
+ // if we don't have a client id for the notifier, then we don't have listeners, then
+ // we don't need to notify anything
+
+ // the const cast is needed, because UNO parameters are never const
+ const AccessibleEventObject aEvent(
+ const_cast< uno::XWeak * >( static_cast< const uno::XWeak * >( this )),
+ nId, rNew, rOld, -1 );
+
+ // let the notifier handle this event
+ ::comphelper::AccessibleEventNotifier::addEvent( m_nEventNotifierId, aEvent );
+
+ aGuard.clear();
+}
+
+void AccessibleBase::KillAllChildren()
+{
+ ClearableMutexGuard aGuard( m_aMutex );
+
+ // make local copy for notification, and remove all children
+ ChildListVectorType aLocalChildList;
+ aLocalChildList.swap( m_aChildList );
+ m_aChildOIDMap.clear();
+
+ aGuard.clear();
+
+ // call dispose for all children
+ // and notify listeners
+ Reference< lang::XComponent > xComp;
+ Any aEmpty, aOld;
+ for (auto const& localChild : aLocalChildList)
+ {
+ aOld <<= localChild;
+ BroadcastAccEvent( AccessibleEventId::CHILD, aEmpty, aOld );
+
+ xComp.set(localChild, UNO_QUERY);
+ if( xComp.is())
+ xComp->dispose();
+ }
+ m_bChildrenInitialized = false;
+}
+
+void AccessibleBase::SetInfo( const AccessibleElementInfo & rNewInfo )
+{
+ m_aAccInfo = rNewInfo;
+ if( m_bMayHaveChildren )
+ {
+ KillAllChildren();
+ }
+ BroadcastAccEvent( AccessibleEventId::INVALIDATE_ALL_CHILDREN, uno::Any(), uno::Any());
+}
+
+// ________ (XComponent::dispose) ________
+void SAL_CALL AccessibleBase::disposing()
+{
+ {
+ MutexGuard aGuard(m_aMutex);
+ OSL_ENSURE(!m_bIsDisposed, "dispose() called twice");
+
+ // notify disposing to all AccessibleEvent listeners asynchronous
+ if (m_nEventNotifierId)
+ {
+ ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(m_nEventNotifierId,
+ *this);
+ m_nEventNotifierId = 0;
+ }
+
+ // reset pointers
+ m_aAccInfo.m_pParent = nullptr;
+
+ m_nStateSet = AccessibleStateType::DEFUNC;
+
+ m_bIsDisposed = true;
+
+ }
+ // call listeners unguarded
+
+ if( m_bMayHaveChildren )
+ {
+ KillAllChildren();
+ }
+ else
+ OSL_ENSURE( m_aChildList.empty(), "Child list should be empty" );
+}
+
+// ________ XAccessible ________
+Reference< XAccessibleContext > SAL_CALL AccessibleBase::getAccessibleContext()
+{
+ return this;
+}
+
+// ________ AccessibleBase::XAccessibleContext ________
+sal_Int64 SAL_CALL AccessibleBase::getAccessibleChildCount()
+{
+ ClearableMutexGuard aGuard( m_aMutex );
+ if( ! m_bMayHaveChildren ||
+ m_bIsDisposed )
+ return 0;
+
+ bool bMustUpdateChildren = ( m_bMayHaveChildren &&
+ ! m_bChildrenInitialized );
+
+ aGuard.clear();
+
+ // update unguarded
+ if( bMustUpdateChildren )
+ UpdateChildren();
+
+ return ImplGetAccessibleChildCount();
+}
+
+sal_Int64 AccessibleBase::ImplGetAccessibleChildCount() const
+{
+ return m_aChildList.size();
+}
+
+Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleChild( sal_Int64 i )
+{
+ CheckDisposeState();
+ Reference< XAccessible > xResult;
+
+ ClearableMutexGuard aGuard( m_aMutex );
+ bool bMustUpdateChildren = ( m_bMayHaveChildren &&
+ ! m_bChildrenInitialized );
+
+ aGuard.clear();
+
+ if( bMustUpdateChildren )
+ UpdateChildren();
+
+ xResult.set( ImplGetAccessibleChildById( i ));
+
+ return xResult;
+}
+
+Reference< XAccessible > AccessibleBase::ImplGetAccessibleChildById( sal_Int64 i ) const
+{
+ Reference< XAccessible > xResult;
+
+ MutexGuard aGuard( m_aMutex);
+ if( ! m_bMayHaveChildren ||
+ i < 0 ||
+ o3tl::make_unsigned( i ) >= m_aChildList.size() )
+ {
+ OUString aBuf = "Index " + OUString::number( i ) + " is invalid for range [ 0, " +
+ OUString::number( m_aChildList.size() - 1 ) +
+ " ]";
+ lang::IndexOutOfBoundsException aEx( aBuf,
+ const_cast< ::cppu::OWeakObject * >(
+ static_cast< const ::cppu::OWeakObject * >( this )));
+ throw aEx;
+ }
+ else
+ xResult.set( m_aChildList[ i ] );
+
+ return xResult;
+}
+
+Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleParent()
+{
+ CheckDisposeState();
+ Reference< XAccessible > aResult;
+ if( m_aAccInfo.m_pParent )
+ aResult.set( m_aAccInfo.m_pParent );
+
+ return aResult;
+}
+
+sal_Int64 SAL_CALL AccessibleBase::getAccessibleIndexInParent()
+{
+ CheckDisposeState();
+
+ if( m_aAccInfo.m_spObjectHierarchy )
+ return m_aAccInfo.m_spObjectHierarchy->getIndexInParent( GetId() );
+ return -1;
+}
+
+sal_Int16 SAL_CALL AccessibleBase::getAccessibleRole()
+{
+ return AccessibleRole::SHAPE;
+}
+
+Reference< XAccessibleRelationSet > SAL_CALL AccessibleBase::getAccessibleRelationSet()
+{
+ Reference< XAccessibleRelationSet > aResult;
+ return aResult;
+}
+
+sal_Int64 SAL_CALL AccessibleBase::getAccessibleStateSet()
+{
+ if( ! m_bStateSetInitialized )
+ {
+ rtl::Reference< ::chart::ChartController > xSelSupp( GetInfo().m_xChartController );
+ if ( xSelSupp.is() )
+ {
+ ObjectIdentifier aOID( xSelSupp->getSelection() );
+ if ( aOID.isValid() && GetId() == aOID )
+ {
+ AddState( AccessibleStateType::SELECTED );
+ AddState( AccessibleStateType::FOCUSED );
+ }
+ }
+ m_bStateSetInitialized = true;
+ }
+
+ return m_nStateSet;
+}
+
+lang::Locale SAL_CALL AccessibleBase::getLocale()
+{
+ CheckDisposeState();
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+// ________ AccessibleBase::XAccessibleComponent ________
+sal_Bool SAL_CALL AccessibleBase::containsPoint( const awt::Point& aPoint )
+{
+ awt::Rectangle aRect( getBounds() );
+
+ // contains() works with relative coordinates
+ aRect.X = 0;
+ aRect.Y = 0;
+
+ return ( aPoint.X >= aRect.X &&
+ aPoint.Y >= aRect.Y &&
+ aPoint.X < (aRect.X + aRect.Width) &&
+ aPoint.Y < (aRect.Y + aRect.Height) );
+}
+
+Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleAtPoint( const awt::Point& aPoint )
+{
+ CheckDisposeState();
+ Reference< XAccessible > aResult;
+ awt::Rectangle aRect( getBounds());
+
+ // children are positioned relative to this object, so translate bound rect
+ aRect.X = 0;
+ aRect.Y = 0;
+
+ // children must be inside the own bound rect
+ if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) &&
+ ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height)))
+ {
+ ClearableMutexGuard aGuard( m_aMutex );
+ ChildListVectorType aLocalChildList( m_aChildList );
+ aGuard.clear();
+
+ Reference< XAccessibleComponent > aComp;
+ for (auto const& localChild : aLocalChildList)
+ {
+ aComp.set(localChild, UNO_QUERY);
+ if( aComp.is())
+ {
+ aRect = aComp->getBounds();
+ if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) &&
+ ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height)))
+ {
+ aResult = localChild;
+ break;
+ }
+ }
+ }
+ }
+
+ return aResult;
+}
+
+awt::Rectangle SAL_CALL AccessibleBase::getBounds()
+{
+ rtl::Reference<ChartView> pChartView = m_aAccInfo.m_xView.get();
+ if( pChartView )
+ {
+ VclPtr<vcl::Window> pWindow( VCLUnoHelper::GetWindow( m_aAccInfo.m_xWindow ));
+ awt::Rectangle aLogicRect( pChartView->getRectangleOfObject( m_aAccInfo.m_aOID.getObjectCID() ));
+ if( pWindow )
+ {
+ tools::Rectangle aRect( aLogicRect.X, aLogicRect.Y,
+ aLogicRect.X + aLogicRect.Width,
+ aLogicRect.Y + aLogicRect.Height );
+ SolarMutexGuard aSolarGuard;
+ aRect = pWindow->LogicToPixel( aRect );
+
+ // aLogicRect is relative to the page, but we need a value relative
+ // to the parent object
+ awt::Point aParentLocOnScreen;
+ uno::Reference< XAccessibleComponent > xParent( getAccessibleParent(), uno::UNO_QUERY );
+ if( xParent.is() )
+ aParentLocOnScreen = xParent->getLocationOnScreen();
+
+ awt::Point aULOnScreen = GetUpperLeftOnScreen();
+ awt::Point aOffset( aParentLocOnScreen.X - aULOnScreen.X,
+ aParentLocOnScreen.Y - aULOnScreen.Y );
+
+ return awt::Rectangle( aRect.Left() - aOffset.X, aRect.Top() - aOffset.Y,
+ aRect.getOpenWidth(), aRect.getOpenHeight());
+ }
+ }
+
+ return awt::Rectangle();
+}
+
+awt::Point SAL_CALL AccessibleBase::getLocation()
+{
+ CheckDisposeState();
+ awt::Rectangle aBBox( getBounds() );
+ return awt::Point( aBBox.X, aBBox.Y );
+}
+
+awt::Point SAL_CALL AccessibleBase::getLocationOnScreen()
+{
+ CheckDisposeState();
+
+ if (AccessibleBase* pParent = m_aAccInfo.m_pParent)
+ {
+ awt::Point aLocThisRel( getLocation());
+ awt::Point aUpperLeft(pParent->getLocationOnScreen());
+
+ return awt::Point( aUpperLeft.X + aLocThisRel.X,
+ aUpperLeft.Y + aLocThisRel.Y );
+ }
+ else
+ return getLocation();
+}
+
+awt::Size SAL_CALL AccessibleBase::getSize()
+{
+ CheckDisposeState();
+ awt::Rectangle aBBox( getBounds() );
+ return awt::Size( aBBox.Width, aBBox.Height );
+}
+
+void SAL_CALL AccessibleBase::grabFocus()
+{
+ CheckDisposeState();
+
+ rtl::Reference< ::chart::ChartController > xSelSupp( GetInfo().m_xChartController );
+ if ( xSelSupp.is() )
+ {
+ xSelSupp->select( GetId().getAny() );
+ }
+}
+
+sal_Int32 SAL_CALL AccessibleBase::getForeground()
+{
+ return sal_Int32(getColor( ACC_BASE_FOREGROUND ));
+}
+
+sal_Int32 SAL_CALL AccessibleBase::getBackground()
+{
+ return sal_Int32(getColor( ACC_BASE_BACKGROUND ));
+}
+
+Color AccessibleBase::getColor( eColorType eColType )
+{
+ Color nResult = COL_TRANSPARENT;
+ if( m_bAlwaysTransparent )
+ return nResult;
+
+ ObjectIdentifier aOID( m_aAccInfo.m_aOID );
+ ObjectType eType( aOID.getObjectType() );
+ Reference< beans::XPropertySet > xObjProp;
+ OUString aObjectCID = aOID.getObjectCID();
+ if( eType == OBJECTTYPE_LEGEND_ENTRY )
+ {
+ // for colors get the data series/point properties
+ std::u16string_view aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID ));
+ aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle );
+ }
+
+ xObjProp =
+ ObjectIdentifier::getObjectPropertySet(
+ aObjectCID, m_aAccInfo.m_xChartDocument );
+ if( xObjProp.is())
+ {
+ try
+ {
+ OUString aPropName;
+ OUString aStylePropName;
+
+ switch( eType )
+ {
+ case OBJECTTYPE_LEGEND_ENTRY:
+ case OBJECTTYPE_DATA_SERIES:
+ case OBJECTTYPE_DATA_POINT:
+ if( eColType == ACC_BASE_FOREGROUND )
+ {
+ aPropName = "BorderColor";
+ aStylePropName = "BorderTransparency";
+ }
+ else
+ {
+ aPropName = "Color";
+ aStylePropName = "Transparency";
+ }
+ break;
+ default:
+ if( eColType == ACC_BASE_FOREGROUND )
+ {
+ aPropName = "LineColor";
+ aStylePropName = "LineTransparence";
+ }
+ else
+ {
+ aPropName = "FillColor";
+ aStylePropName = "FillTransparence";
+ }
+ break;
+ }
+
+ bool bTransparent = m_bAlwaysTransparent;
+ Reference< beans::XPropertySetInfo > xInfo = xObjProp->getPropertySetInfo();
+ if( xInfo.is() &&
+ xInfo->hasPropertyByName( aStylePropName ))
+ {
+ if( eColType == ACC_BASE_FOREGROUND )
+ {
+ drawing::LineStyle aLStyle;
+ if( xObjProp->getPropertyValue( aStylePropName ) >>= aLStyle )
+ bTransparent = (aLStyle == drawing::LineStyle_NONE);
+ }
+ else
+ {
+ drawing::FillStyle aFStyle;
+ if( xObjProp->getPropertyValue( aStylePropName ) >>= aFStyle )
+ bTransparent = (aFStyle == drawing::FillStyle_NONE);
+ }
+ }
+
+ if( !bTransparent &&
+ xInfo.is() &&
+ xInfo->hasPropertyByName( aPropName ))
+ {
+ xObjProp->getPropertyValue( aPropName ) >>= nResult;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return nResult;
+}
+
+// ________ AccessibleBase::XServiceInfo ________
+OUString SAL_CALL AccessibleBase::getImplementationName()
+{
+ return "AccessibleBase";
+}
+
+sal_Bool SAL_CALL AccessibleBase::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+uno::Sequence< OUString > SAL_CALL AccessibleBase::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.accessibility.Accessible",
+ "com.sun.star.accessibility.AccessibleContext"
+ };
+}
+
+// ________ AccessibleBase::XEventListener ________
+void SAL_CALL AccessibleBase::disposing( const lang::EventObject& /*Source*/ )
+{
+}
+
+// ________ XAccessibleEventBroadcasters ________
+void SAL_CALL AccessibleBase::addAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
+{
+ MutexGuard aGuard( m_aMutex );
+
+ if ( xListener.is() )
+ {
+ if ( !m_nEventNotifierId )
+ m_nEventNotifierId = ::comphelper::AccessibleEventNotifier::registerClient();
+
+ ::comphelper::AccessibleEventNotifier::addEventListener( m_nEventNotifierId, xListener );
+ }
+}
+
+void SAL_CALL AccessibleBase::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
+{
+ MutexGuard aGuard( m_aMutex );
+
+ if ( xListener.is() && m_nEventNotifierId)
+ {
+ sal_Int32 nListenerCount = ::comphelper::AccessibleEventNotifier::removeEventListener( m_nEventNotifierId, xListener );
+ if ( !nListenerCount )
+ {
+ // no listeners anymore
+ ::comphelper::AccessibleEventNotifier::revokeClient( m_nEventNotifierId );
+ m_nEventNotifierId = 0;
+ }
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/accessibility/AccessibleChartElement.cxx b/chart2/source/controller/accessibility/AccessibleChartElement.cxx
new file mode 100644
index 0000000000..209d282c2c
--- /dev/null
+++ b/chart2/source/controller/accessibility/AccessibleChartElement.cxx
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AccessibleChartElement.hxx"
+#include <AccessibleTextHelper.hxx>
+#include <CharacterProperties.hxx>
+#include <ChartModel.hxx>
+#include <ChartController.hxx>
+#include <ObjectIdentifier.hxx>
+#include <ObjectNameProvider.hxx>
+#include <servicenames.hxx>
+
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/chart2/XTitle.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+AccessibleChartElement::AccessibleChartElement(
+ const AccessibleElementInfo & rAccInfo,
+ bool bMayHaveChildren ) :
+ impl::AccessibleChartElement_Base( rAccInfo, bMayHaveChildren, false/*bAlwaysTransparent*/ ),
+ m_bHasText( false )
+{
+ AddState( AccessibleStateType::TRANSIENT );
+}
+
+AccessibleChartElement::~AccessibleChartElement()
+{
+ OSL_ASSERT( CheckDisposeState( false /* don't throw exceptions */ ) );
+}
+
+// ________ protected ________
+
+bool AccessibleChartElement::ImplUpdateChildren()
+{
+ bool bResult = false;
+ Reference< chart2::XTitle > xTitle(
+ ObjectIdentifier::getObjectPropertySet(
+ GetInfo().m_aOID.getObjectCID(), GetInfo().m_xChartDocument ),
+ uno::UNO_QUERY );
+ m_bHasText = xTitle.is();
+
+ if( m_bHasText )
+ {
+ InitTextEdit();
+ bResult = true;
+ }
+ else
+ bResult = AccessibleBase::ImplUpdateChildren();
+
+ return bResult;
+}
+
+void AccessibleChartElement::InitTextEdit()
+{
+ if( ! m_xTextHelper.is())
+ {
+ // get hard reference
+ rtl::Reference< ::chart::ChartController > xChartController( GetInfo().m_xChartController );
+ if( xChartController.is())
+ m_xTextHelper = xChartController->createAccessibleTextContext();
+ }
+
+ if( !m_xTextHelper.is())
+ return;
+
+ m_xTextHelper->initialize( GetInfo().m_aOID.getObjectCID(), this, GetInfo().m_xWindow );
+}
+
+// Interfaces
+
+// ________ AccessibleBase::XAccessibleContext ________
+Reference< XAccessible > AccessibleChartElement::ImplGetAccessibleChildById( sal_Int64 i ) const
+{
+ Reference< XAccessible > xResult;
+
+ if( m_bHasText )
+ xResult.set( m_xTextHelper->getAccessibleChild( i ));
+ else
+ xResult.set( AccessibleBase::ImplGetAccessibleChildById( i ));
+
+ return xResult;
+}
+
+sal_Int64 AccessibleChartElement::ImplGetAccessibleChildCount() const
+{
+ if( m_bHasText )
+ {
+ if( m_xTextHelper.is())
+ return m_xTextHelper->getAccessibleChildCount();
+ return 0;
+ }
+
+ return AccessibleBase::ImplGetAccessibleChildCount();
+}
+
+// ________ XServiceInfo ________
+OUString SAL_CALL AccessibleChartElement::getImplementationName()
+{
+ return "AccessibleChartElement";
+}
+
+// ________ AccessibleChartElement::XAccessibleContext (override) ________
+OUString SAL_CALL AccessibleChartElement::getAccessibleName()
+{
+ return ObjectNameProvider::getNameForCID(
+ GetInfo().m_aOID.getObjectCID(), GetInfo().m_xChartDocument );
+}
+
+// ________ AccessibleChartElement::XAccessibleContext (override) ________
+OUString SAL_CALL AccessibleChartElement::getAccessibleDescription()
+{
+ return getToolTipText();
+}
+
+// ________ AccessibleChartElement::XAccessibleExtendedComponent ________
+Reference< awt::XFont > SAL_CALL AccessibleChartElement::getFont()
+{
+ CheckDisposeState();
+
+ Reference< awt::XFont > xFont;
+ Reference< awt::XDevice > xDevice( Reference< awt::XWindow >( GetInfo().m_xWindow ), uno::UNO_QUERY );
+
+ if( xDevice.is())
+ {
+ Reference< beans::XMultiPropertySet > xObjProp(
+ ObjectIdentifier::getObjectPropertySet(
+ GetInfo().m_aOID.getObjectCID(), GetInfo().m_xChartDocument ), uno::UNO_QUERY );
+ awt::FontDescriptor aDescr(
+ CharacterProperties::createFontDescriptorFromPropertySet( xObjProp ));
+ xFont = xDevice->getFont( aDescr );
+ }
+
+ return xFont;
+}
+
+OUString SAL_CALL AccessibleChartElement::getTitledBorderText()
+{
+ return OUString();
+}
+
+OUString SAL_CALL AccessibleChartElement::getToolTipText()
+{
+ CheckDisposeState();
+
+ return ObjectNameProvider::getHelpText(
+ GetInfo().m_aOID.getObjectCID(), GetInfo().m_xChartDocument );
+}
+
+// ________ XAccessibleComponent ________
+sal_Bool SAL_CALL AccessibleChartElement::containsPoint( const awt::Point& aPoint )
+{
+ return AccessibleBase::containsPoint( aPoint );
+}
+
+Reference< XAccessible > SAL_CALL AccessibleChartElement::getAccessibleAtPoint( const awt::Point& aPoint )
+{
+ return AccessibleBase::getAccessibleAtPoint( aPoint );
+}
+
+awt::Rectangle SAL_CALL AccessibleChartElement::getBounds()
+{
+ return AccessibleBase::getBounds();
+}
+
+awt::Point SAL_CALL AccessibleChartElement::getLocation()
+{
+ return AccessibleBase::getLocation();
+}
+
+awt::Point SAL_CALL AccessibleChartElement::getLocationOnScreen()
+{
+ return AccessibleBase::getLocationOnScreen();
+}
+
+awt::Size SAL_CALL AccessibleChartElement::getSize()
+{
+ return AccessibleBase::getSize();
+}
+
+void SAL_CALL AccessibleChartElement::grabFocus()
+{
+ return AccessibleBase::grabFocus();
+}
+
+sal_Int32 SAL_CALL AccessibleChartElement::getForeground()
+{
+ return AccessibleBase::getForeground();
+}
+
+sal_Int32 SAL_CALL AccessibleChartElement::getBackground()
+{
+ return AccessibleBase::getBackground();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/accessibility/AccessibleChartElement.hxx b/chart2/source/controller/accessibility/AccessibleChartElement.hxx
new file mode 100644
index 0000000000..283efed69d
--- /dev/null
+++ b/chart2/source/controller/accessibility/AccessibleChartElement.hxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <AccessibleBase.hxx>
+#include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp>
+
+namespace com::sun::star::accessibility { class XAccessible; }
+namespace com::sun::star::accessibility { class XAccessibleContext; }
+namespace com::sun::star::awt { class XFont; }
+
+namespace chart
+{
+class AccessibleTextHelper;
+
+/** Base class for all Chart Accessibility objects except the root node (see AccessibleChartView)
+
+ This class contains a reference to the ChartModel, thus, components can easily access all core functionality.
+
+ Usage Instructions:
+
+ <ul>
+ <li>define the getAccessibleName() method of XAccessibleContext</li>
+ <li>set the ChartModel using SetChartModel() for the first node before
+ creating any children</li>
+ <li>override UpdateChildren()</li>
+ </ul>
+ */
+
+namespace impl
+{
+typedef ::cppu::ImplInheritanceHelper<
+ AccessibleBase,
+ css::accessibility::XAccessibleExtendedComponent
+ > AccessibleChartElement_Base;
+}
+
+class AccessibleChartElement :
+ public impl::AccessibleChartElement_Base
+{
+public:
+ AccessibleChartElement( const AccessibleElementInfo & rAccInfo,
+ bool bMayHaveChildren );
+ virtual ~AccessibleChartElement() override;
+
+ // ________ AccessibleBase ________
+ virtual bool ImplUpdateChildren() override;
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ ImplGetAccessibleChildById( sal_Int64 i ) const override;
+ virtual sal_Int64 ImplGetAccessibleChildCount() const override;
+
+ // ________ XAccessibleContext ________
+ virtual OUString SAL_CALL getAccessibleName() override;
+ virtual OUString SAL_CALL getAccessibleDescription() override;
+
+ // ________ XAccessibleExtendedComponent ________
+ virtual css::uno::Reference< css::awt::XFont > SAL_CALL getFont() override;
+ virtual OUString SAL_CALL getTitledBorderText() override;
+ virtual OUString SAL_CALL getToolTipText() override;
+
+ // the following interface is implemented in AccessibleBase, however it is
+ // also a (non-virtual) base class of XAccessibleExtendedComponent Thus
+ // these methods have to be overridden and forward to AccessibleBase
+
+ // ________ XAccessibleComponent ________
+ virtual sal_Bool SAL_CALL containsPoint( const css::awt::Point& aPoint ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override;
+ virtual css::awt::Rectangle SAL_CALL getBounds() override;
+ virtual css::awt::Point SAL_CALL getLocation() override;
+ virtual css::awt::Point SAL_CALL getLocationOnScreen() override;
+ virtual css::awt::Size SAL_CALL getSize() override;
+ virtual void SAL_CALL grabFocus() override;
+ virtual sal_Int32 SAL_CALL getForeground() override;
+ virtual sal_Int32 SAL_CALL getBackground() override;
+
+ // ________ XServiceInfo ________
+ virtual OUString SAL_CALL getImplementationName() override;
+
+private:
+ bool m_bHasText;
+ rtl::Reference< ::chart::AccessibleTextHelper >
+ m_xTextHelper;
+
+ void InitTextEdit();
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/accessibility/AccessibleChartShape.cxx b/chart2/source/controller/accessibility/AccessibleChartShape.cxx
new file mode 100644
index 0000000000..771698a840
--- /dev/null
+++ b/chart2/source/controller/accessibility/AccessibleChartShape.cxx
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AccessibleChartShape.hxx"
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <svx/ShapeTypeHandler.hxx>
+#include <svx/AccessibleShape.hxx>
+#include <svx/AccessibleShapeInfo.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+AccessibleChartShape::AccessibleChartShape(
+ const AccessibleElementInfo& rAccInfo )
+ :impl::AccessibleChartShape_Base( rAccInfo, true/*bMayHaveChildren*/, false/*bAlwaysTransparent*/ )
+{
+ if ( !rAccInfo.m_aOID.isAdditionalShape() )
+ return;
+
+ Reference< drawing::XShape > xShape( rAccInfo.m_aOID.getAdditionalShape() );
+ Reference< XAccessible > xParent;
+ if ( rAccInfo.m_pParent )
+ {
+ xParent.set( rAccInfo.m_pParent );
+ }
+ ::accessibility::AccessibleShapeInfo aShapeInfo( xShape, xParent );
+
+ m_aShapeTreeInfo.SetSdrView( rAccInfo.m_pSdrView );
+ m_aShapeTreeInfo.SetController( nullptr );
+ m_aShapeTreeInfo.SetWindow( VCLUnoHelper::GetWindow( rAccInfo.m_xWindow ) );
+ m_aShapeTreeInfo.SetViewForwarder( rAccInfo.m_pViewForwarder );
+
+ ::accessibility::ShapeTypeHandler& rShapeHandler = ::accessibility::ShapeTypeHandler::Instance();
+ m_pAccShape = rShapeHandler.CreateAccessibleObject( aShapeInfo, m_aShapeTreeInfo );
+ if ( m_pAccShape.is() )
+ {
+ m_pAccShape->Init();
+ }
+}
+
+AccessibleChartShape::~AccessibleChartShape()
+{
+ OSL_ASSERT( CheckDisposeState( false /* don't throw exceptions */ ) );
+
+ if ( m_pAccShape.is() )
+ {
+ m_pAccShape->dispose();
+ }
+}
+
+// ________ XServiceInfo ________
+OUString AccessibleChartShape::getImplementationName()
+{
+ return "AccessibleChartShape";
+}
+
+// ________ XAccessibleContext ________
+sal_Int64 AccessibleChartShape::getAccessibleChildCount()
+{
+ sal_Int64 nCount(0);
+ if ( m_pAccShape.is() )
+ {
+ nCount = m_pAccShape->getAccessibleChildCount();
+ }
+ return nCount;
+}
+
+Reference< XAccessible > AccessibleChartShape::getAccessibleChild( sal_Int64 i )
+{
+ Reference< XAccessible > xChild;
+ if ( m_pAccShape.is() )
+ {
+ xChild = m_pAccShape->getAccessibleChild( i );
+ }
+ return xChild;
+}
+
+sal_Int16 AccessibleChartShape::getAccessibleRole()
+{
+ sal_Int16 nRole(0);
+ if ( m_pAccShape.is() )
+ {
+ nRole = m_pAccShape->getAccessibleRole();
+ }
+ return nRole;
+}
+
+OUString AccessibleChartShape::getAccessibleDescription()
+{
+ OUString aDescription;
+ if ( m_pAccShape.is() )
+ {
+ aDescription = m_pAccShape->getAccessibleDescription();
+ }
+ return aDescription;
+}
+
+OUString AccessibleChartShape::getAccessibleName()
+{
+ OUString aName;
+ if ( m_pAccShape.is() )
+ {
+ aName = m_pAccShape->getAccessibleName();
+ }
+ return aName;
+}
+
+// ________ XAccessibleComponent ________
+sal_Bool AccessibleChartShape::containsPoint( const awt::Point& aPoint )
+{
+ bool bReturn = false;
+ if ( m_pAccShape.is() )
+ {
+ bReturn = m_pAccShape->containsPoint( aPoint );
+ }
+ return bReturn;
+}
+
+Reference< XAccessible > AccessibleChartShape::getAccessibleAtPoint( const awt::Point& aPoint )
+{
+ Reference< XAccessible > xResult;
+ if ( m_pAccShape.is() )
+ {
+ xResult.set( m_pAccShape->getAccessibleAtPoint( aPoint ) );
+ }
+ return xResult;
+}
+
+awt::Rectangle AccessibleChartShape::getBounds()
+{
+ awt::Rectangle aBounds;
+ if ( m_pAccShape.is() )
+ {
+ aBounds = m_pAccShape->getBounds();
+ }
+ return aBounds;
+}
+
+awt::Point AccessibleChartShape::getLocation()
+{
+ awt::Point aLocation;
+ if ( m_pAccShape.is() )
+ {
+ aLocation = m_pAccShape->getLocation();
+ }
+ return aLocation;
+}
+
+awt::Point AccessibleChartShape::getLocationOnScreen()
+{
+ awt::Point aLocation;
+ if ( m_pAccShape.is() )
+ {
+ aLocation = m_pAccShape->getLocationOnScreen();
+ }
+ return aLocation;
+}
+
+awt::Size AccessibleChartShape::getSize()
+{
+ awt::Size aSize;
+ if ( m_pAccShape.is() )
+ {
+ aSize = m_pAccShape->getSize();
+ }
+ return aSize;
+}
+
+void AccessibleChartShape::grabFocus()
+{
+ return AccessibleBase::grabFocus();
+}
+
+sal_Int32 AccessibleChartShape::getForeground()
+{
+ sal_Int32 nColor(0);
+ if ( m_pAccShape.is() )
+ {
+ nColor = m_pAccShape->getForeground();
+ }
+ return nColor;
+}
+
+sal_Int32 AccessibleChartShape::getBackground()
+{
+ sal_Int32 nColor(0);
+ if ( m_pAccShape.is() )
+ {
+ nColor = m_pAccShape->getBackground();
+ }
+ return nColor;
+}
+
+// ________ XAccessibleExtendedComponent ________
+Reference< awt::XFont > AccessibleChartShape::getFont()
+{
+ Reference< awt::XFont > xFont;
+ if ( m_pAccShape.is() )
+ {
+ xFont.set( m_pAccShape->getFont() );
+ }
+ return xFont;
+}
+
+OUString AccessibleChartShape::getTitledBorderText()
+{
+ OUString aText;
+ if ( m_pAccShape.is() )
+ {
+ aText = m_pAccShape->getTitledBorderText();
+ }
+ return aText;
+}
+
+OUString AccessibleChartShape::getToolTipText()
+{
+ OUString aText;
+ if ( m_pAccShape.is() )
+ {
+ aText = m_pAccShape->getToolTipText();
+ }
+ return aText;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/accessibility/AccessibleChartShape.hxx b/chart2/source/controller/accessibility/AccessibleChartShape.hxx
new file mode 100644
index 0000000000..c31204ed3c
--- /dev/null
+++ b/chart2/source/controller/accessibility/AccessibleChartShape.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <AccessibleBase.hxx>
+
+#include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <svx/AccessibleShapeTreeInfo.hxx>
+
+namespace accessibility
+{
+class AccessibleShape;
+}
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::ImplInheritanceHelper<
+ AccessibleBase,
+ css::accessibility::XAccessibleExtendedComponent > AccessibleChartShape_Base;
+}
+
+class AccessibleChartShape :
+ public impl::AccessibleChartShape_Base
+{
+public:
+ explicit AccessibleChartShape( const AccessibleElementInfo& rAccInfo );
+ virtual ~AccessibleChartShape() override;
+
+ // ________ XServiceInfo ________
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ // ________ XAccessibleContext ________
+ virtual sal_Int64 SAL_CALL getAccessibleChildCount() override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+ getAccessibleChild( sal_Int64 i ) override;
+ virtual sal_Int16 SAL_CALL getAccessibleRole() override;
+ virtual OUString SAL_CALL getAccessibleDescription() override;
+ virtual OUString SAL_CALL getAccessibleName() override;
+
+ // ________ XAccessibleComponent ________
+ virtual sal_Bool SAL_CALL containsPoint( const css::awt::Point& aPoint ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override;
+ virtual css::awt::Rectangle SAL_CALL getBounds() override;
+ virtual css::awt::Point SAL_CALL getLocation() override;
+ virtual css::awt::Point SAL_CALL getLocationOnScreen() override;
+ virtual css::awt::Size SAL_CALL getSize() override;
+ virtual void SAL_CALL grabFocus() override;
+ virtual sal_Int32 SAL_CALL getForeground() override;
+ virtual sal_Int32 SAL_CALL getBackground() override;
+
+ // ________ XAccessibleExtendedComponent ________
+ virtual css::uno::Reference< css::awt::XFont > SAL_CALL getFont() override;
+ virtual OUString SAL_CALL getTitledBorderText() override;
+ virtual OUString SAL_CALL getToolTipText() override;
+
+private:
+ rtl::Reference<accessibility::AccessibleShape> m_pAccShape;
+ ::accessibility::AccessibleShapeTreeInfo m_aShapeTreeInfo;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/accessibility/AccessibleChartView.cxx b/chart2/source/controller/accessibility/AccessibleChartView.cxx
new file mode 100644
index 0000000000..acedf732cc
--- /dev/null
+++ b/chart2/source/controller/accessibility/AccessibleChartView.cxx
@@ -0,0 +1,415 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <AccessibleChartView.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <ObjectHierarchy.hxx>
+#include <ObjectIdentifier.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+#include "AccessibleViewForwarder.hxx"
+#include <ChartModel.hxx>
+#include <ChartView.hxx>
+#include <ChartController.hxx>
+
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+
+#include <comphelper/servicehelper.hxx>
+
+#include <rtl/ustring.hxx>
+#include <vcl/window.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::WeakReference;
+using ::com::sun::star::uno::Any;
+using osl::MutexGuard;
+
+namespace chart
+{
+
+AccessibleChartView::AccessibleChartView(SdrView* pView ) :
+ impl::AccessibleChartView_Base(
+ AccessibleElementInfo(), // empty for now
+ true, // has children
+ true // always transparent
+ ),
+ m_pSdrView( pView )
+{
+ AddState( AccessibleStateType::OPAQUE );
+}
+
+AccessibleChartView::~AccessibleChartView()
+{
+}
+
+awt::Rectangle AccessibleChartView::GetWindowPosSize() const
+{
+ Reference< awt::XWindow > xWindow( GetInfo().m_xWindow );
+ if( ! xWindow.is())
+ return awt::Rectangle();
+
+ awt::Rectangle aBBox( xWindow->getPosSize() );
+
+ VclPtr<vcl::Window> pWindow( VCLUnoHelper::GetWindow( GetInfo().m_xWindow ));
+ if( pWindow )
+ {
+ SolarMutexGuard aSolarGuard;
+ Point aVCLPoint( pWindow->OutputToAbsoluteScreenPixel( Point( 0, 0 ) ));
+ aBBox.X = aVCLPoint.getX();
+ aBBox.Y = aVCLPoint.getY();
+ }
+
+ return aBBox;
+}
+
+awt::Point AccessibleChartView::GetUpperLeftOnScreen() const
+{
+ awt::Point aParentPosition;
+
+ awt::Rectangle aBBox( GetWindowPosSize() );
+ aParentPosition.X = aBBox.X;
+ aParentPosition.Y = aBBox.Y;
+
+ return aParentPosition;
+}
+
+// ________ XAccessibleContext ________
+OUString SAL_CALL AccessibleChartView::getAccessibleName()
+{
+ return SchResId(STR_OBJECT_DIAGRAM);
+}
+
+OUString SAL_CALL AccessibleChartView::getAccessibleDescription()
+{
+ return getAccessibleName();
+}
+
+Reference< XAccessible > SAL_CALL AccessibleChartView::getAccessibleParent()
+{
+ return Reference< XAccessible >( m_xParent );
+}
+
+sal_Int64 SAL_CALL AccessibleChartView::getAccessibleIndexInParent()
+{
+ // the document is always the only child of the window
+ return 0;
+}
+
+sal_Int16 SAL_CALL AccessibleChartView::getAccessibleRole()
+{
+ return AccessibleRole::DOCUMENT;
+}
+
+// ________ XAccessibleComponent ________
+awt::Rectangle SAL_CALL AccessibleChartView::getBounds()
+{
+ awt::Rectangle aResult( GetWindowPosSize());
+ Reference< XAccessible > xParent( m_xParent );
+ if( xParent.is())
+ {
+ Reference< XAccessibleComponent > xContext( xParent->getAccessibleContext(), uno::UNO_QUERY );
+ if( xContext.is())
+ {
+ awt::Point aParentPosition = xContext->getLocationOnScreen();
+ aResult.X -= aParentPosition.X;
+ aResult.Y -= aParentPosition.Y;
+ }
+ }
+ return aResult;
+}
+
+awt::Point SAL_CALL AccessibleChartView::getLocationOnScreen()
+{
+ awt::Rectangle aBounds( getBounds());
+ awt::Point aResult;
+ Reference< XAccessible > xParent( m_xParent );
+ if( xParent.is())
+ {
+ Reference< XAccessibleComponent > xAccComp(
+ xParent->getAccessibleContext(), uno::UNO_QUERY );
+ aResult = xAccComp->getLocationOnScreen();
+ aResult.X += aBounds.X;
+ aResult.Y += aBounds.Y;
+ }
+ return aResult;
+}
+
+void AccessibleChartView::initialize( ChartController& rNewChartController,
+ const rtl::Reference<::chart::ChartModel>& xNewChartModel,
+ const rtl::Reference<::chart::ChartView>& xNewChartView,
+ const uno::Reference< XAccessible >& xNewParent,
+ const css::uno::Reference<css::awt::XWindow>& xNewWindow )
+{
+ //0: view::XSelectionSupplier offers notifications for selection changes and access to the selection itself
+ //1: frame::XModel representing the chart model - offers access to object data
+ //2: lang::XInterface representing the normal chart view - offers access to some extra object data
+
+ //all arguments are only valid until next initialization
+ bool bChanged = false;
+ bool bOldInvalid = false;
+ bool bNewInvalid = false;
+
+ rtl::Reference< ::chart::ChartController > xChartController;
+ rtl::Reference<::chart::ChartModel> xChartModel;
+ rtl::Reference<::chart::ChartView> xChartView;
+ Reference< XAccessible > xParent;
+ Reference< awt::XWindow > xWindow;
+ {
+ MutexGuard aGuard( m_aMutex);
+ xChartController = m_xChartController;
+ xChartModel = m_xChartModel;
+ xChartView = m_xChartView;
+ xParent.set( m_xParent );
+ xWindow.set( m_xWindow );
+ }
+
+ if( !xChartController.is() || !xChartModel.is() || !xChartView.is() )
+ {
+ bOldInvalid = true;
+ }
+
+ if( xNewChartModel.get() != xChartModel.get() )
+ {
+ xChartModel = xNewChartModel;
+ bChanged = true;
+ }
+
+ if( xNewChartView != xChartView )
+ {
+ xChartView = xNewChartView;
+ bChanged = true;
+ }
+
+ if( xNewParent != xParent )
+ {
+ xParent = xNewParent;
+ bChanged = true;
+ }
+
+ if( xNewWindow != xWindow )
+ {
+ xWindow = xNewWindow;
+ bChanged = true;
+ }
+
+ if(xChartController != &rNewChartController)
+ {
+ if (xChartController)
+ xChartController->removeSelectionChangeListener(this);
+ rNewChartController.addSelectionChangeListener(this);
+ xChartController = &rNewChartController;
+ bChanged = true;
+ }
+
+ if( !xChartController.is() || !xChartModel.is() || !xChartView.is() )
+ {
+ if(xChartController.is())
+ {
+ xChartController->removeSelectionChangeListener(this);
+ xChartController.clear();
+ }
+ xChartModel.clear();
+ xChartView.clear();
+ xParent.clear();
+ xWindow.clear();
+
+ bNewInvalid = true;
+ }
+
+ {
+ MutexGuard aGuard( m_aMutex);
+ m_xChartController = xChartController.get();
+ m_xChartModel = xChartModel.get();
+ m_xChartView = xChartView.get();
+ m_xParent = xParent;
+ m_xWindow = xWindow;
+ }
+
+ if( bOldInvalid && bNewInvalid )
+ bChanged = false;
+
+ if( !bChanged )
+ return;
+
+ {
+ //before notification we prepare for creation of new context
+ //the old context will be deleted after notification than
+ MutexGuard aGuard( m_aMutex);
+ if( xChartModel.is())
+ m_spObjectHierarchy =
+ std::make_shared<ObjectHierarchy>( xChartModel, m_xChartView.get().get() );
+ else
+ m_spObjectHierarchy.reset();
+ }
+
+ {
+ AccessibleElementInfo aAccInfo;
+ aAccInfo.m_aOID = ObjectIdentifier("ROOT");
+ aAccInfo.m_xChartDocument = m_xChartModel;
+ aAccInfo.m_xChartController = m_xChartController;
+ aAccInfo.m_xView = m_xChartView;
+ aAccInfo.m_xWindow = m_xWindow;
+ aAccInfo.m_pParent = nullptr;
+ aAccInfo.m_spObjectHierarchy = m_spObjectHierarchy;
+ aAccInfo.m_pSdrView = m_pSdrView;
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( m_xWindow );
+ m_pViewForwarder.reset( new AccessibleViewForwarder( this, pWindow ) );
+ aAccInfo.m_pViewForwarder = m_pViewForwarder.get();
+ // broadcasts an INVALIDATE_ALL_CHILDREN event globally
+ SetInfo( aAccInfo );
+ }
+}
+
+void AccessibleChartView::initialize()
+{
+ //0: view::XSelectionSupplier offers notifications for selection changes and access to the selection itself
+ //1: frame::XModel representing the chart model - offers access to object data
+ //2: lang::XInterface representing the normal chart view - offers access to some extra object data
+
+ //all arguments are only valid until next initialization
+ bool bChanged = false;
+ bool bOldInvalid = false;
+
+ rtl::Reference< ::chart::ChartController > xChartController;
+ rtl::Reference<::chart::ChartModel> xChartModel;
+ rtl::Reference<::chart::ChartView> xChartView;
+ Reference< XAccessible > xParent;
+ Reference< awt::XWindow > xWindow;
+ {
+ MutexGuard aGuard( m_aMutex);
+ xChartController = m_xChartController;
+ xChartModel = m_xChartModel;
+ xChartView = m_xChartView;
+ xParent.set( m_xParent );
+ xWindow.set( m_xWindow );
+ }
+
+ if( !xChartController.is() || !xChartModel.is() || !xChartView.is() )
+ {
+ bOldInvalid = true;
+ }
+
+ if( xChartModel.is() )
+ {
+ bChanged = true;
+ xChartModel = nullptr;
+ }
+
+ if( xChartView.is() )
+ {
+ bChanged = true;
+ xChartView = nullptr;
+ }
+
+ if( xChartController.is() )
+ {
+ bChanged = true;
+ xChartController->removeSelectionChangeListener(this);
+ xChartController = nullptr;
+ }
+
+ xParent.clear();
+ xWindow.clear();
+
+ {
+ MutexGuard aGuard( m_aMutex);
+ m_xChartController = xChartController.get();
+ m_xChartModel = xChartModel.get();
+ m_xChartView = xChartView.get();
+ m_xParent = WeakReference< XAccessible >(xParent);
+ m_xWindow = WeakReference< awt::XWindow >(xWindow);
+ }
+
+ if( bOldInvalid )
+ bChanged = false;
+
+ if( !bChanged )
+ return;
+
+ {
+ //before notification we prepare for creation of new context
+ //the old context will be deleted after notification than
+ MutexGuard aGuard( m_aMutex);
+ if( xChartModel.is())
+ m_spObjectHierarchy =
+ std::make_shared<ObjectHierarchy>( xChartModel, m_xChartView.get().get() );
+ else
+ m_spObjectHierarchy.reset();
+ }
+
+ {
+ AccessibleElementInfo aAccInfo;
+ aAccInfo.m_aOID = ObjectIdentifier("ROOT");
+ aAccInfo.m_xChartDocument = m_xChartModel;
+ aAccInfo.m_xChartController = m_xChartController;
+ aAccInfo.m_xView = m_xChartView;
+ aAccInfo.m_xWindow = m_xWindow;
+ aAccInfo.m_pParent = nullptr;
+ aAccInfo.m_spObjectHierarchy = m_spObjectHierarchy;
+ aAccInfo.m_pSdrView = m_pSdrView;
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( m_xWindow );
+ m_pViewForwarder.reset( new AccessibleViewForwarder( this, pWindow ) );
+ aAccInfo.m_pViewForwarder = m_pViewForwarder.get();
+ // broadcasts an INVALIDATE_ALL_CHILDREN event globally
+ SetInfo( aAccInfo );
+ }
+}
+
+// view::XSelectionChangeListener
+
+void SAL_CALL AccessibleChartView::selectionChanged( const lang::EventObject& /*rEvent*/ )
+{
+ rtl::Reference< ::chart::ChartController > xChartController;
+ {
+ MutexGuard aGuard( m_aMutex);
+ xChartController = m_xChartController.get();
+ }
+
+ if( !xChartController.is() )
+ return;
+
+ ObjectIdentifier aSelectedOID( xChartController->getSelection() );
+ if ( m_aCurrentSelectionOID.isValid() )
+ {
+ NotifyEvent( EventType::LOST_SELECTION, m_aCurrentSelectionOID );
+ }
+ if( aSelectedOID.isValid() )
+ {
+ NotifyEvent( EventType::GOT_SELECTION, aSelectedOID );
+ }
+ m_aCurrentSelectionOID = aSelectedOID;
+}
+
+// XEventListener
+void SAL_CALL AccessibleChartView::disposing( const lang::EventObject& /*Source*/ )
+{
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/accessibility/AccessibleTextHelper.cxx b/chart2/source/controller/accessibility/AccessibleTextHelper.cxx
new file mode 100644
index 0000000000..ed98cd2967
--- /dev/null
+++ b/chart2/source/controller/accessibility/AccessibleTextHelper.cxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <AccessibleTextHelper.hxx>
+#include <DrawViewWrapper.hxx>
+
+#include <vcl/svapp.hxx>
+
+#include <svx/AccessibleTextHelper.hxx>
+#include <svx/unoshtxt.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/window.hxx>
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <osl/diagnose.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+AccessibleTextHelper::AccessibleTextHelper(
+ DrawViewWrapper * pDrawViewWrapper ) :
+ m_pDrawViewWrapper( pDrawViewWrapper )
+{}
+
+AccessibleTextHelper::~AccessibleTextHelper()
+{
+}
+
+void AccessibleTextHelper::initialize( const OUString& aCID,
+ const Reference< XAccessible >& xEventSource,
+ const Reference< awt::XWindow >& xWindow )
+{
+ OSL_ENSURE( !aCID.isEmpty(), "Empty CID" );
+ OSL_ENSURE( xEventSource.is(), "Empty Event Source" );
+ OSL_ENSURE( xWindow.is(), "Empty Window" );
+ if( !xEventSource.is() || aCID.isEmpty() )
+ return;
+
+ SolarMutexGuard aSolarGuard;
+
+ m_pTextHelper.reset();
+
+ VclPtr<vcl::Window> pWindow( VCLUnoHelper::GetWindow( xWindow ));
+ if( pWindow )
+ {
+ SdrView * pView = m_pDrawViewWrapper;
+ if( pView )
+ {
+ SdrObject * pTextObj = m_pDrawViewWrapper->getNamedSdrObject( aCID );
+ if( pTextObj )
+ {
+ m_pTextHelper.reset( new ::accessibility::AccessibleTextHelper(std::make_unique<SvxTextEditSource>(*pTextObj, nullptr, *pView, *pWindow->GetOutDev())) );
+ m_pTextHelper->SetEventSource( xEventSource );
+ }
+ }
+ }
+
+ OSL_ENSURE( m_pTextHelper, "Couldn't create text helper" );
+}
+
+// ____ XAccessibleContext ____
+sal_Int64 SAL_CALL AccessibleTextHelper::getAccessibleChildCount()
+{
+ if( m_pTextHelper )
+ {
+ SolarMutexGuard aSolarGuard;
+ return m_pTextHelper->GetChildCount();
+ }
+ return 0;
+}
+
+Reference< XAccessible > SAL_CALL AccessibleTextHelper::getAccessibleChild( sal_Int64 i )
+{
+ if( m_pTextHelper )
+ {
+ SolarMutexGuard aSolarGuard;
+ return m_pTextHelper->GetChild( i );
+ }
+ return Reference< XAccessible >();
+}
+
+Reference< XAccessible > SAL_CALL AccessibleTextHelper::getAccessibleParent()
+{
+ OSL_FAIL( "Not implemented in this helper" );
+ return Reference< XAccessible >();
+}
+
+sal_Int64 SAL_CALL AccessibleTextHelper::getAccessibleIndexInParent()
+{
+ OSL_FAIL( "Not implemented in this helper" );
+ return -1;
+}
+
+::sal_Int16 SAL_CALL AccessibleTextHelper::getAccessibleRole()
+{
+ OSL_FAIL( "Not implemented in this helper" );
+ return AccessibleRole::UNKNOWN;
+}
+
+OUString SAL_CALL AccessibleTextHelper::getAccessibleDescription()
+{
+ OSL_FAIL( "Not implemented in this helper" );
+ return OUString();
+}
+
+OUString SAL_CALL AccessibleTextHelper::getAccessibleName()
+{
+ OSL_FAIL( "Not implemented in this helper" );
+ return OUString();
+}
+
+Reference< XAccessibleRelationSet > SAL_CALL AccessibleTextHelper::getAccessibleRelationSet()
+{
+ OSL_FAIL( "Not implemented in this helper" );
+ return Reference< XAccessibleRelationSet >();
+}
+
+sal_Int64 SAL_CALL AccessibleTextHelper::getAccessibleStateSet()
+{
+ OSL_FAIL( "Not implemented in this helper" );
+ return 0;
+}
+
+lang::Locale SAL_CALL AccessibleTextHelper::getLocale()
+{
+ OSL_FAIL( "Not implemented in this helper" );
+ return lang::Locale();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/accessibility/AccessibleViewForwarder.cxx b/chart2/source/controller/accessibility/AccessibleViewForwarder.cxx
new file mode 100644
index 0000000000..dbd8ac0d51
--- /dev/null
+++ b/chart2/source/controller/accessibility/AccessibleViewForwarder.cxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AccessibleViewForwarder.hxx"
+#include <AccessibleChartView.hxx>
+
+#include <vcl/window.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+AccessibleViewForwarder::AccessibleViewForwarder( AccessibleChartView* pAccChartView, vcl::Window* pWindow )
+ :m_pAccChartView( pAccChartView )
+ ,m_pWindow( pWindow )
+ ,m_aMapMode( MapUnit::Map100thMM )
+{
+}
+
+AccessibleViewForwarder::~AccessibleViewForwarder()
+{
+}
+
+// ________ IAccessibleViewforwarder ________
+
+tools::Rectangle AccessibleViewForwarder::GetVisibleArea() const
+{
+ tools::Rectangle aVisibleArea;
+ if ( m_pWindow )
+ {
+ aVisibleArea = m_pWindow->PixelToLogic(
+ tools::Rectangle( Point( 0, 0 ), m_pWindow->GetOutputSizePixel() ),
+ m_aMapMode );
+ }
+ return aVisibleArea;
+}
+
+Point AccessibleViewForwarder::LogicToPixel( const Point& rPoint ) const
+{
+ Point aPoint;
+ if ( m_pAccChartView && m_pWindow )
+ {
+ awt::Point aLocation = m_pAccChartView->getLocationOnScreen();
+ Point aTopLeft( aLocation.X, aLocation.Y );
+ aPoint = m_pWindow->LogicToPixel( rPoint, m_aMapMode ) + aTopLeft;
+ }
+ return aPoint;
+}
+
+Size AccessibleViewForwarder::LogicToPixel( const Size& rSize ) const
+{
+ Size aSize;
+ if ( m_pWindow )
+ {
+ aSize = m_pWindow->LogicToPixel( rSize, m_aMapMode );
+ }
+ return aSize;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/accessibility/AccessibleViewForwarder.hxx b/chart2/source/controller/accessibility/AccessibleViewForwarder.hxx
new file mode 100644
index 0000000000..5bfbd06ad6
--- /dev/null
+++ b/chart2/source/controller/accessibility/AccessibleViewForwarder.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/mapmod.hxx>
+#include <vcl/vclptr.hxx>
+#include <svx/IAccessibleViewForwarder.hxx>
+
+namespace vcl
+{
+class Window;
+}
+
+namespace chart
+{
+class AccessibleChartView;
+
+class AccessibleViewForwarder : public ::accessibility::IAccessibleViewForwarder
+{
+public:
+ AccessibleViewForwarder(AccessibleChartView* pAccChartView, vcl::Window* pWindow);
+ virtual ~AccessibleViewForwarder() override;
+
+ // ________ IAccessibleViewforwarder ________
+ virtual tools::Rectangle GetVisibleArea() const override;
+ virtual Point LogicToPixel(const Point& rPoint) const override;
+ virtual Size LogicToPixel(const Size& rSize) const override;
+
+private:
+ AccessibleViewForwarder(AccessibleViewForwarder const&) = delete;
+ AccessibleViewForwarder& operator=(AccessibleViewForwarder const&) = delete;
+
+ AccessibleChartView* m_pAccChartView;
+ VclPtr<vcl::Window> m_pWindow;
+ MapMode m_aMapMode;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/accessibility/ChartElementFactory.cxx b/chart2/source/controller/accessibility/ChartElementFactory.cxx
new file mode 100644
index 0000000000..a173ac0f4b
--- /dev/null
+++ b/chart2/source/controller/accessibility/ChartElementFactory.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ChartElementFactory.hxx"
+#include <ObjectIdentifier.hxx>
+#include "AccessibleChartElement.hxx"
+
+namespace chart
+{
+rtl::Reference<AccessibleBase>
+ChartElementFactory::CreateChartElement(const AccessibleElementInfo& rAccInfo)
+{
+ ObjectIdentifier aOID(rAccInfo.m_aOID);
+ ObjectType eType(aOID.getObjectType());
+
+ switch (eType)
+ {
+ case OBJECTTYPE_DATA_POINT:
+ case OBJECTTYPE_LEGEND_ENTRY:
+ return new AccessibleChartElement(rAccInfo, false);
+ case OBJECTTYPE_PAGE:
+ case OBJECTTYPE_TITLE:
+ case OBJECTTYPE_LEGEND:
+ case OBJECTTYPE_DIAGRAM:
+ case OBJECTTYPE_DIAGRAM_WALL:
+ case OBJECTTYPE_DIAGRAM_FLOOR:
+ case OBJECTTYPE_AXIS:
+ case OBJECTTYPE_AXIS_UNITLABEL:
+ case OBJECTTYPE_GRID:
+ case OBJECTTYPE_SUBGRID:
+ case OBJECTTYPE_DATA_SERIES:
+ case OBJECTTYPE_DATA_LABELS:
+ case OBJECTTYPE_DATA_LABEL:
+ case OBJECTTYPE_DATA_ERRORS_X:
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ case OBJECTTYPE_DATA_CURVE: // e.g. a statistical method printed as line
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ case OBJECTTYPE_DATA_STOCK_RANGE:
+ case OBJECTTYPE_DATA_STOCK_LOSS:
+ case OBJECTTYPE_DATA_STOCK_GAIN:
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ return new AccessibleChartElement(rAccInfo, true);
+ case OBJECTTYPE_UNKNOWN:
+ break;
+ default:
+ break;
+ }
+
+ return nullptr;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/accessibility/ChartElementFactory.hxx b/chart2/source/controller/accessibility/ChartElementFactory.hxx
new file mode 100644
index 0000000000..08ae64598b
--- /dev/null
+++ b/chart2/source/controller/accessibility/ChartElementFactory.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ref.hxx>
+
+namespace chart
+{
+class AccessibleBase;
+struct AccessibleElementInfo;
+
+class ChartElementFactory
+{
+public:
+ /** @return a newly created object (using the new operator) that corresponds
+ to the given unique id
+ */
+ static rtl::Reference<AccessibleBase> CreateChartElement(const AccessibleElementInfo& rAccInfo);
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/AreaWrapper.cxx b/chart2/source/controller/chartapiwrapper/AreaWrapper.cxx
new file mode 100644
index 0000000000..995a0f92cf
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/AreaWrapper.cxx
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AreaWrapper.hxx"
+#include "Chart2ModelContact.hxx"
+#include <WrappedDirectStateProperty.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <UserDefinedProperties.hxx>
+
+#include <algorithm>
+#include <utility>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart::wrapper
+{
+
+AreaWrapper::AreaWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : m_spChart2ModelContact(std::move(spChart2ModelContact))
+{
+}
+
+AreaWrapper::~AreaWrapper()
+{}
+
+// ____ XShape ____
+awt::Point SAL_CALL AreaWrapper::getPosition()
+{
+ return awt::Point(0,0);
+}
+
+void SAL_CALL AreaWrapper::setPosition( const awt::Point& /*aPosition*/ )
+{
+ OSL_FAIL( "trying to set position of chart area" );
+}
+
+awt::Size SAL_CALL AreaWrapper::getSize()
+{
+ return m_spChart2ModelContact->GetPageSize();
+}
+
+void SAL_CALL AreaWrapper::setSize( const awt::Size& /*aSize*/ )
+{
+ OSL_FAIL( "trying to set size of chart area" );
+}
+
+// ____ XShapeDescriptor (base of XShape) ____
+OUString SAL_CALL AreaWrapper::getShapeType()
+{
+ return "com.sun.star.chart.ChartArea";
+}
+
+// ____ XComponent ____
+void SAL_CALL AreaWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( xSource ) );
+
+ clearWrappedPropertySet();
+}
+
+void SAL_CALL AreaWrapper::addEventListener(
+ const Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL AreaWrapper::removeEventListener(
+ const Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+// WrappedPropertySet
+Reference< beans::XPropertySet > AreaWrapper::getInnerPropertySet()
+{
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ if( xChartDoc.is() )
+ return xChartDoc->getPageBackground();
+ OSL_FAIL("AreaWrapper::getInnerPropertySet() is NULL");
+ return nullptr;
+}
+
+const Sequence< beans::Property >& AreaWrapper::getPropertySequence()
+{
+ static Sequence< Property > aPropSeq = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropSeq;
+}
+
+std::vector< std::unique_ptr<WrappedProperty> > AreaWrapper::createWrappedProperties()
+{
+ std::vector< std::unique_ptr<WrappedProperty> > aWrappedProperties;
+
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty("LineStyle","LineStyle") );
+
+ return aWrappedProperties;
+}
+
+OUString SAL_CALL AreaWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.Area";
+}
+
+sal_Bool SAL_CALL AreaWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL AreaWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.xml.UserDefinedAttributesSupplier",
+ "com.sun.star.beans.PropertySet",
+ "com.sun.star.drawing.FillProperties",
+ "com.sun.star.drawing.LineProperties" };
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/AreaWrapper.hxx b/chart2/source/controller/chartapiwrapper/AreaWrapper.hxx
new file mode 100644
index 0000000000..c150d5bbfc
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/AreaWrapper.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedPropertySet.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <memory>
+
+namespace chart::wrapper
+{
+
+class Chart2ModelContact;
+
+class AreaWrapper : public ::cppu::ImplInheritanceHelper<
+ WrappedPropertySet
+ , css::drawing::XShape
+ , css::lang::XComponent
+ , css::lang::XServiceInfo
+ >
+{
+public:
+ explicit AreaWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~AreaWrapper() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XShape ____
+ virtual css::awt::Point SAL_CALL getPosition() override;
+ virtual void SAL_CALL setPosition( const css::awt::Point& aPosition ) override;
+ virtual css::awt::Size SAL_CALL getSize() override;
+ virtual void SAL_CALL setSize( const css::awt::Size& aSize ) override;
+
+ // ____ XShapeDescriptor (base of XShape) ____
+ virtual OUString SAL_CALL getShapeType() override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference<
+ css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference<
+ css::lang::XEventListener >& aListener ) override;
+
+protected:
+ // ____ WrappedPropertySet ____
+ virtual const css::uno::Sequence< css::beans::Property >& getPropertySequence() override;
+ virtual std::vector< std::unique_ptr<WrappedProperty> > createWrappedProperties() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override;
+
+private:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx b/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx
new file mode 100644
index 0000000000..ea50320e50
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/AxisWrapper.cxx
@@ -0,0 +1,665 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AxisWrapper.hxx"
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <TitleHelper.hxx>
+#include "Chart2ModelContact.hxx"
+#include <WrappedDirectStateProperty.hxx>
+#include "GridWrapper.hxx"
+#include "TitleWrapper.hxx"
+#include <DisposeHelper.hxx>
+#include <unonames.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
+#include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
+#include <com/sun/star/chart2/XAxis.hpp>
+
+#include <CharacterProperties.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <UserDefinedProperties.hxx>
+#include "WrappedCharacterHeightProperty.hxx"
+#include "WrappedTextRotationProperty.hxx"
+#include "WrappedGapwidthProperty.hxx"
+#include "WrappedScaleProperty.hxx"
+#include "WrappedNumberFormatProperty.hxx"
+#include "WrappedScaleTextProperties.hxx"
+
+#include <algorithm>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+namespace
+{
+
+enum
+{
+ PROP_AXIS_MAX,
+ PROP_AXIS_MIN,
+ PROP_AXIS_STEPMAIN,
+ PROP_AXIS_STEPHELP, //deprecated property use 'StepHelpCount' instead
+ PROP_AXIS_STEPHELP_COUNT,
+ PROP_AXIS_AUTO_MAX,
+ PROP_AXIS_AUTO_MIN,
+ PROP_AXIS_AUTO_STEPMAIN,
+ PROP_AXIS_AUTO_STEPHELP,
+ PROP_AXIS_TYPE,
+ PROP_AXIS_TIME_INCREMENT,
+ PROP_AXIS_EXPLICIT_TIME_INCREMENT,
+ PROP_AXIS_LOGARITHMIC,
+ PROP_AXIS_REVERSEDIRECTION,
+ PROP_AXIS_VISIBLE,
+ PROP_AXIS_CROSSOVER_POSITION,
+ PROP_AXIS_CROSSOVER_VALUE,
+ PROP_AXIS_ORIGIN,
+ PROP_AXIS_AUTO_ORIGIN,
+ PROP_AXIS_MARKS,
+ PROP_AXIS_HELPMARKS,
+ PROP_AXIS_MARK_POSITION,
+ PROP_AXIS_DISPLAY_LABELS,
+ PROP_AXIS_NUMBERFORMAT,
+ PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE,
+ PROP_AXIS_LABEL_POSITION,
+ PROP_AXIS_TEXT_ROTATION,
+ PROP_AXIS_ARRANGE_ORDER,
+ PROP_AXIS_TEXTBREAK,
+ PROP_AXIS_CAN_OVERLAP,
+ PROP_AXIS_STACKEDTEXT,
+ PROP_AXIS_OVERLAP,
+ PROP_AXIS_GAP_WIDTH,
+ PROP_AXIS_DISPLAY_UNITS,
+ PROP_AXIS_BUILTINUNIT,
+ PROP_AXIS_TRY_STAGGERING_FIRST,
+ PROP_AXIS_MAJOR_ORIGIN
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ //Properties for scaling:
+ rOutProperties.emplace_back( "Max",
+ PROP_AXIS_MAX,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "Min",
+ PROP_AXIS_MIN,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "StepMain",
+ PROP_AXIS_STEPMAIN,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "StepHelpCount",
+ PROP_AXIS_STEPHELP_COUNT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ //deprecated property use 'StepHelpCount' instead
+ rOutProperties.emplace_back( "StepHelp",
+ PROP_AXIS_STEPHELP,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "AutoMax",
+ PROP_AXIS_AUTO_MAX,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "AutoMin",
+ PROP_AXIS_AUTO_MIN,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "AutoStepMain",
+ PROP_AXIS_AUTO_STEPMAIN,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "AutoStepHelp",
+ PROP_AXIS_AUTO_STEPHELP,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "AxisType",
+ PROP_AXIS_TYPE,
+ cppu::UnoType<sal_Int32>::get(), //type css::chart::ChartAxisType
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "TimeIncrement",
+ PROP_AXIS_TIME_INCREMENT,
+ cppu::UnoType<css::chart::TimeIncrement>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "ExplicitTimeIncrement",
+ PROP_AXIS_EXPLICIT_TIME_INCREMENT,
+ cppu::UnoType<css::chart::TimeIncrement>::get(),
+ beans::PropertyAttribute::READONLY |
+ beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "Logarithmic",
+ PROP_AXIS_LOGARITHMIC,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ReverseDirection",
+ PROP_AXIS_REVERSEDIRECTION,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //todo: this property is missing in the API
+ rOutProperties.emplace_back( "Visible",
+ PROP_AXIS_VISIBLE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "CrossoverPosition",
+ PROP_AXIS_CROSSOVER_POSITION,
+ cppu::UnoType<css::chart::ChartAxisPosition>::get(),
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "CrossoverValue",
+ PROP_AXIS_CROSSOVER_VALUE,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "Origin",
+ PROP_AXIS_ORIGIN,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "AutoOrigin",
+ PROP_AXIS_AUTO_ORIGIN,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //Properties for interval marks:
+ rOutProperties.emplace_back( "Marks",
+ PROP_AXIS_MARKS,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "HelpMarks",
+ PROP_AXIS_HELPMARKS,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "MarkPosition",
+ PROP_AXIS_MARK_POSITION,
+ cppu::UnoType<css::chart::ChartAxisMarkPosition>::get(),
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //Properties for labels:
+ rOutProperties.emplace_back( "DisplayLabels",
+ PROP_AXIS_DISPLAY_LABELS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_NUMFMT,
+ PROP_AXIS_NUMBERFORMAT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LINK_TO_SRC_NUMFMT,
+ PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "LabelPosition",
+ PROP_AXIS_LABEL_POSITION,
+ cppu::UnoType<css::chart::ChartAxisLabelPosition>::get(),
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "TextRotation",
+ PROP_AXIS_TEXT_ROTATION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ArrangeOrder",
+ PROP_AXIS_ARRANGE_ORDER,
+ cppu::UnoType<css::chart::ChartAxisArrangeOrderType>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "TextBreak",
+ PROP_AXIS_TEXTBREAK,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "TextCanOverlap",
+ PROP_AXIS_CAN_OVERLAP,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "StackedText",
+ PROP_AXIS_STACKEDTEXT,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // Properties related to bar charts:
+ rOutProperties.emplace_back( "Overlap",
+ PROP_AXIS_OVERLAP,
+ cppu::UnoType<sal_Int32>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "GapWidth",
+ PROP_AXIS_GAP_WIDTH,
+ cppu::UnoType<sal_Int32>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //Properties for display units:
+ rOutProperties.emplace_back( "DisplayUnits",
+ PROP_AXIS_DISPLAY_UNITS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //Properties for labels:
+ rOutProperties.emplace_back( "BuiltInUnit",
+ PROP_AXIS_BUILTINUNIT,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // Compatibility option: starting from LibreOffice 5.1 the rotated
+ // layout is preferred to staggering for axis labels.
+ rOutProperties.emplace_back( "TryStaggeringFirst",
+ PROP_AXIS_TRY_STAGGERING_FIRST,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "MajorOrigin",
+ PROP_AXIS_MAJOR_ORIGIN,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+}
+
+const Sequence< Property >& StaticAxisWrapperPropertyArray()
+{
+ static Sequence< Property > aPropSeq = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+ ::chart::wrapper::WrappedScaleTextProperties::addProperties( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropSeq;
+};
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+AxisWrapper::AxisWrapper(
+ tAxisType eType, std::shared_ptr<Chart2ModelContact> spChart2ModelContact) :
+ m_spChart2ModelContact(std::move( spChart2ModelContact )),
+ m_eType( eType )
+{
+}
+
+AxisWrapper::~AxisWrapper()
+{
+}
+
+// ____ chart::XAxis ____
+Reference< beans::XPropertySet > SAL_CALL AxisWrapper::getAxisTitle()
+{
+ if( !m_xAxisTitle.is() )
+ {
+ TitleHelper::eTitleType eTitleType( TitleHelper::X_AXIS_TITLE );
+ switch( m_eType )
+ {
+ case X_AXIS:
+ eTitleType = TitleHelper::X_AXIS_TITLE;
+ break;
+ case Y_AXIS:
+ eTitleType = TitleHelper::Y_AXIS_TITLE;
+ break;
+ case Z_AXIS:
+ eTitleType = TitleHelper::Z_AXIS_TITLE;
+ break;
+ case SECOND_X_AXIS:
+ eTitleType = TitleHelper::SECONDARY_X_AXIS_TITLE;
+ break;
+ case SECOND_Y_AXIS:
+ eTitleType = TitleHelper::SECONDARY_Y_AXIS_TITLE;
+ break;
+ default:
+ return nullptr;
+ }
+ m_xAxisTitle = new TitleWrapper( eTitleType, m_spChart2ModelContact );
+ }
+ return m_xAxisTitle;
+}
+Reference< beans::XPropertySet > SAL_CALL AxisWrapper::getMajorGrid()
+{
+ if( !m_xMajorGrid.is() )
+ {
+ GridWrapper::tGridType eGridType( GridWrapper::X_MAJOR_GRID );
+ switch( m_eType )
+ {
+ case X_AXIS:
+ eGridType = GridWrapper::X_MAJOR_GRID;
+ break;
+ case Y_AXIS:
+ eGridType = GridWrapper::Y_MAJOR_GRID;
+ break;
+ case Z_AXIS:
+ eGridType = GridWrapper::Z_MAJOR_GRID;
+ break;
+ default:
+ return nullptr;
+ }
+ m_xMajorGrid = new GridWrapper( eGridType, m_spChart2ModelContact );
+ }
+ return m_xMajorGrid;
+}
+Reference< beans::XPropertySet > SAL_CALL AxisWrapper::getMinorGrid()
+{
+ if( !m_xMinorGrid.is() )
+ {
+ GridWrapper::tGridType eGridType( GridWrapper::X_MAJOR_GRID );
+ switch( m_eType )
+ {
+ case X_AXIS:
+ eGridType = GridWrapper::X_MINOR_GRID;
+ break;
+ case Y_AXIS:
+ eGridType = GridWrapper::Y_MINOR_GRID;
+ break;
+ case Z_AXIS:
+ eGridType = GridWrapper::Z_MINOR_GRID;
+ break;
+ default:
+ return nullptr;
+ }
+ m_xMinorGrid = new GridWrapper( eGridType, m_spChart2ModelContact );
+ }
+ return m_xMinorGrid;
+}
+
+// ____ XShape ____
+awt::Point SAL_CALL AxisWrapper::getPosition()
+{
+ awt::Point aResult( m_spChart2ModelContact->GetAxisPosition( getAxis() ) );
+ return aResult;
+}
+
+void SAL_CALL AxisWrapper::setPosition( const awt::Point& /*aPosition*/ )
+{
+ OSL_FAIL( "trying to set position of Axis" );
+}
+
+awt::Size SAL_CALL AxisWrapper::getSize()
+{
+ awt::Size aSize( m_spChart2ModelContact->GetAxisSize( getAxis() ) );
+ return aSize;
+}
+
+void SAL_CALL AxisWrapper::setSize( const awt::Size& /*aSize*/ )
+{
+ OSL_FAIL( "trying to set size of Axis" );
+}
+
+// ____ XShapeDescriptor (base of XShape) ____
+OUString SAL_CALL AxisWrapper::getShapeType()
+{
+ return "com.sun.star.chart.ChartAxis";
+}
+
+// ____ XNumberFormatsSupplier ____
+uno::Reference< beans::XPropertySet > SAL_CALL AxisWrapper::getNumberFormatSettings()
+{
+ rtl::Reference<ChartModel> xChartModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xChartModel )
+ return xChartModel->getNumberFormatSettings();
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+uno::Reference< util::XNumberFormats > SAL_CALL AxisWrapper::getNumberFormats()
+{
+ rtl::Reference<ChartModel> xChartModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xChartModel )
+ return xChartModel->getNumberFormats();
+
+ return uno::Reference< util::XNumberFormats >();
+}
+
+void AxisWrapper::getDimensionAndMainAxisBool( tAxisType eType, sal_Int32& rnDimensionIndex, bool& rbMainAxis )
+{
+ switch( eType )
+ {
+ case X_AXIS:
+ rnDimensionIndex = 0; rbMainAxis = true; break;
+ case Y_AXIS:
+ rnDimensionIndex = 1; rbMainAxis = true; break;
+ case Z_AXIS:
+ rnDimensionIndex = 2; rbMainAxis = true; break;
+ case SECOND_X_AXIS:
+ rnDimensionIndex = 0; rbMainAxis = false; break;
+ case SECOND_Y_AXIS:
+ rnDimensionIndex = 1; rbMainAxis = false; break;
+ }
+}
+
+// ____ XComponent ____
+void SAL_CALL AxisWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( xSource ) );
+
+ DisposeHelper::DisposeAndClear( m_xAxisTitle );
+ DisposeHelper::DisposeAndClear( m_xMajorGrid );
+ DisposeHelper::DisposeAndClear( m_xMinorGrid );
+
+ clearWrappedPropertySet();
+}
+
+void SAL_CALL AxisWrapper::addEventListener(
+ const Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL AxisWrapper::removeEventListener(
+ const Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+//ReferenceSizePropertyProvider
+void AxisWrapper::updateReferenceSize()
+{
+ Reference< beans::XPropertySet > xProp( getAxis(), uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ if( xProp->getPropertyValue("ReferencePageSize").hasValue() )
+ xProp->setPropertyValue("ReferencePageSize", uno::Any(
+ m_spChart2ModelContact->GetPageSize() ));
+ }
+}
+Any AxisWrapper::getReferenceSize()
+{
+ Any aRet;
+ Reference< beans::XPropertySet > xProp( getAxis(), uno::UNO_QUERY );
+ if( xProp.is() )
+ aRet = xProp->getPropertyValue("ReferencePageSize");
+ return aRet;
+}
+awt::Size AxisWrapper::getCurrentSizeForReference()
+{
+ return m_spChart2ModelContact->GetPageSize();
+}
+
+Reference< chart2::XAxis > AxisWrapper::getAxis()
+{
+ rtl::Reference< Axis > xAxis;
+ try
+ {
+ sal_Int32 nDimensionIndex = 0;
+ bool bMainAxis = true;
+ AxisWrapper::getDimensionAndMainAxisBool( m_eType, nDimensionIndex, bMainAxis );
+
+ rtl::Reference< Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ xAxis = AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram );
+ if( !xAxis.is() )
+ {
+ xAxis = AxisHelper::createAxis( nDimensionIndex, bMainAxis, xDiagram, m_spChart2ModelContact->m_xContext );
+ if( xAxis.is() )
+ xAxis->setPropertyValue("Show", uno::Any( false ) );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return xAxis;
+}
+
+// WrappedPropertySet
+Reference< beans::XPropertySet > AxisWrapper::getInnerPropertySet()
+{
+ return Reference< beans::XPropertySet >( getAxis(), uno::UNO_QUERY );
+}
+
+const Sequence< beans::Property >& AxisWrapper::getPropertySequence()
+{
+ return StaticAxisWrapperPropertyArray();
+}
+
+std::vector< std::unique_ptr<WrappedProperty> > AxisWrapper::createWrappedProperties()
+{
+ std::vector< std::unique_ptr<WrappedProperty> > aWrappedProperties;
+
+ aWrappedProperties.emplace_back( new WrappedTextRotationProperty() );
+ aWrappedProperties.emplace_back( new WrappedProperty("Marks","MajorTickmarks") );
+ aWrappedProperties.emplace_back( new WrappedProperty("HelpMarks","MinorTickmarks") );
+ aWrappedProperties.emplace_back( new WrappedProperty("TextCanOverlap","TextOverlap") );
+ aWrappedProperties.emplace_back( new WrappedProperty("ArrangeOrder","ArrangeOrder") );
+ aWrappedProperties.emplace_back( new WrappedProperty("Visible","Show") );
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty("DisplayLabels","DisplayLabels") );
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty("TryStaggeringFirst","TryStaggeringFirst") );
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty("TextBreak","TextBreak") );
+ aWrappedProperties.emplace_back( new WrappedNumberFormatProperty(m_spChart2ModelContact) );
+ aWrappedProperties.emplace_back( new WrappedLinkNumberFormatProperty );
+ aWrappedProperties.emplace_back( new WrappedProperty("StackedText","StackCharacters") );
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty("CrossoverPosition","CrossoverPosition") );
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty("MajorOrigin","MajorOrigin") );
+ {
+ WrappedGapwidthProperty* pWrappedGapwidthProperty( new WrappedGapwidthProperty( m_spChart2ModelContact ) );
+ WrappedBarOverlapProperty* pWrappedBarOverlapProperty( new WrappedBarOverlapProperty( m_spChart2ModelContact ) );
+ sal_Int32 nDimensionIndex = 0;
+ bool bMainAxis = true;
+ sal_Int32 nAxisIndex = 0;
+ AxisWrapper::getDimensionAndMainAxisBool( m_eType, nDimensionIndex, bMainAxis );
+ if( !bMainAxis )
+ nAxisIndex = 1;
+ pWrappedGapwidthProperty->setDimensionAndAxisIndex( nDimensionIndex, nAxisIndex );
+ pWrappedBarOverlapProperty->setDimensionAndAxisIndex( nDimensionIndex, nAxisIndex );
+ aWrappedProperties.emplace_back( pWrappedGapwidthProperty );
+ aWrappedProperties.emplace_back( pWrappedBarOverlapProperty );
+ }
+
+ WrappedScaleProperty::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+
+ WrappedCharacterHeightProperty::addWrappedProperties( aWrappedProperties, this );
+ WrappedScaleTextProperties::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+
+ return aWrappedProperties;
+}
+
+OUString SAL_CALL AxisWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.Axis";
+}
+
+sal_Bool SAL_CALL AxisWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL AxisWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart.ChartAxis",
+ "com.sun.star.xml.UserDefinedAttributesSupplier",
+ "com.sun.star.style.CharacterProperties"
+ };
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/AxisWrapper.hxx b/chart2/source/controller/chartapiwrapper/AxisWrapper.hxx
new file mode 100644
index 0000000000..e70c85b23f
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/AxisWrapper.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedPropertySet.hxx>
+#include "ReferenceSizePropertyProvider.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/chart/XAxis.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+
+#include <memory>
+
+namespace com::sun::star::chart2 { class XAxis; }
+
+namespace chart::wrapper
+{
+class Chart2ModelContact;
+
+class AxisWrapper : public ::cppu::ImplInheritanceHelper<
+ WrappedPropertySet
+ , css::chart::XAxis
+ , css::drawing::XShape
+ , css::lang::XComponent
+ , css::lang::XServiceInfo
+ , css::util::XNumberFormatsSupplier
+ >
+ , public ReferenceSizePropertyProvider
+{
+public:
+ enum tAxisType
+ {
+ X_AXIS,
+ Y_AXIS,
+ Z_AXIS,
+ SECOND_X_AXIS,
+ SECOND_Y_AXIS
+ };
+
+ AxisWrapper(tAxisType eType, std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~AxisWrapper() override;
+
+ static void getDimensionAndMainAxisBool( tAxisType eType, sal_Int32& rnDimensionIndex, bool& rbMainAxis );
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ //ReferenceSizePropertyProvider
+ virtual void updateReferenceSize() override;
+ virtual css::uno::Any getReferenceSize() override;
+ virtual css::awt::Size getCurrentSizeForReference() override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference<
+ css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference<
+ css::lang::XEventListener >& aListener ) override;
+
+ // ____ chart::XAxis ____
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getAxisTitle( ) override;
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getMajorGrid( ) override;
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getMinorGrid( ) override;
+
+ // ____ XShape ____
+ virtual css::awt::Point SAL_CALL getPosition() override;
+ virtual void SAL_CALL setPosition( const css::awt::Point& aPosition ) override;
+ virtual css::awt::Size SAL_CALL getSize() override;
+ virtual void SAL_CALL setSize( const css::awt::Size& aSize ) override;
+
+ // ____ XShapeDescriptor (base of XShape) ____
+ virtual OUString SAL_CALL getShapeType() override;
+
+ // ____ XNumberFormatsSupplier ____
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getNumberFormatSettings() override;
+ virtual css::uno::Reference<
+ css::util::XNumberFormats > SAL_CALL getNumberFormats() override;
+
+protected:
+ // ____ WrappedPropertySet ____
+ virtual const css::uno::Sequence< css::beans::Property >& getPropertySequence() override;
+ virtual std::vector< std::unique_ptr<WrappedProperty> > createWrappedProperties() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override;
+
+private: //methods
+ css::uno::Reference< css::chart2::XAxis > getAxis();
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+
+ tAxisType m_eType;
+
+ css::uno::Reference< css::beans::XPropertySet > m_xAxisTitle;
+ css::uno::Reference< css::beans::XPropertySet > m_xMajorGrid;
+ css::uno::Reference< css::beans::XPropertySet > m_xMinorGrid;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/Chart2ModelContact.cxx b/chart2/source/controller/chartapiwrapper/Chart2ModelContact.cxx
new file mode 100644
index 0000000000..aab6f4992b
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/Chart2ModelContact.cxx
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Chart2ModelContact.hxx"
+#include <ChartModelHelper.hxx>
+#include <Legend.hxx>
+#include <LegendHelper.hxx>
+#include <CommonConverters.hxx>
+#include <servicenames.hxx>
+#include <ObjectIdentifier.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <ChartView.hxx>
+#include <DiagramHelper.hxx>
+#include <BaseCoordinateSystem.hxx>
+
+#include <ChartModel.hxx>
+
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+
+namespace chart::wrapper
+{
+
+Chart2ModelContact::Chart2ModelContact(
+ const Reference< uno::XComponentContext > & xContext ) :
+ m_xContext( xContext ),
+ m_xChartModel( nullptr )
+{
+}
+
+Chart2ModelContact::~Chart2ModelContact()
+{
+ clear();
+}
+
+void Chart2ModelContact::setDocumentModel( ChartModel* pChartModel )
+{
+ clear();
+ m_xChartModel = pChartModel;
+ if( !pChartModel )
+ return;
+
+ uno::Reference< container::XNameContainer > xDashTable( pChartModel->createInstance("com.sun.star.drawing.DashTable"), uno::UNO_QUERY );
+ uno::Reference< container::XNameContainer > xGradientTable( pChartModel->createInstance("com.sun.star.drawing.GradientTable"), uno::UNO_QUERY );
+ uno::Reference< container::XNameContainer > xHatchTable( pChartModel->createInstance("com.sun.star.drawing.HatchTable"), uno::UNO_QUERY );
+ uno::Reference< container::XNameContainer > xBitmapTable( pChartModel->createInstance("com.sun.star.drawing.BitmapTable"), uno::UNO_QUERY );
+ uno::Reference< container::XNameContainer > xTransparencyGradientTable( pChartModel->createInstance("com.sun.star.drawing.TransparencyGradientTable"), uno::UNO_QUERY );
+ m_aTableMap["LineDashName"] = xDashTable;
+ m_aTableMap["FillGradientName"] = xGradientTable;
+ m_aTableMap["FillHatchName"] = xHatchTable;
+ m_aTableMap["FillBitmapName"] = xBitmapTable;
+ m_aTableMap["FillTransparenceGradientName"] = xTransparencyGradientTable;
+}
+
+void Chart2ModelContact::clear()
+{
+ m_xChartModel.clear();
+ m_xChartView.clear();
+}
+
+rtl::Reference< ChartModel > Chart2ModelContact::getDocumentModel() const
+{
+ return m_xChartModel;
+}
+
+rtl::Reference< ::chart::Diagram > Chart2ModelContact::getDiagram() const
+{
+ try
+ {
+ rtl::Reference<ChartModel> xChartModel = getDocumentModel();
+ if( xChartModel)
+ return xChartModel->getFirstChartDiagram();
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return nullptr;
+}
+
+rtl::Reference< ::chart::ChartView > const & Chart2ModelContact::getChartView() const
+{
+ if(!m_xChartView.is())
+ {
+ // get the chart view
+ rtl::Reference<ChartModel> xChartModel( m_xChartModel );
+ if( xChartModel )
+ {
+ auto xInstance = xChartModel->createInstance( CHART_VIEW_SERVICE_NAME );
+ auto pChartView = dynamic_cast<ChartView*>(xInstance.get());
+ assert(!xInstance || pChartView);
+ m_xChartView = pChartView;
+ }
+ }
+ return m_xChartView;
+}
+
+ExplicitValueProvider* Chart2ModelContact::getExplicitValueProvider() const
+{
+ getChartView();
+
+ //obtain the ExplicitValueProvider from the chart view
+ return m_xChartView.get();
+}
+
+rtl::Reference<SvxDrawPage> Chart2ModelContact::getDrawPage() const
+{
+ rtl::Reference<SvxDrawPage> xResult;
+ ExplicitValueProvider* pProvider( getExplicitValueProvider() );
+ if( pProvider )
+ {
+ xResult = pProvider->getDrawModelWrapper()->getMainDrawPage();
+ }
+ return xResult;
+}
+
+void Chart2ModelContact::getExplicitValuesForAxis(
+ const rtl::Reference< Axis > & xAxis,
+ ExplicitScaleData & rOutExplicitScale,
+ ExplicitIncrementData & rOutExplicitIncrement )
+{
+ ExplicitValueProvider* pProvider( getExplicitValueProvider() );
+ if( pProvider )
+ {
+ pProvider->getExplicitValuesForAxis(
+ xAxis, rOutExplicitScale, rOutExplicitIncrement );
+ }
+}
+
+sal_Int32 Chart2ModelContact::getExplicitNumberFormatKeyForAxis(
+ const rtl::Reference< ::chart::Axis >& xAxis )
+{
+ rtl::Reference< BaseCoordinateSystem > xCooSys(
+ AxisHelper::getCoordinateSystemOfAxis(
+ xAxis, m_xChartModel.get()->getFirstChartDiagram() ) );
+
+ return ExplicitValueProvider::getExplicitNumberFormatKeyForAxis( xAxis, xCooSys
+ , m_xChartModel.get() );
+}
+
+sal_Int32 Chart2ModelContact::getExplicitNumberFormatKeyForSeries(
+ const Reference< chart2::XDataSeries >& xSeries )
+{
+ return ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
+ uno::Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY ));
+}
+
+awt::Size Chart2ModelContact::GetPageSize() const
+{
+ return ChartModelHelper::getPageSize(m_xChartModel.get());
+}
+
+awt::Rectangle Chart2ModelContact::SubstractAxisTitleSizes( const awt::Rectangle& rPositionRect )
+{
+ awt::Rectangle aRect = ExplicitValueProvider::AddSubtractAxisTitleSizes(
+ *m_xChartModel.get(), getChartView().get(), rPositionRect, true );
+ return aRect;
+}
+
+awt::Rectangle Chart2ModelContact::GetDiagramRectangleIncludingTitle() const
+{
+ awt::Rectangle aRect( GetDiagramRectangleIncludingAxes() );
+
+ //add axis title sizes to the diagram size
+ aRect = ExplicitValueProvider::AddSubtractAxisTitleSizes(
+ *m_xChartModel.get(), getChartView().get(), aRect, false );
+
+ return aRect;
+}
+
+awt::Rectangle Chart2ModelContact::GetDiagramRectangleIncludingAxes() const
+{
+ awt::Rectangle aRect(0,0,0,0);
+ rtl::Reference< Diagram > xDiagram = m_xChartModel.get()->getFirstChartDiagram();
+
+ if( xDiagram && xDiagram->getDiagramPositioningMode() == DiagramPositioningMode::Including )
+ aRect = DiagramHelper::getDiagramRectangleFromModel(m_xChartModel.get());
+ else
+ {
+ ExplicitValueProvider* pProvider( getExplicitValueProvider() );
+ if( pProvider )
+ aRect = pProvider->getRectangleOfObject("PlotAreaIncludingAxes");
+ }
+ return aRect;
+}
+
+awt::Rectangle Chart2ModelContact::GetDiagramRectangleExcludingAxes() const
+{
+ awt::Rectangle aRect(0,0,0,0);
+ rtl::Reference< Diagram > xDiagram = m_xChartModel.get()->getFirstChartDiagram();
+
+ if( xDiagram && xDiagram->getDiagramPositioningMode() == DiagramPositioningMode::Excluding )
+ aRect = DiagramHelper::getDiagramRectangleFromModel(m_xChartModel.get());
+ else
+ {
+ ExplicitValueProvider* pProvider( getExplicitValueProvider() );
+ if( pProvider )
+ aRect = pProvider->getDiagramRectangleExcludingAxes();
+ }
+ return aRect;
+}
+
+awt::Size Chart2ModelContact::GetLegendSize() const
+{
+ awt::Size aSize;
+ ExplicitValueProvider* pProvider( getExplicitValueProvider() );
+ if( pProvider )
+ {
+ rtl::Reference< Legend > xLegend = LegendHelper::getLegend( *m_xChartModel.get() );
+ OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xLegend, m_xChartModel ) );
+ aSize = ToSize( pProvider->getRectangleOfObject( aCID ) );
+ }
+ return aSize;
+}
+
+awt::Point Chart2ModelContact::GetLegendPosition() const
+{
+ awt::Point aPoint;
+ ExplicitValueProvider* pProvider( getExplicitValueProvider() );
+ if( pProvider )
+ {
+ rtl::Reference< Legend > xLegend = LegendHelper::getLegend( *m_xChartModel.get() );
+ OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xLegend, m_xChartModel ) );
+ aPoint = ToPoint( pProvider->getRectangleOfObject( aCID ) );
+ }
+ return aPoint;
+}
+
+awt::Size Chart2ModelContact::GetTitleSize( const uno::Reference< css::chart2::XTitle > & xTitle ) const
+{
+ awt::Size aSize;
+ ExplicitValueProvider* pProvider( getExplicitValueProvider() );
+ if( pProvider && xTitle.is() )
+ {
+ OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, m_xChartModel ) );
+ aSize = ToSize( pProvider->getRectangleOfObject( aCID ) );
+ }
+ return aSize;
+}
+
+awt::Point Chart2ModelContact::GetTitlePosition( const uno::Reference< css::chart2::XTitle > & xTitle ) const
+{
+ awt::Point aPoint;
+ ExplicitValueProvider* pProvider( getExplicitValueProvider() );
+ if( pProvider && xTitle.is() )
+ {
+ OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, m_xChartModel.get() ) );
+ aPoint = ToPoint( pProvider->getRectangleOfObject( aCID ) );
+ }
+ return aPoint;
+}
+
+awt::Size Chart2ModelContact::GetAxisSize( const uno::Reference< css::chart2::XAxis > & xAxis ) const
+{
+ awt::Size aSize;
+ ExplicitValueProvider* pProvider( getExplicitValueProvider() );
+ if( pProvider && xAxis.is() )
+ {
+ OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, m_xChartModel.get() ) );
+ aSize = ToSize( pProvider->getRectangleOfObject( aCID ) );
+ }
+ return aSize;
+}
+
+awt::Point Chart2ModelContact::GetAxisPosition( const uno::Reference< css::chart2::XAxis > & xAxis ) const
+{
+ awt::Point aPoint;
+ ExplicitValueProvider* pProvider( getExplicitValueProvider() );
+ if( pProvider && xAxis.is() )
+ {
+ OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, m_xChartModel.get() ) );
+ aPoint = ToPoint( pProvider->getRectangleOfObject( aCID ) );
+ }
+ return aPoint;
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/Chart2ModelContact.hxx b/chart2/source/controller/chartapiwrapper/Chart2ModelContact.hxx
new file mode 100644
index 0000000000..261f268624
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/Chart2ModelContact.hxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <rtl/ref.hxx>
+#include <svx/unopage.hxx>
+#include <unotools/weakref.hxx>
+#include <ChartModel.hxx>
+#include <Diagram.hxx>
+#include <map>
+
+namespace chart { struct ExplicitIncrementData; }
+namespace chart { struct ExplicitScaleData; }
+namespace com::sun::star::chart2 { class XAxis; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::chart2 { class XTitle; }
+namespace com::sun::star::container { class XNameContainer; }
+namespace com::sun::star::drawing { class XDrawPage; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::lang { class XUnoTunnel; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+
+namespace chart
+{
+class ExplicitValueProvider;
+class ChartModel;
+
+namespace wrapper
+{
+
+class Chart2ModelContact final
+{
+public:
+ explicit Chart2ModelContact( const css::uno::Reference< css::uno::XComponentContext >& xContext );
+ ~Chart2ModelContact();
+
+public:
+ void setDocumentModel( ChartModel* pChartModel );
+ void clear();
+
+ rtl::Reference<ChartModel> getDocumentModel() const;
+
+ rtl::Reference< ::chart::Diagram > getDiagram() const;
+
+ rtl::Reference<SvxDrawPage> getDrawPage() const;
+
+ /** get the current values calculated for an axis in the current view in
+ case properties are 'auto'.
+ */
+ void getExplicitValuesForAxis(
+ const rtl::Reference< ::chart::Axis > & xAxis,
+ ExplicitScaleData & rOutExplicitScale,
+ ExplicitIncrementData & rOutExplicitIncrement );
+
+ sal_Int32 getExplicitNumberFormatKeyForAxis(
+ const rtl::Reference< ::chart::Axis >& xAxis );
+
+ static sal_Int32 getExplicitNumberFormatKeyForSeries(
+ const css::uno::Reference< css::chart2::XDataSeries >& xSeries );
+
+ /** Returns the size of the page in logic coordinates. This value is used
+ for setting an appropriate "ReferencePageSize" for FontHeights.
+ */
+ css::awt::Size GetPageSize() const;
+
+ /** calculates the current axes title sizes and subtract that space them from the given rectangle
+ */
+ css::awt::Rectangle SubstractAxisTitleSizes( const css::awt::Rectangle& rPositionRect );
+
+ /** Returns the position and size of the diagram in logic coordinates (100th mm) including
+ the space used for axes including axes titles.
+ */
+ css::awt::Rectangle GetDiagramRectangleIncludingTitle() const;
+
+ /** Returns the position and size of the diagram in logic coordinates (100th mm) including
+ the space used for axes excluding axes titles.
+ */
+ css::awt::Rectangle GetDiagramRectangleIncludingAxes() const;
+
+ /** Returns the position and size of the diagram in logic coordinates (100th mm) excluding
+ the space used for axes (inner plot area).
+ */
+ css::awt::Rectangle GetDiagramRectangleExcludingAxes() const;
+
+ /** Returns the size of the object in logic coordinates.
+ */
+ css::awt::Size GetLegendSize() const;
+
+ /** Returns the position of the object in logic coordinates.
+ */
+ css::awt::Point GetLegendPosition() const;
+
+ /** Returns the size of the object in logic coordinates.
+ */
+ css::awt::Size GetTitleSize( const css::uno::Reference< css::chart2::XTitle > & xTitle ) const;
+
+ /** Returns the position of the object in logic coordinates.
+ */
+ css::awt::Point GetTitlePosition( const css::uno::Reference< css::chart2::XTitle > & xTitle ) const;
+
+ /** Returns the size of the object in logic coordinates.
+ */
+ css::awt::Size GetAxisSize( const css::uno::Reference< css::chart2::XAxis > & xAxis ) const;
+
+ /** Returns the position of the object in logic coordinates.
+ */
+ css::awt::Point GetAxisPosition( const css::uno::Reference< css::chart2::XAxis > & xAxis ) const;
+
+private: //methods
+ ExplicitValueProvider* getExplicitValueProvider() const;
+ rtl::Reference< ChartView > const & getChartView() const;
+
+public: //member
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+
+private: //member
+ unotools::WeakReference< ChartModel > m_xChartModel;
+
+ mutable rtl::Reference< ChartView > m_xChartView;
+
+ std::map< OUString, css::uno::Reference< css::container::XNameContainer > > m_aTableMap;
+};
+
+} // namespace wrapper
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx b/chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx
new file mode 100644
index 0000000000..84b98f0d80
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx
@@ -0,0 +1,703 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ChartDataWrapper.hxx"
+#include <DiagramHelper.hxx>
+#include <DataSourceHelper.hxx>
+#include <ChartModelHelper.hxx>
+#include <InternalDataProvider.hxx>
+#include <ControllerLockGuard.hxx>
+#include "Chart2ModelContact.hxx"
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/chart/XChartDocument.hpp>
+
+#include <float.h>
+#include <cmath>
+#include <limits>
+#include <utility>
+#include <osl/diagnose.h>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::chart2::XAnyDescriptionAccess;
+using ::com::sun::star::chart::XComplexDescriptionAccess;
+using ::com::sun::star::chart::XChartData;
+using ::com::sun::star::chart::XChartDataArray;
+using ::com::sun::star::chart::XDateCategories;
+
+namespace
+{
+
+uno::Sequence< uno::Sequence< double > > lcl_getNANInsteadDBL_MIN( const uno::Sequence< uno::Sequence< double > >& rData )
+{
+ uno::Sequence< uno::Sequence< double > > aRet;
+ const sal_Int32 nOuterSize = rData.getLength();
+ aRet.realloc( nOuterSize );
+ auto pRet = aRet.getArray();
+ for( sal_Int32 nOuter=0; nOuter<nOuterSize; ++nOuter )
+ {
+ sal_Int32 nInnerSize = rData[nOuter].getLength();
+ pRet[nOuter].realloc( nInnerSize );
+ auto pRet_nOuter = pRet[nOuter].getArray();
+ for( sal_Int32 nInner=0; nInner<nInnerSize; ++nInner )
+ {
+ pRet_nOuter[nInner] = rData[nOuter][nInner];
+ double& rValue = pRet_nOuter[nInner];
+ if( rValue == DBL_MIN )
+ rValue = std::numeric_limits<double>::quiet_NaN();
+ }
+ }
+ return aRet;
+}
+
+uno::Sequence< uno::Sequence< double > > lcl_getDBL_MINInsteadNAN( const uno::Sequence< uno::Sequence< double > >& rData )
+{
+ uno::Sequence< uno::Sequence< double > > aRet;
+ const sal_Int32 nOuterSize = rData.getLength();
+ aRet.realloc( nOuterSize );
+ auto pRet = aRet.getArray();
+ for( sal_Int32 nOuter=0; nOuter<nOuterSize; ++nOuter )
+ {
+ sal_Int32 nInnerSize = rData[nOuter].getLength();
+ pRet[nOuter].realloc( nInnerSize );
+ auto pRet_nOuter = pRet[nOuter].getArray();
+ for( sal_Int32 nInner=0; nInner<nInnerSize; ++nInner )
+ {
+ pRet_nOuter[nInner] = rData[nOuter][nInner];
+ double& rValue = pRet_nOuter[nInner];
+ if( std::isnan( rValue ) )
+ rValue = DBL_MIN;
+ }
+ }
+ return aRet;
+}
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+struct lcl_Operator
+{
+ lcl_Operator()
+ {
+ }
+ virtual ~lcl_Operator()
+ {
+ }
+ virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) = 0;
+
+ virtual bool setsCategories( bool /*bDataInColumns*/ )
+ {
+ return false;
+ }
+};
+
+namespace {
+
+struct lcl_AllOperator : public lcl_Operator
+{
+ explicit lcl_AllOperator( const Reference< XChartData >& xDataToApply )
+ : m_xDataToApply( xDataToApply )
+ {
+ }
+
+ virtual bool setsCategories( bool /*bDataInColumns*/ ) override
+ {
+ return true;
+ }
+
+ virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) override
+ {
+ if( !xDataAccess.is() )
+ return;
+
+ Reference< XAnyDescriptionAccess > xNewAny( m_xDataToApply, uno::UNO_QUERY );
+ Reference< XComplexDescriptionAccess > xNewComplex( m_xDataToApply, uno::UNO_QUERY );
+ if( xNewAny.is() )
+ {
+ xDataAccess->setData( xNewAny->getData() );
+ xDataAccess->setComplexRowDescriptions( xNewAny->getComplexRowDescriptions() );
+ xDataAccess->setComplexColumnDescriptions( xNewAny->getComplexColumnDescriptions() );
+ }
+ else if( xNewComplex.is() )
+ {
+ xDataAccess->setData( xNewComplex->getData() );
+ xDataAccess->setComplexRowDescriptions( xNewComplex->getComplexRowDescriptions() );
+ xDataAccess->setComplexColumnDescriptions( xNewComplex->getComplexColumnDescriptions() );
+ }
+ else
+ {
+ Reference< XChartDataArray > xNew( m_xDataToApply, uno::UNO_QUERY );
+ if( xNew.is() )
+ {
+ xDataAccess->setData( xNew->getData() );
+ xDataAccess->setRowDescriptions( xNew->getRowDescriptions() );
+ xDataAccess->setColumnDescriptions( xNew->getColumnDescriptions() );
+ }
+ }
+ }
+
+ Reference< XChartData > m_xDataToApply;
+};
+
+struct lcl_DataOperator : public lcl_Operator
+{
+ explicit lcl_DataOperator( const Sequence< Sequence< double > >& rData )
+ : m_rData( rData )
+ {
+ }
+
+ virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) override
+ {
+ if( xDataAccess.is() )
+ xDataAccess->setData( lcl_getNANInsteadDBL_MIN( m_rData ) );
+ }
+
+ const Sequence< Sequence< double > >& m_rData;
+};
+
+struct lcl_RowDescriptionsOperator : public lcl_Operator
+{
+ lcl_RowDescriptionsOperator( const Sequence< OUString >& rRowDescriptions
+ , rtl::Reference<::chart::ChartModel> xChartDoc )
+ : m_rRowDescriptions( rRowDescriptions )
+ , m_xChartDoc(std::move(xChartDoc))
+ , m_bDataInColumns(true)
+ {
+ }
+
+ virtual bool setsCategories( bool bDataInColumns ) override
+ {
+ m_bDataInColumns = bDataInColumns;
+ return bDataInColumns;
+ }
+
+ virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) override
+ {
+ if( xDataAccess.is() )
+ {
+ xDataAccess->setRowDescriptions( m_rRowDescriptions );
+ if( m_bDataInColumns )
+ DiagramHelper::switchToTextCategories( m_xChartDoc );
+ }
+ }
+
+ const Sequence< OUString >& m_rRowDescriptions;
+ rtl::Reference<::chart::ChartModel> m_xChartDoc;
+ bool m_bDataInColumns;
+};
+
+struct lcl_ComplexRowDescriptionsOperator : public lcl_Operator
+{
+ lcl_ComplexRowDescriptionsOperator( const Sequence< Sequence< OUString > >& rComplexRowDescriptions
+ , rtl::Reference<::chart::ChartModel> xChartDoc )
+ : m_rComplexRowDescriptions( rComplexRowDescriptions )
+ , m_xChartDoc(std::move(xChartDoc))
+ , m_bDataInColumns(true)
+ {
+ }
+
+ virtual bool setsCategories( bool bDataInColumns ) override
+ {
+ m_bDataInColumns = bDataInColumns;
+ return bDataInColumns;
+ }
+
+ virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) override
+ {
+ if( xDataAccess.is() )
+ {
+ xDataAccess->setComplexRowDescriptions( m_rComplexRowDescriptions );
+ if( m_bDataInColumns )
+ DiagramHelper::switchToTextCategories( m_xChartDoc );
+ }
+ }
+
+ const Sequence< Sequence< OUString > >& m_rComplexRowDescriptions;
+ rtl::Reference<::chart::ChartModel> m_xChartDoc;
+ bool m_bDataInColumns;
+};
+
+struct lcl_AnyRowDescriptionsOperator : public lcl_Operator
+{
+ explicit lcl_AnyRowDescriptionsOperator( const Sequence< Sequence< uno::Any > >& rAnyRowDescriptions )
+ : m_rAnyRowDescriptions( rAnyRowDescriptions )
+ {
+ }
+
+ virtual bool setsCategories( bool bDataInColumns ) override
+ {
+ return bDataInColumns;
+ }
+
+ virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) override
+ {
+ if( xDataAccess.is() )
+ xDataAccess->setAnyRowDescriptions( m_rAnyRowDescriptions );
+ }
+
+ const Sequence< Sequence< uno::Any > >& m_rAnyRowDescriptions;
+};
+
+struct lcl_ColumnDescriptionsOperator : public lcl_Operator
+{
+ lcl_ColumnDescriptionsOperator( const Sequence< OUString >& rColumnDescriptions
+ , rtl::Reference<::chart::ChartModel> xChartDoc )
+ : m_rColumnDescriptions( rColumnDescriptions )
+ , m_xChartDoc(std::move(xChartDoc))
+ , m_bDataInColumns(true)
+ {
+ }
+
+ virtual bool setsCategories( bool bDataInColumns ) override
+ {
+ m_bDataInColumns = bDataInColumns;
+ return !bDataInColumns;
+ }
+
+ virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) override
+ {
+ if( xDataAccess.is() )
+ {
+ xDataAccess->setColumnDescriptions( m_rColumnDescriptions );
+ if( !m_bDataInColumns )
+ DiagramHelper::switchToTextCategories( m_xChartDoc );
+ }
+ }
+
+ const Sequence< OUString >& m_rColumnDescriptions;
+ rtl::Reference<::chart::ChartModel> m_xChartDoc;
+ bool m_bDataInColumns;
+};
+
+struct lcl_ComplexColumnDescriptionsOperator : public lcl_Operator
+{
+ lcl_ComplexColumnDescriptionsOperator( const Sequence< Sequence< OUString > >& rComplexColumnDescriptions
+ , rtl::Reference<::chart::ChartModel> xChartDoc )
+ : m_rComplexColumnDescriptions( rComplexColumnDescriptions )
+ , m_xChartDoc(std::move(xChartDoc))
+ , m_bDataInColumns(true)
+ {
+ }
+
+ virtual bool setsCategories( bool bDataInColumns ) override
+ {
+ m_bDataInColumns = bDataInColumns;
+ return !bDataInColumns;
+ }
+
+ virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) override
+ {
+ if( xDataAccess.is() )
+ {
+ xDataAccess->setComplexColumnDescriptions( m_rComplexColumnDescriptions );
+ if( !m_bDataInColumns )
+ DiagramHelper::switchToTextCategories( m_xChartDoc );
+ }
+ }
+
+ const Sequence< Sequence< OUString > >& m_rComplexColumnDescriptions;
+ rtl::Reference<::chart::ChartModel> m_xChartDoc;
+ bool m_bDataInColumns;
+};
+
+struct lcl_AnyColumnDescriptionsOperator : public lcl_Operator
+{
+ explicit lcl_AnyColumnDescriptionsOperator( const Sequence< Sequence< uno::Any > >& rAnyColumnDescriptions )
+ : m_rAnyColumnDescriptions( rAnyColumnDescriptions )
+ {
+ }
+
+ virtual bool setsCategories( bool bDataInColumns ) override
+ {
+ return bDataInColumns;
+ }
+
+ virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) override
+ {
+ if( xDataAccess.is() )
+ xDataAccess->setAnyColumnDescriptions( m_rAnyColumnDescriptions );
+ }
+
+ const Sequence< Sequence< uno::Any > >& m_rAnyColumnDescriptions;
+};
+
+struct lcl_DateCategoriesOperator : public lcl_Operator
+{
+ explicit lcl_DateCategoriesOperator( const Sequence< double >& rDates )
+ : m_rDates( rDates )
+ {
+ }
+
+ virtual bool setsCategories( bool /*bDataInColumns*/ ) override
+ {
+ return true;
+ }
+
+ virtual void apply( const Reference< XAnyDescriptionAccess >& xDataAccess ) override
+ {
+ Reference< XDateCategories > xDateCategories( xDataAccess, uno::UNO_QUERY );
+ if( xDateCategories.is() )
+ xDateCategories->setDateCategories( m_rDates );
+ }
+
+ const Sequence< double >& m_rDates;
+};
+
+}
+
+ChartDataWrapper::ChartDataWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : m_spChart2ModelContact(std::move(spChart2ModelContact))
+{
+ osl_atomic_increment( &m_refCount );
+ initDataAccess();
+ osl_atomic_decrement( &m_refCount );
+}
+
+ChartDataWrapper::ChartDataWrapper( std::shared_ptr<Chart2ModelContact> spChart2ModelContact,
+ const Reference< XChartData >& xNewData ) :
+ m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+ osl_atomic_increment( &m_refCount );
+ lcl_AllOperator aOperator( xNewData );
+ applyData( aOperator );
+ osl_atomic_decrement( &m_refCount );
+}
+
+ChartDataWrapper::~ChartDataWrapper()
+{
+ // @todo: implement XComponent and call this in dispose(). In the DTOR the
+ // ref-count is 0, thus creating a stack reference to this calls the DTOR at
+ // the end of the block recursively
+// uno::Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+// m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) );
+}
+
+// ____ XChartDataArray (read)____
+Sequence< Sequence< double > > SAL_CALL ChartDataWrapper::getData()
+{
+ initDataAccess();
+ if( m_xDataAccess.is() )
+ return lcl_getDBL_MINInsteadNAN( m_xDataAccess->getData() );
+ return Sequence< Sequence< double > >();
+}
+Sequence< OUString > SAL_CALL ChartDataWrapper::getRowDescriptions()
+{
+ initDataAccess();
+ if( m_xDataAccess.is() )
+ return m_xDataAccess->getRowDescriptions();
+ return Sequence< OUString >();
+}
+Sequence< OUString > SAL_CALL ChartDataWrapper::getColumnDescriptions()
+{
+ initDataAccess();
+ if( m_xDataAccess.is() )
+ return m_xDataAccess->getColumnDescriptions();
+ return Sequence< OUString > ();
+}
+
+// ____ XComplexDescriptionAccess (read) ____
+Sequence< Sequence< OUString > > SAL_CALL ChartDataWrapper::getComplexRowDescriptions()
+{
+ initDataAccess();
+ if( m_xDataAccess.is() )
+ return m_xDataAccess->getComplexRowDescriptions();
+ return Sequence< Sequence< OUString > >();
+}
+Sequence< Sequence< OUString > > SAL_CALL ChartDataWrapper::getComplexColumnDescriptions()
+{
+ initDataAccess();
+ if( m_xDataAccess.is() )
+ return m_xDataAccess->getComplexColumnDescriptions();
+ return Sequence< Sequence< OUString > >();
+}
+
+// ____ XAnyDescriptionAccess (read) ____
+Sequence< Sequence< uno::Any > > SAL_CALL ChartDataWrapper::getAnyRowDescriptions()
+{
+ initDataAccess();
+ if( m_xDataAccess.is() )
+ return m_xDataAccess->getAnyRowDescriptions();
+ return Sequence< Sequence< uno::Any > >();
+}
+Sequence< Sequence< uno::Any > > SAL_CALL ChartDataWrapper::getAnyColumnDescriptions()
+{
+ initDataAccess();
+ if( m_xDataAccess.is() )
+ return m_xDataAccess->getAnyColumnDescriptions();
+ return Sequence< Sequence< uno::Any > >();
+}
+
+// ____ XDateCategories (read) ____
+Sequence< double > SAL_CALL ChartDataWrapper::getDateCategories()
+{
+ initDataAccess();
+ Reference< XDateCategories > xDateCategories( m_xDataAccess, uno::UNO_QUERY );
+ if( xDateCategories.is() )
+ return xDateCategories->getDateCategories();
+ return Sequence< double >();
+}
+
+// ____ XChartDataArray (write)____
+void SAL_CALL ChartDataWrapper::setData( const Sequence< Sequence< double > >& rData )
+{
+ lcl_DataOperator aOperator( rData );
+ applyData( aOperator );
+}
+void SAL_CALL ChartDataWrapper::setRowDescriptions( const Sequence< OUString >& rRowDescriptions )
+{
+ lcl_RowDescriptionsOperator aOperator( rRowDescriptions, m_spChart2ModelContact->getDocumentModel() );
+ applyData( aOperator );
+}
+void SAL_CALL ChartDataWrapper::setColumnDescriptions( const Sequence< OUString >& rColumnDescriptions )
+{
+ lcl_ColumnDescriptionsOperator aOperator( rColumnDescriptions, m_spChart2ModelContact->getDocumentModel() );
+ applyData( aOperator );
+}
+
+// ____ XComplexDescriptionAccess (write) ____
+void SAL_CALL ChartDataWrapper::setComplexRowDescriptions( const Sequence< Sequence< OUString > >& rRowDescriptions )
+{
+ lcl_ComplexRowDescriptionsOperator aOperator( rRowDescriptions, m_spChart2ModelContact->getDocumentModel() );
+ applyData( aOperator );
+}
+void SAL_CALL ChartDataWrapper::setComplexColumnDescriptions( const Sequence< Sequence< OUString > >& rColumnDescriptions )
+{
+ lcl_ComplexColumnDescriptionsOperator aOperator( rColumnDescriptions, m_spChart2ModelContact->getDocumentModel() );
+ applyData( aOperator );
+}
+
+// ____ XAnyDescriptionAccess (write) ____
+void SAL_CALL ChartDataWrapper::setAnyRowDescriptions( const Sequence< Sequence< uno::Any > >& rRowDescriptions )
+{
+ lcl_AnyRowDescriptionsOperator aOperator( rRowDescriptions );
+ applyData( aOperator );
+}
+void SAL_CALL ChartDataWrapper::setAnyColumnDescriptions( const Sequence< Sequence< uno::Any > >& rColumnDescriptions )
+{
+ lcl_AnyColumnDescriptionsOperator aOperator( rColumnDescriptions );
+ applyData( aOperator );
+}
+
+// ____ XDateCategories (write) ____
+void SAL_CALL ChartDataWrapper::setDateCategories( const Sequence< double >& rDates )
+{
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ ControllerLockGuardUNO aCtrlLockGuard( xChartDoc );
+ lcl_DateCategoriesOperator aOperator( rDates );
+ applyData( aOperator );
+ DiagramHelper::switchToDateCategories( xChartDoc );
+}
+
+// ____ XChartData (base of XChartDataArray) ____
+void SAL_CALL ChartDataWrapper::addChartDataChangeEventListener(
+ const uno::Reference< css::chart::XChartDataChangeEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, aListener );
+}
+
+void SAL_CALL ChartDataWrapper::removeChartDataChangeEventListener(
+ const uno::Reference< css::chart::XChartDataChangeEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+double SAL_CALL ChartDataWrapper::getNotANumber()
+{
+ return DBL_MIN;
+}
+
+sal_Bool SAL_CALL ChartDataWrapper::isNotANumber( double nNumber )
+{
+ return nNumber == DBL_MIN
+ || std::isnan( nNumber )
+ || std::isinf( nNumber );
+}
+
+// ____ XComponent ____
+void SAL_CALL ChartDataWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( static_cast< ::cppu::OWeakObject* >( this )));
+ m_xDataAccess=nullptr;
+}
+
+void SAL_CALL ChartDataWrapper::addEventListener(
+ const uno::Reference< lang::XEventListener > & xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL ChartDataWrapper::removeEventListener(
+ const uno::Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+// ____ XEventListener ____
+void SAL_CALL ChartDataWrapper::disposing( const lang::EventObject& /* Source */ )
+{
+}
+
+void ChartDataWrapper::fireChartDataChangeEvent( css::chart::ChartDataChangeEvent& aEvent )
+{
+ std::unique_lock g(m_aMutex);
+ if( ! m_aEventListenerContainer.getLength(g) )
+ return;
+
+ uno::Reference< uno::XInterface > xSrc( static_cast< cppu::OWeakObject* >( this ));
+ OSL_ASSERT( xSrc.is());
+ if( xSrc.is() )
+ aEvent.Source = xSrc;
+
+ m_aEventListenerContainer.forEach( g,
+ [&aEvent](const uno::Reference<css::lang::XEventListener>& l)
+ {
+ uno::Reference<css::chart::XChartDataChangeEventListener> cl(l, uno::UNO_QUERY);
+ if (cl)
+ cl->chartDataChanged(aEvent);
+ });
+}
+
+void ChartDataWrapper::switchToInternalDataProvider()
+{
+ //create an internal data provider that is connected to the model
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ if( xChartDoc.is() )
+ xChartDoc->createInternalDataProvider( true /*bCloneExistingData*/ );
+ initDataAccess();
+}
+
+void ChartDataWrapper::initDataAccess()
+{
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ if( !xChartDoc.is() )
+ return;
+ if( xChartDoc->hasInternalDataProvider() )
+ m_xDataAccess.set( xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW );
+ else
+ {
+ //create a separate "internal data provider" that is not connected to the model
+ auto xInternal = ChartModelHelper::createInternalDataProvider(
+ xChartDoc, false /*bConnectToModel*/ );
+ m_xDataAccess.set( static_cast<cppu::OWeakObject*>(xInternal.get()), uno::UNO_QUERY_THROW );
+ }
+}
+
+void ChartDataWrapper::applyData( lcl_Operator& rDataOperator )
+{
+ //bool bSetValues, bool bSetRowDescriptions, bool bSetColumnDescriptions
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ if( !xChartDoc.is() )
+ return;
+
+ // remember some diagram properties to reset later
+ bool bStacked = false;
+ bool bPercent = false;
+ bool bDeep = false;
+ uno::Reference< css::chart::XChartDocument > xOldDoc( static_cast<cppu::OWeakObject*>(xChartDoc.get()), uno::UNO_QUERY );
+ OSL_ASSERT( xOldDoc.is());
+ uno::Reference< beans::XPropertySet > xDiaProp( xOldDoc->getDiagram(), uno::UNO_QUERY );
+ if( xDiaProp.is())
+ {
+ xDiaProp->getPropertyValue("Stacked") >>= bStacked;
+ xDiaProp->getPropertyValue("Percent") >>= bPercent;
+ xDiaProp->getPropertyValue("Deep") >>= bDeep;
+ }
+
+ //detect arguments for the new data source
+ OUString aRangeString;
+ bool bUseColumns = true;
+ bool bFirstCellAsLabel = true;
+ bool bHasCategories = true;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+
+ (void)DataSourceHelper::detectRangeSegmentation(
+ xChartDoc,
+ aRangeString, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories );
+
+ if( !bHasCategories && rDataOperator.setsCategories( bUseColumns ) )
+ bHasCategories = true;
+
+ aRangeString = "all";
+ uno::Sequence< beans::PropertyValue > aArguments( DataSourceHelper::createArguments(
+ aRangeString, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories ) );
+
+ // -- locked controllers
+ ControllerLockGuardUNO aCtrlLockGuard( xChartDoc );
+
+ // create and attach new data source
+ switchToInternalDataProvider();
+ rDataOperator.apply(m_xDataAccess);
+ uno::Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
+ OSL_ASSERT( xDataProvider.is() );
+ if( !xDataProvider.is() )
+ return;
+ uno::Reference< chart2::data::XDataSource > xSource( xDataProvider->createDataSource( aArguments ) );
+
+ rtl::Reference< Diagram > xDia( xChartDoc->getFirstChartDiagram() );
+ if( xDia.is() )
+ xDia->setDiagramData( xSource, aArguments );
+
+ //correct stacking mode
+ if( bStacked || bPercent || bDeep )
+ {
+ StackMode eStackMode = StackMode::YStacked;
+ if( bDeep )
+ eStackMode = StackMode::ZStacked;
+ else if( bPercent )
+ eStackMode = StackMode::YStackedPercent;
+ xDia->setStackMode( eStackMode );
+ }
+
+ // notify listeners
+ css::chart::ChartDataChangeEvent aEvent(
+ static_cast< ::cppu::OWeakObject* >( this ),
+ css::chart::ChartDataChangeType_ALL, 0, 0, 0, 0 );
+ fireChartDataChangeEvent( aEvent );
+ // \-- locked controllers
+}
+
+OUString SAL_CALL ChartDataWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.ChartData";
+}
+
+sal_Bool SAL_CALL ChartDataWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ChartDataWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart.ChartDataArray",
+ "com.sun.star.chart.ChartData"
+ };
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/ChartDataWrapper.hxx b/chart2/source/controller/chartapiwrapper/ChartDataWrapper.hxx
new file mode 100644
index 0000000000..3c6602d4e0
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/ChartDataWrapper.hxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
+#include <com/sun/star/chart/XDateCategories.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+
+#include <memory>
+
+namespace chart::wrapper
+{
+
+class Chart2ModelContact;
+struct lcl_Operator;
+
+class ChartDataWrapper final : public
+ ::cppu::WeakImplHelper<
+ css::chart2::XAnyDescriptionAccess,
+ css::chart::XDateCategories,
+ css::lang::XServiceInfo,
+ css::lang::XEventListener,
+ css::lang::XComponent >
+{
+public:
+ explicit ChartDataWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ ChartDataWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact
+ , const css::uno::Reference< css::chart::XChartData >& xNewData );
+ virtual ~ChartDataWrapper() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+private:
+ // ____ XDateCategories ____
+ virtual css::uno::Sequence< double > SAL_CALL getDateCategories() override;
+ virtual void SAL_CALL setDateCategories( const css::uno::Sequence< double >& rDates ) override;
+
+ // ____ XAnyDescriptionAccess ____
+ virtual css::uno::Sequence< css::uno::Sequence< css::uno::Any > > SAL_CALL
+ getAnyRowDescriptions() override;
+ virtual void SAL_CALL setAnyRowDescriptions(
+ const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& aRowDescriptions ) override;
+ virtual css::uno::Sequence< css::uno::Sequence< css::uno::Any > > SAL_CALL
+ getAnyColumnDescriptions() override;
+ virtual void SAL_CALL setAnyColumnDescriptions(
+ const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& aColumnDescriptions ) override;
+
+ // ____ XComplexDescriptionAccess (base of XAnyDescriptionAccess) ____
+ virtual css::uno::Sequence< css::uno::Sequence< OUString > > SAL_CALL
+ getComplexRowDescriptions() override;
+ virtual void SAL_CALL setComplexRowDescriptions(
+ const css::uno::Sequence< css::uno::Sequence< OUString > >& aRowDescriptions ) override;
+ virtual css::uno::Sequence< css::uno::Sequence< OUString > > SAL_CALL
+ getComplexColumnDescriptions() override;
+ virtual void SAL_CALL setComplexColumnDescriptions(
+ const css::uno::Sequence< css::uno::Sequence< OUString > >& aColumnDescriptions ) override;
+
+ // ____ XChartDataArray (base of XComplexDescriptionAccess) ____
+ virtual css::uno::Sequence< css::uno::Sequence< double > > SAL_CALL getData() override;
+ virtual void SAL_CALL setData( const css::uno::Sequence< css::uno::Sequence< double > >& aData ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getRowDescriptions() override;
+ virtual void SAL_CALL setRowDescriptions( const css::uno::Sequence< OUString >& aRowDescriptions ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getColumnDescriptions() override;
+ virtual void SAL_CALL setColumnDescriptions( const css::uno::Sequence< OUString >& aColumnDescriptions ) override;
+
+ // ____ XChartData (base of XChartDataArray) ____
+ virtual void SAL_CALL addChartDataChangeEventListener( const css::uno::Reference< css::chart::XChartDataChangeEventListener >& aListener ) override;
+ virtual void SAL_CALL removeChartDataChangeEventListener( const css::uno::Reference< css::chart::XChartDataChangeEventListener >& aListener ) override;
+ virtual double SAL_CALL getNotANumber() override;
+ virtual sal_Bool SAL_CALL isNotANumber( double nNumber ) override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+
+ // ____ XEventListener ____
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ void fireChartDataChangeEvent( css::chart::ChartDataChangeEvent& aEvent );
+
+ void switchToInternalDataProvider();
+ void initDataAccess();
+ void applyData( lcl_Operator& rDataOperator );
+
+ std::mutex m_aMutex;
+ css::uno::Reference< css::chart2::XAnyDescriptionAccess > m_xDataAccess;
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx b/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx
new file mode 100644
index 0000000000..ea01ae000b
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx
@@ -0,0 +1,1442 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartDocumentWrapper.hxx>
+#include <ChartView.hxx>
+#include <ChartViewHelper.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <servicenames.hxx>
+#include <PropertyHelper.hxx>
+#include <TitleHelper.hxx>
+#include <Legend.hxx>
+#include <LegendHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <DisposeHelper.hxx>
+#include "DataSeriesPointWrapper.hxx"
+#include <chartview/ExplicitValueProvider.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include "Chart2ModelContact.hxx"
+#include <BaseCoordinateSystem.hxx>
+
+#include <ChartModel.hxx>
+
+#include <DiagramHelper.hxx>
+#include <DataSourceHelper.hxx>
+#include <ChartModelHelper.hxx>
+#include <AxisHelper.hxx>
+#include <ThreeDHelper.hxx>
+
+#include "TitleWrapper.hxx"
+#include "ChartDataWrapper.hxx"
+#include "DiagramWrapper.hxx"
+#include "LegendWrapper.hxx"
+#include "AreaWrapper.hxx"
+#include "WrappedAddInProperty.hxx"
+#include <WrappedIgnoreProperty.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <utility>
+#include <vcl/settings.hxx>
+
+#include <com/sun/star/drawing/ShapeCollection.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+#include <map>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart;
+
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+enum eServiceType
+{
+ SERVICE_NAME_AREA_DIAGRAM = 0,
+ SERVICE_NAME_BAR_DIAGRAM,
+ SERVICE_NAME_DONUT_DIAGRAM,
+ SERVICE_NAME_LINE_DIAGRAM,
+ SERVICE_NAME_NET_DIAGRAM,
+ SERVICE_NAME_FILLED_NET_DIAGRAM,
+ SERVICE_NAME_PIE_DIAGRAM,
+ SERVICE_NAME_STOCK_DIAGRAM,
+ SERVICE_NAME_XY_DIAGRAM,
+ SERVICE_NAME_BUBBLE_DIAGRAM,
+
+ SERVICE_NAME_DASH_TABLE,
+ SERVICE_NAME_GRADIENT_TABLE,
+ SERVICE_NAME_HATCH_TABLE,
+ SERVICE_NAME_BITMAP_TABLE,
+ SERVICE_NAME_TRANSP_GRADIENT_TABLE,
+ SERVICE_NAME_MARKER_TABLE,
+
+ SERVICE_NAME_NAMESPACE_MAP,
+ SERVICE_NAME_EXPORT_GRAPHIC_STORAGE_RESOLVER,
+ SERVICE_NAME_IMPORT_GRAPHIC_STORAGE_RESOLVER
+};
+
+typedef std::map< OUString, enum eServiceType > tServiceNameMap;
+
+tServiceNameMap & lcl_getStaticServiceNameMap()
+{
+ static tServiceNameMap aServiceNameMap {
+ {"com.sun.star.chart.AreaDiagram", SERVICE_NAME_AREA_DIAGRAM},
+ {"com.sun.star.chart.BarDiagram", SERVICE_NAME_BAR_DIAGRAM},
+ {"com.sun.star.chart.DonutDiagram", SERVICE_NAME_DONUT_DIAGRAM},
+ {"com.sun.star.chart.LineDiagram", SERVICE_NAME_LINE_DIAGRAM},
+ {"com.sun.star.chart.NetDiagram", SERVICE_NAME_NET_DIAGRAM},
+ {"com.sun.star.chart.FilledNetDiagram", SERVICE_NAME_FILLED_NET_DIAGRAM},
+ {"com.sun.star.chart.PieDiagram", SERVICE_NAME_PIE_DIAGRAM},
+ {"com.sun.star.chart.StockDiagram", SERVICE_NAME_STOCK_DIAGRAM},
+ {"com.sun.star.chart.XYDiagram", SERVICE_NAME_XY_DIAGRAM},
+ {"com.sun.star.chart.BubbleDiagram", SERVICE_NAME_BUBBLE_DIAGRAM},
+
+ {"com.sun.star.drawing.DashTable", SERVICE_NAME_DASH_TABLE},
+ {"com.sun.star.drawing.GradientTable", SERVICE_NAME_GRADIENT_TABLE},
+ {"com.sun.star.drawing.HatchTable", SERVICE_NAME_HATCH_TABLE},
+ {"com.sun.star.drawing.BitmapTable", SERVICE_NAME_BITMAP_TABLE},
+ {"com.sun.star.drawing.TransparencyGradientTable", SERVICE_NAME_TRANSP_GRADIENT_TABLE},
+ {"com.sun.star.drawing.MarkerTable", SERVICE_NAME_MARKER_TABLE},
+
+ {"com.sun.star.xml.NamespaceMap", SERVICE_NAME_NAMESPACE_MAP},
+ {"com.sun.star.document.ExportGraphicStorageHandler", SERVICE_NAME_EXPORT_GRAPHIC_STORAGE_RESOLVER},
+ {"com.sun.star.document.ImportGraphicStorageHandler", SERVICE_NAME_IMPORT_GRAPHIC_STORAGE_RESOLVER}
+ };
+
+ return aServiceNameMap;
+}
+
+enum
+{
+ PROP_DOCUMENT_HAS_MAIN_TITLE,
+ PROP_DOCUMENT_HAS_SUB_TITLE,
+ PROP_DOCUMENT_HAS_LEGEND,
+ PROP_DOCUMENT_LABELS_IN_FIRST_ROW,
+ PROP_DOCUMENT_LABELS_IN_FIRST_COLUMN,
+ PROP_DOCUMENT_ADDIN,
+ PROP_DOCUMENT_BASEDIAGRAM,
+ PROP_DOCUMENT_ADDITIONAL_SHAPES,
+ PROP_DOCUMENT_UPDATE_ADDIN,
+ PROP_DOCUMENT_NULL_DATE,
+ PROP_DOCUMENT_ENABLE_COMPLEX_CHARTTYPES,
+ PROP_DOCUMENT_ENABLE_DATATABLE_DIALOG
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "HasMainTitle",
+ PROP_DOCUMENT_HAS_MAIN_TITLE,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasSubTitle",
+ PROP_DOCUMENT_HAS_SUB_TITLE,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasLegend",
+ PROP_DOCUMENT_HAS_LEGEND,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // really needed?
+ rOutProperties.emplace_back( "DataSourceLabelsInFirstRow",
+ PROP_DOCUMENT_LABELS_IN_FIRST_ROW,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "DataSourceLabelsInFirstColumn",
+ PROP_DOCUMENT_LABELS_IN_FIRST_COLUMN,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //add-in
+ rOutProperties.emplace_back( "AddIn",
+ PROP_DOCUMENT_ADDIN,
+ cppu::UnoType<util::XRefreshable>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "BaseDiagram",
+ PROP_DOCUMENT_BASEDIAGRAM,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "AdditionalShapes",
+ PROP_DOCUMENT_ADDITIONAL_SHAPES,
+ cppu::UnoType<drawing::XShapes>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::READONLY );
+ rOutProperties.emplace_back( "RefreshAddInAllowed",
+ PROP_DOCUMENT_UPDATE_ADDIN,
+ cppu::UnoType<bool>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::TRANSIENT );
+
+ // table:null-date // i99104
+ rOutProperties.emplace_back( "NullDate",
+ PROP_DOCUMENT_NULL_DATE,
+ ::cppu::UnoType<css::util::DateTime>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "EnableComplexChartTypes",
+ PROP_DOCUMENT_ENABLE_COMPLEX_CHARTTYPES,
+ cppu::UnoType<bool>::get(),
+ //#i112666# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "EnableDataTableDialog",
+ PROP_DOCUMENT_ENABLE_DATATABLE_DIALOG,
+ cppu::UnoType<bool>::get(),
+ //#i112666# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+const Sequence< Property > & StaticChartDocumentWrapperPropertyArray()
+{
+ static Sequence< Property > aPropSeq = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropSeq;
+}
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+namespace {
+
+//PROP_DOCUMENT_LABELS_IN_FIRST_ROW
+class WrappedDataSourceLabelsInFirstRowProperty : public WrappedProperty
+{
+public:
+ explicit WrappedDataSourceLabelsInFirstRowProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedDataSourceLabelsInFirstRowProperty::WrappedDataSourceLabelsInFirstRowProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("DataSourceLabelsInFirstRow",OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+ m_aOuterValue = WrappedDataSourceLabelsInFirstRowProperty::getPropertyDefault( nullptr );
+}
+
+void WrappedDataSourceLabelsInFirstRowProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bLabelsInFirstRow = true;
+ if( ! (rOuterValue >>= bLabelsInFirstRow) )
+ throw lang::IllegalArgumentException("Property DataSourceLabelsInFirstRow requires value of type boolean", nullptr, 0 );
+
+ m_aOuterValue = rOuterValue;
+ bool bNewValue = bLabelsInFirstRow;
+
+ OUString aRangeString;
+ bool bUseColumns = true;
+ bool bFirstCellAsLabel = true;
+ bool bHasCategories = true;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+
+ if( !DataSourceHelper::detectRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aRangeString, aSequenceMapping, bUseColumns
+ , bFirstCellAsLabel, bHasCategories ) )
+ return;
+
+ if( bUseColumns && bNewValue != bFirstCellAsLabel )
+ {
+ DataSourceHelper::setRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aSequenceMapping, bUseColumns ,bNewValue, bHasCategories );
+ }
+ else if( !bUseColumns && bNewValue != bHasCategories )
+ {
+ DataSourceHelper::setRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aSequenceMapping, bUseColumns , bFirstCellAsLabel, bNewValue );
+ }
+}
+
+Any WrappedDataSourceLabelsInFirstRowProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ OUString aRangeString;
+ bool bUseColumns = true;
+ bool bFirstCellAsLabel = true;
+ bool bHasCategories = true;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+
+ if( DataSourceHelper::detectRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aRangeString, aSequenceMapping, bUseColumns
+ , bFirstCellAsLabel, bHasCategories ) )
+ {
+ bool bLabelsInFirstRow = true;
+ if( bUseColumns )
+ bLabelsInFirstRow = bFirstCellAsLabel;
+ else
+ bLabelsInFirstRow = bHasCategories;
+
+ m_aOuterValue <<= bLabelsInFirstRow;
+ }
+ return m_aOuterValue;
+}
+
+Any WrappedDataSourceLabelsInFirstRowProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= true;
+ return aRet;
+}
+
+namespace {
+
+//PROP_DOCUMENT_LABELS_IN_FIRST_COLUMN
+class WrappedDataSourceLabelsInFirstColumnProperty : public WrappedProperty
+{
+public:
+ explicit WrappedDataSourceLabelsInFirstColumnProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedDataSourceLabelsInFirstColumnProperty::WrappedDataSourceLabelsInFirstColumnProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("DataSourceLabelsInFirstColumn",OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+ m_aOuterValue = WrappedDataSourceLabelsInFirstColumnProperty::getPropertyDefault( nullptr );
+}
+
+void WrappedDataSourceLabelsInFirstColumnProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bLabelsInFirstRow = true;
+ if( ! (rOuterValue >>= bLabelsInFirstRow) )
+ throw lang::IllegalArgumentException("Property DataSourceLabelsInFirstRow requires value of type boolean", nullptr, 0 );
+
+ m_aOuterValue = rOuterValue;
+ bool bNewValue = bLabelsInFirstRow;
+
+ OUString aRangeString;
+ bool bUseColumns = true;
+ bool bFirstCellAsLabel = true;
+ bool bHasCategories = true;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+
+ if( !DataSourceHelper::detectRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aRangeString, aSequenceMapping, bUseColumns
+ , bFirstCellAsLabel, bHasCategories ) )
+ return;
+
+ if( bUseColumns && bNewValue != bHasCategories )
+ {
+ DataSourceHelper::setRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aSequenceMapping, bUseColumns, bFirstCellAsLabel, bNewValue );
+ }
+ else if( !bUseColumns && bNewValue != bFirstCellAsLabel )
+ {
+ DataSourceHelper::setRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aSequenceMapping, bUseColumns , bNewValue, bHasCategories );
+ }
+}
+
+Any WrappedDataSourceLabelsInFirstColumnProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ OUString aRangeString;
+ bool bUseColumns = true;
+ bool bFirstCellAsLabel = true;
+ bool bHasCategories = true;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+
+ if( DataSourceHelper::detectRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aRangeString, aSequenceMapping, bUseColumns
+ , bFirstCellAsLabel, bHasCategories ) )
+ {
+ bool bLabelsInFirstColumn = true;
+ if( bUseColumns )
+ bLabelsInFirstColumn = bHasCategories;
+ else
+ bLabelsInFirstColumn = bFirstCellAsLabel;
+
+ m_aOuterValue <<= bLabelsInFirstColumn;
+ }
+ return m_aOuterValue;
+}
+
+Any WrappedDataSourceLabelsInFirstColumnProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= true;
+ return aRet;
+}
+
+namespace {
+
+//PROP_DOCUMENT_HAS_LEGEND
+class WrappedHasLegendProperty : public WrappedProperty
+{
+public:
+ explicit WrappedHasLegendProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+};
+
+}
+
+WrappedHasLegendProperty::WrappedHasLegendProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("HasLegend",OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+}
+
+void WrappedHasLegendProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bNewValue = true;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException("Property HasLegend requires value of type boolean", nullptr, 0 );
+
+ try
+ {
+ rtl::Reference< Legend > xLegend = LegendHelper::getLegend( *m_spChart2ModelContact->getDocumentModel(), m_spChart2ModelContact->m_xContext,bNewValue );
+ if(xLegend.is())
+ {
+ bool bOldValue = true;
+ Any aAOld = xLegend->getPropertyValue("Show");
+ aAOld >>= bOldValue;
+ if( bOldValue != bNewValue )
+ xLegend->setPropertyValue("Show", uno::Any( bNewValue ));
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+Any WrappedHasLegendProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ Any aRet;
+ try
+ {
+ rtl::Reference< Legend > xLegend =
+ LegendHelper::getLegend( *m_spChart2ModelContact->getDocumentModel() );
+ if( xLegend.is())
+ aRet = xLegend->getPropertyValue("Show");
+ else
+ aRet <<= false;
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return aRet;
+}
+
+Any WrappedHasLegendProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+namespace {
+
+//PROP_DOCUMENT_HAS_MAIN_TITLE
+class WrappedHasMainTitleProperty : public WrappedProperty
+{
+public:
+ explicit WrappedHasMainTitleProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+};
+
+}
+
+WrappedHasMainTitleProperty::WrappedHasMainTitleProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("HasMainTitle",OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+}
+
+void WrappedHasMainTitleProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bNewValue = true;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException("Property HasMainTitle requires value of type boolean", nullptr, 0 );
+
+ try
+ {
+ if( bNewValue )
+ TitleHelper::createTitle( TitleHelper::MAIN_TITLE, "main-title", m_spChart2ModelContact->getDocumentModel(), m_spChart2ModelContact->m_xContext );
+ else
+ TitleHelper::removeTitle( TitleHelper::MAIN_TITLE, m_spChart2ModelContact->getDocumentModel() );
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+Any WrappedHasMainTitleProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ Any aRet;
+ try
+ {
+ aRet <<= TitleHelper::getTitle( TitleHelper::MAIN_TITLE, m_spChart2ModelContact->getDocumentModel() ).is();
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return aRet;
+}
+
+Any WrappedHasMainTitleProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+namespace {
+
+//PROP_DOCUMENT_HAS_SUB_TITLE
+class WrappedHasSubTitleProperty : public WrappedProperty
+{
+public:
+ explicit WrappedHasSubTitleProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+};
+
+}
+
+WrappedHasSubTitleProperty::WrappedHasSubTitleProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("HasSubTitle",OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+}
+
+void WrappedHasSubTitleProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bNewValue = true;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException("Property HasSubTitle requires value of type boolean", nullptr, 0 );
+
+ try
+ {
+ if( bNewValue )
+ TitleHelper::createTitle( TitleHelper::SUB_TITLE, "", m_spChart2ModelContact->getDocumentModel(), m_spChart2ModelContact->m_xContext );
+ else
+ TitleHelper::removeTitle( TitleHelper::SUB_TITLE, m_spChart2ModelContact->getDocumentModel() );
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+Any WrappedHasSubTitleProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ Any aRet;
+ try
+ {
+ aRet <<= TitleHelper::getTitle( TitleHelper::SUB_TITLE, m_spChart2ModelContact->getDocumentModel() ).is();
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return aRet;
+}
+
+Any WrappedHasSubTitleProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+ChartDocumentWrapper::ChartDocumentWrapper(
+ const Reference< uno::XComponentContext > & xContext ) :
+ m_spChart2ModelContact( std::make_shared<Chart2ModelContact>( xContext ) ),
+ m_bUpdateAddIn( true ),
+ m_bIsDisposed( false )
+{
+}
+
+ChartDocumentWrapper::~ChartDocumentWrapper()
+{
+ stopAllComponentListening();
+}
+
+// ____ XInterface (for new interfaces) ____
+// [-loplugin:unoaggregation]
+uno::Any SAL_CALL ChartDocumentWrapper::queryInterface( const uno::Type& aType )
+{
+ if( m_xDelegator.is())
+ // calls queryAggregation if the delegator doesn't know aType
+ return m_xDelegator->queryInterface( aType );
+ else
+ return queryAggregation( aType );
+}
+
+// ____ chart::XChartDocument (old API wrapper) ____
+Reference< drawing::XShape > SAL_CALL ChartDocumentWrapper::getTitle()
+{
+ if( !m_xTitle.is() )
+ {
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ m_xTitle = new TitleWrapper( TitleHelper::MAIN_TITLE, m_spChart2ModelContact );
+ }
+ return m_xTitle;
+}
+
+Reference< drawing::XShape > SAL_CALL ChartDocumentWrapper::getSubTitle()
+{
+ if( !m_xSubTitle.is() )
+ {
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ m_xSubTitle = new TitleWrapper( TitleHelper::SUB_TITLE, m_spChart2ModelContact );
+ }
+ return m_xSubTitle;
+}
+
+Reference< drawing::XShape > SAL_CALL ChartDocumentWrapper::getLegend()
+{
+ if( ! m_xLegend.is())
+ {
+ m_xLegend = new LegendWrapper( m_spChart2ModelContact );
+ }
+
+ return m_xLegend;
+}
+
+Reference< beans::XPropertySet > SAL_CALL ChartDocumentWrapper::getArea()
+{
+ if( ! m_xArea.is())
+ {
+ m_xArea.set( new AreaWrapper( m_spChart2ModelContact ) );
+ }
+
+ return m_xArea;
+}
+
+Reference< XDiagram > SAL_CALL ChartDocumentWrapper::getDiagram()
+{
+ if( !m_xDiagram.is() )
+ {
+ try
+ {
+ m_xDiagram = new DiagramWrapper( m_spChart2ModelContact );
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return m_xDiagram;
+}
+
+void SAL_CALL ChartDocumentWrapper::setDiagram( const Reference< XDiagram >& xDiagram )
+{
+ uno::Reference< util::XRefreshable > xAddIn( xDiagram, uno::UNO_QUERY );
+ if( xAddIn.is() )
+ {
+ setAddIn( xAddIn );
+ }
+ else if( xDiagram.is() && xDiagram != m_xDiagram )
+ {
+ // set new wrapped diagram at new chart. This requires the old
+ // diagram given as parameter to implement the new interface. If
+ // this is not possible throw an exception
+ Reference< chart2::XDiagramProvider > xNewDiaProvider( xDiagram, uno::UNO_QUERY_THROW );
+ Reference< chart2::XDiagram > xNewDia( xNewDiaProvider->getDiagram());
+
+ try
+ {
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ if( xChartDoc.is() )
+ {
+ // set the new diagram
+ xChartDoc->setFirstDiagram( xNewDia );
+ m_xDiagram = xDiagram;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+}
+
+Reference< XChartData > SAL_CALL ChartDocumentWrapper::getData()
+{
+ if( !m_xChartData.is() )
+ {
+ m_xChartData.set( new ChartDataWrapper( m_spChart2ModelContact ) );
+ }
+ //@todo: check hasInternalDataProvider also in else?
+
+ return m_xChartData;
+}
+
+void SAL_CALL ChartDocumentWrapper::attachData( const Reference< XChartData >& xNewData )
+{
+ if( !xNewData.is() )
+ return;
+
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ m_xChartData.set( new ChartDataWrapper( m_spChart2ModelContact, xNewData ) );
+}
+
+// ____ XModel ____
+sal_Bool SAL_CALL ChartDocumentWrapper::attachResource(
+ const OUString& URL,
+ const Sequence< beans::PropertyValue >& Arguments )
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ return xModel->attachResource( URL, Arguments );
+ return false;
+}
+
+OUString SAL_CALL ChartDocumentWrapper::getURL()
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ return xModel->getURL();
+ return OUString();
+}
+
+Sequence< beans::PropertyValue > SAL_CALL ChartDocumentWrapper::getArgs()
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ return xModel->getArgs();
+ return Sequence< beans::PropertyValue >();
+}
+
+void SAL_CALL ChartDocumentWrapper::connectController( const Reference< frame::XController >& Controller )
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ xModel->connectController( Controller );
+}
+
+void SAL_CALL ChartDocumentWrapper::disconnectController(
+ const Reference< frame::XController >& Controller )
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ xModel->disconnectController( Controller );
+}
+
+void SAL_CALL ChartDocumentWrapper::lockControllers()
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ xModel->lockControllers();
+}
+
+void SAL_CALL ChartDocumentWrapper::unlockControllers()
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ xModel->unlockControllers();
+}
+
+sal_Bool SAL_CALL ChartDocumentWrapper::hasControllersLocked()
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ return xModel->hasControllersLocked();
+ return false;
+}
+
+Reference< frame::XController > SAL_CALL ChartDocumentWrapper::getCurrentController()
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ return xModel->getCurrentController();
+ return nullptr;
+}
+
+void SAL_CALL ChartDocumentWrapper::setCurrentController(
+ const Reference< frame::XController >& Controller )
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ xModel->setCurrentController( Controller );
+}
+
+Reference< uno::XInterface > SAL_CALL ChartDocumentWrapper::getCurrentSelection()
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ return xModel->getCurrentSelection();
+ return nullptr;
+}
+
+// ____ XComponent ____
+void SAL_CALL ChartDocumentWrapper::dispose()
+{
+ if( m_bIsDisposed )
+ return;
+
+ m_bIsDisposed = true;
+
+ try
+ {
+ Reference< lang::XComponent > xFormerDelegator( m_xDelegator, uno::UNO_QUERY );
+ DisposeHelper::DisposeAndClear( m_xTitle );
+ DisposeHelper::DisposeAndClear( m_xSubTitle );
+ DisposeHelper::DisposeAndClear( m_xLegend );
+ DisposeHelper::DisposeAndClear( m_xChartData );
+ DisposeHelper::DisposeAndClear( m_xDiagram );
+ DisposeHelper::DisposeAndClear( m_xArea );
+ m_xChartView.clear();
+ m_xShapeFactory.clear();
+ m_xDelegator.clear();
+
+ clearWrappedPropertySet();
+ m_spChart2ModelContact->clear();
+ impl_resetAddIn();
+
+ stopAllComponentListening();
+
+ try
+ {
+ if( xFormerDelegator.is())
+ xFormerDelegator->dispose();
+ }
+ catch (const lang::DisposedException&)
+ {
+ // this is ok, don't panic
+ }
+ }
+ catch (const uno::Exception &)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ChartDocumentWrapper::impl_resetAddIn()
+{
+ Reference< util::XRefreshable > xAddIn( m_xAddIn );
+ m_xAddIn.clear();
+
+ if( !xAddIn.is() )
+ return;
+
+ try
+ {
+ //make sure that the add-in does not hold a references to us anymore:
+ Reference< lang::XComponent > xComp( xAddIn, uno::UNO_QUERY );
+ if( xComp.is())
+ xComp->dispose();
+ else
+ {
+ uno::Reference< lang::XInitialization > xInit( xAddIn, uno::UNO_QUERY );
+ if( xInit.is() )
+ {
+ uno::Any aParam;
+ uno::Reference< css::chart::XChartDocument > xDoc;
+ aParam <<= xDoc;
+ uno::Sequence< uno::Any > aSeq( &aParam, 1 );
+ xInit->initialize( aSeq );
+ }
+ }
+ }
+ catch (const uno::RuntimeException&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ChartDocumentWrapper::setBaseDiagram( const OUString& rBaseDiagram )
+{
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ m_aBaseDiagram = rBaseDiagram;
+
+ uno::Reference< XDiagram > xDiagram( ChartDocumentWrapper::createInstance( rBaseDiagram ), uno::UNO_QUERY );
+ if( xDiagram.is() )
+ setDiagram( xDiagram );
+}
+
+void ChartDocumentWrapper::setAddIn( const Reference< util::XRefreshable >& xAddIn )
+{
+ if( m_xAddIn == xAddIn )
+ return;
+
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ impl_resetAddIn();
+ m_xAddIn = xAddIn;
+ // initialize AddIn with this as chart document
+ uno::Reference< lang::XInitialization > xInit( m_xAddIn, uno::UNO_QUERY );
+ if( xInit.is() )
+ {
+ uno::Any aParam;
+ uno::Reference< XChartDocument > xDoc(this);
+ aParam <<= xDoc;
+ uno::Sequence< uno::Any > aSeq( &aParam, 1 );
+ xInit->initialize( aSeq );
+ }
+}
+
+void ChartDocumentWrapper::setUpdateAddIn( bool bUpdateAddIn )
+{
+ m_bUpdateAddIn = bUpdateAddIn;
+}
+
+Reference< drawing::XShapes > ChartDocumentWrapper::getAdditionalShapes() const
+{
+ // get additional non-chart shapes for XML export
+ uno::Reference< drawing::XShapes > xFoundShapes;
+ rtl::Reference<SvxDrawPage> xDrawPage( impl_getDrawPage() );
+
+ if( !xDrawPage.is() )
+ return xFoundShapes;
+
+ uno::Reference<drawing::XShapes> xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) );
+
+ // iterate 'flat' over all top-level objects
+ // and determine all that are no chart objects
+ std::vector< uno::Reference< drawing::XShape > > aShapeVector;
+ sal_Int32 nSubCount = xDrawPage->getCount();
+ uno::Reference< drawing::XShape > xShape;
+ for( sal_Int32 nS = 0; nS < nSubCount; nS++ )
+ {
+ if( xDrawPage->getByIndex( nS ) >>= xShape )
+ {
+ if( xShape.is() && xChartRoot!=xShape )
+ aShapeVector.push_back( xShape );
+ }
+ }
+
+ if( !aShapeVector.empty() )
+ {
+ // create a shape collection
+ xFoundShapes = drawing::ShapeCollection::create(
+ comphelper::getProcessComponentContext());
+
+ OSL_ENSURE( xFoundShapes.is(), "Couldn't create a shape collection!" );
+ if( xFoundShapes.is())
+ {
+ for (auto const& shape : aShapeVector)
+ xFoundShapes->add(shape);
+ }
+ }
+
+ return xFoundShapes;
+}
+
+void SAL_CALL ChartDocumentWrapper::addEventListener( const Reference< lang::XEventListener >& xListener )
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ xModel->addEventListener( xListener );
+}
+
+void SAL_CALL ChartDocumentWrapper::removeEventListener( const Reference< lang::XEventListener >& aListener )
+{
+ rtl::Reference< ChartModel > xModel( m_spChart2ModelContact->getDocumentModel() );
+ if( xModel.is() )
+ xModel->removeEventListener( aListener );
+}
+
+// ____ XDrawPageSupplier ____
+uno::Reference< drawing::XDrawPage > SAL_CALL ChartDocumentWrapper::getDrawPage()
+{
+ return impl_getDrawPage();
+}
+
+rtl::Reference<SvxDrawPage> ChartDocumentWrapper::impl_getDrawPage() const
+{
+ return m_spChart2ModelContact->getDrawPage();
+}
+
+namespace {
+
+uno::Reference< lang::XMultiServiceFactory > getShapeFactory(const rtl::Reference<ChartView>& xChartView)
+{
+ if( xChartView )
+ return xChartView->getDrawModelWrapper()->getShapeFactory();
+
+ return uno::Reference< lang::XMultiServiceFactory >();
+}
+
+}
+
+// ____ XMultiServiceFactory ____
+uno::Reference< uno::XInterface > SAL_CALL ChartDocumentWrapper::createInstance(
+ const OUString& aServiceSpecifier )
+{
+ uno::Reference< uno::XInterface > xResult;
+
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ if( !xChartDoc.is() )
+ return xResult;
+
+ bool bServiceFound = false;
+ tServiceNameMap & rMap = lcl_getStaticServiceNameMap();
+
+ tServiceNameMap::const_iterator aIt( rMap.find( aServiceSpecifier ));
+ if( aIt != rMap.end())
+ {
+ bool bCreateDiagram = false;
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager =
+ xChartDoc->getTypeManager();
+ rtl::Reference< ::chart::ChartTypeTemplate > xTemplate;
+
+ switch( (*aIt).second )
+ {
+ case SERVICE_NAME_AREA_DIAGRAM:
+ if( xChartTypeManager.is())
+ {
+ xTemplate =
+ xChartTypeManager->createTemplate("com.sun.star.chart2.template.Area");
+ bCreateDiagram = true;
+ }
+ break;
+ case SERVICE_NAME_BAR_DIAGRAM:
+ if( xChartTypeManager.is())
+ {
+ // this is for bar and column (the latter is the default if
+ // no "Vertical=false" property was set)
+ xTemplate =
+ xChartTypeManager->createTemplate("com.sun.star.chart2.template.Column");
+ bCreateDiagram = true;
+ }
+ break;
+ case SERVICE_NAME_DONUT_DIAGRAM:
+ if( xChartTypeManager.is())
+ {
+ xTemplate =
+ xChartTypeManager->createTemplate("com.sun.star.chart2.template.Donut");
+ bCreateDiagram = true;
+ }
+ break;
+ case SERVICE_NAME_LINE_DIAGRAM:
+ if( xChartTypeManager.is())
+ {
+ xTemplate =
+ xChartTypeManager->createTemplate("com.sun.star.chart2.template.Line");
+ bCreateDiagram = true;
+ }
+ break;
+ case SERVICE_NAME_NET_DIAGRAM:
+ if( xChartTypeManager.is())
+ {
+ xTemplate =
+ xChartTypeManager->createTemplate("com.sun.star.chart2.template.Net");
+ bCreateDiagram = true;
+ }
+ break;
+ case SERVICE_NAME_FILLED_NET_DIAGRAM:
+ if( xChartTypeManager.is())
+ {
+ xTemplate =
+ xChartTypeManager->createTemplate("com.sun.star.chart2.template.FilledNet");
+ bCreateDiagram = true;
+ }
+ break;
+ case SERVICE_NAME_PIE_DIAGRAM:
+ if( xChartTypeManager.is())
+ {
+ xTemplate =
+ xChartTypeManager->createTemplate("com.sun.star.chart2.template.Pie");
+ bCreateDiagram = true;
+ }
+ break;
+ case SERVICE_NAME_STOCK_DIAGRAM:
+ if( xChartTypeManager.is())
+ {
+ xTemplate =
+ xChartTypeManager->createTemplate("com.sun.star.chart2.template.StockLowHighClose");
+ bCreateDiagram = true;
+ }
+ break;
+ case SERVICE_NAME_XY_DIAGRAM:
+ if( xChartTypeManager.is())
+ {
+ xTemplate =
+ xChartTypeManager->createTemplate("com.sun.star.chart2.template.ScatterLineSymbol");
+ bCreateDiagram = true;
+ }
+ break;
+
+ case SERVICE_NAME_BUBBLE_DIAGRAM:
+ if( xChartTypeManager.is())
+ {
+ xTemplate =
+ xChartTypeManager->createTemplate("com.sun.star.chart2.template.Bubble");
+ bCreateDiagram = true;
+ }
+ break;
+
+ case SERVICE_NAME_DASH_TABLE:
+ case SERVICE_NAME_GRADIENT_TABLE:
+ case SERVICE_NAME_HATCH_TABLE:
+ case SERVICE_NAME_BITMAP_TABLE:
+ case SERVICE_NAME_TRANSP_GRADIENT_TABLE:
+ case SERVICE_NAME_MARKER_TABLE:
+ xResult.set( xChartDoc->createInstance( aIt->first ), uno::UNO_QUERY );
+ break;
+
+ case SERVICE_NAME_NAMESPACE_MAP:
+ break;
+ case SERVICE_NAME_EXPORT_GRAPHIC_STORAGE_RESOLVER:
+ break;
+ case SERVICE_NAME_IMPORT_GRAPHIC_STORAGE_RESOLVER:
+ break;
+ }
+
+ if( bCreateDiagram && xTemplate.is() )
+ {
+ try
+ {
+ uno::Reference< chart2::XDiagram > xDia( xChartDoc->getFirstDiagram());
+ if( xDia.is())
+ {
+ // locked controllers
+ ControllerLockGuardUNO aCtrlLockGuard( xChartDoc );
+ rtl::Reference< Diagram > xDiagram = xChartDoc->getFirstChartDiagram();
+ ThreeDLookScheme e3DScheme = xDiagram->detectScheme();
+ rtl::Reference< ::chart::ChartTypeManager > xTemplateManager = xChartDoc->getTypeManager();
+ Diagram::tTemplateWithServiceName aTemplateWithService(
+ xDiagram->getTemplate( xTemplateManager ));
+ if( aTemplateWithService.xChartTypeTemplate.is())
+ aTemplateWithService.xChartTypeTemplate->resetStyles2( xDiagram );//#i109371#
+ xTemplate->changeDiagram( xDiagram );
+ if( AllSettings::GetMathLayoutRTL() )
+ AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) );
+ xDiagram->setScheme( e3DScheme );
+ }
+ else
+ {
+ // locked controllers
+ ControllerLockGuardUNO aCtrlLockGuard( xChartDoc );
+ xDia.set( xTemplate->createDiagramByDataSource(
+ uno::Reference< chart2::data::XDataSource >(),
+ uno::Sequence< beans::PropertyValue >()));
+ xChartDoc->setFirstDiagram( xDia );
+ }
+
+ xResult = static_cast< ::cppu::OWeakObject* >( new DiagramWrapper( m_spChart2ModelContact ));
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ bServiceFound = true;
+ }
+ else if( aServiceSpecifier == "com.sun.star.comp.chart2.DataSeriesWrapper" )
+ {
+ Reference< beans::XPropertySet > xDataSeries( new DataSeriesPointWrapper( m_spChart2ModelContact ) );
+ xResult.set( xDataSeries );
+ bServiceFound = true;
+ }
+ else if( aServiceSpecifier == CHART_VIEW_SERVICE_NAME )
+ {
+ if( !m_xChartView.is() )
+ {
+ rtl::Reference<::chart::ChartModel> pChartModel = new ::chart::ChartModel(m_spChart2ModelContact->m_xContext);
+ rtl::Reference<ChartView> xChartView = new ::chart::ChartView(m_spChart2ModelContact->m_xContext, *pChartModel);
+
+ try
+ {
+ m_xChartView = xChartView;
+
+ Sequence< Any > aArguments{ Any(Reference<frame::XModel>(this)),
+ Any(true) }; // bRefreshAddIn
+ xChartView->initialize(aArguments);
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ xResult.set( static_cast<cppu::OWeakObject*>(m_xChartView.get()) );
+ bServiceFound = true;
+ }
+ else
+ {
+ // try to create a shape
+ try
+ {
+ if( !m_xShapeFactory.is() && m_xChartView.is() )
+ {
+ m_xShapeFactory = getShapeFactory( m_xChartView );
+ }
+ else
+ {
+ rtl::Reference<ChartModel> pModel = m_spChart2ModelContact->getDocumentModel();
+ if(pModel)
+ {
+ m_xChartView = pModel->getChartView();
+ m_xShapeFactory = getShapeFactory( m_xChartView );
+ }
+ }
+
+ if( m_xShapeFactory.is() )
+ {
+ xResult = m_xShapeFactory->createInstance( aServiceSpecifier );
+ bServiceFound = true;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ // couldn't create shape
+ }
+ }
+
+ // finally, try to create an addin
+ if( !bServiceFound )
+ {
+ try
+ {
+ Reference< lang::XMultiServiceFactory > xFact(
+ m_spChart2ModelContact->m_xContext->getServiceManager(), uno::UNO_QUERY_THROW );
+ uno::Reference< util::XRefreshable > xAddIn(
+ xFact->createInstance( aServiceSpecifier ), uno::UNO_QUERY );
+ if( xAddIn.is() )
+ {
+ xResult = xAddIn;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ // couldn't create service
+ }
+ }
+
+ return xResult;
+}
+
+uno::Reference< uno::XInterface > SAL_CALL ChartDocumentWrapper::createInstanceWithArguments(
+ const OUString& ServiceSpecifier,
+ const uno::Sequence< uno::Any >& Arguments )
+{
+ OSL_ENSURE( Arguments.hasElements(), "createInstanceWithArguments: Warning: Arguments are ignored" );
+
+ return createInstance( ServiceSpecifier );
+}
+
+uno::Sequence< OUString > SAL_CALL ChartDocumentWrapper::getAvailableServiceNames()
+{
+ return comphelper::mapKeysToSequence( lcl_getStaticServiceNameMap() );
+}
+
+// ____ XAggregation ____
+void SAL_CALL ChartDocumentWrapper::setDelegator(
+ const uno::Reference< uno::XInterface >& rDelegator )
+{
+ if( m_bIsDisposed )
+ {
+ if( rDelegator.is() )
+ throw lang::DisposedException("ChartDocumentWrapper is disposed",
+ static_cast< ::cppu::OWeakObject* >( this ));
+ return;
+ }
+
+ if( rDelegator.is())
+ {
+ m_xDelegator = rDelegator;
+ ChartModel* pChartModel = dynamic_cast<ChartModel*>(rDelegator.get());
+ assert(pChartModel);
+ m_spChart2ModelContact->setDocumentModel( pChartModel );
+ }
+ else
+ {
+ // this is a sort of dispose() from the new model,so release resources here
+ try
+ {
+ dispose();
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+}
+
+uno::Any SAL_CALL ChartDocumentWrapper::queryAggregation( const uno::Type& rType )
+{
+ return ChartDocumentWrapper_Base::queryInterface( rType );
+}
+
+// ____ ::utl::OEventListenerAdapter ____
+void ChartDocumentWrapper::_disposing( const lang::EventObject& rSource )
+{
+ if( rSource.Source == m_xTitle )
+ m_xTitle.clear();
+ else if( rSource.Source == m_xSubTitle )
+ m_xSubTitle.clear();
+ else if( rSource.Source == m_xLegend )
+ m_xLegend.clear();
+ else if( rSource.Source == m_xChartData )
+ m_xChartData.clear();
+ else if( rSource.Source == m_xDiagram )
+ m_xDiagram.clear();
+ else if( rSource.Source == m_xArea )
+ m_xArea.clear();
+ else if( rSource.Source == m_xAddIn )
+ m_xAddIn.clear();
+ else if( rSource.Source == static_cast<cppu::OWeakObject*>(m_xChartView.get()) )
+ m_xChartView.clear();
+}
+
+// ____ XPropertySet ____
+void SAL_CALL ChartDocumentWrapper::setPropertyValue(const OUString& rPropertyName, const css::uno::Any& rValue)
+{
+ if (rPropertyName == u"ODFImport_UpdateView")
+ {
+ // A hack used at load time to notify the view that it needs an update
+ // See SchXMLImport::~SchXMLImport
+ if (auto xChartModel = rValue.query<css::chart2::XChartDocument>())
+ ChartViewHelper::setViewToDirtyState_UNO(xChartModel);
+ return;
+ }
+ ChartDocumentWrapper_Base::setPropertyValue(rPropertyName, rValue);
+}
+
+// WrappedPropertySet
+Reference< beans::XPropertySet > ChartDocumentWrapper::getInnerPropertySet()
+{
+ return nullptr;
+}
+const Sequence< beans::Property >& ChartDocumentWrapper::getPropertySequence()
+{
+ return StaticChartDocumentWrapperPropertyArray();
+}
+
+std::vector< std::unique_ptr<WrappedProperty> > ChartDocumentWrapper::createWrappedProperties()
+{
+ std::vector< std::unique_ptr<WrappedProperty> > aWrappedProperties;
+ aWrappedProperties.emplace_back( new WrappedDataSourceLabelsInFirstRowProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedDataSourceLabelsInFirstColumnProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedHasLegendProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedHasMainTitleProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedHasSubTitleProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedAddInProperty( *this ) );
+ aWrappedProperties.emplace_back( new WrappedBaseDiagramProperty( *this ) );
+ aWrappedProperties.emplace_back( new WrappedAdditionalShapesProperty( *this ) );
+ aWrappedProperties.emplace_back( new WrappedRefreshAddInAllowedProperty( *this ) );
+ aWrappedProperties.emplace_back( new WrappedIgnoreProperty("NullDate",Any() ) ); // i99104
+ aWrappedProperties.emplace_back( new WrappedIgnoreProperty("EnableComplexChartTypes", uno::Any(true) ) );
+ aWrappedProperties.emplace_back( new WrappedIgnoreProperty("EnableDataTableDialog", uno::Any(true) ) );
+
+ return aWrappedProperties;
+}
+
+OUString SAL_CALL ChartDocumentWrapper::getImplementationName()
+{
+ return CHART_CHARTAPIWRAPPER_IMPLEMENTATION_NAME;
+}
+
+sal_Bool SAL_CALL ChartDocumentWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ChartDocumentWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart.ChartDocument",
+ CHART_CHARTAPIWRAPPER_SERVICE_NAME,
+ "com.sun.star.xml.UserDefinedAttributesSupplier",
+ "com.sun.star.beans.PropertySet"
+ };
+}
+
+} // namespace chart::wrapper
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_ChartDocumentWrapper_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::wrapper::ChartDocumentWrapper(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx b/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx
new file mode 100644
index 0000000000..ac9a53ce33
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx
@@ -0,0 +1,890 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DataSeriesPointWrapper.hxx"
+#include "Chart2ModelContact.hxx"
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesProperties.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <CharacterProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include "WrappedCharacterHeightProperty.hxx"
+#include <WrappedProperty.hxx>
+#include <WrappedIgnoreProperty.hxx>
+#include "WrappedStatisticProperties.hxx"
+#include "WrappedSymbolProperties.hxx"
+#include "WrappedDataCaptionProperties.hxx"
+#include "WrappedSeriesAreaOrLineProperty.hxx"
+#include "WrappedScaleTextProperties.hxx"
+#include "WrappedNumberFormatProperty.hxx"
+#include "WrappedTextRotationProperty.hxx"
+#include <unonames.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <rtl/math.hxx>
+
+#include <algorithm>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart/ChartAxisAssign.hpp>
+#include <com/sun/star/chart/ChartErrorCategory.hpp>
+#include <com/sun/star/chart/ChartSymbolType.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::chart::wrapper;
+using namespace ::chart::DataSeriesProperties;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Any;
+
+namespace
+{
+
+enum
+{
+ //data point properties
+ PROP_SERIES_DATAPOINT_SOLIDTYPE,
+ PROP_SERIES_DATAPOINT_SEGMENT_OFFSET,
+ PROP_SERIES_DATAPOINT_PERCENT_DIAGONAL,
+ PROP_SERIES_DATAPOINT_LABEL_SEPARATOR,
+ PROP_SERIES_NUMBERFORMAT,
+ PROP_SERIES_LINK_NUMBERFORMAT_TO_SOURCE,
+ PROP_SERIES_PERCENTAGE_NUMBERFORMAT,
+ PROP_SERIES_DATAPOINT_TEXT_WORD_WRAP,
+ PROP_SERIES_DATAPOINT_LABEL_PLACEMENT,
+ //other series properties
+ PROP_SERIES_ATTACHED_AXIS,
+ PROP_SERIES_SHOW_CUSTOM_LEADERLINES,
+ PROP_SERIES_DATAPOINT_TEXT_ROTATION,
+ PROP_SERIES_DATAPOINT_LABEL_BORDER_STYLE,
+ PROP_SERIES_DATAPOINT_LABEL_BORDER_WIDTH,
+ PROP_SERIES_DATAPOINT_LABEL_BORDER_COLOR,
+ PROP_SERIES_DATAPOINT_LABEL_BORDER_TRANS,
+ PROP_SERIES_DATAPOINT_LABEL_FILL_STYLE,
+ PROP_SERIES_DATAPOINT_LABEL_FILL_COLOR,
+ PROP_SERIES_DATAPOINT_LABEL_FILL_BACKGROUND,
+ PROP_SERIES_DATAPOINT_LABEL_FILL_HATCH_NAME
+};
+
+void lcl_AddPropertiesToVector_PointProperties(
+ std::vector< Property > & rOutProperties )
+{
+ //service chart::Chart3DBarProperties
+ rOutProperties.emplace_back( "SolidType",
+ PROP_SERIES_DATAPOINT_SOLIDTYPE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "SegmentOffset",
+ PROP_SERIES_DATAPOINT_SEGMENT_OFFSET,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "D3DPercentDiagonal",
+ PROP_SERIES_DATAPOINT_PERCENT_DIAGONAL,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "LabelSeparator",
+ PROP_SERIES_DATAPOINT_LABEL_SEPARATOR,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_NUMFMT,
+ PROP_SERIES_NUMBERFORMAT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LINK_TO_SRC_NUMFMT,
+ PROP_SERIES_LINK_NUMBERFORMAT_TO_SOURCE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "PercentageNumberFormat",
+ PROP_SERIES_PERCENTAGE_NUMBERFORMAT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "TextWordWrap",
+ PROP_SERIES_DATAPOINT_TEXT_WORD_WRAP,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "LabelPlacement",
+ PROP_SERIES_DATAPOINT_LABEL_PLACEMENT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "TextRotation",
+ PROP_SERIES_DATAPOINT_TEXT_ROTATION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_STYLE,
+ PROP_SERIES_DATAPOINT_LABEL_BORDER_STYLE,
+ cppu::UnoType<drawing::LineStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_STYLE,
+ PROP_SERIES_DATAPOINT_LABEL_FILL_STYLE,
+ cppu::UnoType<drawing::FillStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_COLOR,
+ PROP_SERIES_DATAPOINT_LABEL_FILL_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_BACKGROUND,
+ PROP_SERIES_DATAPOINT_LABEL_FILL_BACKGROUND,
+ cppu::UnoType<sal_Bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_HATCH_NAME,
+ PROP_SERIES_DATAPOINT_LABEL_FILL_HATCH_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_WIDTH,
+ PROP_SERIES_DATAPOINT_LABEL_BORDER_WIDTH,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_COLOR,
+ PROP_SERIES_DATAPOINT_LABEL_BORDER_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID // "maybe auto"
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_TRANS,
+ PROP_SERIES_DATAPOINT_LABEL_BORDER_TRANS,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+void lcl_AddPropertiesToVector_SeriesOnly(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "Axis",
+ PROP_SERIES_ATTACHED_AXIS,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ShowCustomLeaderLines",
+ PROP_SERIES_SHOW_CUSTOM_LEADERLINES,
+ cppu::UnoType<sal_Bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+uno::Sequence< Property > lcl_GetPropertySequence( DataSeriesPointWrapper::eType _eType )
+{
+ std::vector< css::beans::Property > aProperties;
+
+ lcl_AddPropertiesToVector_PointProperties( aProperties );
+ if( _eType == DataSeriesPointWrapper::DATA_SERIES )
+ {
+ lcl_AddPropertiesToVector_SeriesOnly( aProperties );
+ WrappedStatisticProperties::addProperties( aProperties );
+ }
+ WrappedSymbolProperties::addProperties( aProperties ); //for series and points
+ WrappedDataCaptionProperties::addProperties( aProperties ); //for series and points
+
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+ ::chart::wrapper::WrappedScaleTextProperties::addProperties( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+}
+
+const Sequence< Property >& StaticSeriesWrapperPropertyArray()
+{
+ static Sequence< Property > aPropSeq( lcl_GetPropertySequence( DataSeriesPointWrapper::DATA_SERIES ) );
+ return aPropSeq;
+};
+
+const Sequence< Property >& StaticPointWrapperPropertyArray()
+{
+ static Sequence< Property > aPropSeq( lcl_GetPropertySequence( DataSeriesPointWrapper::DATA_POINT ) );
+ return aPropSeq;
+};
+
+//PROP_SERIES_ATTACHED_AXIS
+class WrappedAttachedAxisProperty : public ::chart::WrappedProperty
+{
+public:
+ explicit WrappedAttachedAxisProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact);
+
+ virtual void setPropertyValue( const Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+protected:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+};
+
+WrappedAttachedAxisProperty::WrappedAttachedAxisProperty(
+ const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact )
+ : WrappedProperty("Axis",OUString())
+ , m_spChart2ModelContact( spChart2ModelContact )
+{
+}
+
+Any WrappedAttachedAxisProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= css::chart::ChartAxisAssign::PRIMARY_Y;
+ return aRet;
+}
+
+Any WrappedAttachedAxisProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Any aRet;
+
+ rtl::Reference< ::chart::DataSeries > xDataSeries( dynamic_cast<::chart::DataSeries*>(xInnerPropertySet.get()) );
+ bool bAttachedToMainAxis = ::chart::DiagramHelper::isSeriesAttachedToMainAxis( xDataSeries );
+ if( bAttachedToMainAxis )
+ aRet <<= css::chart::ChartAxisAssign::PRIMARY_Y;
+ else
+ aRet <<= css::chart::ChartAxisAssign::SECONDARY_Y;
+ return aRet;
+}
+
+void WrappedAttachedAxisProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ rtl::Reference< ::chart::DataSeries > xDataSeries( dynamic_cast<::chart::DataSeries*>(xInnerPropertySet.get()) );
+
+ sal_Int32 nChartAxisAssign = css::chart::ChartAxisAssign::PRIMARY_Y;
+ if( ! (rOuterValue >>= nChartAxisAssign) )
+ throw lang::IllegalArgumentException("Property Axis requires value of type sal_Int32", nullptr, 0 );
+
+ bool bNewAttachedToMainAxis = nChartAxisAssign == css::chart::ChartAxisAssign::PRIMARY_Y;
+ bool bOldAttachedToMainAxis = ::chart::DiagramHelper::isSeriesAttachedToMainAxis( xDataSeries );
+
+ if( bNewAttachedToMainAxis != bOldAttachedToMainAxis)
+ {
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() )
+ xDiagram->attachSeriesToAxis( bNewAttachedToMainAxis, xDataSeries, m_spChart2ModelContact->m_xContext, false );
+ }
+}
+
+class WrappedSegmentOffsetProperty : public ::chart::WrappedProperty
+{
+public:
+ WrappedSegmentOffsetProperty();
+
+protected:
+ virtual Any convertInnerToOuterValue( const Any& rInnerValue ) const override;
+ virtual Any convertOuterToInnerValue( const Any& rOuterValue ) const override;
+};
+
+WrappedSegmentOffsetProperty::WrappedSegmentOffsetProperty() :
+ WrappedProperty("SegmentOffset","Offset")
+{}
+
+Any WrappedSegmentOffsetProperty::convertInnerToOuterValue( const Any& rInnerValue ) const
+{
+ // convert new double offset to former integer segment-offset
+ double fOffset = 0;
+ Any aResult( rInnerValue );
+
+ if( rInnerValue >>= fOffset )
+ aResult <<= static_cast< sal_Int32 >( ::rtl::math::round( fOffset * 100.0 ));
+
+ return aResult;
+}
+
+Any WrappedSegmentOffsetProperty::convertOuterToInnerValue( const Any& rOuterValue ) const
+{
+ // convert former integer segment-offset to new double offset
+ sal_Int32 nOffset = 0;
+ Any aResult( rOuterValue );
+
+ if( rOuterValue >>= nOffset )
+ aResult <<= static_cast< double >( nOffset ) / 100.0;
+
+ return aResult;
+}
+
+class WrappedLineColorProperty : public WrappedSeriesAreaOrLineProperty
+{
+public:
+ explicit WrappedLineColorProperty( DataSeriesPointWrapper* pDataSeriesPointWrapper );
+
+ virtual void setPropertyValue( const Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual void setPropertyToDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+protected:
+ DataSeriesPointWrapper* m_pDataSeriesPointWrapper;
+ mutable Any m_aDefaultValue;
+};
+
+WrappedLineColorProperty::WrappedLineColorProperty(
+ DataSeriesPointWrapper* pDataSeriesPointWrapper )
+ : WrappedSeriesAreaOrLineProperty("LineColor","BorderColor","Color", pDataSeriesPointWrapper )
+ , m_pDataSeriesPointWrapper( pDataSeriesPointWrapper )
+ , m_aDefaultValue(uno::Any(sal_Int32( 0x0099ccff ))) // blue 8
+{
+}
+
+void WrappedLineColorProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if( !m_pDataSeriesPointWrapper || !m_pDataSeriesPointWrapper->isLinesForbidden() )
+ WrappedSeriesAreaOrLineProperty::setPropertyValue( rOuterValue, xInnerPropertySet );
+}
+
+void WrappedLineColorProperty::setPropertyToDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ if( !m_pDataSeriesPointWrapper || !m_pDataSeriesPointWrapper->isLinesForbidden() )
+ WrappedSeriesAreaOrLineProperty::setPropertyToDefault( xInnerPropertyState );
+}
+
+Any WrappedLineColorProperty::getPropertyDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ if( m_pDataSeriesPointWrapper && !m_pDataSeriesPointWrapper->isSupportingAreaProperties() )
+ return m_aDefaultValue;
+ else
+ return WrappedSeriesAreaOrLineProperty::getPropertyDefault( xInnerPropertyState );
+}
+
+class WrappedLineStyleProperty : public WrappedSeriesAreaOrLineProperty
+{
+public:
+ explicit WrappedLineStyleProperty( DataSeriesPointWrapper* pDataSeriesPointWrapper );
+
+ virtual void setPropertyValue( const Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual void setPropertyToDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+protected:
+ DataSeriesPointWrapper* m_pDataSeriesPointWrapper;
+};
+
+WrappedLineStyleProperty::WrappedLineStyleProperty(
+ DataSeriesPointWrapper* pDataSeriesPointWrapper )
+ : WrappedSeriesAreaOrLineProperty("LineStyle","BorderStyle", "LineStyle", pDataSeriesPointWrapper )
+ , m_pDataSeriesPointWrapper( pDataSeriesPointWrapper )
+{
+}
+
+void WrappedLineStyleProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Any aNewValue(rOuterValue);
+ if( m_pDataSeriesPointWrapper && m_pDataSeriesPointWrapper->isLinesForbidden() )
+ {
+ aNewValue <<= drawing::LineStyle_NONE;
+ }
+ WrappedSeriesAreaOrLineProperty::setPropertyValue( aNewValue, xInnerPropertySet );
+}
+
+void WrappedLineStyleProperty::setPropertyToDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ if( !m_pDataSeriesPointWrapper || !m_pDataSeriesPointWrapper->isLinesForbidden() )
+ WrappedSeriesAreaOrLineProperty::setPropertyToDefault( xInnerPropertyState );
+}
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+DataSeriesPointWrapper::DataSeriesPointWrapper( std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : m_spChart2ModelContact( std::move(spChart2ModelContact) )
+ , m_eType( DATA_SERIES )
+ , m_nSeriesIndexInNewAPI( -1 )
+ , m_nPointIndex( -1 )
+ , m_bLinesAllowed(true)
+{
+ //need initialize call afterwards
+}
+
+void SAL_CALL DataSeriesPointWrapper::initialize( const uno::Sequence< uno::Any >& aArguments )
+{
+ OSL_PRECOND(aArguments.hasElements(),"need at least 1 argument to initialize the DataSeriesPointWrapper: series reference + optional datapoint index");
+
+ m_nSeriesIndexInNewAPI = -1;//ignored in this case
+ m_nPointIndex = -1;
+ if( aArguments.hasElements() )
+ {
+ uno::Reference<chart2::XDataSeries> xTmp;
+ aArguments[0] >>= xTmp;
+ auto p = dynamic_cast<DataSeries*>(xTmp.get());
+ assert(p);
+ m_xDataSeries = p;
+ if( aArguments.getLength() >= 2 )
+ aArguments[1] >>= m_nPointIndex;
+ }
+
+ if( !m_xDataSeries.is() )
+ throw uno::Exception(
+ "DataSeries index invalid", static_cast< ::cppu::OWeakObject * >( this ));
+
+ //todo: check upper border of point index
+
+ if( m_nPointIndex >= 0 )
+ m_eType = DATA_POINT;
+ else
+ m_eType = DATA_SERIES;
+}
+
+DataSeriesPointWrapper::DataSeriesPointWrapper(eType _eType,
+ sal_Int32 nSeriesIndexInNewAPI ,
+ sal_Int32 nPointIndex, //ignored for series
+ std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : m_spChart2ModelContact( std::move(spChart2ModelContact) )
+ , m_eType( _eType )
+ , m_nSeriesIndexInNewAPI( nSeriesIndexInNewAPI )
+ , m_nPointIndex( (_eType == DATA_POINT) ? nPointIndex : -1 )
+ , m_bLinesAllowed( false )
+{
+}
+
+DataSeriesPointWrapper::~DataSeriesPointWrapper()
+{
+}
+
+// ____ XComponent ____
+void SAL_CALL DataSeriesPointWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ uno::Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( xSource ) );
+
+ m_xDataSeries.clear();
+ clearWrappedPropertySet();
+}
+
+void SAL_CALL DataSeriesPointWrapper::addEventListener(
+ const uno::Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL DataSeriesPointWrapper::removeEventListener(
+ const uno::Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+// ____ XEventListener ____
+void SAL_CALL DataSeriesPointWrapper::disposing( const lang::EventObject& /*Source*/ )
+{
+}
+
+bool DataSeriesPointWrapper::isSupportingAreaProperties()
+{
+ rtl::Reference< DataSeries > xSeries( getDataSeries() );
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ rtl::Reference< ::chart::ChartType > xChartType( xDiagram->getChartTypeOfSeries( xSeries ) );
+ sal_Int32 nDimensionCount = xDiagram->getDimension();
+
+ return ChartTypeHelper::isSupportingAreaProperties( xChartType, nDimensionCount );
+}
+
+rtl::Reference< DataSeries > DataSeriesPointWrapper::getDataSeries()
+{
+ rtl::Reference< DataSeries > xSeries = m_xDataSeries;
+ if( !xSeries.is() )
+ {
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ std::vector< rtl::Reference< DataSeries > > aSeriesList =
+ xDiagram->getDataSeries();
+
+ if( m_nSeriesIndexInNewAPI >= 0 && o3tl::make_unsigned(m_nSeriesIndexInNewAPI) < aSeriesList.size() )
+ xSeries = aSeriesList[m_nSeriesIndexInNewAPI];
+ }
+
+ return xSeries;
+}
+
+Reference< beans::XPropertySet > DataSeriesPointWrapper::getDataPointProperties()
+{
+ Reference< beans::XPropertySet > xPointProp;
+
+ rtl::Reference< DataSeries > xSeries( getDataSeries() );
+
+ // may throw an IllegalArgumentException
+ if( xSeries.is() )
+ xPointProp = xSeries->getDataPointByIndex( m_nPointIndex );
+
+ return xPointProp;
+}
+
+//ReferenceSizePropertyProvider
+void DataSeriesPointWrapper::updateReferenceSize()
+{
+ Reference< beans::XPropertySet > xProp = getInnerPropertySet();
+ if( xProp.is() )
+ {
+ if( xProp->getPropertyValue("ReferencePageSize").hasValue() )
+ xProp->setPropertyValue("ReferencePageSize", uno::Any(
+ m_spChart2ModelContact->GetPageSize() ));
+ }
+}
+Any DataSeriesPointWrapper::getReferenceSize()
+{
+ Any aRet;
+ Reference< beans::XPropertySet > xProp = getInnerPropertySet();
+ if( xProp.is() )
+ aRet = xProp->getPropertyValue("ReferencePageSize");
+ return aRet;
+}
+awt::Size DataSeriesPointWrapper::getCurrentSizeForReference()
+{
+ return m_spChart2ModelContact->GetPageSize();
+}
+
+// WrappedPropertySet
+
+//XPropertyState
+beans::PropertyState SAL_CALL DataSeriesPointWrapper::getPropertyState( const OUString& rPropertyName )
+{
+ beans::PropertyState aState( beans::PropertyState_DIRECT_VALUE );
+ try
+ {
+ if (rPropertyName == "SymbolBitmap" || rPropertyName == "SymbolBitmapURL")
+ {
+ uno::Any aAny = WrappedPropertySet::getPropertyValue("SymbolType");
+ sal_Int32 nVal = css::chart::ChartSymbolType::NONE;
+ if (aAny >>= nVal)
+ {
+ if (nVal != css::chart::ChartSymbolType::BITMAPURL)
+ return beans::PropertyState::PropertyState_DEFAULT_VALUE;
+ }
+ }
+
+ if( m_eType == DATA_SERIES )
+ aState = WrappedPropertySet::getPropertyState( rPropertyName );
+ else
+ {
+ if( rPropertyName == "FillColor")
+ {
+ rtl::Reference< DataSeries > xSeries = getDataSeries();
+ bool bVaryColorsByPoint = false;
+ // "VaryColorsByPoint"
+ if( xSeries.is() && (xSeries->getFastPropertyValue(PROP_DATASERIES_VARY_COLORS_BY_POINT) >>= bVaryColorsByPoint)
+ && bVaryColorsByPoint )
+ return beans::PropertyState_DIRECT_VALUE;
+ }
+ else if( rPropertyName == "Lines"
+ || rPropertyName == "SymbolType"
+ || rPropertyName == "SymbolSize" )
+ return WrappedPropertySet::getPropertyState( rPropertyName );
+
+ uno::Any aDefault( getPropertyDefault( rPropertyName ) );
+ uno::Any aValue( getPropertyValue( rPropertyName ) );
+ if( aDefault==aValue )
+ aState = beans::PropertyState_DEFAULT_VALUE;
+ }
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ throw;
+ }
+ catch( const uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( const lang::WrappedTargetException& e )
+ {
+ css::uno::Any a(e.TargetException);
+ throw css::lang::WrappedTargetRuntimeException(
+ "wrapped Exception " + e.Message,
+ css::uno::Reference<css::uno::XInterface>(), a);
+ }
+ catch( const uno::Exception& e )
+ {
+ css::uno::Any a(cppu::getCaughtException());
+ throw css::lang::WrappedTargetRuntimeException(
+ "wrapped Exception " + e.Message,
+ css::uno::Reference<css::uno::XInterface>(), a);
+ }
+ return aState;
+}
+
+void SAL_CALL DataSeriesPointWrapper::setPropertyToDefault( const OUString& rPropertyName )
+{
+ if( m_eType == DATA_SERIES )
+ WrappedPropertySet::setPropertyToDefault( rPropertyName );
+ else
+ {
+ //for data points the default is given by the series
+ setPropertyValue( rPropertyName, getPropertyDefault( rPropertyName ) );
+ }
+}
+Any SAL_CALL DataSeriesPointWrapper::getPropertyDefault( const OUString& rPropertyName )
+{
+ Any aRet;
+ try
+ {
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ if( nHandle > 0 )
+ {
+ //always take the series current value as default for points
+ rtl::Reference< DataSeries > xInnerPropertySet = getDataSeries();
+ if( xInnerPropertySet.is() )
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName );
+ if( pWrappedProperty )
+ aRet = pWrappedProperty->getPropertyValue(xInnerPropertySet);
+ else
+ aRet = xInnerPropertySet->getPropertyValue( rPropertyName );
+ }
+ }
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ aRet = WrappedPropertySet::getPropertyDefault( rPropertyName );
+ }
+ return aRet;
+}
+
+Reference< beans::XPropertySet > DataSeriesPointWrapper::getInnerPropertySet()
+{
+ if( m_eType == DATA_SERIES )
+ return getDataSeries();
+ return getDataPointProperties();
+}
+
+const Sequence< beans::Property >& DataSeriesPointWrapper::getPropertySequence()
+{
+ if( m_eType == DATA_SERIES )
+ return StaticSeriesWrapperPropertyArray();
+ else
+ return StaticPointWrapperPropertyArray();
+}
+
+std::vector< std::unique_ptr<WrappedProperty> > DataSeriesPointWrapper::createWrappedProperties()
+{
+ std::vector< std::unique_ptr<WrappedProperty> > aWrappedProperties;
+
+ WrappedCharacterHeightProperty::addWrappedProperties( aWrappedProperties, this );
+
+ if( m_eType == DATA_SERIES )
+ {
+ WrappedStatisticProperties::addWrappedPropertiesForSeries( aWrappedProperties, m_spChart2ModelContact );
+ aWrappedProperties.emplace_back( new WrappedAttachedAxisProperty( m_spChart2ModelContact ) );
+
+ aWrappedProperties.emplace_back( new WrappedNumberFormatProperty(m_spChart2ModelContact) );
+ aWrappedProperties.emplace_back( new WrappedLinkNumberFormatProperty );
+ }
+
+ WrappedSymbolProperties::addWrappedPropertiesForSeries( aWrappedProperties, m_spChart2ModelContact );
+ WrappedDataCaptionProperties::addWrappedPropertiesForSeries( aWrappedProperties, m_spChart2ModelContact );
+ WrappedScaleTextProperties::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+
+ //add unnamed line properties (different inner names here)
+
+ aWrappedProperties.emplace_back( new WrappedProperty("FillColor","Color") );
+ aWrappedProperties.emplace_back( new WrappedLineStyleProperty( this ) );
+ aWrappedProperties.emplace_back( new WrappedLineColorProperty( this ) );
+ aWrappedProperties.emplace_back( new WrappedSeriesAreaOrLineProperty("LineDashName","BorderDashName","LineDashName", this ) );
+ aWrappedProperties.emplace_back( new WrappedSeriesAreaOrLineProperty("LineTransparence","BorderTransparency","Transparency", this ) );
+ aWrappedProperties.emplace_back( new WrappedSeriesAreaOrLineProperty("LineWidth","BorderWidth","LineWidth", this ) );
+ aWrappedProperties.emplace_back( new WrappedSeriesAreaOrLineProperty("LineCap","LineCap","LineCap", this ) );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillStyle","FillStyle" ) );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillTransparence","Transparency") );
+
+ aWrappedProperties.emplace_back( new WrappedIgnoreProperty("LineJoint", uno::Any( drawing::LineJoint_ROUND ) ) );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillTransparenceGradientName","TransparencyGradientName") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillGradientName","GradientName") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillGradientStepCount","GradientStepCount") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillHatchName","HatchName") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBitmapName","FillBitmapName") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBackground","FillBackground") );
+
+ //bitmap properties
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBitmapMode","FillBitmapMode") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBitmapSizeX","FillBitmapSizeX") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBitmapSizeY","FillBitmapSizeY") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBitmapLogicalSize","FillBitmapLogicalSize") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBitmapOffsetX","FillBitmapOffsetX") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBitmapOffsetY","FillBitmapOffsetY") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBitmapRectanglePoint","FillBitmapRectanglePoint") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBitmapPositionOffsetX","FillBitmapPositionOffsetX") );
+ aWrappedProperties.emplace_back( new WrappedProperty("FillBitmapPositionOffsetY","FillBitmapPositionOffsetY") );
+
+ aWrappedProperties.emplace_back( new WrappedProperty("SolidType","Geometry3D") );
+ aWrappedProperties.emplace_back( new WrappedSegmentOffsetProperty() );
+ aWrappedProperties.emplace_back( new WrappedProperty("D3DPercentDiagonal","PercentDiagonal") );
+
+ aWrappedProperties.emplace_back( new WrappedTextRotationProperty() );
+
+ return aWrappedProperties;
+}
+
+void SAL_CALL DataSeriesPointWrapper::setPropertyValue( const OUString& rPropertyName, const Any& rValue )
+{
+ if(rPropertyName == "Lines")
+ {
+ if( ! (rValue >>= m_bLinesAllowed) )
+ throw lang::IllegalArgumentException("Property Lines requires value of type sal_Bool", nullptr, 0 );
+ }
+
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ static const sal_Int32 nErrorCategoryHandle = getInfoHelper().getHandleByName("ErrorCategory");
+ if( nErrorCategoryHandle == nHandle )
+ {
+ css::chart::ChartErrorCategory aNewValue = css::chart::ChartErrorCategory_NONE;
+ rValue >>= aNewValue;
+ Any aLow, aHigh;
+ bool bSetHighAndLowValues = false;
+ switch(aNewValue)
+ {
+ case css::chart::ChartErrorCategory_CONSTANT_VALUE:
+ aHigh = getPropertyValue("ConstantErrorHigh");
+ aLow = getPropertyValue("ConstantErrorLow");
+ bSetHighAndLowValues = true;
+ break;
+ case css::chart::ChartErrorCategory_PERCENT:
+ aHigh = aLow = getPropertyValue("PercentageError");
+ bSetHighAndLowValues = true;
+ break;
+ case css::chart::ChartErrorCategory_ERROR_MARGIN:
+ aHigh = aLow = getPropertyValue("ErrorMargin");
+ bSetHighAndLowValues = true;
+ break;
+ default:
+ break;
+ }
+
+ WrappedPropertySet::setPropertyValue( rPropertyName, rValue );
+
+ if(bSetHighAndLowValues)
+ {
+ switch(aNewValue)
+ {
+ case css::chart::ChartErrorCategory_CONSTANT_VALUE:
+ setPropertyValue("ConstantErrorHigh",aHigh);
+ setPropertyValue("ConstantErrorLow",aLow);
+ break;
+ case css::chart::ChartErrorCategory_PERCENT:
+ setPropertyValue("PercentageError",aHigh);
+ break;
+ case css::chart::ChartErrorCategory_ERROR_MARGIN:
+ setPropertyValue("ErrorMargin",aHigh);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ WrappedPropertySet::setPropertyValue( rPropertyName, rValue );
+}
+
+Any SAL_CALL DataSeriesPointWrapper::getPropertyValue( const OUString& rPropertyName )
+{
+ if( m_eType == DATA_POINT )
+ {
+ if( rPropertyName == "FillColor" )
+ {
+ rtl::Reference< DataSeries > xSeries = getDataSeries();
+ bool bVaryColorsByPoint = false;
+ // "VaryColorsByPoint"
+ if( xSeries.is() && (xSeries->getFastPropertyValue(PROP_DATASERIES_VARY_COLORS_BY_POINT) >>= bVaryColorsByPoint)
+ && bVaryColorsByPoint )
+ {
+ uno::Reference< beans::XPropertyState > xPointState( DataSeriesPointWrapper::getDataPointProperties(), uno::UNO_QUERY );
+ if( xPointState.is() && xPointState->getPropertyState("Color") == beans::PropertyState_DEFAULT_VALUE )
+ {
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() )
+ {
+ Reference< chart2::XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme() );
+ if( xColorScheme.is() )
+ return uno::Any( xColorScheme->getColorByIndex( m_nPointIndex ) );
+ }
+ }
+ }
+ }
+ }
+ return WrappedPropertySet::getPropertyValue( rPropertyName );
+}
+
+OUString SAL_CALL DataSeriesPointWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.DataSeries";
+}
+
+sal_Bool SAL_CALL DataSeriesPointWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL DataSeriesPointWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart.ChartDataRowProperties",
+ "com.sun.star.chart.ChartDataPointProperties",
+ "com.sun.star.xml.UserDefinedAttributesSupplier",
+ "com.sun.star.beans.PropertySet",
+ "com.sun.star.drawing.FillProperties",
+ "com.sun.star.drawing.LineProperties",
+ "com.sun.star.style.CharacterProperties"
+ };
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.hxx b/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.hxx
new file mode 100644
index 0000000000..4c79bb25e9
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.hxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedPropertySet.hxx>
+#include "ReferenceSizePropertyProvider.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <rtl/ref.hxx>
+#include <memory>
+
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace chart { class DataSeries; }
+
+namespace chart::wrapper
+{
+
+class Chart2ModelContact;
+
+class DataSeriesPointWrapper final : public ::cppu::ImplInheritanceHelper<
+ WrappedPropertySet
+ , css::lang::XServiceInfo
+ , css::lang::XInitialization
+ , css::lang::XComponent
+ , css::lang::XEventListener
+ >
+ , public ReferenceSizePropertyProvider
+
+{
+public:
+ enum eType
+ {
+ DATA_SERIES,
+ DATA_POINT
+ };
+
+ //this constructor needs an initialize call afterwards
+ explicit DataSeriesPointWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ DataSeriesPointWrapper(eType eType
+ , sal_Int32 nSeriesIndexInNewAPI
+ , sal_Int32 nPointIndex //ignored for series
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual ~DataSeriesPointWrapper() override;
+
+ bool isSupportingAreaProperties();
+ bool isLinesForbidden() const { return !m_bLinesAllowed;}
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ___lang::XInitialization___
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ //ReferenceSizePropertyProvider
+ virtual void updateReferenceSize() override;
+ virtual css::uno::Any getReferenceSize() override;
+ virtual css::awt::Size getCurrentSizeForReference() override;
+
+private:
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+
+ // ____ XEventListener ____
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // ____ WrappedPropertySet ____
+ virtual const css::uno::Sequence< css::beans::Property >& getPropertySequence() override;
+ virtual std::vector< std::unique_ptr<WrappedProperty> > createWrappedProperties() override;
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+ virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override;
+
+ virtual css::beans::PropertyState SAL_CALL getPropertyState( const OUString& PropertyName ) override;
+ virtual void SAL_CALL setPropertyToDefault( const OUString& PropertyName ) override;
+ virtual css::uno::Any SAL_CALL getPropertyDefault( const OUString& aPropertyName ) override;
+
+ //own methods
+ rtl::Reference< ::chart::DataSeries > getDataSeries();
+ css::uno::Reference< css::beans::XPropertySet > getDataPointProperties();
+
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+
+ eType m_eType;
+ sal_Int32 m_nSeriesIndexInNewAPI;
+ sal_Int32 m_nPointIndex;
+
+ bool m_bLinesAllowed;
+
+ //this should only be used, if the DataSeriesPointWrapper is initialized via the XInitialize interface
+ //because a big change in the chartmodel may lead to a dataseriespointer that is not connected to the model anymore
+ //with the indices instead we can always get the new dataseries
+ rtl::Reference< ::chart::DataSeries > m_xDataSeries;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx b/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx
new file mode 100644
index 0000000000..711d3017a8
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx
@@ -0,0 +1,1898 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DiagramWrapper.hxx"
+#include <servicenames_charttypes.hxx>
+#include "DataSeriesPointWrapper.hxx"
+#include <DataSeriesProperties.hxx>
+#include "AxisWrapper.hxx"
+#include "Chart2ModelContact.hxx"
+#include "WallFloorWrapper.hxx"
+#include "MinMaxLineWrapper.hxx"
+#include "UpDownBarWrapper.hxx"
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <DataSourceHelper.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <DataSeries.hxx>
+#include <WrappedIgnoreProperty.hxx>
+#include "WrappedAxisAndGridExistenceProperties.hxx"
+#include "WrappedStatisticProperties.hxx"
+#include "WrappedSymbolProperties.hxx"
+#include "WrappedDataCaptionProperties.hxx"
+#include "WrappedSplineProperties.hxx"
+#include "WrappedStockProperties.hxx"
+#include "WrappedSceneProperty.hxx"
+#include <ControllerLockGuard.hxx>
+#include <DisposeHelper.hxx>
+#include "WrappedAutomaticPositionProperties.hxx"
+#include <CommonConverters.hxx>
+#include <unonames.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart/ChartSolidType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include <SceneProperties.hxx>
+
+#include <algorithm>
+#include <map>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <o3tl/string_view.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+using namespace ::chart::wrapper;
+using namespace ::chart::DataSeriesProperties;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::chart::XAxis;
+
+namespace
+{
+
+enum
+{
+ PROP_DIAGRAM_ATTRIBUTED_DATA_POINTS,
+ PROP_DIAGRAM_PERCENT_STACKED,
+ PROP_DIAGRAM_STACKED,
+ PROP_DIAGRAM_THREE_D,
+ PROP_DIAGRAM_SOLIDTYPE,
+ PROP_DIAGRAM_DEEP,
+ PROP_DIAGRAM_VERTICAL,
+ PROP_DIAGRAM_NUMBER_OF_LINES,
+ PROP_DIAGRAM_STACKED_BARS_CONNECTED,
+ PROP_DIAGRAM_DATAROW_SOURCE,
+
+ PROP_DIAGRAM_GROUP_BARS_PER_AXIS,
+ PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS,
+
+ PROP_DIAGRAM_SORT_BY_X_VALUES,
+
+ PROP_DIAGRAM_STARTING_ANGLE,
+
+ PROP_DIAGRAM_RIGHT_ANGLED_AXES,
+ PROP_DIAGRAM_PERSPECTIVE,
+ PROP_DIAGRAM_ROTATION_HORIZONTAL,
+ PROP_DIAGRAM_ROTATION_VERTICAL,
+
+ PROP_DIAGRAM_MISSING_VALUE_TREATMENT,
+
+ PROP_DIAGRAM_HAS_X_AXIS,
+ PROP_DIAGRAM_HAS_X_AXIS_DESCR,
+ PROP_DIAGRAM_HAS_X_AXIS_TITLE,
+ PROP_DIAGRAM_HAS_X_AXIS_GRID,
+ PROP_DIAGRAM_HAS_X_AXIS_HELP_GRID,
+
+ PROP_DIAGRAM_HAS_Y_AXIS,
+ PROP_DIAGRAM_HAS_Y_AXIS_DESCR,
+ PROP_DIAGRAM_HAS_Y_AXIS_TITLE,
+ PROP_DIAGRAM_HAS_Y_AXIS_GRID,
+ PROP_DIAGRAM_HAS_Y_AXIS_HELP_GRID,
+
+ PROP_DIAGRAM_HAS_Z_AXIS,
+ PROP_DIAGRAM_HAS_Z_AXIS_DESCR,
+ PROP_DIAGRAM_HAS_Z_AXIS_TITLE,
+ PROP_DIAGRAM_HAS_Z_AXIS_GRID,
+ PROP_DIAGRAM_HAS_Z_AXIS_HELP_GRID,
+
+ PROP_DIAGRAM_HAS_SECOND_X_AXIS,
+ PROP_DIAGRAM_HAS_SECOND_X_AXIS_DESCR,
+
+ PROP_DIAGRAM_HAS_SECOND_Y_AXIS,
+ PROP_DIAGRAM_HAS_SECOND_Y_AXIS_DESCR,
+
+ PROP_DIAGRAM_HAS_SECOND_X_AXIS_TITLE,
+ PROP_DIAGRAM_HAS_SECOND_Y_AXIS_TITLE,
+
+ PROP_DIAGRAM_AUTOMATIC_SIZE,
+ PROP_DIAGRAM_EXTERNALDATA
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "AttributedDataPoints",
+ PROP_DIAGRAM_ATTRIBUTED_DATA_POINTS,
+ cppu::UnoType<uno::Sequence< uno::Sequence< sal_Int32 > >>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ // see com.sun.star.chart.StackableDiagram
+ rOutProperties.emplace_back( "Percent",
+ PROP_DIAGRAM_PERCENT_STACKED,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "Stacked",
+ PROP_DIAGRAM_STACKED,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "Dim3D",
+ PROP_DIAGRAM_THREE_D,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // see com.sun.star.chart.Chart3DBarProperties
+ rOutProperties.emplace_back( "SolidType",
+ PROP_DIAGRAM_SOLIDTYPE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // see com.sun.star.chart.BarDiagram
+ rOutProperties.emplace_back( "Deep",
+ PROP_DIAGRAM_DEEP,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "Vertical",
+ PROP_DIAGRAM_VERTICAL,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "NumberOfLines",
+ PROP_DIAGRAM_NUMBER_OF_LINES,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "StackedBarsConnected",
+ PROP_DIAGRAM_STACKED_BARS_CONNECTED,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "DataRowSource",
+ PROP_DIAGRAM_DATAROW_SOURCE,
+ cppu::UnoType<css::chart::ChartDataRowSource>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "GroupBarsPerAxis",
+ PROP_DIAGRAM_GROUP_BARS_PER_AXIS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "IncludeHiddenCells",
+ PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //new for XY charts
+ rOutProperties.emplace_back( CHART_UNONAME_SORT_BY_XVALUES,
+ PROP_DIAGRAM_SORT_BY_X_VALUES,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //for pie and donut charts
+ rOutProperties.emplace_back( "StartingAngle",
+ PROP_DIAGRAM_STARTING_ANGLE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //new for 3D charts
+ rOutProperties.emplace_back( "RightAngledAxes",
+ PROP_DIAGRAM_RIGHT_ANGLED_AXES,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "Perspective",
+ PROP_DIAGRAM_PERSPECTIVE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "RotationHorizontal",
+ PROP_DIAGRAM_ROTATION_HORIZONTAL,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "RotationVertical",
+ PROP_DIAGRAM_ROTATION_VERTICAL,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+
+ // XAxisXSupplier
+ rOutProperties.emplace_back( "HasXAxis",
+ PROP_DIAGRAM_HAS_X_AXIS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasXAxisDescription",
+ PROP_DIAGRAM_HAS_X_AXIS_DESCR,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasXAxisTitle",
+ PROP_DIAGRAM_HAS_X_AXIS_TITLE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasXAxisGrid",
+ PROP_DIAGRAM_HAS_X_AXIS_GRID,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasXAxisHelpGrid",
+ PROP_DIAGRAM_HAS_X_AXIS_HELP_GRID,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // XAxisYSupplier
+ rOutProperties.emplace_back( "HasYAxis",
+ PROP_DIAGRAM_HAS_Y_AXIS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasYAxisDescription",
+ PROP_DIAGRAM_HAS_Y_AXIS_DESCR,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasYAxisTitle",
+ PROP_DIAGRAM_HAS_Y_AXIS_TITLE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasYAxisGrid",
+ PROP_DIAGRAM_HAS_Y_AXIS_GRID,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasYAxisHelpGrid",
+ PROP_DIAGRAM_HAS_Y_AXIS_HELP_GRID,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // XAxisZSupplier
+ rOutProperties.emplace_back( "HasZAxis",
+ PROP_DIAGRAM_HAS_Z_AXIS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasZAxisDescription",
+ PROP_DIAGRAM_HAS_Z_AXIS_DESCR,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasZAxisTitle",
+ PROP_DIAGRAM_HAS_Z_AXIS_TITLE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasZAxisGrid",
+ PROP_DIAGRAM_HAS_Z_AXIS_GRID,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasZAxisHelpGrid",
+ PROP_DIAGRAM_HAS_Z_AXIS_HELP_GRID,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // XTwoAxisXSupplier
+ rOutProperties.emplace_back( "HasSecondaryXAxis",
+ PROP_DIAGRAM_HAS_SECOND_X_AXIS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasSecondaryXAxisDescription",
+ PROP_DIAGRAM_HAS_SECOND_X_AXIS_DESCR,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // XTwoAxisYSupplier
+ rOutProperties.emplace_back( "HasSecondaryYAxis",
+ PROP_DIAGRAM_HAS_SECOND_Y_AXIS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasSecondaryYAxisDescription",
+ PROP_DIAGRAM_HAS_SECOND_Y_AXIS_DESCR,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // XSecondAxisTitleSupplier
+ rOutProperties.emplace_back( "HasSecondaryXAxisTitle",
+ PROP_DIAGRAM_HAS_SECOND_X_AXIS_TITLE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "HasSecondaryYAxisTitle",
+ PROP_DIAGRAM_HAS_SECOND_Y_AXIS_TITLE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "MissingValueTreatment",
+ PROP_DIAGRAM_MISSING_VALUE_TREATMENT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "AutomaticSize",
+ PROP_DIAGRAM_AUTOMATIC_SIZE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ExternalData",
+ PROP_DIAGRAM_EXTERNALDATA,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+}
+
+const Sequence< Property >& StaticDiagramWrapperPropertyArray()
+{
+ static Sequence< Property > aPropSeq = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+ ::chart::SceneProperties::AddPropertiesToVector( aProperties );
+ WrappedStatisticProperties::addProperties( aProperties );
+ WrappedSymbolProperties::addProperties( aProperties );
+ WrappedDataCaptionProperties::addProperties( aProperties );
+ WrappedSplineProperties::addProperties( aProperties );
+ WrappedStockProperties::addProperties( aProperties );
+ WrappedAutomaticPositionProperties::addProperties( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropSeq;
+};
+
+bool lcl_isXYChart( const rtl::Reference< ::chart::Diagram >& xDiagram )
+{
+ bool bRet = false;
+ rtl::Reference< ::chart::ChartType > xChartType( xDiagram->getChartTypeByIndex( 0 ) );
+ if( xChartType.is() )
+ {
+ OUString aChartType( xChartType->getChartType() );
+ if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) )
+ bRet = true;
+ }
+ return bRet;
+}
+
+sal_Int32 lcl_getNewAPIIndexForOldAPIIndex(
+ sal_Int32 nOldAPIIndex
+ , const rtl::Reference< ::chart::Diagram >& xDiagram )
+{
+ sal_Int32 nNewAPIIndex = nOldAPIIndex;
+
+ if( lcl_isXYChart( xDiagram ) )
+ {
+ if( nNewAPIIndex >= 1 )
+ nNewAPIIndex -= 1;
+ }
+
+ std::vector< rtl::Reference< ::chart::DataSeries > > aSeriesList =
+ xDiagram->getDataSeries();
+ if( nNewAPIIndex >= static_cast<sal_Int32>(aSeriesList.size()) )
+ nNewAPIIndex = -1;
+
+ return nNewAPIIndex;
+}
+
+OUString lcl_getDiagramType( std::u16string_view rTemplateServiceName )
+{
+ static constexpr OUString aPrefix(u"com.sun.star.chart2.template."_ustr);
+
+ if( o3tl::starts_with(rTemplateServiceName, aPrefix) )
+ {
+ const std::u16string_view aName( rTemplateServiceName.substr( aPrefix.getLength()));
+
+ // "Area" "StackedArea" "PercentStackedArea" "ThreeDArea"
+ // "StackedThreeDArea" "PercentStackedThreeDArea"
+ if( aName.find( u"Area" ) != std::u16string_view::npos )
+ return "com.sun.star.chart.AreaDiagram";
+
+ // "Pie" "PieAllExploded" "ThreeDPie" "ThreeDPieAllExploded"
+ if( aName.find( u"Pie" ) != std::u16string_view::npos )
+ return "com.sun.star.chart.PieDiagram";
+
+ // "Column" "StackedColumn" "PercentStackedColumn" "ThreeDColumnDeep"
+ // "ThreeDColumnFlat" "StackedThreeDColumnFlat"
+ // "PercentStackedThreeDColumnFlat" "Bar" "StackedBar"
+ // "PercentStackedBar" "ThreeDBarDeep" "ThreeDBarFlat"
+ // "StackedThreeDBarFlat" "PercentStackedThreeDBarFlat" "ColumnWithLine"
+ // "StackedColumnWithLine"
+ if( aName.find( u"Column" ) != std::u16string_view::npos || aName.find( u"Bar" ) != std::u16string_view::npos )
+ return "com.sun.star.chart.BarDiagram";
+
+ // "Donut" "DonutAllExploded" "ThreeDDonut" "ThreeDDonutAllExploded"
+ if( aName.find( u"Donut" ) != std::u16string_view::npos )
+ return "com.sun.star.chart.DonutDiagram";
+
+ // "ScatterLineSymbol" "ScatterLine" "ScatterSymbol" "ThreeDScatter"
+ if( aName.find( u"Scatter" ) != std::u16string_view::npos )
+ return "com.sun.star.chart.XYDiagram";
+
+ // "FilledNet" "StackedFilledNet" "PercentStackedFilledNet"
+ if( aName.find( u"FilledNet" ) != std::u16string_view::npos )
+ return "com.sun.star.chart.FilledNetDiagram";
+
+ // "Net" "NetSymbol" "NetLine" "StackedNet" "StackedNetSymbol"
+ // "StackedNetLine" "PercentStackedNet" "PercentStackedNetSymbol"
+ // "PercentStackedNetLine"
+ if( aName.find( u"Net" ) != std::u16string_view::npos )
+ return "com.sun.star.chart.NetDiagram";
+
+ // "StockLowHighClose" "StockOpenLowHighClose" "StockVolumeLowHighClose"
+ // "StockVolumeOpenLowHighClose"
+ if( aName.find( u"Stock" ) != std::u16string_view::npos )
+ return "com.sun.star.chart.StockDiagram";
+
+ if( aName.find( u"Bubble" ) != std::u16string_view::npos )
+ return "com.sun.star.chart.BubbleDiagram";
+
+ // Note: this must be checked after Bar, Net and Scatter
+
+ // "Symbol" "StackedSymbol" "PercentStackedSymbol" "Line" "StackedLine"
+ // "PercentStackedLine" "LineSymbol" "StackedLineSymbol"
+ // "PercentStackedLineSymbol" "ThreeDLine" "StackedThreeDLine"
+ // "PercentStackedThreeDLine" "ThreeDLineDeep"
+ if( aName.find( u"Line" ) != std::u16string_view::npos || aName.find( u"Symbol" ) != std::u16string_view::npos )
+ return "com.sun.star.chart.LineDiagram";
+
+ OSL_FAIL( "unknown template" );
+ }
+
+ return OUString();
+}
+
+typedef std::map< OUString, OUString > tMakeStringStringMap;
+
+const tMakeStringStringMap& lcl_getChartTypeNameMap()
+{
+ static tMakeStringStringMap g_aChartTypeNameMap{
+ {"com.sun.star.chart2.LineChartType", "com.sun.star.chart.LineDiagram"},
+ {"com.sun.star.chart2.AreaChartType", "com.sun.star.chart.AreaDiagram"},
+ {"com.sun.star.chart2.ColumnChartType", "com.sun.star.chart.BarDiagram"},
+ {"com.sun.star.chart2.PieChartType", "com.sun.star.chart.PieDiagram"},
+ {"com.sun.star.chart2.DonutChartType", "com.sun.star.chart.DonutDiagram"},
+ {"com.sun.star.chart2.ScatterChartType", "com.sun.star.chart.XYDiagram"},
+ {"com.sun.star.chart2.FilledNetChartType", "com.sun.star.chart.FilledNetDiagram"},
+ {"com.sun.star.chart2.NetChartType", "com.sun.star.chart.NetDiagram"},
+ {"com.sun.star.chart2.CandleStickChartType", "com.sun.star.chart.StockDiagram"},
+ {"com.sun.star.chart2.BubbleChartType", "com.sun.star.chart.BubbleDiagram"}
+ };
+ return g_aChartTypeNameMap;
+}
+
+OUString lcl_getOldChartTypeName( const OUString & rNewChartTypeName )
+{
+ OUString aOld(rNewChartTypeName);
+
+ const tMakeStringStringMap& rMap = lcl_getChartTypeNameMap();
+ tMakeStringStringMap::const_iterator aIt( rMap.find( rNewChartTypeName ));
+ if( aIt != rMap.end())
+ {
+ aOld = aIt->second;
+ }
+ return aOld;
+}
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+DiagramWrapper::DiagramWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : m_spChart2ModelContact(std::move(spChart2ModelContact))
+{
+}
+
+DiagramWrapper::~DiagramWrapper()
+{}
+
+// ____ XDiagram ____
+OUString SAL_CALL DiagramWrapper::getDiagramType()
+{
+ OUString aRet;
+
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xChartDoc.is() && xDiagram.is() )
+ {
+ Reference< beans::XPropertySet > xChartDocProp( static_cast<cppu::OWeakObject*>(xChartDoc.get()), uno::UNO_QUERY );
+ if( xChartDocProp.is() )
+ {
+ uno::Reference< util::XRefreshable > xAddIn;
+ if( xChartDocProp->getPropertyValue( "AddIn" ) >>= xAddIn )
+ {
+ uno::Reference< lang::XServiceName > xServiceName( xAddIn, uno::UNO_QUERY );
+ if( xServiceName.is())
+ return xServiceName->getServiceName();
+ }
+ }
+
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = xChartDoc->getTypeManager();
+ Diagram::tTemplateWithServiceName aTemplateAndService =
+ xDiagram->getTemplate( xChartTypeManager );
+
+ aRet = lcl_getDiagramType( aTemplateAndService.sServiceName );
+ }
+
+ if( !aRet.isEmpty())
+ return aRet;
+
+ // none of the standard templates matched
+ // use first chart type
+ if (xDiagram)
+ {
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeByIndex( 0 ) );
+ if( xChartType.is() )
+ {
+ aRet = xChartType->getChartType();
+ if( !aRet.isEmpty() )
+ aRet = lcl_getOldChartTypeName( aRet );
+ }
+ }
+ if( aRet.isEmpty())
+ aRet = "com.sun.star.chart.BarDiagram";
+
+ return aRet;
+}
+
+Reference<
+ beans::XPropertySet > SAL_CALL DiagramWrapper::getDataRowProperties( sal_Int32 nRow )
+{
+ if( nRow < 0 )
+ throw lang::IndexOutOfBoundsException("DataSeries index invalid",
+ static_cast< ::cppu::OWeakObject * >( this ));
+
+ sal_Int32 nNewAPIIndex = lcl_getNewAPIIndexForOldAPIIndex( nRow, m_spChart2ModelContact->getDiagram() );
+ if( nNewAPIIndex < 0 )
+ throw lang::IndexOutOfBoundsException("DataSeries index invalid",
+ static_cast< ::cppu::OWeakObject * >( this ));
+
+ Reference< beans::XPropertySet > xRet( new DataSeriesPointWrapper(
+ DataSeriesPointWrapper::DATA_SERIES, nNewAPIIndex, 0, m_spChart2ModelContact ) );
+ return xRet;
+}
+
+Reference<
+ beans::XPropertySet > SAL_CALL DiagramWrapper::getDataPointProperties( sal_Int32 nCol, sal_Int32 nRow )
+{
+ if( nCol < 0 || nRow < 0 )
+ throw lang::IndexOutOfBoundsException("DataSeries index invalid",
+ static_cast< ::cppu::OWeakObject * >( this ));
+
+ sal_Int32 nNewAPIIndex = lcl_getNewAPIIndexForOldAPIIndex( nRow, m_spChart2ModelContact->getDiagram() );
+ if( nNewAPIIndex < 0 )
+ throw lang::IndexOutOfBoundsException("DataSeries index invalid",
+ static_cast< ::cppu::OWeakObject * >( this ));
+
+ //todo: check borders of point index
+
+ Reference< beans::XPropertySet > xRet( new DataSeriesPointWrapper(
+ DataSeriesPointWrapper::DATA_POINT, nNewAPIIndex, nCol, m_spChart2ModelContact ) );
+
+ return xRet;
+}
+
+// ____ XShape (base of XDiagram) ____
+awt::Point SAL_CALL DiagramWrapper::getPosition()
+{
+ awt::Point aPosition = ToPoint( m_spChart2ModelContact->GetDiagramRectangleIncludingAxes() );
+ return aPosition;
+}
+
+void SAL_CALL DiagramWrapper::setPosition( const awt::Point& aPosition )
+{
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ Reference< beans::XPropertySet > xProp( getInnerPropertySet() );
+ if( !xProp.is() )
+ return;
+
+ awt::Size aPageSize( m_spChart2ModelContact->GetPageSize() );
+
+ chart2::RelativePosition aRelativePosition;
+ aRelativePosition.Anchor = drawing::Alignment_TOP_LEFT;
+ aRelativePosition.Primary = double(aPosition.X)/double(aPageSize.Width);
+ aRelativePosition.Secondary = double(aPosition.Y)/double(aPageSize.Height);
+ if( aRelativePosition.Primary < 0 || aRelativePosition.Secondary < 0 || aRelativePosition.Primary > 1 || aRelativePosition.Secondary > 1 )
+ {
+ OSL_FAIL("DiagramWrapper::setPosition called with a position out of range -> automatic values are taken instead" );
+ uno::Any aEmpty;
+ xProp->setPropertyValue( "RelativePosition", aEmpty );
+ return;
+ }
+ xProp->setPropertyValue( "RelativePosition", uno::Any(aRelativePosition) );
+ xProp->setPropertyValue( "PosSizeExcludeAxes", uno::Any(false) );
+}
+
+awt::Size SAL_CALL DiagramWrapper::getSize()
+{
+ awt::Size aSize = ToSize( m_spChart2ModelContact->GetDiagramRectangleIncludingAxes() );
+ return aSize;
+}
+
+void SAL_CALL DiagramWrapper::setSize( const awt::Size& aSize )
+{
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ Reference< beans::XPropertySet > xProp( getInnerPropertySet() );
+ if( !xProp.is() )
+ return;
+
+ awt::Size aPageSize( m_spChart2ModelContact->GetPageSize() );
+
+ chart2::RelativeSize aRelativeSize;
+ aRelativeSize.Primary = double(aSize.Width)/double(aPageSize.Width);
+ aRelativeSize.Secondary = double(aSize.Height)/double(aPageSize.Height);
+
+ if( aRelativeSize.Primary > 1 || aRelativeSize.Secondary > 1 )
+ {
+ OSL_FAIL("DiagramWrapper::setSize called with sizes bigger than page -> automatic values are taken instead" );
+ uno::Any aEmpty;
+ xProp->setPropertyValue( "RelativeSize", aEmpty );
+ return;
+ }
+
+ xProp->setPropertyValue( "RelativeSize", uno::Any(aRelativeSize) );
+ xProp->setPropertyValue( "PosSizeExcludeAxes", uno::Any(false) );
+}
+
+// ____ XShapeDescriptor (base of XShape) ____
+OUString SAL_CALL DiagramWrapper::getShapeType()
+{
+ return "com.sun.star.chart.Diagram";
+}
+
+// ____ XDiagramPositioning ____
+
+void SAL_CALL DiagramWrapper::setAutomaticDiagramPositioning()
+{
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ uno::Reference< beans::XPropertySet > xDiaProps( getDiagram(), uno::UNO_QUERY );
+ if( xDiaProps.is() )
+ {
+ xDiaProps->setPropertyValue( "RelativeSize", Any() );
+ xDiaProps->setPropertyValue( "RelativePosition", Any() );
+ }
+}
+sal_Bool SAL_CALL DiagramWrapper::isAutomaticDiagramPositioning( )
+{
+ uno::Reference< beans::XPropertySet > xDiaProps( getDiagram(), uno::UNO_QUERY );
+ if( xDiaProps.is() )
+ {
+ Any aRelativeSize( xDiaProps->getPropertyValue( "RelativeSize" ) );
+ Any aRelativePosition( xDiaProps->getPropertyValue( "RelativePosition" ) );
+ if( aRelativeSize.hasValue() && aRelativePosition.hasValue() )
+ return false;
+ }
+ return true;
+}
+void SAL_CALL DiagramWrapper::setDiagramPositionExcludingAxes( const awt::Rectangle& rPositionRect )
+{
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ DiagramHelper::setDiagramPositioning( m_spChart2ModelContact->getDocumentModel(), rPositionRect );
+ uno::Reference< beans::XPropertySet > xDiaProps( getDiagram(), uno::UNO_QUERY );
+ if( xDiaProps.is() )
+ xDiaProps->setPropertyValue("PosSizeExcludeAxes", uno::Any(true) );
+}
+sal_Bool SAL_CALL DiagramWrapper::isExcludingDiagramPositioning()
+{
+ uno::Reference< beans::XPropertySet > xDiaProps( getDiagram(), uno::UNO_QUERY );
+ if( xDiaProps.is() )
+ {
+ Any aRelativeSize( xDiaProps->getPropertyValue( "RelativeSize" ) );
+ Any aRelativePosition( xDiaProps->getPropertyValue( "RelativePosition" ) );
+ if( aRelativeSize.hasValue() && aRelativePosition.hasValue() )
+ {
+ bool bPosSizeExcludeAxes = false;
+ xDiaProps->getPropertyValue( "PosSizeExcludeAxes" ) >>= bPosSizeExcludeAxes;
+ return bPosSizeExcludeAxes;
+ }
+ }
+ return false;
+}
+awt::Rectangle SAL_CALL DiagramWrapper::calculateDiagramPositionExcludingAxes( )
+{
+ return m_spChart2ModelContact->GetDiagramRectangleExcludingAxes();
+}
+void SAL_CALL DiagramWrapper::setDiagramPositionIncludingAxes( const awt::Rectangle& rPositionRect )
+{
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ DiagramHelper::setDiagramPositioning( m_spChart2ModelContact->getDocumentModel(), rPositionRect );
+ uno::Reference< beans::XPropertySet > xDiaProps( getDiagram(), uno::UNO_QUERY );
+ if( xDiaProps.is() )
+ xDiaProps->setPropertyValue("PosSizeExcludeAxes", uno::Any(false) );
+}
+awt::Rectangle SAL_CALL DiagramWrapper::calculateDiagramPositionIncludingAxes( )
+{
+ return m_spChart2ModelContact->GetDiagramRectangleIncludingAxes();
+}
+void SAL_CALL DiagramWrapper::setDiagramPositionIncludingAxesAndAxisTitles( const awt::Rectangle& rPositionRect )
+{
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ awt::Rectangle aRect( m_spChart2ModelContact->SubstractAxisTitleSizes(rPositionRect) );
+ DiagramWrapper::setDiagramPositionIncludingAxes( aRect );
+}
+css::awt::Rectangle SAL_CALL DiagramWrapper::calculateDiagramPositionIncludingAxesAndAxisTitles( )
+{
+ return m_spChart2ModelContact->GetDiagramRectangleIncludingTitle();
+}
+
+// ____ XAxisSupplier ____
+Reference< XAxis > SAL_CALL DiagramWrapper::getAxis( sal_Int32 nDimensionIndex )
+{
+ Reference< XAxis > xAxis;
+ if(!nDimensionIndex)
+ {
+ if( !m_xXAxis.is() )
+ m_xXAxis = new AxisWrapper( AxisWrapper::X_AXIS, m_spChart2ModelContact );
+ xAxis = m_xXAxis;
+ }
+ else if(nDimensionIndex==1)
+ {
+ if( !m_xYAxis.is() )
+ m_xYAxis = new AxisWrapper( AxisWrapper::Y_AXIS, m_spChart2ModelContact );
+ xAxis = m_xYAxis;
+ }
+ else if(nDimensionIndex==2)
+ {
+ if( !m_xZAxis.is() )
+ m_xZAxis = new AxisWrapper( AxisWrapper::Z_AXIS, m_spChart2ModelContact );
+ xAxis = m_xZAxis;
+ }
+ return xAxis;
+}
+
+Reference< XAxis > SAL_CALL DiagramWrapper::getSecondaryAxis( sal_Int32 nDimensionIndex )
+{
+ Reference< XAxis > xAxis;
+ if(!nDimensionIndex)
+ {
+ if( !m_xSecondXAxis.is() )
+ m_xSecondXAxis = new AxisWrapper( AxisWrapper::SECOND_X_AXIS, m_spChart2ModelContact );
+ xAxis = m_xSecondXAxis;
+ }
+ else if(nDimensionIndex==1)
+ {
+ if( !m_xSecondYAxis.is() )
+ m_xSecondYAxis = new AxisWrapper( AxisWrapper::SECOND_Y_AXIS, m_spChart2ModelContact );
+ xAxis = m_xSecondYAxis;
+ }
+ return xAxis;
+}
+
+// ____ XAxisZSupplier ____
+Reference< drawing::XShape > SAL_CALL DiagramWrapper::getZAxisTitle()
+{
+ Reference< drawing::XShape > xRet;
+ Reference< XAxis > xAxis( getAxis(2) );
+ if( xAxis.is() )
+ xRet.set( xAxis->getAxisTitle(), uno::UNO_QUERY );
+ return xRet;
+}
+
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getZMainGrid()
+{
+ Reference< beans::XPropertySet > xRet;
+ Reference< XAxis > xAxis( getAxis(2) );
+ if( xAxis.is() )
+ xRet = xAxis->getMajorGrid();
+ return xRet;
+}
+
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getZHelpGrid()
+{
+ Reference< beans::XPropertySet > xRet;
+ Reference< XAxis > xAxis( getAxis(2) );
+ if( xAxis.is() )
+ xRet = xAxis->getMinorGrid();
+ return xRet;
+}
+
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getZAxis()
+{
+ if( ! m_xZAxis.is())
+ m_xZAxis = new AxisWrapper( AxisWrapper::Z_AXIS, m_spChart2ModelContact );
+ return Reference< beans::XPropertySet >( m_xZAxis, uno::UNO_QUERY );
+}
+
+// ____ XTwoAxisXSupplier ____
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getSecondaryXAxis()
+{
+ if( ! m_xSecondXAxis.is())
+ m_xSecondXAxis = new AxisWrapper( AxisWrapper::SECOND_X_AXIS, m_spChart2ModelContact );
+ return Reference< beans::XPropertySet >( m_xSecondXAxis, uno::UNO_QUERY );
+}
+
+// ____ XAxisXSupplier (base of XTwoAxisXSupplier) ____
+Reference< drawing::XShape > SAL_CALL DiagramWrapper::getXAxisTitle()
+{
+ Reference< drawing::XShape > xRet;
+ Reference< XAxis > xAxis( getAxis(0) );
+ if( xAxis.is() )
+ xRet.set( xAxis->getAxisTitle(), uno::UNO_QUERY );
+ return xRet;
+}
+
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getXAxis()
+{
+ if( ! m_xXAxis.is())
+ m_xXAxis = new AxisWrapper( AxisWrapper::X_AXIS, m_spChart2ModelContact );
+ return Reference< beans::XPropertySet >( m_xXAxis, uno::UNO_QUERY );
+}
+
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getXMainGrid()
+{
+ Reference< beans::XPropertySet > xRet;
+ Reference< XAxis > xAxis( getAxis(0) );
+ if( xAxis.is() )
+ xRet = xAxis->getMajorGrid();
+ return xRet;
+}
+
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getXHelpGrid()
+{
+ Reference< beans::XPropertySet > xRet;
+ Reference< XAxis > xAxis( getAxis(0) );
+ if( xAxis.is() )
+ xRet = xAxis->getMinorGrid();
+ return xRet;
+}
+
+// ____ XTwoAxisYSupplier ____
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getSecondaryYAxis()
+{
+ if( ! m_xSecondYAxis.is())
+ m_xSecondYAxis = new AxisWrapper( AxisWrapper::SECOND_Y_AXIS, m_spChart2ModelContact );
+ return Reference< beans::XPropertySet >( m_xSecondYAxis, uno::UNO_QUERY );
+}
+
+// ____ XAxisYSupplier (base of XTwoAxisYSupplier) ____
+Reference< drawing::XShape > SAL_CALL DiagramWrapper::getYAxisTitle()
+{
+ Reference< drawing::XShape > xRet;
+ Reference< XAxis > xAxis( getAxis(1) );
+ if( xAxis.is() )
+ xRet.set( xAxis->getAxisTitle(), uno::UNO_QUERY );
+ return xRet;
+}
+
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getYAxis()
+{
+ if( ! m_xYAxis.is())
+ m_xYAxis = new AxisWrapper( AxisWrapper::Y_AXIS, m_spChart2ModelContact );
+ return Reference< beans::XPropertySet >( m_xYAxis, uno::UNO_QUERY );
+}
+
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getYMainGrid()
+{
+ Reference< beans::XPropertySet > xRet;
+ Reference< XAxis > xAxis( getAxis(1) );
+ if( xAxis.is() )
+ xRet = xAxis->getMajorGrid();
+ return xRet;
+}
+
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getYHelpGrid()
+{
+ Reference< beans::XPropertySet > xRet;
+ Reference< XAxis > xAxis( getAxis(1) );
+ if( xAxis.is() )
+ xRet = xAxis->getMinorGrid();
+ return xRet;
+}
+
+// ____ XSecondAxisTitleSupplier ____
+Reference< drawing::XShape > SAL_CALL DiagramWrapper::getSecondXAxisTitle()
+{
+ Reference< drawing::XShape > xRet;
+ Reference< XAxis > xAxis( getSecondaryAxis(0) );
+ if( xAxis.is() )
+ xRet.set( xAxis->getAxisTitle(), uno::UNO_QUERY );
+ return xRet;
+}
+
+Reference< drawing::XShape > SAL_CALL DiagramWrapper::getSecondYAxisTitle()
+{
+ Reference< drawing::XShape > xRet;
+ Reference< XAxis > xAxis( getSecondaryAxis(1) );
+ if( xAxis.is() )
+ xRet.set( xAxis->getAxisTitle(), uno::UNO_QUERY );
+ return xRet;
+}
+
+// ____ XStatisticDisplay ____
+Reference<
+ beans::XPropertySet > SAL_CALL DiagramWrapper::getUpBar()
+{
+ if( !m_xUpBarWrapper.is() )
+ {
+ m_xUpBarWrapper = new UpDownBarWrapper( true, m_spChart2ModelContact );
+ }
+ return m_xUpBarWrapper;
+}
+
+Reference<
+ beans::XPropertySet > SAL_CALL DiagramWrapper::getDownBar()
+{
+ if( !m_xDownBarWrapper.is() )
+ {
+ m_xDownBarWrapper = new UpDownBarWrapper( false, m_spChart2ModelContact );
+ }
+ return m_xDownBarWrapper;
+}
+
+Reference<
+ beans::XPropertySet > SAL_CALL DiagramWrapper::getMinMaxLine()
+{
+ if( !m_xMinMaxLineWrapper.is() )
+ {
+ m_xMinMaxLineWrapper = new MinMaxLineWrapper( m_spChart2ModelContact );
+ }
+ return m_xMinMaxLineWrapper;
+}
+
+// ____ X3DDisplay ____
+Reference< beans::XPropertySet > SAL_CALL DiagramWrapper::getWall()
+{
+ if( !m_xWall.is() )
+ {
+ m_xWall = new WallFloorWrapper( true, m_spChart2ModelContact );
+ }
+ return m_xWall;
+}
+
+Reference<
+ beans::XPropertySet > SAL_CALL DiagramWrapper::getFloor()
+{
+ if( !m_xFloor.is() )
+ {
+ m_xFloor = new WallFloorWrapper( false, m_spChart2ModelContact );
+ }
+ return m_xFloor;
+}
+
+// ____ X3DDefaultSetter ____
+void SAL_CALL DiagramWrapper::set3DSettingsToDefault()
+{
+ rtl::Reference< ::chart::Diagram > x3DDefaultSetter( m_spChart2ModelContact->getDiagram() );
+ if( x3DDefaultSetter.is() )
+ x3DDefaultSetter->set3DSettingsToDefault();
+}
+
+void SAL_CALL DiagramWrapper::setDefaultRotation()
+{
+ rtl::Reference< ::chart::Diagram > x3DDefaultSetter( m_spChart2ModelContact->getDiagram() );
+ if( x3DDefaultSetter.is() )
+ x3DDefaultSetter->setDefaultRotation();
+}
+
+void SAL_CALL DiagramWrapper::setDefaultIllumination()
+{
+ rtl::Reference< ::chart::Diagram > x3DDefaultSetter( m_spChart2ModelContact->getDiagram() );
+ if( x3DDefaultSetter.is() )
+ x3DDefaultSetter->setDefaultIllumination();
+}
+
+// ____ XComponent ____
+void SAL_CALL DiagramWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( static_cast< ::cppu::OWeakObject* >( this )));
+
+ DisposeHelper::DisposeAndClear( m_xXAxis );
+ DisposeHelper::DisposeAndClear( m_xYAxis );
+ DisposeHelper::DisposeAndClear( m_xZAxis );
+ DisposeHelper::DisposeAndClear( m_xSecondXAxis );
+ DisposeHelper::DisposeAndClear( m_xSecondYAxis );
+ DisposeHelper::DisposeAndClear( m_xWall );
+ DisposeHelper::DisposeAndClear( m_xFloor );
+ DisposeHelper::DisposeAndClear( m_xMinMaxLineWrapper );
+ DisposeHelper::DisposeAndClear( m_xUpBarWrapper );
+ DisposeHelper::DisposeAndClear( m_xDownBarWrapper );
+
+ clearWrappedPropertySet();
+}
+
+void SAL_CALL DiagramWrapper::addEventListener(
+ const Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL DiagramWrapper::removeEventListener(
+ const Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+namespace {
+
+//PROP_DIAGRAM_DATAROW_SOURCE
+class WrappedDataRowSourceProperty : public WrappedProperty
+{
+public:
+ explicit WrappedDataRowSourceProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedDataRowSourceProperty::WrappedDataRowSourceProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("DataRowSource",OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+ m_aOuterValue = WrappedDataRowSourceProperty::getPropertyDefault( nullptr );
+}
+
+void WrappedDataRowSourceProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ css::chart::ChartDataRowSource eChartDataRowSource = css::chart::ChartDataRowSource_ROWS;
+ if( ! (rOuterValue >>= eChartDataRowSource) )
+ {
+ sal_Int32 nNew = sal_Int32(css::chart::ChartDataRowSource_ROWS);
+ if( !(rOuterValue >>= nNew) )
+ throw lang::IllegalArgumentException( "Property DataRowSource requires css::chart::ChartDataRowSource value", nullptr, 0 );
+ eChartDataRowSource = css::chart::ChartDataRowSource(nNew);
+ }
+
+ m_aOuterValue = rOuterValue;
+
+ bool bNewUseColumns = eChartDataRowSource == css::chart::ChartDataRowSource_COLUMNS;
+
+ OUString aRangeString;
+ bool bUseColumns = true;
+ bool bFirstCellAsLabel = true;
+ bool bHasCategories = true;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+
+ if( DataSourceHelper::detectRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aRangeString, aSequenceMapping, bUseColumns
+ , bFirstCellAsLabel, bHasCategories ) )
+ {
+ if( bUseColumns != bNewUseColumns )
+ {
+ aSequenceMapping.realloc(0);
+ DataSourceHelper::setRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aSequenceMapping, bNewUseColumns , bFirstCellAsLabel , bHasCategories);
+ }
+ }
+}
+
+Any WrappedDataRowSourceProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ OUString aRangeString;
+ bool bUseColumns = true;
+ bool bFirstCellAsLabel = true;
+ bool bHasCategories = true;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+
+ if( DataSourceHelper::detectRangeSegmentation(
+ m_spChart2ModelContact->getDocumentModel(), aRangeString, aSequenceMapping, bUseColumns
+ , bFirstCellAsLabel, bHasCategories ) )
+ {
+ css::chart::ChartDataRowSource eChartDataRowSource = css::chart::ChartDataRowSource_ROWS;
+ if(bUseColumns)
+ eChartDataRowSource = css::chart::ChartDataRowSource_COLUMNS;
+
+ m_aOuterValue <<= eChartDataRowSource;
+ }
+
+ return m_aOuterValue;
+}
+
+Any WrappedDataRowSourceProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= css::chart::ChartDataRowSource_COLUMNS;
+ return aRet;
+}
+
+namespace {
+
+//PROP_DIAGRAM_STACKED
+//PROP_DIAGRAM_DEEP
+//PROP_DIAGRAM_PERCENT_STACKED
+class WrappedStackingProperty : public WrappedProperty
+{
+public:
+ WrappedStackingProperty(StackMode eStackMode, std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+protected: //methods
+ bool detectInnerValue( StackMode& eInnerStackMode ) const;
+
+private: //member
+std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ const StackMode m_eStackMode;
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedStackingProperty::WrappedStackingProperty(StackMode eStackMode, std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty(OUString(),OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+ , m_eStackMode( eStackMode )
+{
+ switch( m_eStackMode )
+ {
+ case StackMode::YStacked:
+ m_aOuterName = "Stacked";
+ break;
+ case StackMode::YStackedPercent:
+ m_aOuterName = "Percent";
+ break;
+ case StackMode::ZStacked:
+ m_aOuterName = "Deep";
+ break;
+ default:
+ OSL_FAIL( "unexpected stack mode" );
+ break;
+ }
+}
+
+bool WrappedStackingProperty::detectInnerValue( StackMode& eStackMode ) const
+{
+ bool bHasDetectableInnerValue = false;
+ bool bIsAmbiguous = false;
+ rtl::Reference<Diagram> xDiagram = m_spChart2ModelContact->getDiagram();
+ eStackMode = xDiagram ? xDiagram->getStackMode( bHasDetectableInnerValue, bIsAmbiguous ) : StackMode::NONE;
+ return bHasDetectableInnerValue;
+}
+
+void WrappedStackingProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bNewValue = false;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException( "Stacking Properties require boolean values", nullptr, 0 );
+
+ StackMode eInnerStackMode;
+ bool bHasDetectableInnerValue = detectInnerValue( eInnerStackMode );
+
+ if( !bHasDetectableInnerValue )
+ {
+ m_aOuterValue = rOuterValue;
+ return;
+ }
+
+ if( bNewValue && eInnerStackMode == m_eStackMode )
+ return;
+ if( !bNewValue && eInnerStackMode != m_eStackMode )
+ return;
+
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() )
+ {
+ StackMode eNewStackMode = bNewValue ? m_eStackMode : StackMode::NONE;
+ xDiagram->setStackMode( eNewStackMode );
+ }
+}
+
+Any WrappedStackingProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ StackMode eInnerStackMode;
+ if( detectInnerValue( eInnerStackMode ) )
+ {
+ bool bValue = (eInnerStackMode == m_eStackMode);
+ return Any(bValue);
+ }
+ return m_aOuterValue;
+}
+
+Any WrappedStackingProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+namespace {
+
+//PROP_DIAGRAM_THREE_D
+class WrappedDim3DProperty : public WrappedProperty
+{
+public:
+ explicit WrappedDim3DProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedDim3DProperty::WrappedDim3DProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("Dim3D",OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+ m_aOuterValue = WrappedDim3DProperty::getPropertyDefault( nullptr );
+}
+
+void WrappedDim3DProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bNew3D = false;
+ if( ! (rOuterValue >>= bNew3D) )
+ throw lang::IllegalArgumentException( "Property Dim3D requires boolean value", nullptr, 0 );
+
+ m_aOuterValue = rOuterValue;
+
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( !xDiagram.is() )
+ return;
+
+ bool bOld3D = xDiagram->getDimension() == 3;
+ if( bOld3D != bNew3D )
+ xDiagram->setDimension( bNew3D ? 3 : 2 );
+}
+
+Any WrappedDim3DProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() )
+ {
+ bool b3D = xDiagram->getDimension() == 3;
+ m_aOuterValue <<= b3D;
+ }
+ return m_aOuterValue;
+}
+
+Any WrappedDim3DProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+namespace {
+
+//PROP_DIAGRAM_VERTICAL
+class WrappedVerticalProperty : public WrappedProperty
+{
+public:
+ explicit WrappedVerticalProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedVerticalProperty::WrappedVerticalProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("Vertical",OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+ m_aOuterValue = WrappedVerticalProperty::getPropertyDefault( nullptr );
+}
+
+void WrappedVerticalProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bNewVertical = false;
+ if( ! (rOuterValue >>= bNewVertical) )
+ throw lang::IllegalArgumentException( "Property Vertical requires boolean value", nullptr, 0 );
+
+ m_aOuterValue = rOuterValue;
+
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( !xDiagram.is() )
+ return;
+
+ bool bFound = false;
+ bool bAmbiguous = false;
+ bool bOldVertical = xDiagram->getVertical( bFound, bAmbiguous );
+ if( bFound && ( bOldVertical != bNewVertical || bAmbiguous ) )
+ xDiagram->setVertical( bNewVertical );
+}
+
+Any WrappedVerticalProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() )
+ {
+ bool bFound = false;
+ bool bAmbiguous = false;
+ bool bVertical = xDiagram->getVertical( bFound, bAmbiguous );
+ if( bFound )
+ m_aOuterValue <<= bVertical;
+ }
+ return m_aOuterValue;
+}
+
+Any WrappedVerticalProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+namespace {
+
+//PROP_DIAGRAM_NUMBER_OF_LINES
+class WrappedNumberOfLinesProperty : public WrappedProperty
+{
+public:
+ explicit WrappedNumberOfLinesProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+protected: //methods
+ bool detectInnerValue( uno::Any& rInnerValue ) const;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedNumberOfLinesProperty::WrappedNumberOfLinesProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("NumberOfLines",OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+ , m_aOuterValue( getPropertyDefault(nullptr) )
+{
+}
+
+bool WrappedNumberOfLinesProperty::detectInnerValue( uno::Any& rInnerValue ) const
+{
+ sal_Int32 nNumberOfLines = 0;
+ bool bHasDetectableInnerValue = false;
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ if( xDiagram.is() && xChartDoc.is() )
+ {
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector =
+ xDiagram->getDataSeries();
+ if( !aSeriesVector.empty() )
+ {
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = xChartDoc->getTypeManager();
+ Diagram::tTemplateWithServiceName aTemplateAndService =
+ xDiagram->getTemplate( xChartTypeManager );
+ if( aTemplateAndService.sServiceName == "com.sun.star.chart2.template.ColumnWithLine" )
+ {
+ try
+ {
+ uno::Reference< beans::XPropertySet > xProp( static_cast<cppu::OWeakObject*>(aTemplateAndService.xChartTypeTemplate.get()), uno::UNO_QUERY );
+ xProp->getPropertyValue( m_aOuterName ) >>= nNumberOfLines;
+ bHasDetectableInnerValue = true;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ }
+ if(bHasDetectableInnerValue)
+ rInnerValue <<= nNumberOfLines;
+ return bHasDetectableInnerValue;
+}
+
+void WrappedNumberOfLinesProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ sal_Int32 nNewValue;
+ if( ! (rOuterValue >>= nNewValue) )
+ throw lang::IllegalArgumentException( "property NumberOfLines requires sal_Int32 value", nullptr, 0 );
+
+ m_aOuterValue = rOuterValue;
+
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( !xChartDoc || !xDiagram )
+ return;
+ sal_Int32 nDimension = xDiagram->getDimension();
+ if( nDimension != 2 )
+ return;
+
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = xChartDoc->getTypeManager();
+ Diagram::tTemplateWithServiceName aTemplateAndService =
+ xDiagram->getTemplate( xChartTypeManager );
+
+ rtl::Reference< ChartTypeTemplate > xTemplate;
+ if( aTemplateAndService.sServiceName == "com.sun.star.chart2.template.ColumnWithLine" )
+ {
+ if( nNewValue != 0 )
+ {
+ xTemplate = aTemplateAndService.xChartTypeTemplate;
+ try
+ {
+ sal_Int32 nOldValue = 0;
+ uno::Reference< beans::XPropertySet > xProp( static_cast<cppu::OWeakObject*>(xTemplate.get()), uno::UNO_QUERY );
+ xProp->getPropertyValue( m_aOuterName ) >>= nOldValue;
+ if( nOldValue == nNewValue )
+ return;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ else
+ {
+ xTemplate = xChartTypeManager->createTemplate("com.sun.star.chart2.template.Column");
+ }
+ }
+ else if( aTemplateAndService.sServiceName == "com.sun.star.chart2.template.Column" )
+ {
+ if( nNewValue == 0 )
+ return;
+ xTemplate = xChartTypeManager->createTemplate( "com.sun.star.chart2.template.ColumnWithLine" );
+ }
+
+ if(!xTemplate.is())
+ return;
+
+ try
+ {
+ // locked controllers
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ uno::Reference< beans::XPropertySet > xProp( static_cast<cppu::OWeakObject*>(xTemplate.get()), uno::UNO_QUERY );
+ xProp->setPropertyValue( "NumberOfLines", uno::Any(nNewValue) );
+ xTemplate->changeDiagram( xDiagram );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+Any WrappedNumberOfLinesProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ Any aRet;
+ if( !detectInnerValue( aRet ) )
+ aRet = m_aOuterValue;
+ return aRet;
+}
+
+Any WrappedNumberOfLinesProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= sal_Int32( 0 );
+ return aRet;
+}
+
+namespace {
+
+//PROP_DIAGRAM_ATTRIBUTED_DATA_POINTS
+class WrappedAttributedDataPointsProperty : public WrappedProperty
+{
+public:
+ explicit WrappedAttributedDataPointsProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedAttributedDataPointsProperty::WrappedAttributedDataPointsProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("AttributedDataPoints",OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+ m_aOuterValue = WrappedAttributedDataPointsProperty::getPropertyDefault( nullptr );
+}
+
+void WrappedAttributedDataPointsProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ uno::Sequence< uno::Sequence< sal_Int32 > > aNewValue;
+ if( ! (rOuterValue >>= aNewValue) )
+ throw lang::IllegalArgumentException( "Property AttributedDataPoints requires value of type uno::Sequence< uno::Sequence< sal_Int32 > >", nullptr, 0 );
+
+ m_aOuterValue = rOuterValue;
+
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+
+ if( !xDiagram )
+ return;
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector =
+ xDiagram->getDataSeries();
+ sal_Int32 i = 0;
+ for (auto const& series : aSeriesVector)
+ {
+ uno::Any aVal;
+ if( i < aNewValue.getLength() )
+ aVal <<= aNewValue[i];
+ else
+ {
+ //set empty sequence
+ uno::Sequence< sal_Int32 > aSeq;
+ aVal <<= aSeq;
+ }
+ series->setFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS, aVal ); // "AttributedDataPoints"
+ ++i;
+ }
+}
+
+Any WrappedAttributedDataPointsProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+
+ if( xDiagram )
+ {
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector =
+ xDiagram->getDataSeries();
+
+ uno::Sequence< uno::Sequence< sal_Int32 > > aResult( aSeriesVector.size() );
+ auto aResultRange = asNonConstRange(aResult);
+ sal_Int32 i = 0;
+ for (auto const& series : aSeriesVector)
+ {
+ uno::Any aVal(
+ series->getFastPropertyValue(PROP_DATASERIES_ATTRIBUTED_DATA_POINTS)); // "AttributedDataPoints"
+ uno::Sequence< sal_Int32 > aSeq;
+ if( aVal >>= aSeq )
+ aResultRange[ i ] = aSeq;
+ ++i;
+ }
+ m_aOuterValue <<= aResult;
+ }
+ return m_aOuterValue;
+}
+
+Any WrappedAttributedDataPointsProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ uno::Sequence< uno::Sequence< sal_Int32 > > aSeq;
+ aRet <<= aSeq;
+ return aRet;
+}
+
+namespace {
+
+//PROP_DIAGRAM_SOLIDTYPE
+class WrappedSolidTypeProperty : public WrappedProperty
+{
+public:
+ explicit WrappedSolidTypeProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedSolidTypeProperty::WrappedSolidTypeProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty( "SolidType", OUString() )
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+ m_aOuterValue = WrappedSolidTypeProperty::getPropertyDefault( nullptr );
+}
+
+void WrappedSolidTypeProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ sal_Int32 nNewSolidType = css::chart::ChartSolidType::RECTANGULAR_SOLID;
+ if( ! (rOuterValue >>= nNewSolidType) )
+ throw lang::IllegalArgumentException( "Property SolidType requires integer value", nullptr, 0 );
+
+ m_aOuterValue = rOuterValue;
+
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( !xDiagram.is() )
+ return;
+
+ bool bFound = false;
+ bool bAmbiguous = false;
+ sal_Int32 nOldSolidType = xDiagram->getGeometry3D( bFound, bAmbiguous );
+ if( bFound && ( nOldSolidType != nNewSolidType || bAmbiguous ) )
+ xDiagram->setGeometry3D( nNewSolidType );
+}
+
+Any WrappedSolidTypeProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() )
+ {
+ bool bFound = false;
+ bool bAmbiguous = false;
+ sal_Int32 nGeometry = xDiagram->getGeometry3D( bFound, bAmbiguous );
+ if( bFound )
+ m_aOuterValue <<= nGeometry;
+ }
+ return m_aOuterValue;
+}
+
+Any WrappedSolidTypeProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ return uno::Any( css::chart::ChartSolidType::RECTANGULAR_SOLID );
+}
+
+namespace {
+
+class WrappedAutomaticSizeProperty : public WrappedProperty
+{
+public:
+ WrappedAutomaticSizeProperty();
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+};
+
+}
+
+WrappedAutomaticSizeProperty::WrappedAutomaticSizeProperty()
+ : WrappedProperty( "AutomaticSize", OUString() )
+{
+}
+
+void WrappedAutomaticSizeProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if( !xInnerPropertySet.is() )
+ return;
+
+ bool bNewValue = true;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException( "Property AutomaticSize requires value of type boolean", nullptr, 0 );
+
+ try
+ {
+ if( bNewValue )
+ {
+ Any aRelativeSize( xInnerPropertySet->getPropertyValue( "RelativeSize" ) );
+ if( aRelativeSize.hasValue() )
+ xInnerPropertySet->setPropertyValue( "RelativeSize", Any() );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+Any WrappedAutomaticSizeProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Any aRet( getPropertyDefault( Reference< beans::XPropertyState >( xInnerPropertySet, uno::UNO_QUERY ) ) );
+ if( xInnerPropertySet.is() )
+ {
+ Any aRelativeSize( xInnerPropertySet->getPropertyValue( "RelativeSize" ) );
+ if( !aRelativeSize.hasValue() )
+ aRet <<= true;
+ }
+ return aRet;
+}
+
+Any WrappedAutomaticSizeProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+namespace {
+
+//PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS
+class WrappedIncludeHiddenCellsProperty : public WrappedProperty
+{
+public:
+ explicit WrappedIncludeHiddenCellsProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+ virtual Any getPropertyValue(const Reference<beans::XPropertySet>& xInnerPropertySet) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+};
+
+}
+
+WrappedIncludeHiddenCellsProperty::WrappedIncludeHiddenCellsProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty("IncludeHiddenCells","IncludeHiddenCells")
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+}
+
+void WrappedIncludeHiddenCellsProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bNewValue = false;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException( "Property IncludeHiddenCells requires boolean value", nullptr, 0 );
+
+ ChartModelHelper::setIncludeHiddenCells( bNewValue, *m_spChart2ModelContact->getDocumentModel() );
+}
+
+Any WrappedIncludeHiddenCellsProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bValue = ChartModelHelper::isIncludeHiddenCells( m_spChart2ModelContact->getDocumentModel() );
+ return uno::Any(bValue);
+}
+
+// ____ XDiagramProvider ____
+Reference< chart2::XDiagram > SAL_CALL DiagramWrapper::getDiagram()
+{
+ return m_spChart2ModelContact->getDiagram();
+}
+
+void SAL_CALL DiagramWrapper::setDiagram(
+ const Reference< chart2::XDiagram >& /*xDiagram*/ )
+{
+ //@todo: remove this method from interface
+ OSL_FAIL("DiagramWrapper::setDiagram is not implemented, should be removed and not be called" );
+}
+
+Reference< beans::XPropertySet > DiagramWrapper::getInnerPropertySet()
+{
+ return m_spChart2ModelContact->getDiagram();
+}
+
+const Sequence< beans::Property >& DiagramWrapper::getPropertySequence()
+{
+ return StaticDiagramWrapperPropertyArray();
+}
+
+std::vector< std::unique_ptr<WrappedProperty> > DiagramWrapper::createWrappedProperties()
+{
+ std::vector< std::unique_ptr<WrappedProperty> > aWrappedProperties;
+
+ WrappedAxisAndGridExistenceProperties::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+ WrappedAxisTitleExistenceProperties::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+ WrappedAxisLabelExistenceProperties::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+ WrappedSceneProperty::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+ WrappedIgnoreProperties::addIgnoreFillProperties( aWrappedProperties );
+ WrappedIgnoreProperties::addIgnoreLineProperties( aWrappedProperties );
+ WrappedStatisticProperties::addWrappedPropertiesForDiagram( aWrappedProperties, m_spChart2ModelContact );
+ WrappedSymbolProperties::addWrappedPropertiesForDiagram( aWrappedProperties, m_spChart2ModelContact );
+ WrappedDataCaptionProperties::addWrappedPropertiesForDiagram( aWrappedProperties, m_spChart2ModelContact );
+ WrappedSplineProperties::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+ WrappedStockProperties::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+ WrappedAutomaticPositionProperties::addWrappedProperties( aWrappedProperties );
+
+ aWrappedProperties.emplace_back( new WrappedDataRowSourceProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedStackingProperty( StackMode::YStacked,m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedStackingProperty( StackMode::YStackedPercent, m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedStackingProperty( StackMode::ZStacked, m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedDim3DProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedVerticalProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedNumberOfLinesProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedAttributedDataPointsProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedProperty( "StackedBarsConnected", "ConnectBars" ) );
+ aWrappedProperties.emplace_back( new WrappedSolidTypeProperty( m_spChart2ModelContact ) );
+ aWrappedProperties.emplace_back( new WrappedAutomaticSizeProperty() );
+ aWrappedProperties.emplace_back( new WrappedIncludeHiddenCellsProperty( m_spChart2ModelContact ) );
+
+ return aWrappedProperties;
+}
+
+OUString SAL_CALL DiagramWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.Diagram";
+}
+
+sal_Bool SAL_CALL DiagramWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL DiagramWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart.Diagram",
+ "com.sun.star.xml.UserDefinedAttributesSupplier",
+ "com.sun.star.chart.StackableDiagram",
+ "com.sun.star.chart.ChartAxisXSupplier",
+ "com.sun.star.chart.ChartAxisYSupplier",
+ "com.sun.star.chart.ChartAxisZSupplier",
+ "com.sun.star.chart.ChartTwoAxisXSupplier",
+ "com.sun.star.chart.ChartTwoAxisYSupplier"
+ };
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/DiagramWrapper.hxx b/chart2/source/controller/chartapiwrapper/DiagramWrapper.hxx
new file mode 100644
index 0000000000..3a3a8383de
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/DiagramWrapper.hxx
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedPropertySet.hxx>
+
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/chart/XDiagramPositioning.hpp>
+#include <com/sun/star/chart2/XDiagramProvider.hpp>
+#include <com/sun/star/chart/XDiagram.hpp>
+#include <com/sun/star/chart/XAxisSupplier.hpp>
+#include <com/sun/star/chart/XAxisZSupplier.hpp>
+#include <com/sun/star/chart/XTwoAxisXSupplier.hpp>
+#include <com/sun/star/chart/XTwoAxisYSupplier.hpp>
+#include <com/sun/star/chart/XStatisticDisplay.hpp>
+#include <com/sun/star/chart/X3DDisplay.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp>
+
+#include <com/sun/star/chart/X3DDefaultSetter.hpp>
+#include <memory>
+
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::lang { class XEventListener; }
+
+namespace chart::wrapper
+{
+
+class Chart2ModelContact;
+
+class DiagramWrapper : public cppu::ImplInheritanceHelper<
+ WrappedPropertySet
+ , css::chart::XDiagram
+ , css::chart::XAxisSupplier
+ , css::chart::XAxisZSupplier
+ , css::chart::XTwoAxisXSupplier // : XAxisXSupplier
+ , css::chart::XTwoAxisYSupplier // : XAxisYSupplier
+ , css::chart::XStatisticDisplay
+ , css::chart::X3DDisplay
+ , css::chart::X3DDefaultSetter
+ , css::lang::XServiceInfo
+ , css::lang::XComponent
+ , css::chart::XDiagramPositioning
+ , css::chart2::XDiagramProvider
+ , css::chart::XSecondAxisTitleSupplier
+ >
+{
+public:
+ explicit DiagramWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~DiagramWrapper() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference<
+ css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference<
+ css::lang::XEventListener >& aListener ) override;
+
+ // ____ XDiagram ____
+ virtual OUString SAL_CALL getDiagramType() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getDataRowProperties( sal_Int32 nRow ) override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getDataPointProperties( sal_Int32 nCol, sal_Int32 nRow ) override;
+
+ // ____ XShape (base of XDiagram) ____
+ virtual css::awt::Point SAL_CALL getPosition() override;
+ virtual void SAL_CALL setPosition( const css::awt::Point& aPosition ) override;
+ virtual css::awt::Size SAL_CALL getSize() override;
+ virtual void SAL_CALL setSize( const css::awt::Size& aSize ) override;
+
+ // ____ XShapeDescriptor (base of XShape) ____
+ virtual OUString SAL_CALL getShapeType() override;
+
+ // ____ XAxisSupplier ____
+ virtual css::uno::Reference<
+ css::chart::XAxis > SAL_CALL getAxis( sal_Int32 nDimensionIndex ) override;
+ virtual css::uno::Reference<
+ css::chart::XAxis > SAL_CALL getSecondaryAxis( sal_Int32 nDimensionIndex ) override;
+
+ // ____ XAxisZSupplier ____
+ virtual css::uno::Reference<
+ css::drawing::XShape > SAL_CALL getZAxisTitle() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getZMainGrid() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getZHelpGrid() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getZAxis() override;
+
+ // ____ XTwoAxisXSupplier ____
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getSecondaryXAxis() override;
+
+ // ____ XAxisXSupplier (base of XTwoAxisXSupplier) ____
+ virtual css::uno::Reference<
+ css::drawing::XShape > SAL_CALL getXAxisTitle() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getXAxis() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getXMainGrid() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getXHelpGrid() override;
+
+ // ____ XTwoAxisYSupplier ____
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getSecondaryYAxis() override;
+
+ // ____ XAxisYSupplier (base of XTwoAxisYSupplier) ____
+ virtual css::uno::Reference<
+ css::drawing::XShape > SAL_CALL getYAxisTitle() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getYAxis() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getYHelpGrid() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getYMainGrid() override;
+
+ // ____ XSecondAxisTitleSupplier ____
+ virtual css::uno::Reference<
+ css::drawing::XShape > SAL_CALL getSecondXAxisTitle() override;
+ virtual css::uno::Reference<
+ css::drawing::XShape > SAL_CALL getSecondYAxisTitle() override;
+
+ // ____ XStatisticDisplay ____
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getUpBar() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getDownBar() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getMinMaxLine() override;
+
+ // ____ X3DDisplay ____
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getWall() override;
+ virtual css::uno::Reference<
+ css::beans::XPropertySet > SAL_CALL getFloor() override;
+
+ // ____ X3DDefaultSetter ____
+ virtual void SAL_CALL set3DSettingsToDefault() override;
+ virtual void SAL_CALL setDefaultRotation() override;
+ virtual void SAL_CALL setDefaultIllumination() override;
+
+ // ____ XDiagramPositioning ____
+ virtual void SAL_CALL setAutomaticDiagramPositioning( ) override;
+ virtual sal_Bool SAL_CALL isAutomaticDiagramPositioning( ) override;
+ virtual void SAL_CALL setDiagramPositionExcludingAxes( const css::awt::Rectangle& PositionRect ) override;
+ virtual sal_Bool SAL_CALL isExcludingDiagramPositioning( ) override;
+ virtual css::awt::Rectangle SAL_CALL calculateDiagramPositionExcludingAxes( ) override;
+ virtual void SAL_CALL setDiagramPositionIncludingAxes( const css::awt::Rectangle& PositionRect ) override;
+ virtual css::awt::Rectangle SAL_CALL calculateDiagramPositionIncludingAxes( ) override;
+ virtual void SAL_CALL setDiagramPositionIncludingAxesAndAxisTitles( const css::awt::Rectangle& PositionRect ) override;
+ virtual css::awt::Rectangle SAL_CALL calculateDiagramPositionIncludingAxesAndAxisTitles( ) override;
+
+ // ____ XDiagramProvider ____
+ virtual css::uno::Reference< css::chart2::XDiagram > SAL_CALL getDiagram() override;
+ virtual void SAL_CALL setDiagram( const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) override;
+
+protected:
+ // ____ WrappedPropertySet ____
+ virtual const css::uno::Sequence< css::beans::Property >& getPropertySequence() override;
+ virtual std::vector< std::unique_ptr<WrappedProperty> > createWrappedProperties() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override;
+
+private:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+
+ css::uno::Reference<
+ css::chart::XAxis > m_xXAxis;
+ css::uno::Reference<
+ css::chart::XAxis > m_xYAxis;
+ css::uno::Reference<
+ css::chart::XAxis > m_xZAxis;
+ css::uno::Reference<
+ css::chart::XAxis > m_xSecondXAxis;
+ css::uno::Reference<
+ css::chart::XAxis > m_xSecondYAxis;
+
+ css::uno::Reference<
+ css::beans::XPropertySet > m_xWall;
+ css::uno::Reference<
+ css::beans::XPropertySet > m_xFloor;
+
+ css::uno::Reference<
+ css::beans::XPropertySet > m_xMinMaxLineWrapper;
+ css::uno::Reference<
+ css::beans::XPropertySet > m_xUpBarWrapper;
+ css::uno::Reference<
+ css::beans::XPropertySet > m_xDownBarWrapper;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/GridWrapper.cxx b/chart2/source/controller/chartapiwrapper/GridWrapper.cxx
new file mode 100644
index 0000000000..c6f7317cf4
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/GridWrapper.cxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "GridWrapper.hxx"
+#include <AxisHelper.hxx>
+#include "Chart2ModelContact.hxx"
+#include <AxisIndexDefines.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <GridProperties.hxx>
+
+#include <LinePropertiesHelper.hxx>
+#include <UserDefinedProperties.hxx>
+#include <WrappedDefaultProperty.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <algorithm>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart::wrapper
+{
+
+GridWrapper::GridWrapper(tGridType eType, std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : m_spChart2ModelContact(std::move(spChart2ModelContact))
+ , m_eType(eType)
+{
+}
+
+GridWrapper::~GridWrapper()
+{}
+
+void GridWrapper::getDimensionAndSubGridBool( tGridType eType, sal_Int32& rnDimensionIndex, bool& rbSubGrid )
+{
+ rnDimensionIndex = 1;
+ rbSubGrid = false;
+
+ switch( eType )
+ {
+ case X_MAJOR_GRID:
+ rnDimensionIndex = 0; rbSubGrid = false; break;
+ case Y_MAJOR_GRID:
+ rnDimensionIndex = 1; rbSubGrid = false; break;
+ case Z_MAJOR_GRID:
+ rnDimensionIndex = 2; rbSubGrid = false; break;
+ case X_MINOR_GRID:
+ rnDimensionIndex = 0; rbSubGrid = true; break;
+ case Y_MINOR_GRID:
+ rnDimensionIndex = 1; rbSubGrid = true; break;
+ case Z_MINOR_GRID:
+ rnDimensionIndex = 2; rbSubGrid = true; break;
+ }
+}
+
+// ____ XComponent ____
+void SAL_CALL GridWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( xSource ) );
+
+ clearWrappedPropertySet();
+}
+
+void SAL_CALL GridWrapper::addEventListener(
+ const Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL GridWrapper::removeEventListener(
+ const Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+// WrappedPropertySet
+
+Reference< beans::XPropertySet > GridWrapper::getInnerPropertySet()
+{
+ Reference< beans::XPropertySet > xRet;
+ try
+ {
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ rtl::Reference< BaseCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 /*nCooSysIndex*/ ) );
+
+ sal_Int32 nDimensionIndex = 1;
+ bool bSubGrid = false;
+ getDimensionAndSubGridBool( m_eType, nDimensionIndex, bSubGrid );
+
+ sal_Int32 nSubGridIndex = bSubGrid ? 0 : -1;
+ xRet = AxisHelper::getGridProperties( xCooSys , nDimensionIndex, MAIN_AXIS_INDEX, nSubGridIndex );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return xRet;
+}
+
+const Sequence< beans::Property >& GridWrapper::getPropertySequence()
+{
+ static Sequence< Property > aPropSeq = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropSeq;
+}
+
+std::vector< std::unique_ptr<WrappedProperty> > GridWrapper::createWrappedProperties()
+{
+ std::vector< std::unique_ptr<WrappedProperty> > aWrappedProperties;
+
+ aWrappedProperties.emplace_back( new WrappedDefaultProperty( "LineColor", "LineColor", uno::Any( sal_Int32( 0x000000) ) ) ); // black
+
+ return aWrappedProperties;
+}
+
+OUString SAL_CALL GridWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.Grid";
+}
+
+sal_Bool SAL_CALL GridWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL GridWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart.ChartGrid",
+ "com.sun.star.xml.UserDefinedAttributesSupplier",
+ "com.sun.star.drawing.LineProperties",
+ "com.sun.star.beans.PropertySet"
+ };
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/GridWrapper.hxx b/chart2/source/controller/chartapiwrapper/GridWrapper.hxx
new file mode 100644
index 0000000000..c978f3bb8d
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/GridWrapper.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedPropertySet.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <memory>
+
+namespace chart::wrapper
+{
+
+class Chart2ModelContact;
+
+class GridWrapper : public ::cppu::ImplInheritanceHelper<
+ WrappedPropertySet
+ , css::lang::XComponent
+ , css::lang::XServiceInfo
+ >
+{
+public:
+ enum tGridType
+ {
+ X_MAJOR_GRID,
+ Y_MAJOR_GRID,
+ Z_MAJOR_GRID,
+ X_MINOR_GRID,
+ Y_MINOR_GRID,
+ Z_MINOR_GRID
+ };
+
+ GridWrapper(tGridType eType, std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~GridWrapper() override;
+
+ static void getDimensionAndSubGridBool( tGridType eType, sal_Int32& rnDimensionIndex, bool& rbSubGrid );
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+
+protected:
+ // ____ WrappedPropertySet ____
+ virtual const css::uno::Sequence< css::beans::Property >& getPropertySequence() override;
+ virtual std::vector< std::unique_ptr<WrappedProperty> > createWrappedProperties() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override;
+
+private:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+
+ tGridType m_eType;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/LegendWrapper.cxx b/chart2/source/controller/chartapiwrapper/LegendWrapper.cxx
new file mode 100644
index 0000000000..9ec8f02819
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/LegendWrapper.cxx
@@ -0,0 +1,413 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "LegendWrapper.hxx"
+#include "Chart2ModelContact.hxx"
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart/ChartLegendPosition.hpp>
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart/ChartLegendExpansion.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+
+#include <CharacterProperties.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include "WrappedCharacterHeightProperty.hxx"
+#include <PositionAndSizeHelper.hxx>
+#include <WrappedDirectStateProperty.hxx>
+#include "WrappedAutomaticPositionProperties.hxx"
+#include "WrappedScaleTextProperties.hxx"
+
+#include <algorithm>
+#include <utility>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+namespace {
+
+class WrappedLegendAlignmentProperty : public WrappedProperty
+{
+public:
+ WrappedLegendAlignmentProperty();
+
+ virtual void setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const override;
+ virtual Any getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const override;
+
+protected:
+ virtual Any convertInnerToOuterValue( const Any& rInnerValue ) const override;
+ virtual Any convertOuterToInnerValue( const Any& rOuterValue ) const override;
+};
+
+}
+
+WrappedLegendAlignmentProperty::WrappedLegendAlignmentProperty()
+ : ::chart::WrappedProperty( "Alignment", "AnchorPosition" )
+{
+}
+
+Any WrappedLegendAlignmentProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Any aRet;
+ if( xInnerPropertySet.is() )
+ {
+ bool bShowLegend = true;
+ xInnerPropertySet->getPropertyValue( "Show" ) >>= bShowLegend;
+ if(!bShowLegend)
+ {
+ aRet <<= css::chart::ChartLegendPosition_NONE;
+ }
+ else
+ {
+ aRet = xInnerPropertySet->getPropertyValue( m_aInnerName );
+ aRet = convertInnerToOuterValue( aRet );
+ }
+ }
+ return aRet;
+}
+
+void WrappedLegendAlignmentProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if(!xInnerPropertySet.is())
+ return;
+
+ bool bNewShowLegend = true;
+ bool bOldShowLegend = true;
+ {
+ css::chart::ChartLegendPosition eOuterPos(css::chart::ChartLegendPosition_NONE);
+ if( (rOuterValue >>= eOuterPos) && eOuterPos == css::chart::ChartLegendPosition_NONE )
+ bNewShowLegend = false;
+ xInnerPropertySet->getPropertyValue( "Show" ) >>= bOldShowLegend;
+ }
+ if(bNewShowLegend!=bOldShowLegend)
+ {
+ xInnerPropertySet->setPropertyValue( "Show", uno::Any(bNewShowLegend) );
+ }
+ if(!bNewShowLegend)
+ return;
+
+ //set corresponding LegendPosition
+ Any aInnerValue = convertOuterToInnerValue( rOuterValue );
+ xInnerPropertySet->setPropertyValue( m_aInnerName, aInnerValue );
+
+ //correct LegendExpansion
+ chart2::LegendPosition eNewInnerPos(chart2::LegendPosition_LINE_END);
+ if( aInnerValue >>= eNewInnerPos )
+ {
+ css::chart::ChartLegendExpansion eNewExpansion =
+ ( eNewInnerPos == chart2::LegendPosition_LINE_END ||
+ eNewInnerPos == chart2::LegendPosition_LINE_START )
+ ? css::chart::ChartLegendExpansion_HIGH
+ : css::chart::ChartLegendExpansion_WIDE;
+
+ css::chart::ChartLegendExpansion eOldExpansion( css::chart::ChartLegendExpansion_HIGH );
+ bool bExpansionWasSet(
+ xInnerPropertySet->getPropertyValue( "Expansion" ) >>= eOldExpansion );
+
+ if( !bExpansionWasSet || (eOldExpansion != eNewExpansion))
+ xInnerPropertySet->setPropertyValue( "Expansion", uno::Any( eNewExpansion ));
+ }
+
+ //correct RelativePosition
+ Any aRelativePosition( xInnerPropertySet->getPropertyValue("RelativePosition") );
+ if(aRelativePosition.hasValue())
+ {
+ xInnerPropertySet->setPropertyValue( "RelativePosition", Any() );
+ }
+}
+
+Any WrappedLegendAlignmentProperty::convertInnerToOuterValue( const Any& rInnerValue ) const
+{
+ css::chart::ChartLegendPosition ePos = css::chart::ChartLegendPosition_NONE;
+
+ chart2::LegendPosition eNewPos;
+ if( rInnerValue >>= eNewPos )
+ {
+ switch( eNewPos )
+ {
+ case chart2::LegendPosition_LINE_START:
+ ePos = css::chart::ChartLegendPosition_LEFT;
+ break;
+ case chart2::LegendPosition_LINE_END:
+ ePos = css::chart::ChartLegendPosition_RIGHT;
+ break;
+ case chart2::LegendPosition_PAGE_START:
+ ePos = css::chart::ChartLegendPosition_TOP;
+ break;
+ case chart2::LegendPosition_PAGE_END:
+ ePos = css::chart::ChartLegendPosition_BOTTOM;
+ break;
+
+ default:
+ ePos = css::chart::ChartLegendPosition_NONE;
+ break;
+ }
+ }
+ return uno::Any( ePos );
+}
+Any WrappedLegendAlignmentProperty::convertOuterToInnerValue( const Any& rOuterValue ) const
+{
+ chart2::LegendPosition eNewPos = chart2::LegendPosition_LINE_END;
+
+ css::chart::ChartLegendPosition ePos;
+ if( rOuterValue >>= ePos )
+ {
+ switch( ePos )
+ {
+ case css::chart::ChartLegendPosition_LEFT:
+ eNewPos = chart2::LegendPosition_LINE_START;
+ break;
+ case css::chart::ChartLegendPosition_RIGHT:
+ eNewPos = chart2::LegendPosition_LINE_END;
+ break;
+ case css::chart::ChartLegendPosition_TOP:
+ eNewPos = chart2::LegendPosition_PAGE_START;
+ break;
+ case css::chart::ChartLegendPosition_BOTTOM:
+ eNewPos = chart2::LegendPosition_PAGE_END;
+ break;
+ default: // NONE
+ break;
+ }
+ }
+
+ return uno::Any( eNewPos );
+}
+}
+
+namespace
+{
+
+enum
+{
+ PROP_LEGEND_ALIGNMENT,
+ PROP_LEGEND_EXPANSION
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "Alignment",
+ PROP_LEGEND_ALIGNMENT,
+ cppu::UnoType<css::chart::ChartLegendPosition>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "Expansion",
+ PROP_LEGEND_EXPANSION,
+ cppu::UnoType<css::chart::ChartLegendExpansion>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+const Sequence< Property >& StaticLegendWrapperPropertyArray()
+{
+ static Sequence< Property > aPropSeq = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+ ::chart::wrapper::WrappedAutomaticPositionProperties::addProperties( aProperties );
+ ::chart::wrapper::WrappedScaleTextProperties::addProperties( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropSeq;
+};
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+LegendWrapper::LegendWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : m_spChart2ModelContact(std::move(spChart2ModelContact))
+{
+}
+
+LegendWrapper::~LegendWrapper()
+{
+}
+
+// ____ XShape ____
+awt::Point SAL_CALL LegendWrapper::getPosition()
+{
+ return m_spChart2ModelContact->GetLegendPosition();
+}
+
+void SAL_CALL LegendWrapper::setPosition( const awt::Point& aPosition )
+{
+ Reference< beans::XPropertySet > xProp( getInnerPropertySet() );
+ if( xProp.is() )
+ {
+ awt::Size aPageSize( m_spChart2ModelContact->GetPageSize() );
+
+ chart2::RelativePosition aRelativePosition;
+ aRelativePosition.Anchor = drawing::Alignment_TOP_LEFT;
+ aRelativePosition.Primary = aPageSize.Width == 0 ? 0 : double(aPosition.X)/double(aPageSize.Width);
+ aRelativePosition.Secondary = aPageSize.Height == 0 ? 0 : double(aPosition.Y)/double(aPageSize.Height);
+ xProp->setPropertyValue( "RelativePosition", uno::Any(aRelativePosition) );
+ }
+}
+
+awt::Size SAL_CALL LegendWrapper::getSize()
+{
+ return m_spChart2ModelContact->GetLegendSize();
+}
+
+void SAL_CALL LegendWrapper::setSize( const awt::Size& aSize )
+{
+ Reference< beans::XPropertySet > xProp( getInnerPropertySet() );
+ if( xProp.is() )
+ {
+ awt::Size aPageSize( m_spChart2ModelContact->GetPageSize() );
+ awt::Rectangle aPageRectangle( 0,0,aPageSize.Width,aPageSize.Height);
+
+ awt::Point aPos( getPosition() );
+ awt::Rectangle aNewPositionAndSize(aPos.X,aPos.Y,aSize.Width,aSize.Height);
+
+ PositionAndSizeHelper::moveObject( OBJECTTYPE_LEGEND
+ , xProp, aNewPositionAndSize, awt::Rectangle(), aPageRectangle );
+ }
+}
+
+// ____ XShapeDescriptor (base of XShape) ____
+OUString SAL_CALL LegendWrapper::getShapeType()
+{
+ return "com.sun.star.chart.ChartLegend";
+}
+
+// ____ XComponent ____
+void SAL_CALL LegendWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( xSource ) );
+
+ clearWrappedPropertySet();
+}
+
+void SAL_CALL LegendWrapper::addEventListener(
+ const Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL LegendWrapper::removeEventListener(
+ const Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+//ReferenceSizePropertyProvider
+void LegendWrapper::updateReferenceSize()
+{
+ Reference< beans::XPropertySet > xProp = getInnerPropertySet();
+ if( xProp.is() )
+ {
+ if( xProp->getPropertyValue( "ReferencePageSize" ).hasValue() )
+ xProp->setPropertyValue( "ReferencePageSize", uno::Any(
+ m_spChart2ModelContact->GetPageSize() ));
+ }
+}
+Any LegendWrapper::getReferenceSize()
+{
+ Any aRet;
+ Reference< beans::XPropertySet > xProp = getInnerPropertySet();
+ if( xProp.is() )
+ aRet = xProp->getPropertyValue( "ReferencePageSize" );
+
+ return aRet;
+}
+awt::Size LegendWrapper::getCurrentSizeForReference()
+{
+ return m_spChart2ModelContact->GetPageSize();
+}
+
+// WrappedPropertySet
+Reference< beans::XPropertySet > LegendWrapper::getInnerPropertySet()
+{
+ Reference< beans::XPropertySet > xRet;
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() )
+ xRet.set( xDiagram->getLegend(), uno::UNO_QUERY );
+ OSL_ENSURE(xRet.is(),"LegendWrapper::getInnerPropertySet() is NULL");
+ return xRet;
+}
+
+const Sequence< beans::Property >& LegendWrapper::getPropertySequence()
+{
+ return StaticLegendWrapperPropertyArray();
+}
+
+std::vector< std::unique_ptr<WrappedProperty> > LegendWrapper::createWrappedProperties()
+{
+ std::vector< std::unique_ptr<WrappedProperty> > aWrappedProperties;
+
+ aWrappedProperties.emplace_back( new WrappedLegendAlignmentProperty() );
+ aWrappedProperties.emplace_back( new WrappedProperty( "Expansion", "Expansion"));
+ WrappedCharacterHeightProperty::addWrappedProperties( aWrappedProperties, this );
+ //same problem as for wall: the defaults in the old chart are different for different charttypes, so we need to export explicitly
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty("FillStyle", "FillStyle"));
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty("FillColor", "FillColor"));
+ WrappedAutomaticPositionProperties::addWrappedProperties( aWrappedProperties );
+ WrappedScaleTextProperties::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+
+ return aWrappedProperties;
+}
+
+OUString SAL_CALL LegendWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.Legend";
+}
+
+sal_Bool SAL_CALL LegendWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL LegendWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart.ChartLegend",
+ "com.sun.star.drawing.Shape",
+ "com.sun.star.xml.UserDefinedAttributesSupplier",
+ "com.sun.star.style.CharacterProperties"
+ };
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/LegendWrapper.hxx b/chart2/source/controller/chartapiwrapper/LegendWrapper.hxx
new file mode 100644
index 0000000000..5b4deac2a1
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/LegendWrapper.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedPropertySet.hxx>
+#include "ReferenceSizePropertyProvider.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <memory>
+
+namespace chart::wrapper
+{
+
+class Chart2ModelContact;
+
+class LegendWrapper : public ::cppu::ImplInheritanceHelper<
+ WrappedPropertySet
+ , css::drawing::XShape
+ , css::lang::XComponent
+ , css::lang::XServiceInfo
+ >
+ , public ReferenceSizePropertyProvider
+{
+public:
+ explicit LegendWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~LegendWrapper() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ //ReferenceSizePropertyProvider
+ virtual void updateReferenceSize() override;
+ virtual css::uno::Any getReferenceSize() override;
+ virtual css::awt::Size getCurrentSizeForReference() override;
+
+ // ____ XShape ____
+ virtual css::awt::Point SAL_CALL getPosition() override;
+ virtual void SAL_CALL setPosition( const css::awt::Point& aPosition ) override;
+ virtual css::awt::Size SAL_CALL getSize() override;
+ virtual void SAL_CALL setSize( const css::awt::Size& aSize ) override;
+
+ // ____ XShapeDescriptor (base of XShape) ____
+ virtual OUString SAL_CALL getShapeType() override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference<
+ css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference<
+ css::lang::XEventListener >& aListener ) override;
+
+protected:
+ // ____ WrappedPropertySet ____
+ virtual const css::uno::Sequence< css::beans::Property >& getPropertySequence() override;
+ virtual std::vector< std::unique_ptr<WrappedProperty> > createWrappedProperties() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override;
+
+private:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.cxx b/chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.cxx
new file mode 100644
index 0000000000..3b40bcb5a0
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.cxx
@@ -0,0 +1,352 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "MinMaxLineWrapper.hxx"
+#include "Chart2ModelContact.hxx"
+#include <ChartType.hxx>
+#include <DiagramHelper.hxx>
+#include <servicenames_charttypes.hxx>
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <comphelper/sequence.hxx>
+#include <DataSeries.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <UserDefinedProperties.hxx>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+namespace
+{
+
+Sequence< Property >& StaticMinMaxLineWrapperPropertyArray()
+{
+ static Sequence< Property > aPropSeq = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropSeq;
+};
+
+::cppu::OPropertyArrayHelper& StaticMinMaxLineWrapperInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper( StaticMinMaxLineWrapperPropertyArray() );
+ return aPropHelper;
+};
+
+uno::Reference< beans::XPropertySetInfo >& StaticMinMaxLineWrapperInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo( StaticMinMaxLineWrapperInfoHelper() ) );
+ return xPropertySetInfo;
+};
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+MinMaxLineWrapper::MinMaxLineWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : m_spChart2ModelContact(std::move( spChart2ModelContact ))
+ , m_aWrappedLineJointProperty( "LineJoint", uno::Any( drawing::LineJoint_NONE ))
+{
+}
+
+MinMaxLineWrapper::~MinMaxLineWrapper()
+{
+}
+
+// ____ XComponent ____
+void SAL_CALL MinMaxLineWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( xSource ) );
+}
+
+void SAL_CALL MinMaxLineWrapper::addEventListener(
+ const Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL MinMaxLineWrapper::removeEventListener(
+ const Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+//XPropertySet
+uno::Reference< beans::XPropertySetInfo > SAL_CALL MinMaxLineWrapper::getPropertySetInfo()
+{
+ return StaticMinMaxLineWrapperInfo();
+}
+
+void SAL_CALL MinMaxLineWrapper::setPropertyValue( const OUString& rPropertyName, const uno::Any& rValue )
+{
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ const std::vector< rtl::Reference< ChartType > > & aTypes = xDiagram->getChartTypes();
+ for( rtl::Reference< ChartType > const & xType : aTypes )
+ {
+ if( xType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK )
+ {
+ const std::vector< rtl::Reference< DataSeries > > & aSeriesSeq( xType->getDataSeries2() );
+ if(!aSeriesSeq.empty())
+ {
+ if(aSeriesSeq[0].is())
+ {
+ if( rPropertyName == "LineColor" )
+ aSeriesSeq[0]->setPropertyValue( "Color", rValue );
+ else if( rPropertyName == "LineTransparence" )
+ aSeriesSeq[0]->setPropertyValue( "Transparency", rValue );
+ else if( rPropertyName == m_aWrappedLineJointProperty.getOuterName() )
+ m_aWrappedLineJointProperty.setPropertyValue( rValue, aSeriesSeq[0] );
+ else
+ aSeriesSeq[0]->setPropertyValue( rPropertyName, rValue );
+ return;
+ }
+ }
+ }
+ }
+}
+uno::Any SAL_CALL MinMaxLineWrapper::getPropertyValue( const OUString& rPropertyName )
+{
+ Any aRet;
+
+ rtl::Reference< DataSeries > xPropSet;
+
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ const std::vector< rtl::Reference< ChartType > > aTypes = xDiagram->getChartTypes();
+ for( rtl::Reference< ChartType > const & xType : aTypes )
+ {
+ if( xType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK )
+ {
+ const std::vector< rtl::Reference< DataSeries > > & aSeriesSeq( xType->getDataSeries2() );
+ if(!aSeriesSeq.empty())
+ {
+ xPropSet = aSeriesSeq[0];
+ break;
+ }
+ }
+ }
+ if(xPropSet.is())
+ {
+ if( rPropertyName == "LineColor" )
+ aRet = xPropSet->getPropertyValue( "Color" );
+ else if( rPropertyName == "LineTransparence" )
+ aRet = xPropSet->getPropertyValue( "Transparency" );
+ else if( rPropertyName == m_aWrappedLineJointProperty.getOuterName() )
+ aRet = m_aWrappedLineJointProperty.getPropertyValue( xPropSet );
+ else
+ aRet = xPropSet->getPropertyValue( rPropertyName );
+
+ }
+ return aRet;
+}
+
+void SAL_CALL MinMaxLineWrapper::addPropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL MinMaxLineWrapper::removePropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL MinMaxLineWrapper::addVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL MinMaxLineWrapper::removeVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+
+//XMultiPropertySet
+//getPropertySetInfo() already declared in XPropertySet
+void SAL_CALL MinMaxLineWrapper::setPropertyValues( const uno::Sequence< OUString >& rNameSeq, const uno::Sequence< uno::Any >& rValueSeq )
+{
+ sal_Int32 nMinCount = std::min( rValueSeq.getLength(), rNameSeq.getLength() );
+ for(sal_Int32 nN=0; nN<nMinCount; nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ try
+ {
+ setPropertyValue( aPropertyName, rValueSeq[nN] );
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ //todo: store unknown properties elsewhere
+}
+uno::Sequence< uno::Any > SAL_CALL MinMaxLineWrapper::getPropertyValues( const uno::Sequence< OUString >& rNameSeq )
+{
+ Sequence< Any > aRetSeq;
+ if( rNameSeq.hasElements() )
+ {
+ aRetSeq.realloc( rNameSeq.getLength() );
+ auto pRetSeq = aRetSeq.getArray();
+ for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ pRetSeq[nN] = getPropertyValue( aPropertyName );
+ }
+ }
+ return aRetSeq;
+}
+void SAL_CALL MinMaxLineWrapper::addPropertiesChangeListener(
+ const uno::Sequence< OUString >& /* aPropertyNames */,
+ const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL MinMaxLineWrapper::removePropertiesChangeListener(
+ const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL MinMaxLineWrapper::firePropertiesChangeEvent(
+ const uno::Sequence< OUString >& /* aPropertyNames */,
+ const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+//XPropertyState
+beans::PropertyState SAL_CALL MinMaxLineWrapper::getPropertyState( const OUString& rPropertyName )
+{
+ if( rPropertyName == m_aWrappedLineJointProperty.getOuterName() )
+ return beans::PropertyState_DEFAULT_VALUE;
+
+ uno::Any aDefault( getPropertyDefault( rPropertyName ) );
+ uno::Any aValue( getPropertyValue( rPropertyName ) );
+
+ if( aDefault == aValue )
+ return beans::PropertyState_DEFAULT_VALUE;
+
+ return beans::PropertyState_DIRECT_VALUE;
+}
+uno::Sequence< beans::PropertyState > SAL_CALL MinMaxLineWrapper::getPropertyStates( const uno::Sequence< OUString >& rNameSeq )
+{
+ Sequence< beans::PropertyState > aRetSeq;
+ if( rNameSeq.hasElements() )
+ {
+ aRetSeq.realloc( rNameSeq.getLength() );
+ auto pRetSeq = aRetSeq.getArray();
+ for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ pRetSeq[nN] = getPropertyState( aPropertyName );
+ }
+ }
+ return aRetSeq;
+}
+void SAL_CALL MinMaxLineWrapper::setPropertyToDefault( const OUString& rPropertyName )
+{
+ setPropertyValue( rPropertyName, getPropertyDefault(rPropertyName) );
+}
+
+uno::Any SAL_CALL MinMaxLineWrapper::getPropertyDefault( const OUString& rPropertyName )
+{
+ static const ::chart::tPropertyValueMap aStaticDefaults = []
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ return aTmp;
+ }();
+ tPropertyValueMap::const_iterator aFound( aStaticDefaults.find( StaticMinMaxLineWrapperInfoHelper().getHandleByName( rPropertyName ) ) );
+ if( aFound == aStaticDefaults.end() )
+ return uno::Any();
+ return (*aFound).second;
+}
+
+//XMultiPropertyStates
+//getPropertyStates() already declared in XPropertyState
+void SAL_CALL MinMaxLineWrapper::setAllPropertiesToDefault( )
+{
+ const Sequence< beans::Property >& rPropSeq = StaticMinMaxLineWrapperPropertyArray();
+ for(beans::Property const & prop : rPropSeq)
+ {
+ setPropertyToDefault( prop.Name );
+ }
+}
+void SAL_CALL MinMaxLineWrapper::setPropertiesToDefault( const uno::Sequence< OUString >& rNameSeq )
+{
+ for(OUString const & s : rNameSeq)
+ {
+ setPropertyToDefault( s );
+ }
+}
+uno::Sequence< uno::Any > SAL_CALL MinMaxLineWrapper::getPropertyDefaults( const uno::Sequence< OUString >& rNameSeq )
+{
+ Sequence< Any > aRetSeq;
+ if( rNameSeq.hasElements() )
+ {
+ aRetSeq.realloc( rNameSeq.getLength() );
+ auto pRetSeq = aRetSeq.getArray();
+ for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ pRetSeq[nN] = getPropertyDefault( aPropertyName );
+ }
+ }
+ return aRetSeq;
+}
+
+OUString SAL_CALL MinMaxLineWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.ChartLine";
+}
+
+sal_Bool SAL_CALL MinMaxLineWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL MinMaxLineWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart.ChartLine",
+ "com.sun.star.xml.UserDefinedAttributesSupplier",
+ "com.sun.star.drawing.LineProperties"
+ };
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.hxx b/chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.hxx
new file mode 100644
index 0000000000..337ca8bdeb
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/MinMaxLineWrapper.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedIgnoreProperty.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertyStates.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <memory>
+
+namespace chart::wrapper
+{
+
+class Chart2ModelContact;
+
+class MinMaxLineWrapper : public ::cppu::WeakImplHelper
+ < css::lang::XComponent
+ , css::lang::XServiceInfo
+ , css::beans::XPropertySet
+ , css::beans::XMultiPropertySet
+ , css::beans::XPropertyState
+ , css::beans::XMultiPropertyStates
+ >
+{
+public:
+ explicit MinMaxLineWrapper(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~MinMaxLineWrapper() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+
+ //XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+
+ //XMultiPropertySet
+ //getPropertySetInfo() already declared in XPropertySet
+ virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ virtual void SAL_CALL addPropertiesChangeListener( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertiesChangeListener( const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener ) override;
+ virtual void SAL_CALL firePropertiesChangeEvent( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener ) override;
+
+ //XPropertyState
+ virtual css::beans::PropertyState SAL_CALL getPropertyState( const OUString& PropertyName ) override;
+ virtual css::uno::Sequence< css::beans::PropertyState > SAL_CALL getPropertyStates( const css::uno::Sequence< OUString >& aPropertyName ) override;
+ virtual void SAL_CALL setPropertyToDefault( const OUString& PropertyName ) override;
+ virtual css::uno::Any SAL_CALL getPropertyDefault( const OUString& aPropertyName ) override;
+
+ //XMultiPropertyStates
+ //getPropertyStates() already declared in XPropertyState
+ virtual void SAL_CALL setAllPropertiesToDefault( ) override;
+ virtual void SAL_CALL setPropertiesToDefault( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPropertyDefaults( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+
+private: //member
+ std::mutex m_aMutex;
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+
+ WrappedIgnoreProperty m_aWrappedLineJointProperty;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/ReferenceSizePropertyProvider.hxx b/chart2/source/controller/chartapiwrapper/ReferenceSizePropertyProvider.hxx
new file mode 100644
index 0000000000..4451c3cce7
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/ReferenceSizePropertyProvider.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/awt/Size.hpp>
+
+namespace chart::wrapper
+{
+class ReferenceSizePropertyProvider
+{
+public:
+ virtual void updateReferenceSize() = 0;
+ virtual css::uno::Any getReferenceSize() = 0;
+ virtual css::awt::Size getCurrentSizeForReference() = 0;
+
+protected:
+ ~ReferenceSizePropertyProvider() {}
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/TitleWrapper.cxx b/chart2/source/controller/chartapiwrapper/TitleWrapper.cxx
new file mode 100644
index 0000000000..75d6c9e98f
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/TitleWrapper.cxx
@@ -0,0 +1,502 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "TitleWrapper.hxx"
+#include "Chart2ModelContact.hxx"
+#include <ControllerLockGuard.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/XTitle.hpp>
+
+#include <CharacterProperties.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include "WrappedCharacterHeightProperty.hxx"
+#include "WrappedTextRotationProperty.hxx"
+#include "WrappedAutomaticPositionProperties.hxx"
+#include "WrappedScaleTextProperties.hxx"
+
+#include <algorithm>
+#include <rtl/ustrbuf.hxx>
+#include <cppuhelper/propshlp.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+namespace {
+
+class WrappedTitleStringProperty : public WrappedProperty
+{
+public:
+ explicit WrappedTitleStringProperty( const Reference< uno::XComponentContext >& xContext );
+
+ virtual void setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const override;
+ virtual Any getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const override;
+ virtual Any getPropertyDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const override;
+
+protected:
+ Reference< uno::XComponentContext > m_xContext;
+};
+
+}
+
+WrappedTitleStringProperty::WrappedTitleStringProperty( const Reference< uno::XComponentContext >& xContext )
+ : ::chart::WrappedProperty( "String", OUString() )
+ , m_xContext( xContext )
+{
+}
+
+void WrappedTitleStringProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Title* pTitle = dynamic_cast<Title*>(xInnerPropertySet.get());
+ if(pTitle)
+ {
+ OUString aString;
+ rOuterValue >>= aString;
+ TitleHelper::setCompleteString( aString, pTitle, m_xContext );
+ }
+}
+Any WrappedTitleStringProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Any aRet( getPropertyDefault( Reference< beans::XPropertyState >( xInnerPropertySet, uno::UNO_QUERY ) ) );
+ Reference< chart2::XTitle > xTitle(xInnerPropertySet,uno::UNO_QUERY);
+ if(xTitle.is())
+ {
+ const Sequence< Reference< chart2::XFormattedString > > aStrings( xTitle->getText());
+
+ OUStringBuffer aBuf;
+ for( Reference< chart2::XFormattedString > const & formattedStr : aStrings )
+ {
+ aBuf.append( formattedStr->getString());
+ }
+ aRet <<= aBuf.makeStringAndClear();
+ }
+ return aRet;
+}
+Any WrappedTitleStringProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ return uno::Any( OUString() );//default title is an empty String
+}
+
+namespace {
+
+class WrappedStackedTextProperty : public WrappedProperty
+{
+public:
+ WrappedStackedTextProperty();
+};
+
+}
+
+WrappedStackedTextProperty::WrappedStackedTextProperty()
+ : ::chart::WrappedProperty( "StackedText", "StackCharacters" )
+{
+}
+
+}// end namespace chart
+
+namespace
+{
+
+enum
+{
+ PROP_TITLE_STRING,
+ PROP_TITLE_TEXT_ROTATION,
+ PROP_TITLE_TEXT_STACKED
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "String",
+ PROP_TITLE_STRING,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "TextRotation",
+ PROP_TITLE_TEXT_ROTATION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "StackedText",
+ PROP_TITLE_TEXT_STACKED,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+const Sequence< Property > & StaticTitleWrapperPropertyArray()
+{
+ static Sequence< Property > aPropSeq = []()
+ {
+ std::vector< beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+ ::chart::wrapper::WrappedAutomaticPositionProperties::addProperties( aProperties );
+ ::chart::wrapper::WrappedScaleTextProperties::addProperties( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropSeq;
+};
+
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+TitleWrapper::TitleWrapper( ::chart::TitleHelper::eTitleType eTitleType,
+ std::shared_ptr<Chart2ModelContact> spChart2ModelContact ) :
+ m_spChart2ModelContact(std::move( spChart2ModelContact )),
+ m_eTitleType(eTitleType)
+{
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ if( !getTitleObject().is() ) //#i83831# create an empty title at the model, thus references to properties can be mapped correctly
+ TitleHelper::createTitle( m_eTitleType, OUString(), m_spChart2ModelContact->getDocumentModel(), m_spChart2ModelContact->m_xContext );
+}
+
+TitleWrapper::~TitleWrapper()
+{
+}
+
+// ____ XShape ____
+awt::Point SAL_CALL TitleWrapper::getPosition()
+{
+ return m_spChart2ModelContact->GetTitlePosition( getTitleObject() );
+}
+
+void SAL_CALL TitleWrapper::setPosition( const awt::Point& aPosition )
+{
+ Reference< beans::XPropertySet > xPropertySet( getInnerPropertySet() );
+ if(xPropertySet.is())
+ {
+ awt::Size aPageSize( m_spChart2ModelContact->GetPageSize() );
+
+ chart2::RelativePosition aRelativePosition;
+ aRelativePosition.Anchor = drawing::Alignment_TOP_LEFT;
+ aRelativePosition.Primary = double(aPosition.X)/double(aPageSize.Width);
+ aRelativePosition.Secondary = double(aPosition.Y)/double(aPageSize.Height);
+ xPropertySet->setPropertyValue( "RelativePosition", uno::Any(aRelativePosition) );
+ }
+}
+
+awt::Size SAL_CALL TitleWrapper::getSize()
+{
+ return m_spChart2ModelContact->GetTitleSize( getTitleObject() );
+}
+
+void SAL_CALL TitleWrapper::setSize( const awt::Size& /*aSize*/ )
+{
+ OSL_FAIL( "trying to set size of title" );
+}
+
+// ____ XShapeDescriptor (base of XShape) ____
+OUString SAL_CALL TitleWrapper::getShapeType()
+{
+ return "com.sun.star.chart.ChartTitle";
+}
+
+// ____ XComponent ____
+void SAL_CALL TitleWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( xSource ) );
+
+ clearWrappedPropertySet();
+}
+
+void SAL_CALL TitleWrapper::addEventListener(
+ const Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL TitleWrapper::removeEventListener(
+ const Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+Reference< beans::XPropertySet > TitleWrapper::getFirstCharacterPropertySet()
+{
+ Reference< beans::XPropertySet > xProp;
+
+ Reference< chart2::XTitle > xTitle( getTitleObject() );
+ if( xTitle.is())
+ {
+ Sequence< Reference< chart2::XFormattedString > > aStrings( xTitle->getText());
+ if( aStrings.hasElements() )
+ xProp.set( aStrings[0], uno::UNO_QUERY );
+ }
+
+ return xProp;
+}
+
+void TitleWrapper::getFastCharacterPropertyValue( sal_Int32 nHandle, Any& rValue )
+{
+ OSL_ASSERT( FAST_PROPERTY_ID_START_CHAR_PROP <= nHandle &&
+ nHandle < CharacterProperties::FAST_PROPERTY_ID_END_CHAR_PROP );
+
+ Reference< beans::XPropertySet > xProp = getFirstCharacterPropertySet();
+ Reference< beans::XFastPropertySet > xFastProp( xProp, uno::UNO_QUERY );
+ if(xProp.is())
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( nHandle );
+ if( pWrappedProperty )
+ {
+ rValue = pWrappedProperty->getPropertyValue( xProp );
+ }
+ else if( xFastProp.is() )
+ {
+ rValue = xFastProp->getFastPropertyValue( nHandle );
+ }
+ }
+
+}
+
+void TitleWrapper::setFastCharacterPropertyValue(
+ sal_Int32 nHandle, const Any& rValue )
+{
+ OSL_ASSERT( FAST_PROPERTY_ID_START_CHAR_PROP <= nHandle &&
+ nHandle < CharacterProperties::FAST_PROPERTY_ID_END_CHAR_PROP );
+
+ Reference< chart2::XTitle > xTitle( getTitleObject() );
+ if( !xTitle.is())
+ return;
+
+ const Sequence< Reference< chart2::XFormattedString > > aStrings( xTitle->getText());
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( nHandle );
+
+ for( Reference< chart2::XFormattedString > const & formattedStr : aStrings )
+ {
+ Reference< beans::XFastPropertySet > xFastPropertySet( formattedStr, uno::UNO_QUERY );
+ Reference< beans::XPropertySet > xPropSet( xFastPropertySet, uno::UNO_QUERY );
+
+ if( pWrappedProperty )
+ pWrappedProperty->setPropertyValue( rValue, xPropSet );
+ else if( xFastPropertySet.is() )
+ xFastPropertySet->setFastPropertyValue( nHandle, rValue );
+ }
+}
+
+// WrappedPropertySet
+
+void SAL_CALL TitleWrapper::setPropertyValue( const OUString& rPropertyName, const Any& rValue )
+{
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ if( CharacterProperties::IsCharacterPropertyHandle( nHandle ) )
+ {
+ setFastCharacterPropertyValue( nHandle, rValue );
+ }
+ else
+ WrappedPropertySet::setPropertyValue( rPropertyName, rValue );
+}
+
+Any SAL_CALL TitleWrapper::getPropertyValue( const OUString& rPropertyName )
+{
+ Any aRet;
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ if( CharacterProperties::IsCharacterPropertyHandle( nHandle ) )
+ getFastCharacterPropertyValue( nHandle, aRet );
+ else
+ aRet = WrappedPropertySet::getPropertyValue( rPropertyName );
+ return aRet;
+}
+
+beans::PropertyState SAL_CALL TitleWrapper::getPropertyState( const OUString& rPropertyName )
+{
+ beans::PropertyState aState( beans::PropertyState_DIRECT_VALUE );
+
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ if( CharacterProperties::IsCharacterPropertyHandle( nHandle ) )
+ {
+ Reference< beans::XPropertyState > xPropState( getFirstCharacterPropertySet(), uno::UNO_QUERY );
+ if( xPropState.is() )
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName );
+ if( pWrappedProperty )
+ aState = pWrappedProperty->getPropertyState( xPropState );
+ else
+ aState = xPropState->getPropertyState( rPropertyName );
+ }
+ }
+ else
+ aState = WrappedPropertySet::getPropertyState( rPropertyName );
+
+ return aState;
+}
+void SAL_CALL TitleWrapper::setPropertyToDefault( const OUString& rPropertyName )
+{
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ if( CharacterProperties::IsCharacterPropertyHandle( nHandle ) )
+ {
+ Any aDefault = getPropertyDefault( rPropertyName );
+ setFastCharacterPropertyValue( nHandle, aDefault );
+ }
+ else
+ WrappedPropertySet::setPropertyToDefault( rPropertyName );
+}
+Any SAL_CALL TitleWrapper::getPropertyDefault( const OUString& rPropertyName )
+{
+ Any aRet;
+
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ if( CharacterProperties::IsCharacterPropertyHandle( nHandle ) )
+ {
+ Reference< beans::XPropertyState > xPropState( getFirstCharacterPropertySet(), uno::UNO_QUERY );
+ if( xPropState.is() )
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName );
+ if( pWrappedProperty )
+ aRet = pWrappedProperty->getPropertyDefault(xPropState);
+ else
+ aRet = xPropState->getPropertyDefault( rPropertyName );
+ }
+ }
+ else
+ aRet = WrappedPropertySet::getPropertyDefault( rPropertyName );
+
+ return aRet;
+}
+
+void SAL_CALL TitleWrapper::addPropertyChangeListener( const OUString& rPropertyName, const Reference< beans::XPropertyChangeListener >& xListener )
+{
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ if( CharacterProperties::IsCharacterPropertyHandle( nHandle ) )
+ {
+ Reference< beans::XPropertySet > xPropSet = getFirstCharacterPropertySet();
+ if( xPropSet.is() )
+ xPropSet->addPropertyChangeListener( rPropertyName, xListener );
+ }
+ else
+ WrappedPropertySet::addPropertyChangeListener( rPropertyName, xListener );
+}
+void SAL_CALL TitleWrapper::removePropertyChangeListener( const OUString& rPropertyName, const Reference< beans::XPropertyChangeListener >& xListener )
+{
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ if( CharacterProperties::IsCharacterPropertyHandle( nHandle ) )
+ {
+ Reference< beans::XPropertySet > xPropSet = getFirstCharacterPropertySet();
+ if( xPropSet.is() )
+ xPropSet->removePropertyChangeListener( rPropertyName, xListener );
+ }
+ else
+ WrappedPropertySet::removePropertyChangeListener( rPropertyName, xListener );
+}
+
+//ReferenceSizePropertyProvider
+void TitleWrapper::updateReferenceSize()
+{
+ Reference< beans::XPropertySet > xProp( getTitleObject(), uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ if( xProp->getPropertyValue( "ReferencePageSize" ).hasValue() )
+ xProp->setPropertyValue( "ReferencePageSize", uno::Any(
+ m_spChart2ModelContact->GetPageSize() ));
+ }
+}
+Any TitleWrapper::getReferenceSize()
+{
+ Any aRet;
+ Reference< beans::XPropertySet > xProp( getTitleObject(), uno::UNO_QUERY );
+ if( xProp.is() )
+ aRet = xProp->getPropertyValue( "ReferencePageSize" );
+
+ return aRet;
+}
+awt::Size TitleWrapper::getCurrentSizeForReference()
+{
+ return m_spChart2ModelContact->GetPageSize();
+}
+
+Reference< chart2::XTitle > TitleWrapper::getTitleObject()
+{
+ return TitleHelper::getTitle( m_eTitleType, m_spChart2ModelContact->getDocumentModel() );
+}
+
+// WrappedPropertySet
+
+Reference< beans::XPropertySet > TitleWrapper::getInnerPropertySet()
+{
+ return Reference< beans::XPropertySet >( getTitleObject(), uno::UNO_QUERY );
+}
+
+const Sequence< beans::Property >& TitleWrapper::getPropertySequence()
+{
+ return StaticTitleWrapperPropertyArray();
+}
+
+std::vector< std::unique_ptr<WrappedProperty> > TitleWrapper::createWrappedProperties()
+{
+ std::vector< std::unique_ptr<WrappedProperty> > aWrappedProperties;
+
+ aWrappedProperties.emplace_back( new WrappedTitleStringProperty( m_spChart2ModelContact->m_xContext ) );
+ aWrappedProperties.emplace_back( new WrappedTextRotationProperty( true ) );
+ aWrappedProperties.emplace_back( new WrappedStackedTextProperty() );
+ WrappedCharacterHeightProperty::addWrappedProperties( aWrappedProperties, this );
+ WrappedAutomaticPositionProperties::addWrappedProperties( aWrappedProperties );
+ WrappedScaleTextProperties::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
+
+ return aWrappedProperties;
+}
+
+OUString SAL_CALL TitleWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.Title";
+}
+
+sal_Bool SAL_CALL TitleWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL TitleWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart.ChartTitle",
+ "com.sun.star.drawing.Shape",
+ "com.sun.star.xml.UserDefinedAttributesSupplier",
+ "com.sun.star.style.CharacterProperties"
+ };
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/TitleWrapper.hxx b/chart2/source/controller/chartapiwrapper/TitleWrapper.hxx
new file mode 100644
index 0000000000..aecf5f3042
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/TitleWrapper.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedPropertySet.hxx>
+#include "ReferenceSizePropertyProvider.hxx"
+#include <TitleHelper.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <memory>
+
+namespace chart::wrapper { class Chart2ModelContact; }
+namespace com::sun::star::chart2 { class XTitle; }
+
+namespace chart::wrapper
+{
+
+class TitleWrapper final : public ::cppu::ImplInheritanceHelper<
+ WrappedPropertySet
+ , css::drawing::XShape
+ , css::lang::XComponent
+ , css::lang::XServiceInfo
+ >
+ , public ReferenceSizePropertyProvider
+{
+public:
+ TitleWrapper( ::chart::TitleHelper::eTitleType eTitleType,
+ std::shared_ptr<Chart2ModelContact> spChart2ModelContact );
+ virtual ~TitleWrapper() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ //ReferenceSizePropertyProvider
+ virtual void updateReferenceSize() override;
+ virtual css::uno::Any getReferenceSize() override;
+ virtual css::awt::Size getCurrentSizeForReference() override;
+
+private:
+ // ____ XShape ____
+ virtual css::awt::Point SAL_CALL getPosition() override;
+ virtual void SAL_CALL setPosition( const css::awt::Point& aPosition ) override;
+ virtual css::awt::Size SAL_CALL getSize() override;
+ virtual void SAL_CALL setSize( const css::awt::Size& aSize ) override;
+
+ // ____ XShapeDescriptor (base of XShape) ____
+ virtual OUString SAL_CALL getShapeType() override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+
+ // character properties have to be handled differently (via the XFormattedString elements)
+ void getFastCharacterPropertyValue( sal_Int32 nHandle, css::uno::Any& rValue );
+ /// @throws css::uno::Exception
+ void setFastCharacterPropertyValue( sal_Int32 nHandle, const css::uno::Any& rValue );
+
+ // ____ WrappedPropertySet ____
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+
+ virtual css::beans::PropertyState SAL_CALL getPropertyState( const OUString& PropertyName ) override;
+
+ virtual void SAL_CALL setPropertyToDefault( const OUString& PropertyName ) override;
+ virtual css::uno::Any SAL_CALL getPropertyDefault( const OUString& aPropertyName ) override;
+
+ virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override;
+
+ virtual const css::uno::Sequence< css::beans::Property >& getPropertySequence() override;
+ virtual std::vector< std::unique_ptr<WrappedProperty> > createWrappedProperties() override;
+
+ css::uno::Reference< css::beans::XPropertySet > getFirstCharacterPropertySet();
+
+ css::uno::Reference< css::chart2::XTitle > getTitleObject();
+
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+
+ ::chart::TitleHelper::eTitleType m_eTitleType;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/UpDownBarWrapper.cxx b/chart2/source/controller/chartapiwrapper/UpDownBarWrapper.cxx
new file mode 100644
index 0000000000..721fa26682
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/UpDownBarWrapper.cxx
@@ -0,0 +1,317 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "UpDownBarWrapper.hxx"
+#include "Chart2ModelContact.hxx"
+#include <ChartType.hxx>
+#include <DiagramHelper.hxx>
+#include <servicenames_charttypes.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/propshlp.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+namespace
+{
+
+const Sequence< Property > & StaticUpDownBarWrapperPropertyArray()
+{
+ static Sequence< Property > aPropSeq = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropSeq;
+};
+
+::cppu::OPropertyArrayHelper& StaticUpDownBarWrapperInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper( StaticUpDownBarWrapperPropertyArray() );
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+UpDownBarWrapper::UpDownBarWrapper(
+ bool bUp, std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : m_spChart2ModelContact(std::move( spChart2ModelContact ))
+ , m_aPropertySetName( bUp ? OUString( "WhiteDay" ) : OUString( "BlackDay" ))
+{
+}
+
+UpDownBarWrapper::~UpDownBarWrapper()
+{
+}
+
+// ____ XComponent ____
+void SAL_CALL UpDownBarWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( xSource ) );
+}
+
+void SAL_CALL UpDownBarWrapper::addEventListener(
+ const Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL UpDownBarWrapper::removeEventListener(
+ const Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+//XPropertySet
+uno::Reference< beans::XPropertySetInfo > SAL_CALL UpDownBarWrapper::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticUpDownBarWrapperInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+void SAL_CALL UpDownBarWrapper::setPropertyValue( const OUString& rPropertyName, const uno::Any& rValue )
+{
+ Reference< beans::XPropertySet > xPropSet;
+
+ const std::vector< rtl::Reference< ChartType > > aTypes =
+ m_spChart2ModelContact->getDiagram()->getChartTypes();
+ for( rtl::Reference< ChartType > const & xType : aTypes )
+ {
+ if( xType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK )
+ {
+ xType->getPropertyValue( m_aPropertySetName ) >>= xPropSet;
+ }
+ }
+ if(xPropSet.is())
+ xPropSet->setPropertyValue( rPropertyName, rValue );
+}
+uno::Any SAL_CALL UpDownBarWrapper::getPropertyValue( const OUString& rPropertyName )
+{
+ Any aRet;
+
+ Reference< beans::XPropertySet > xPropSet;
+
+ const std::vector< rtl::Reference< ChartType > > aTypes =
+ m_spChart2ModelContact->getDiagram()->getChartTypes();
+ for( rtl::Reference<ChartType > const & xType : aTypes )
+ {
+ if( xType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK )
+ {
+ xType->getPropertyValue( m_aPropertySetName ) >>= xPropSet;
+ }
+ }
+ if(xPropSet.is())
+ aRet = xPropSet->getPropertyValue( rPropertyName );
+ return aRet;
+}
+
+void SAL_CALL UpDownBarWrapper::addPropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL UpDownBarWrapper::removePropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL UpDownBarWrapper::addVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL UpDownBarWrapper::removeVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
+{
+ OSL_FAIL("not implemented");
+}
+
+//XMultiPropertySet
+//getPropertySetInfo() already declared in XPropertySet
+void SAL_CALL UpDownBarWrapper::setPropertyValues( const uno::Sequence< OUString >& rNameSeq, const uno::Sequence< uno::Any >& rValueSeq )
+{
+ sal_Int32 nMinCount = std::min( rValueSeq.getLength(), rNameSeq.getLength() );
+ for(sal_Int32 nN=0; nN<nMinCount; nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ try
+ {
+ setPropertyValue( aPropertyName, rValueSeq[nN] );
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ //todo: store unknown properties elsewhere
+}
+uno::Sequence< uno::Any > SAL_CALL UpDownBarWrapper::getPropertyValues( const uno::Sequence< OUString >& rNameSeq )
+{
+ Sequence< Any > aRetSeq;
+ if( rNameSeq.hasElements() )
+ {
+ aRetSeq.realloc( rNameSeq.getLength() );
+ auto pRetSeq = aRetSeq.getArray();
+ for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ pRetSeq[nN] = getPropertyValue( aPropertyName );
+ }
+ }
+ return aRetSeq;
+}
+void SAL_CALL UpDownBarWrapper::addPropertiesChangeListener( const uno::Sequence< OUString >& /* aPropertyNames */, const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL UpDownBarWrapper::removePropertiesChangeListener( const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL UpDownBarWrapper::firePropertiesChangeEvent( const uno::Sequence< OUString >& /* aPropertyNames */, const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+//XPropertyState
+beans::PropertyState SAL_CALL UpDownBarWrapper::getPropertyState( const OUString& rPropertyName )
+{
+ uno::Any aDefault( getPropertyDefault( rPropertyName ) );
+ uno::Any aValue( getPropertyValue( rPropertyName ) );
+
+ if( aDefault == aValue )
+ return beans::PropertyState_DEFAULT_VALUE;
+
+ return beans::PropertyState_DIRECT_VALUE;
+}
+uno::Sequence< beans::PropertyState > SAL_CALL UpDownBarWrapper::getPropertyStates( const uno::Sequence< OUString >& rNameSeq )
+{
+ Sequence< beans::PropertyState > aRetSeq;
+ if( rNameSeq.hasElements() )
+ {
+ aRetSeq.realloc( rNameSeq.getLength() );
+ auto pRetSeq = aRetSeq.getArray();
+ for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ pRetSeq[nN] = getPropertyState( aPropertyName );
+ }
+ }
+ return aRetSeq;
+}
+void SAL_CALL UpDownBarWrapper::setPropertyToDefault( const OUString& rPropertyName )
+{
+ setPropertyValue( rPropertyName, getPropertyDefault(rPropertyName) );
+}
+
+uno::Any SAL_CALL UpDownBarWrapper::getPropertyDefault( const OUString& rPropertyName )
+{
+ static const ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+ return aTmp;
+ }();
+ tPropertyValueMap::const_iterator aFound( aStaticDefaults.find( StaticUpDownBarWrapperInfoHelper().getHandleByName( rPropertyName ) ) );
+ if( aFound == aStaticDefaults.end() )
+ return uno::Any();
+ return (*aFound).second;
+}
+
+//XMultiPropertyStates
+//getPropertyStates() already declared in XPropertyState
+void SAL_CALL UpDownBarWrapper::setAllPropertiesToDefault( )
+{
+ const Sequence< beans::Property >& rPropSeq = StaticUpDownBarWrapperPropertyArray();
+ for(beans::Property const & prop : rPropSeq)
+ {
+ setPropertyToDefault( prop.Name );
+ }
+}
+void SAL_CALL UpDownBarWrapper::setPropertiesToDefault( const uno::Sequence< OUString >& rNameSeq )
+{
+ for(OUString const & s : rNameSeq)
+ {
+ setPropertyToDefault( s );
+ }
+}
+uno::Sequence< uno::Any > SAL_CALL UpDownBarWrapper::getPropertyDefaults( const uno::Sequence< OUString >& rNameSeq )
+{
+ Sequence< Any > aRetSeq;
+ if( rNameSeq.hasElements() )
+ {
+ aRetSeq.realloc( rNameSeq.getLength() );
+ auto pRetSeq = aRetSeq.getArray();
+ for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ pRetSeq[nN] = getPropertyDefault( aPropertyName );
+ }
+ }
+ return aRetSeq;
+}
+
+OUString SAL_CALL UpDownBarWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.ChartArea";
+}
+
+sal_Bool SAL_CALL UpDownBarWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL UpDownBarWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart.ChartArea",
+ "com.sun.star.drawing.LineProperties",
+ "com.sun.star.drawing.FillProperties",
+ "com.sun.star.xml.UserDefinedAttributesSupplier"
+ };
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/UpDownBarWrapper.hxx b/chart2/source/controller/chartapiwrapper/UpDownBarWrapper.hxx
new file mode 100644
index 0000000000..740097fc30
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/UpDownBarWrapper.hxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <comphelper/interfacecontainer4.hxx>
+
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertyStates.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <memory>
+
+namespace chart::wrapper
+{
+
+class Chart2ModelContact;
+
+class UpDownBarWrapper : public ::cppu::WeakImplHelper
+ < css::lang::XComponent
+ , css::lang::XServiceInfo
+ , css::beans::XPropertySet
+ , css::beans::XMultiPropertySet
+ , css::beans::XPropertyState
+ , css::beans::XMultiPropertyStates
+ >
+{
+public:
+ UpDownBarWrapper(bool bUp, std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~UpDownBarWrapper() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference<
+ css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference<
+ css::lang::XEventListener >& aListener ) override;
+
+ //XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+
+ //XMultiPropertySet
+ //getPropertySetInfo() already declared in XPropertySet
+ virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ virtual void SAL_CALL addPropertiesChangeListener( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertiesChangeListener( const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener ) override;
+ virtual void SAL_CALL firePropertiesChangeEvent( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener ) override;
+
+ //XPropertyState
+ virtual css::beans::PropertyState SAL_CALL getPropertyState( const OUString& PropertyName ) override;
+ virtual css::uno::Sequence< css::beans::PropertyState > SAL_CALL getPropertyStates( const css::uno::Sequence< OUString >& aPropertyName ) override;
+ virtual void SAL_CALL setPropertyToDefault( const OUString& PropertyName ) override;
+ virtual css::uno::Any SAL_CALL getPropertyDefault( const OUString& aPropertyName ) override;
+
+ //XMultiPropertyStates
+ //getPropertyStates() already declared in XPropertyState
+ virtual void SAL_CALL setAllPropertiesToDefault( ) override;
+ virtual void SAL_CALL setPropertiesToDefault( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPropertyDefaults( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+
+private: //member
+ std::mutex m_aMutex;
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+
+ OUString m_aPropertySetName;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WallFloorWrapper.cxx b/chart2/source/controller/chartapiwrapper/WallFloorWrapper.cxx
new file mode 100644
index 0000000000..dc5742aef6
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WallFloorWrapper.cxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WallFloorWrapper.hxx"
+#include "Chart2ModelContact.hxx"
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <FillProperties.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <UserDefinedProperties.hxx>
+#include <WrappedDirectStateProperty.hxx>
+
+#include <algorithm>
+#include <utility>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart::wrapper
+{
+
+WallFloorWrapper::WallFloorWrapper( bool bWall,
+ std::shared_ptr<Chart2ModelContact> spChart2ModelContact ) :
+ m_spChart2ModelContact(std::move( spChart2ModelContact )),
+ m_bWall( bWall )
+
+{
+}
+
+WallFloorWrapper::~WallFloorWrapper()
+{
+}
+
+// ____ XComponent ____
+void SAL_CALL WallFloorWrapper::dispose()
+{
+ std::unique_lock g(m_aMutex);
+ Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ m_aEventListenerContainer.disposeAndClear( g, lang::EventObject( xSource ) );
+
+ clearWrappedPropertySet();
+}
+
+void SAL_CALL WallFloorWrapper::addEventListener(
+ const Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.addInterface( g, xListener );
+}
+
+void SAL_CALL WallFloorWrapper::removeEventListener(
+ const Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aEventListenerContainer.removeInterface( g, aListener );
+}
+
+// WrappedPropertySet
+Reference< beans::XPropertySet > WallFloorWrapper::getInnerPropertySet()
+{
+ Reference< beans::XPropertySet > xRet;
+
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() )
+ {
+ if( m_bWall )
+ xRet.set( xDiagram->getWall() );
+ else
+ xRet.set( xDiagram->getFloor() );
+ }
+
+ return xRet;
+}
+
+const Sequence< beans::Property >& WallFloorWrapper::getPropertySequence()
+{
+ static Sequence< Property > aPropSeq = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropSeq;
+}
+
+std::vector< std::unique_ptr<WrappedProperty> > WallFloorWrapper::createWrappedProperties()
+{
+ std::vector< std::unique_ptr<WrappedProperty> > aWrappedProperties;
+
+ // use direct state always, so that in XML the value is always
+ // exported. Because in the old chart the defaults is as follows:
+ // Floor: SOLID (new and old model default), Wall: NONE, except for some chart types (line, scatter)
+ if( m_bWall )
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty( "FillStyle", "FillStyle" ));
+ aWrappedProperties.emplace_back( new WrappedDirectStateProperty( "FillColor", "FillColor" ));
+
+ return aWrappedProperties;
+}
+
+OUString SAL_CALL WallFloorWrapper::getImplementationName()
+{
+ return "com.sun.star.comp.chart.WallOrFloor";
+}
+
+sal_Bool SAL_CALL WallFloorWrapper::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL WallFloorWrapper::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.xml.UserDefinedAttributesSupplier",
+ "com.sun.star.drawing.FillProperties",
+ "com.sun.star.drawing.LineProperties",
+ "com.sun.star.beans.PropertySet"
+ };
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WallFloorWrapper.hxx b/chart2/source/controller/chartapiwrapper/WallFloorWrapper.hxx
new file mode 100644
index 0000000000..4a85bd8d5b
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WallFloorWrapper.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedPropertySet.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <memory>
+
+namespace chart::wrapper
+{
+
+class Chart2ModelContact;
+
+class WallFloorWrapper : public ::cppu::ImplInheritanceHelper<
+ WrappedPropertySet
+ , css::lang::XComponent
+ , css::lang::XServiceInfo
+ >
+{
+public:
+ WallFloorWrapper(bool bWall, std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~WallFloorWrapper() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+
+protected:
+ // ____ WrappedPropertySet ____
+ virtual const css::uno::Sequence< css::beans::Property >& getPropertySequence() override;
+ virtual std::vector< std::unique_ptr<WrappedProperty> > createWrappedProperties() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override;
+
+private:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListenerContainer;
+
+ bool m_bWall;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedAddInProperty.cxx b/chart2/source/controller/chartapiwrapper/WrappedAddInProperty.cxx
new file mode 100644
index 0000000000..24a6dfb78a
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedAddInProperty.cxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedAddInProperty.hxx"
+#include <ChartDocumentWrapper.hxx>
+#include <com/sun/star/util/XRefreshable.hpp>
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using namespace ::com::sun::star;
+
+namespace chart::wrapper
+{
+
+WrappedAddInProperty::WrappedAddInProperty( ChartDocumentWrapper& rChartDocumentWrapper )
+ : ::chart::WrappedProperty( "AddIn", OUString() )
+ , m_rChartDocumentWrapper( rChartDocumentWrapper )
+{
+}
+WrappedAddInProperty::~WrappedAddInProperty()
+{
+}
+
+void WrappedAddInProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ Reference< util::XRefreshable > xAddIn;
+ if( ! (rOuterValue >>= xAddIn) )
+ throw lang::IllegalArgumentException( "AddIn properties require type XRefreshable", nullptr, 0 );
+
+ m_rChartDocumentWrapper.setAddIn( xAddIn );
+}
+
+Any WrappedAddInProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ return uno::Any( m_rChartDocumentWrapper.getAddIn() );
+}
+
+WrappedBaseDiagramProperty::WrappedBaseDiagramProperty( ChartDocumentWrapper& rChartDocumentWrapper )
+ : ::chart::WrappedProperty( "BaseDiagram" , OUString() )
+ , m_rChartDocumentWrapper( rChartDocumentWrapper )
+{
+}
+WrappedBaseDiagramProperty::~WrappedBaseDiagramProperty()
+{
+}
+
+void WrappedBaseDiagramProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ OUString aBaseDiagram;
+ if( ! (rOuterValue >>= aBaseDiagram) )
+ throw lang::IllegalArgumentException( "BaseDiagram properties require type OUString", nullptr, 0 );
+
+ m_rChartDocumentWrapper.setBaseDiagram( aBaseDiagram );
+}
+
+Any WrappedBaseDiagramProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ return uno::Any( m_rChartDocumentWrapper.getBaseDiagram() );
+}
+
+WrappedAdditionalShapesProperty::WrappedAdditionalShapesProperty( ChartDocumentWrapper& rChartDocumentWrapper )
+ : ::chart::WrappedProperty( "AdditionalShapes" , OUString() )
+ , m_rChartDocumentWrapper( rChartDocumentWrapper )
+{
+}
+WrappedAdditionalShapesProperty::~WrappedAdditionalShapesProperty()
+{
+}
+
+void WrappedAdditionalShapesProperty::setPropertyValue( const Any& /*rOuterValue*/, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ throw lang::IllegalArgumentException( "AdditionalShapes is a read only property", nullptr, 0 );
+}
+
+Any WrappedAdditionalShapesProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ return uno::Any( m_rChartDocumentWrapper.getAdditionalShapes() );
+}
+
+WrappedRefreshAddInAllowedProperty::WrappedRefreshAddInAllowedProperty( ChartDocumentWrapper& rChartDocumentWrapper )
+ : ::chart::WrappedProperty( "RefreshAddInAllowed" , OUString() )
+ , m_rChartDocumentWrapper( rChartDocumentWrapper )
+{
+}
+WrappedRefreshAddInAllowedProperty::~WrappedRefreshAddInAllowedProperty()
+{
+}
+
+void WrappedRefreshAddInAllowedProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /* xInnerPropertySet */ ) const
+{
+ bool bUpdateAddIn = true;
+ if( ! (rOuterValue >>= bUpdateAddIn) )
+ throw lang::IllegalArgumentException( "The property RefreshAddInAllowed requires type boolean", nullptr, 0 );
+
+ m_rChartDocumentWrapper.setUpdateAddIn( bUpdateAddIn );
+}
+
+Any WrappedRefreshAddInAllowedProperty::getPropertyValue( const Reference< beans::XPropertySet >& /* xInnerPropertySet */ ) const
+{
+ return uno::Any( m_rChartDocumentWrapper.getUpdateAddIn() );
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedAddInProperty.hxx b/chart2/source/controller/chartapiwrapper/WrappedAddInProperty.hxx
new file mode 100644
index 0000000000..b87ab15d76
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedAddInProperty.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedProperty.hxx>
+
+namespace chart::wrapper { class ChartDocumentWrapper; }
+
+namespace chart::wrapper
+{
+
+class WrappedAddInProperty : public WrappedProperty
+{
+public:
+ explicit WrappedAddInProperty( ChartDocumentWrapper& rChartDocumentWrapper );
+ virtual ~WrappedAddInProperty() override;
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+private:
+ ChartDocumentWrapper& m_rChartDocumentWrapper;
+};
+
+class WrappedBaseDiagramProperty : public WrappedProperty
+{
+public:
+ explicit WrappedBaseDiagramProperty( ChartDocumentWrapper& rChartDocumentWrapper );
+ virtual ~WrappedBaseDiagramProperty() override;
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+private:
+ ChartDocumentWrapper& m_rChartDocumentWrapper;
+};
+
+class WrappedAdditionalShapesProperty : public WrappedProperty
+{
+public:
+ explicit WrappedAdditionalShapesProperty( ChartDocumentWrapper& rChartDocumentWrapper );
+ virtual ~WrappedAdditionalShapesProperty() override;
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+private:
+ ChartDocumentWrapper& m_rChartDocumentWrapper;
+};
+
+class WrappedRefreshAddInAllowedProperty : public WrappedProperty
+{
+public:
+ explicit WrappedRefreshAddInAllowedProperty( ChartDocumentWrapper& rChartDocumentWrapper );
+ virtual ~WrappedRefreshAddInAllowedProperty() override;
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+private:
+ ChartDocumentWrapper& m_rChartDocumentWrapper;
+};
+
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.cxx
new file mode 100644
index 0000000000..b88468c994
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.cxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedAutomaticPositionProperties.hxx"
+#include <FastPropertyIdRanges.hxx>
+#include <WrappedProperty.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::beans::Property;
+
+namespace chart::wrapper
+{
+
+namespace {
+
+class WrappedAutomaticPositionProperty : public WrappedProperty
+{
+public:
+ WrappedAutomaticPositionProperty();
+
+ virtual void setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const override;
+ virtual Any getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const override;
+ virtual Any getPropertyDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const override;
+};
+
+}
+
+WrappedAutomaticPositionProperty::WrappedAutomaticPositionProperty()
+ : ::chart::WrappedProperty( "AutomaticPosition" , OUString() )
+{
+}
+
+void WrappedAutomaticPositionProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if( !xInnerPropertySet.is() )
+ return;
+
+ bool bNewValue = true;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException( "Property AutomaticPosition requires value of type boolean", nullptr, 0 );
+
+ try
+ {
+ if( bNewValue )
+ {
+ Any aRelativePosition( xInnerPropertySet->getPropertyValue( "RelativePosition" ) );
+ if( aRelativePosition.hasValue() )
+ xInnerPropertySet->setPropertyValue( "RelativePosition", Any() );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+Any WrappedAutomaticPositionProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Any aRet( getPropertyDefault( Reference< beans::XPropertyState >( xInnerPropertySet, uno::UNO_QUERY ) ) );
+ if( xInnerPropertySet.is() )
+ {
+ Any aRelativePosition( xInnerPropertySet->getPropertyValue( "RelativePosition" ) );
+ if( !aRelativePosition.hasValue() )
+ aRet <<= true;
+ }
+ return aRet;
+}
+
+Any WrappedAutomaticPositionProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+namespace
+{
+enum
+{
+ PROP_CHART_AUTOMATIC_POSITION = FAST_PROPERTY_ID_START_CHART_AUTOPOSITION_PROP
+};
+
+}//anonymous namespace
+
+void WrappedAutomaticPositionProperties::addProperties( std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "AutomaticPosition",
+ PROP_CHART_AUTOMATIC_POSITION,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+void WrappedAutomaticPositionProperties::addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList )
+{
+ rList.emplace_back( new WrappedAutomaticPositionProperty() );
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.hxx b/chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.hxx
new file mode 100644
index 0000000000..a98a0aa72b
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedAutomaticPositionProperties.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <memory>
+#include <vector>
+
+namespace chart
+{
+class WrappedProperty;
+}
+namespace com::sun::star::beans
+{
+struct Property;
+}
+
+namespace chart::wrapper
+{
+class WrappedAutomaticPositionProperties
+{
+public:
+ static void addProperties(std::vector<css::beans::Property>& rOutProperties);
+ static void addWrappedProperties(std::vector<std::unique_ptr<WrappedProperty>>& rList);
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.cxx
new file mode 100644
index 0000000000..2b047ebfaf
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.cxx
@@ -0,0 +1,407 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include "WrappedAxisAndGridExistenceProperties.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <WrappedProperty.hxx>
+#include "Chart2ModelContact.hxx"
+#include <TitleHelper.hxx>
+#include <utility>
+#include <osl/diagnose.h>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+
+namespace chart::wrapper
+{
+
+namespace {
+
+class WrappedAxisAndGridExistenceProperty : public WrappedProperty
+{
+public:
+ WrappedAxisAndGridExistenceProperty( bool bAxis, bool bMain, sal_Int32 nDimensionIndex
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact );
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ bool m_bAxis;
+ bool m_bMain;
+ sal_Int32 m_nDimensionIndex;
+};
+
+}
+
+void WrappedAxisAndGridExistenceProperties::addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( true, true, 0, spChart2ModelContact ) );//x axis
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( true, false, 0, spChart2ModelContact ) );//x secondary axis
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( false, true, 0, spChart2ModelContact ) );//x grid
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( false, false, 0, spChart2ModelContact ) );//x help grid
+
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( true, true, 1, spChart2ModelContact ) );//y axis
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( true, false, 1, spChart2ModelContact ) );//y secondary axis
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( false, true, 1, spChart2ModelContact ) );//y grid
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( false, false, 1, spChart2ModelContact ) );//y help grid
+
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( true, true, 2, spChart2ModelContact ) );//z axis
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( false, true, 2, spChart2ModelContact ) );//z grid
+ rList.emplace_back( new WrappedAxisAndGridExistenceProperty( false, false, 2, spChart2ModelContact ) );//z help grid
+}
+
+WrappedAxisAndGridExistenceProperty::WrappedAxisAndGridExistenceProperty( bool bAxis, bool bMain, sal_Int32 nDimensionIndex
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact )
+ : WrappedProperty(OUString(),OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+ , m_bAxis( bAxis )
+ , m_bMain( bMain )
+ , m_nDimensionIndex( nDimensionIndex )
+{
+ switch( m_nDimensionIndex )
+ {
+ case 0:
+ {
+ if( m_bAxis )
+ {
+ if( m_bMain )
+ m_aOuterName = "HasXAxis";
+ else
+ m_aOuterName = "HasSecondaryXAxis";
+ }
+ else
+ {
+ if( m_bMain )
+ m_aOuterName = "HasXAxisGrid";
+ else
+ m_aOuterName = "HasXAxisHelpGrid";
+ }
+ }
+ break;
+ case 2:
+ {
+ if( m_bAxis )
+ {
+ OSL_ENSURE(m_bMain,"there is no secondary z axis at the old api");
+ m_bMain = true;
+ m_aOuterName = "HasZAxis";
+ }
+ else
+ {
+ if( m_bMain )
+ m_aOuterName = "HasZAxisGrid";
+ else
+ m_aOuterName = "HasZAxisHelpGrid";
+ }
+ }
+ break;
+ default:
+ {
+ if( m_bAxis )
+ {
+ if( m_bMain )
+ m_aOuterName = "HasYAxis";
+ else
+ m_aOuterName = "HasSecondaryYAxis";
+ }
+ else
+ {
+ if( m_bMain )
+ m_aOuterName = "HasYAxisGrid";
+ else
+ m_aOuterName = "HasYAxisHelpGrid";
+ }
+ }
+ break;
+ }
+}
+
+void WrappedAxisAndGridExistenceProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ bool bNewValue = false;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException( "Has axis or grid properties require boolean values", nullptr, 0 );
+
+ bool bOldValue = false;
+ getPropertyValue( xInnerPropertySet ) >>= bOldValue;
+
+ if( bOldValue == bNewValue )
+ return;
+
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( bNewValue )
+ {
+ if( m_bAxis )
+ AxisHelper::showAxis( m_nDimensionIndex, m_bMain, xDiagram, m_spChart2ModelContact->m_xContext );
+ else
+ AxisHelper::showGrid( m_nDimensionIndex, 0, m_bMain, xDiagram );
+ }
+ else
+ {
+ if( m_bAxis )
+ AxisHelper::hideAxis( m_nDimensionIndex, m_bMain, xDiagram );
+ else
+ AxisHelper::hideGrid( m_nDimensionIndex, 0, m_bMain, xDiagram );
+ }
+}
+
+Any WrappedAxisAndGridExistenceProperty::getPropertyValue( const Reference< beans::XPropertySet >& /* xInnerPropertySet */ ) const
+{
+ Any aRet;
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if(m_bAxis)
+ {
+ bool bShown = AxisHelper::isAxisShown( m_nDimensionIndex, m_bMain, xDiagram );
+ aRet <<= bShown;
+ }
+ else
+ {
+ bool bShown = AxisHelper::isGridShown( m_nDimensionIndex, 0, m_bMain, xDiagram );
+ aRet <<= bShown;
+ }
+ return aRet;
+}
+
+Any WrappedAxisAndGridExistenceProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+namespace {
+
+class WrappedAxisTitleExistenceProperty : public WrappedProperty
+{
+public:
+ WrappedAxisTitleExistenceProperty( sal_Int32 nTitleIndex
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact );
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ TitleHelper::eTitleType m_eTitleType;
+};
+
+}
+
+void WrappedAxisTitleExistenceProperties::addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ rList.emplace_back( new WrappedAxisTitleExistenceProperty( 0, spChart2ModelContact ) );//x axis title
+ rList.emplace_back( new WrappedAxisTitleExistenceProperty( 1, spChart2ModelContact ) );//y axis title
+ rList.emplace_back( new WrappedAxisTitleExistenceProperty( 2, spChart2ModelContact ) );//z axis title
+ rList.emplace_back( new WrappedAxisTitleExistenceProperty( 3, spChart2ModelContact ) );//secondary x axis title
+ rList.emplace_back( new WrappedAxisTitleExistenceProperty( 4, spChart2ModelContact ) );//secondary y axis title
+}
+
+WrappedAxisTitleExistenceProperty::WrappedAxisTitleExistenceProperty(sal_Int32 nTitleIndex
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty(OUString(),OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+ , m_eTitleType( TitleHelper::Y_AXIS_TITLE )
+{
+ switch( nTitleIndex )
+ {
+ case 0:
+ m_aOuterName = "HasXAxisTitle";
+ m_eTitleType = TitleHelper::X_AXIS_TITLE;
+ break;
+ case 2:
+ m_aOuterName = "HasZAxisTitle";
+ m_eTitleType = TitleHelper::Z_AXIS_TITLE;
+ break;
+ case 3:
+ m_aOuterName = "HasSecondaryXAxisTitle";
+ m_eTitleType = TitleHelper::SECONDARY_X_AXIS_TITLE;
+ break;
+ case 4:
+ m_aOuterName = "HasSecondaryYAxisTitle";
+ m_eTitleType = TitleHelper::SECONDARY_Y_AXIS_TITLE;
+ break;
+ default:
+ m_aOuterName = "HasYAxisTitle";
+ m_eTitleType = TitleHelper::Y_AXIS_TITLE;
+ break;
+ }
+}
+
+void WrappedAxisTitleExistenceProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ bool bNewValue = false;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException( "Has axis or grid properties require boolean values", nullptr, 0 );
+
+ bool bOldValue = false;
+ getPropertyValue( xInnerPropertySet ) >>= bOldValue;
+
+ if( bOldValue == bNewValue )
+ return;
+
+ if( bNewValue )
+ {
+ TitleHelper::createTitle( m_eTitleType, OUString()
+ , m_spChart2ModelContact->getDocumentModel(), m_spChart2ModelContact->m_xContext );
+ }
+ else
+ {
+ TitleHelper::removeTitle( m_eTitleType, m_spChart2ModelContact->getDocumentModel() );
+ }
+}
+
+Any WrappedAxisTitleExistenceProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bHasTitle = false;
+
+ rtl::Reference< Title > xTitle( TitleHelper::getTitle( m_eTitleType, m_spChart2ModelContact->getDocumentModel() ) );
+ if( xTitle.is() && !TitleHelper::getCompleteString( xTitle ).isEmpty() )
+ bHasTitle = true;
+
+ Any aRet;
+ aRet <<= bHasTitle;
+ return aRet;
+
+}
+
+Any WrappedAxisTitleExistenceProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+namespace {
+
+class WrappedAxisLabelExistenceProperty : public WrappedProperty
+{
+public:
+ WrappedAxisLabelExistenceProperty( bool bMain, sal_Int32 nDimensionIndex
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact );
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ bool m_bMain;
+ sal_Int32 m_nDimensionIndex;
+};
+
+}
+
+void WrappedAxisLabelExistenceProperties::addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ rList.emplace_back( new WrappedAxisLabelExistenceProperty( true, 0, spChart2ModelContact ) );//x axis
+ rList.emplace_back( new WrappedAxisLabelExistenceProperty( true, 1, spChart2ModelContact ) );//y axis
+ rList.emplace_back( new WrappedAxisLabelExistenceProperty( true, 2, spChart2ModelContact ) );//z axis
+ rList.emplace_back( new WrappedAxisLabelExistenceProperty( false, 0, spChart2ModelContact ) );//secondary x axis
+ rList.emplace_back( new WrappedAxisLabelExistenceProperty( false, 1, spChart2ModelContact ) );//secondary y axis
+}
+
+WrappedAxisLabelExistenceProperty::WrappedAxisLabelExistenceProperty(bool bMain, sal_Int32 nDimensionIndex
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty(OUString(),OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+ , m_bMain( bMain )
+ , m_nDimensionIndex( nDimensionIndex )
+{
+ switch( m_nDimensionIndex )
+ {
+ case 0:
+ m_aOuterName = m_bMain ? std::u16string_view(u"HasXAxisDescription") : std::u16string_view(u"HasSecondaryXAxisDescription");
+ break;
+ case 2:
+ OSL_ENSURE(m_bMain,"there is no description available for a secondary z axis");
+ m_aOuterName = "HasZAxisDescription";
+ break;
+ default:
+ m_aOuterName = m_bMain ? std::u16string_view(u"HasYAxisDescription") : std::u16string_view(u"HasSecondaryYAxisDescription");
+ break;
+ }
+}
+
+void WrappedAxisLabelExistenceProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ bool bNewValue = false;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException( "Has axis or grid properties require boolean values", nullptr, 0 );
+
+ bool bOldValue = false;
+ getPropertyValue( xInnerPropertySet ) >>= bOldValue;
+
+ if( bOldValue == bNewValue )
+ return;
+
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ rtl::Reference< Axis > xProp = AxisHelper::getAxis( m_nDimensionIndex, m_bMain, xDiagram );
+ if( !xProp.is() && bNewValue )
+ {
+ //create axis if needed
+ xProp = AxisHelper::createAxis( m_nDimensionIndex, m_bMain, xDiagram, m_spChart2ModelContact->m_xContext );
+ if( xProp.is() )
+ xProp->setPropertyValue( "Show", uno::Any( false ) );
+ }
+ if( xProp.is() )
+ xProp->setPropertyValue( "DisplayLabels", rOuterValue );
+}
+
+Any WrappedAxisLabelExistenceProperty::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ Any aRet;
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ rtl::Reference< Axis > xProp = AxisHelper::getAxis( m_nDimensionIndex, m_bMain, xDiagram );
+ if( xProp.is() )
+ aRet = xProp->getPropertyValue( "DisplayLabels" );
+ else
+ aRet <<= false;
+ return aRet;
+}
+
+Any WrappedAxisLabelExistenceProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= true;
+ return aRet;
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.hxx b/chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.hxx
new file mode 100644
index 0000000000..c15bee7113
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedAxisAndGridExistenceProperties.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <vector>
+
+namespace chart { class WrappedProperty; }
+namespace chart::wrapper { class Chart2ModelContact; }
+
+namespace chart::wrapper
+{
+
+class WrappedAxisAndGridExistenceProperties
+{
+public:
+ static void addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+};
+
+class WrappedAxisTitleExistenceProperties
+{
+public:
+ static void addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+};
+
+class WrappedAxisLabelExistenceProperties
+{
+public:
+ static void addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.cxx b/chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.cxx
new file mode 100644
index 0000000000..67ea51b0e9
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.cxx
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedCharacterHeightProperty.hxx"
+#include <RelativeSizeHelper.hxx>
+#include "ReferenceSizePropertyProvider.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <osl/diagnose.h>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+
+namespace chart::wrapper
+{
+WrappedCharacterHeightProperty_Base::WrappedCharacterHeightProperty_Base(
+ const OUString& rOuterEqualsInnerName
+ , ReferenceSizePropertyProvider* pRefSizePropProvider )
+ : WrappedProperty( rOuterEqualsInnerName, rOuterEqualsInnerName )
+ , m_pRefSizePropProvider( pRefSizePropProvider )
+{
+}
+WrappedCharacterHeightProperty_Base::~WrappedCharacterHeightProperty_Base()
+{
+}
+
+void WrappedCharacterHeightProperty::addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , ReferenceSizePropertyProvider* pRefSizePropProvider )
+{
+ rList.emplace_back( new WrappedCharacterHeightProperty( pRefSizePropProvider ) );
+ rList.emplace_back( new WrappedAsianCharacterHeightProperty( pRefSizePropProvider ) );
+ rList.emplace_back( new WrappedComplexCharacterHeightProperty( pRefSizePropProvider ) );
+}
+
+void WrappedCharacterHeightProperty_Base::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if(xInnerPropertySet.is())
+ {
+ if( m_pRefSizePropProvider )
+ m_pRefSizePropProvider->updateReferenceSize();
+ xInnerPropertySet->setPropertyValue( m_aInnerName, rOuterValue );
+ }
+}
+
+Any WrappedCharacterHeightProperty_Base::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Any aRet;
+ if( xInnerPropertySet.is() )
+ {
+ aRet = xInnerPropertySet->getPropertyValue( m_aInnerName );
+ float fHeight = 0;
+ if( aRet >>= fHeight )
+ {
+ if( m_pRefSizePropProvider )
+ {
+ awt::Size aReferenceSize;
+ if( m_pRefSizePropProvider->getReferenceSize() >>= aReferenceSize )
+ {
+ awt::Size aCurrentSize = m_pRefSizePropProvider->getCurrentSizeForReference();
+ aRet <<= static_cast< float >(
+ RelativeSizeHelper::calculate( fHeight, aReferenceSize, aCurrentSize ));
+ }
+ }
+ }
+ }
+ return aRet;
+}
+
+Any WrappedCharacterHeightProperty_Base::getPropertyDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ Any aRet;
+ if( xInnerPropertyState.is() )
+ {
+ aRet = xInnerPropertyState->getPropertyDefault( m_aInnerName );
+ }
+ return aRet;
+}
+
+beans::PropertyState WrappedCharacterHeightProperty_Base::getPropertyState( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ return beans::PropertyState_DIRECT_VALUE;
+}
+
+Any WrappedCharacterHeightProperty_Base::convertInnerToOuterValue( const Any& rInnerValue ) const
+{
+ OSL_FAIL("should not be used: WrappedCharacterHeightProperty_Base::convertInnerToOuterValue - check if you miss data");
+ return rInnerValue;
+}
+Any WrappedCharacterHeightProperty_Base::convertOuterToInnerValue( const Any& rOuterValue ) const
+{
+ OSL_FAIL("should not be used: WrappedCharacterHeightProperty_Base::convertOuterToInnerValue - check if you miss data");
+ return rOuterValue;
+}
+
+WrappedCharacterHeightProperty::WrappedCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider )
+ : WrappedCharacterHeightProperty_Base( "CharHeight", pRefSizePropProvider )
+{
+}
+WrappedCharacterHeightProperty::~WrappedCharacterHeightProperty()
+{
+}
+
+WrappedAsianCharacterHeightProperty::WrappedAsianCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider )
+ : WrappedCharacterHeightProperty_Base( "CharHeightAsian", pRefSizePropProvider )
+{
+}
+WrappedAsianCharacterHeightProperty::~WrappedAsianCharacterHeightProperty()
+{
+}
+
+WrappedComplexCharacterHeightProperty::WrappedComplexCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider )
+ : WrappedCharacterHeightProperty_Base( "CharHeightComplex", pRefSizePropProvider )
+{
+}
+WrappedComplexCharacterHeightProperty::~WrappedComplexCharacterHeightProperty()
+{
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.hxx b/chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.hxx
new file mode 100644
index 0000000000..be9457d0ff
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedCharacterHeightProperty.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedProperty.hxx>
+
+#include <vector>
+
+namespace chart::wrapper
+{
+
+class ReferenceSizePropertyProvider;
+
+class WrappedCharacterHeightProperty_Base : public WrappedProperty
+{
+public:
+ WrappedCharacterHeightProperty_Base( const OUString& rOuterEqualsInnerName, ReferenceSizePropertyProvider* pRefSizePropProvider );
+ virtual ~WrappedCharacterHeightProperty_Base() override;
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+ virtual css::beans::PropertyState getPropertyState( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+protected:
+ virtual css::uno::Any convertInnerToOuterValue( const css::uno::Any& rInnerValue ) const override;
+ virtual css::uno::Any convertOuterToInnerValue( const css::uno::Any& rOuterValue ) const override;
+
+private:
+ ReferenceSizePropertyProvider* m_pRefSizePropProvider;
+};
+
+class WrappedCharacterHeightProperty : public WrappedCharacterHeightProperty_Base
+{
+public:
+ explicit WrappedCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider );
+ virtual ~WrappedCharacterHeightProperty() override;
+
+ static void addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList, ReferenceSizePropertyProvider* pRefSizePropProvider );
+};
+
+class WrappedAsianCharacterHeightProperty : public WrappedCharacterHeightProperty_Base
+{
+public:
+ explicit WrappedAsianCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider );
+ virtual ~WrappedAsianCharacterHeightProperty() override;
+};
+
+class WrappedComplexCharacterHeightProperty : public WrappedCharacterHeightProperty_Base
+{
+public:
+ explicit WrappedComplexCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider );
+ virtual ~WrappedComplexCharacterHeightProperty() override;
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.cxx
new file mode 100644
index 0000000000..d317210c36
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.cxx
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedDataCaptionProperties.hxx"
+#include "WrappedSeriesOrDiagramProperty.hxx"
+#include <FastPropertyIdRanges.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart/ChartDataCaption.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::beans::Property;
+
+namespace chart::wrapper
+{
+
+namespace
+{
+
+class WrappedDataCaptionProperty : public WrappedSeriesOrDiagramProperty< sal_Int32 >
+{
+public:
+ virtual sal_Int32 getValueFromSeries( const css::uno::Reference< css::beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const css::uno::Reference< css::beans::XPropertySet >& xSeriesPropertySet, const sal_Int32& aNewValue ) const override;
+
+ explicit WrappedDataCaptionProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+};
+
+enum
+{
+ //data caption properties
+ PROP_CHART_DATAPOINT_DATA_CAPTION = FAST_PROPERTY_ID_START_CHART_DATACAPTION_PROP
+};
+
+sal_Int32 lcl_LabelToCaption( const chart2::DataPointLabel& rLabel )
+{
+ sal_Int32 nCaption=0;
+
+ if( rLabel.ShowNumber )
+ nCaption |= css::chart::ChartDataCaption::VALUE;
+ if( rLabel.ShowNumberInPercent )
+ nCaption |= css::chart::ChartDataCaption::PERCENT;
+ if( rLabel.ShowCategoryName )
+ nCaption |= css::chart::ChartDataCaption::TEXT;
+ if( rLabel.ShowLegendSymbol )
+ nCaption |= css::chart::ChartDataCaption::SYMBOL;
+ if (rLabel.ShowSeriesName)
+ nCaption |= css::chart::ChartDataCaption::DATA_SERIES;
+
+ return nCaption;
+}
+
+chart2::DataPointLabel lcl_CaptionToLabel( sal_Int32 nCaption )
+{
+ chart2::DataPointLabel aLabel(false,false,false,false,false,false);
+
+ if( nCaption & css::chart::ChartDataCaption::VALUE )
+ aLabel.ShowNumber = true;
+ if( nCaption & css::chart::ChartDataCaption::PERCENT )
+ aLabel.ShowNumberInPercent = true;
+ if( nCaption & css::chart::ChartDataCaption::TEXT )
+ aLabel.ShowCategoryName = true;
+ if( nCaption & css::chart::ChartDataCaption::SYMBOL )
+ aLabel.ShowLegendSymbol = true;
+ if( nCaption & css::chart::ChartDataCaption::CUSTOM )
+ aLabel.ShowCustomLabel = true;
+ if( nCaption & css::chart::ChartDataCaption::DATA_SERIES )
+ aLabel.ShowSeriesName = true;
+
+ return aLabel;
+}
+
+void lcl_addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact
+ , tSeriesOrDiagramPropertyType ePropertyType )
+{
+ //if !spChart2ModelContact.get() is then the created properties do belong to a single series or single datapoint
+ //otherwise they do belong to the whole diagram
+
+ rList.emplace_back( new WrappedDataCaptionProperty( spChart2ModelContact, ePropertyType ) );
+}
+
+}//anonymous namespace
+
+void WrappedDataCaptionProperties::addProperties( std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "DataCaption",
+ PROP_CHART_DATAPOINT_DATA_CAPTION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+void WrappedDataCaptionProperties::addWrappedPropertiesForSeries( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ lcl_addWrappedProperties( rList, spChart2ModelContact, DATA_SERIES );
+}
+
+void WrappedDataCaptionProperties::addWrappedPropertiesForDiagram( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ lcl_addWrappedProperties( rList, spChart2ModelContact, DIAGRAM );
+}
+
+WrappedDataCaptionProperty::WrappedDataCaptionProperty(
+ const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact
+ , tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedSeriesOrDiagramProperty< sal_Int32 >( "DataCaption"
+ , uno::Any( sal_Int32(0) ), spChart2ModelContact, ePropertyType )
+{
+}
+
+sal_Int32 WrappedDataCaptionProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ sal_Int32 aRet = 0;
+ m_aDefaultValue >>= aRet;
+ chart2::DataPointLabel aLabel;
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel ) )
+ aRet = lcl_LabelToCaption( aLabel );
+ return aRet;
+}
+
+void WrappedDataCaptionProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const sal_Int32& nCaption ) const
+{
+ if(!xSeriesPropertySet.is())
+ return;
+
+ chart2::DataPointLabel aLabel = lcl_CaptionToLabel( nCaption );
+ xSeriesPropertySet->setPropertyValue( CHART_UNONAME_LABEL, uno::Any( aLabel ) );
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.hxx b/chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.hxx
new file mode 100644
index 0000000000..a2bcaa302c
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedDataCaptionProperties.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/types.h>
+#include <memory>
+#include <vector>
+
+namespace chart { class WrappedProperty; }
+namespace chart::wrapper { class Chart2ModelContact; }
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart::wrapper
+{
+
+class WrappedDataCaptionProperties
+{
+public:
+ static void addProperties( std::vector< css::beans::Property > & rOutProperties );
+ static void addWrappedPropertiesForSeries( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+ static void addWrappedPropertiesForDiagram( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.cxx b/chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.cxx
new file mode 100644
index 0000000000..3c0cbb3531
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.cxx
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cstddef>
+
+#include "WrappedGapwidthProperty.hxx"
+#include "Chart2ModelContact.hxx"
+#include <ChartType.hxx>
+#include <DiagramHelper.hxx>
+#include <tools/long.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+namespace chart::wrapper
+{
+
+const sal_Int32 DEFAULT_GAPWIDTH = 100;
+const sal_Int32 DEFAULT_OVERLAP = 0;
+
+WrappedBarPositionProperty_Base::WrappedBarPositionProperty_Base(
+ const OUString& rOuterName
+ , OUString aInnerSequencePropertyName
+ , sal_Int32 nDefaultValue
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact )
+ : WrappedDefaultProperty( rOuterName, OUString(), uno::Any( nDefaultValue ) )
+ , m_nDimensionIndex(0)
+ , m_nAxisIndex(0)
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+ , m_nDefaultValue( nDefaultValue )
+ , m_InnerSequencePropertyName(std::move( aInnerSequencePropertyName ))
+{
+}
+
+void WrappedBarPositionProperty_Base::setDimensionAndAxisIndex( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ m_nDimensionIndex = nDimensionIndex;
+ m_nAxisIndex = nAxisIndex;
+}
+
+WrappedBarPositionProperty_Base::~WrappedBarPositionProperty_Base()
+{
+}
+
+void WrappedBarPositionProperty_Base::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ sal_Int32 nNewValue = 0;
+ if( ! (rOuterValue >>= nNewValue) )
+ throw lang::IllegalArgumentException( "GapWidth and Overlap property require value of type sal_Int32", nullptr, 0 );
+
+ m_aOuterValue = rOuterValue;
+
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( !xDiagram.is() )
+ return;
+
+ if( m_nDimensionIndex!=1 )
+ return;
+
+ const std::vector< rtl::Reference< ChartType > > aChartTypeList( xDiagram->getChartTypes() );
+ for( rtl::Reference< ChartType > const & chartType : aChartTypeList )
+ {
+ try
+ {
+ Sequence< sal_Int32 > aBarPositionSequence;
+ chartType->getPropertyValue( m_InnerSequencePropertyName ) >>= aBarPositionSequence;
+
+ tools::Long nOldLength = aBarPositionSequence.getLength();
+ if( nOldLength <= m_nAxisIndex )
+ aBarPositionSequence.realloc( m_nAxisIndex+1 );
+ auto pBarPositionSequence = aBarPositionSequence.getArray();
+ for( sal_Int32 i=nOldLength; i<m_nAxisIndex; i++ )
+ {
+ pBarPositionSequence[i] = m_nDefaultValue;
+ }
+ pBarPositionSequence[m_nAxisIndex] = nNewValue;
+
+ chartType->setPropertyValue( m_InnerSequencePropertyName, uno::Any( aBarPositionSequence ) );
+ }
+ catch( uno::Exception& e )
+ {
+ //the above properties are not supported by all charttypes (only by column and bar)
+ //in that cases this exception is ok
+ e.Context.is();//to have debug information without compilation warnings
+ }
+ }
+}
+
+Any WrappedBarPositionProperty_Base::getPropertyValue( const Reference< beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() )
+ {
+ bool bInnerValueDetected = false;
+ sal_Int32 nInnerValue = m_nDefaultValue;
+
+ if( m_nDimensionIndex==1 )
+ {
+ std::vector< rtl::Reference< ChartType > > aChartTypeList = xDiagram->getChartTypes();
+ for( std::size_t nN = 0; nN < aChartTypeList.size() && !bInnerValueDetected; nN++ )
+ {
+ try
+ {
+ Sequence< sal_Int32 > aBarPositionSequence;
+ aChartTypeList[nN]->getPropertyValue( m_InnerSequencePropertyName ) >>= aBarPositionSequence;
+ if( m_nAxisIndex < aBarPositionSequence.getLength() )
+ {
+ nInnerValue = aBarPositionSequence[m_nAxisIndex];
+ bInnerValueDetected = true;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ //the above properties are not supported by all charttypes (only by column and bar)
+ //in that cases this exception is ok
+ e.Context.is();//to have debug information without compilation warnings
+ }
+ }
+ }
+ if( bInnerValueDetected )
+ {
+ m_aOuterValue <<= nInnerValue;
+ }
+ }
+ return m_aOuterValue;
+}
+
+WrappedGapwidthProperty::WrappedGapwidthProperty(
+ const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact)
+ : WrappedBarPositionProperty_Base( "GapWidth", "GapwidthSequence", DEFAULT_GAPWIDTH, spChart2ModelContact )
+{
+}
+WrappedGapwidthProperty::~WrappedGapwidthProperty()
+{
+}
+
+WrappedBarOverlapProperty::WrappedBarOverlapProperty(
+ const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact )
+ : WrappedBarPositionProperty_Base( "Overlap", "OverlapSequence", DEFAULT_OVERLAP, spChart2ModelContact )
+{
+}
+WrappedBarOverlapProperty::~WrappedBarOverlapProperty()
+{
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.hxx b/chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.hxx
new file mode 100644
index 0000000000..6ac43e9f76
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedGapwidthProperty.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedDefaultProperty.hxx>
+
+#include <memory>
+
+namespace chart::wrapper { class Chart2ModelContact; }
+
+namespace chart::wrapper
+{
+
+class WrappedBarPositionProperty_Base : public WrappedDefaultProperty
+{
+public:
+ WrappedBarPositionProperty_Base(
+ const OUString& rOuterName
+ , OUString aInnerSequencePropertyName
+ , sal_Int32 nDefaultValue
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact );
+ virtual ~WrappedBarPositionProperty_Base() override;
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ void setDimensionAndAxisIndex( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+
+private:
+ sal_Int32 m_nDimensionIndex;
+ sal_Int32 m_nAxisIndex;
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+
+ sal_Int32 m_nDefaultValue;
+ OUString m_InnerSequencePropertyName;
+
+ mutable css::uno::Any m_aOuterValue;
+};
+
+class WrappedGapwidthProperty : public WrappedBarPositionProperty_Base
+{
+public:
+ explicit WrappedGapwidthProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact);
+ virtual ~WrappedGapwidthProperty() override;
+};
+
+class WrappedBarOverlapProperty : public WrappedBarPositionProperty_Base
+{
+public:
+ explicit WrappedBarOverlapProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact);
+ virtual ~WrappedBarOverlapProperty() override;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.cxx b/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.cxx
new file mode 100644
index 0000000000..971e69a585
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedNumberFormatProperty.hxx"
+#include "Chart2ModelContact.hxx"
+#include <Axis.hxx>
+#include <com/sun/star/chart2/XAxis.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <unonames.hxx>
+#include <utility>
+#include <osl/diagnose.h>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+
+namespace chart::wrapper
+{
+
+WrappedNumberFormatProperty::WrappedNumberFormatProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedDirectStateProperty( CHART_UNONAME_NUMFMT, CHART_UNONAME_NUMFMT )
+ , m_spChart2ModelContact(std::move(spChart2ModelContact))
+{
+}
+
+WrappedNumberFormatProperty::~WrappedNumberFormatProperty()
+{
+}
+
+void WrappedNumberFormatProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ sal_Int32 nFormat = 0;
+ if( ! (rOuterValue >>= nFormat) )
+ throw lang::IllegalArgumentException( "Property 'NumberFormat' requires value of type sal_Int32", nullptr, 0 );
+
+ if(xInnerPropertySet.is())
+ xInnerPropertySet->setPropertyValue(getInnerName(), convertOuterToInnerValue(rOuterValue));
+}
+
+Any WrappedNumberFormatProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if( !xInnerPropertySet.is() )
+ {
+ OSL_FAIL("missing xInnerPropertySet in WrappedNumberFormatProperty::getPropertyValue");
+ return Any();
+ }
+ Any aRet( xInnerPropertySet->getPropertyValue(getInnerName()));
+ if( !aRet.hasValue() )
+ {
+ sal_Int32 nKey = 0;
+ Reference< chart2::XDataSeries > xSeries( xInnerPropertySet, uno::UNO_QUERY );
+ if( xSeries.is() )
+ nKey = Chart2ModelContact::getExplicitNumberFormatKeyForSeries( xSeries );
+ else
+ {
+ rtl::Reference< Axis > xAxis = dynamic_cast<Axis*>(xInnerPropertySet.get());
+ assert(xAxis || !xInnerPropertySet);
+ nKey = m_spChart2ModelContact->getExplicitNumberFormatKeyForAxis( xAxis );
+ }
+ aRet <<= nKey;
+ }
+ return aRet;
+}
+
+Any WrappedNumberFormatProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ return uno::Any( sal_Int32( 0 ) );
+}
+
+WrappedLinkNumberFormatProperty::WrappedLinkNumberFormatProperty() :
+ WrappedDirectStateProperty(CHART_UNONAME_LINK_TO_SRC_NUMFMT, CHART_UNONAME_LINK_TO_SRC_NUMFMT)
+{
+}
+
+WrappedLinkNumberFormatProperty::~WrappedLinkNumberFormatProperty()
+{
+}
+
+void WrappedLinkNumberFormatProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if( !xInnerPropertySet.is() )
+ {
+ OSL_FAIL("missing xInnerPropertySet in WrappedNumberFormatProperty::setPropertyValue");
+ return;
+ }
+
+ xInnerPropertySet->setPropertyValue(getInnerName(), rOuterValue);
+}
+
+Any WrappedLinkNumberFormatProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if( !xInnerPropertySet.is() )
+ {
+ OSL_FAIL("missing xInnerPropertySet in WrappedNumberFormatProperty::getPropertyValue");
+ return getPropertyDefault(nullptr);
+ }
+
+ return xInnerPropertySet->getPropertyValue(getInnerName());
+}
+
+Any WrappedLinkNumberFormatProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ return uno::Any( true ); // bLink
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.hxx b/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.hxx
new file mode 100644
index 0000000000..cf2f706c61
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedDirectStateProperty.hxx>
+
+#include <memory>
+
+namespace chart::wrapper { class Chart2ModelContact; }
+
+namespace chart::wrapper
+{
+
+
+class WrappedNumberFormatProperty : public WrappedDirectStateProperty
+{
+public:
+ explicit WrappedNumberFormatProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~WrappedNumberFormatProperty() override;
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+ friend class WrappedLinkNumberFormatProperty;
+private:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+};
+
+class WrappedLinkNumberFormatProperty : public WrappedDirectStateProperty
+{
+public:
+ explicit WrappedLinkNumberFormatProperty();
+ virtual ~WrappedLinkNumberFormatProperty() override;
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedScaleProperty.cxx b/chart2/source/controller/chartapiwrapper/WrappedScaleProperty.cxx
new file mode 100644
index 0000000000..0edbf16bc9
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedScaleProperty.cxx
@@ -0,0 +1,589 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedScaleProperty.hxx"
+#include "Chart2ModelContact.hxx"
+#include <CommonConverters.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/XAxis.hpp>
+#include <com/sun/star/chart/ChartAxisType.hpp>
+#include <chartview/ExplicitScaleValues.hxx>
+#include <utility>
+#include <osl/diagnose.h>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::chart::TimeIncrement;
+
+namespace chart::wrapper
+{
+
+WrappedScaleProperty::WrappedScaleProperty(tScaleProperty eScaleProperty
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : WrappedProperty(OUString(),OUString())
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+ , m_eScaleProperty( eScaleProperty )
+{
+ switch( m_eScaleProperty )
+ {
+ case SCALE_PROP_MAX:
+ m_aOuterName = "Max";
+ break;
+ case SCALE_PROP_MIN:
+ m_aOuterName = "Min";
+ break;
+ case SCALE_PROP_ORIGIN:
+ m_aOuterName = "Origin";
+ break;
+ case SCALE_PROP_STEPMAIN:
+ m_aOuterName = "StepMain";
+ break;
+ case SCALE_PROP_STEPHELP:
+ m_aOuterName = "StepHelp";
+ break;
+ case SCALE_PROP_STEPHELP_COUNT:
+ m_aOuterName = "StepHelpCount";
+ break;
+ case SCALE_PROP_AUTO_MAX:
+ m_aOuterName = "AutoMax";
+ break;
+ case SCALE_PROP_AUTO_MIN:
+ m_aOuterName = "AutoMin";
+ break;
+ case SCALE_PROP_AUTO_ORIGIN:
+ m_aOuterName = "AutoOrigin";
+ break;
+ case SCALE_PROP_AUTO_STEPMAIN:
+ m_aOuterName = "AutoStepMain";
+ break;
+ case SCALE_PROP_AUTO_STEPHELP:
+ m_aOuterName = "AutoStepHelp";
+ break;
+ case SCALE_PROP_AXIS_TYPE:
+ m_aOuterName = "AxisType";
+ break;
+ case SCALE_PROP_DATE_INCREMENT:
+ m_aOuterName = "TimeIncrement";
+ break;
+ case SCALE_PROP_EXPLICIT_DATE_INCREMENT:
+ m_aOuterName = "ExplicitTimeIncrement";
+ break;
+ case SCALE_PROP_LOGARITHMIC:
+ m_aOuterName = "Logarithmic";
+ break;
+ case SCALE_PROP_REVERSEDIRECTION:
+ m_aOuterName = "ReverseDirection";
+ break;
+ default:
+ OSL_FAIL("unknown scale property");
+ break;
+ }
+}
+
+WrappedScaleProperty::~WrappedScaleProperty()
+{
+}
+
+void WrappedScaleProperty::addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_MAX, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_MIN, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_ORIGIN, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_STEPMAIN, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_STEPHELP, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_STEPHELP_COUNT, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_AUTO_MAX, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_AUTO_MIN, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_AUTO_ORIGIN, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_AUTO_STEPMAIN, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_AUTO_STEPHELP, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_AXIS_TYPE, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_DATE_INCREMENT, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_EXPLICIT_DATE_INCREMENT, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_LOGARITHMIC, spChart2ModelContact ) );
+ rList.emplace_back( new WrappedScaleProperty( SCALE_PROP_REVERSEDIRECTION, spChart2ModelContact ) );
+}
+
+void WrappedScaleProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ setPropertyValue( m_eScaleProperty, rOuterValue, xInnerPropertySet );
+}
+
+Any WrappedScaleProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ return getPropertyValue( m_eScaleProperty, xInnerPropertySet );
+}
+
+void WrappedScaleProperty::setPropertyValue( tScaleProperty eScaleProperty, const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ m_aOuterValue = rOuterValue;
+
+ Reference< chart2::XAxis > xAxis( xInnerPropertySet, uno::UNO_QUERY );
+ OSL_ENSURE(xAxis.is(),"need an XAxis");
+ if(!xAxis.is())
+ return;
+
+ bool bSetScaleData = false;
+
+ chart2::ScaleData aScaleData( xAxis->getScaleData() );
+
+ bool bBool = false;
+ switch( eScaleProperty )
+ {
+ case SCALE_PROP_MAX:
+ {
+ aScaleData.Maximum = rOuterValue;
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_MIN:
+ {
+ aScaleData.Minimum = rOuterValue;
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_STEPMAIN:
+ {
+ aScaleData.IncrementData.Distance = rOuterValue;
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_STEPHELP:
+ {
+ Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements );
+ if( !rSubIncrements.hasElements() )
+ rSubIncrements.realloc( 1 );
+ auto pSubIncrements = rSubIncrements.getArray();
+
+ double fStepHelp = 0;
+ if( rOuterValue >>= fStepHelp )
+ {
+ double fStepMain = 0;
+ if( AxisHelper::isLogarithmic(aScaleData.Scaling) )
+ {
+ sal_Int32 nIntervalCount = static_cast< sal_Int32 >(fStepHelp);
+ pSubIncrements[ 0 ].IntervalCount <<= nIntervalCount;
+ }
+ else if( (fStepHelp != 0.0) &&
+ (aScaleData.IncrementData.Distance >>= fStepMain) )
+ {
+ // approximate interval count
+ sal_Int32 nIntervalCount = static_cast< sal_Int32 >(fStepMain / fStepHelp);//cppcheck-suppress zerodiv
+ pSubIncrements[ 0 ].IntervalCount <<= nIntervalCount;
+ }
+ }
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_STEPHELP_COUNT:
+ {
+ Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements );
+ if( !rSubIncrements.hasElements() )
+ rSubIncrements.realloc( 1 );
+ auto pSubIncrements = rSubIncrements.getArray();
+ sal_Int32 nIntervalCount=0;
+ if( rOuterValue>>=nIntervalCount )
+ pSubIncrements[ 0 ].IntervalCount <<= nIntervalCount;
+ else
+ pSubIncrements[ 0 ].IntervalCount = Any();
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_AUTO_MAX:
+ {
+ if( (rOuterValue >>= bBool) && bBool )
+ aScaleData.Maximum = Any();
+ else
+ aScaleData.Maximum = getPropertyValue( SCALE_PROP_MAX, xInnerPropertySet );
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_AUTO_MIN:
+ {
+ if( (rOuterValue >>= bBool) && bBool )
+ aScaleData.Minimum = Any();
+ else
+ aScaleData.Minimum = getPropertyValue( SCALE_PROP_MIN, xInnerPropertySet );
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_AUTO_STEPMAIN:
+ {
+ if( (rOuterValue >>= bBool) && bBool )
+ aScaleData.IncrementData.Distance = Any();
+ else
+ aScaleData.IncrementData.Distance = getPropertyValue( SCALE_PROP_STEPMAIN, xInnerPropertySet );
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_AUTO_STEPHELP:
+ {
+ Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements );
+ if( !rSubIncrements.hasElements() )
+ rSubIncrements.realloc( 1 );
+ auto pSubIncrements = rSubIncrements.getArray();
+
+ if( (rOuterValue >>= bBool) && bBool )
+ pSubIncrements[ 0 ].IntervalCount = Any();
+ else
+ pSubIncrements[ 0 ].IntervalCount = getPropertyValue( SCALE_PROP_STEPHELP_COUNT, xInnerPropertySet );
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_ORIGIN:
+ {
+ aScaleData.Origin = rOuterValue;
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_AUTO_ORIGIN:
+ {
+ if( (rOuterValue >>= bBool) && bBool )
+ aScaleData.Origin = Any();
+ else
+ aScaleData.Origin = getPropertyValue( SCALE_PROP_ORIGIN, xInnerPropertySet );
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_AXIS_TYPE:
+ {
+ sal_Int32 nType = 0;
+ if( rOuterValue >>= nType )
+ {
+ if( nType == css::chart::ChartAxisType::AUTOMATIC )
+ {
+ aScaleData.AutoDateAxis = true;
+ if( aScaleData.AxisType == AxisType::DATE )
+ aScaleData.AxisType = AxisType::CATEGORY;
+ }
+ else if( nType == css::chart::ChartAxisType::CATEGORY )
+ {
+ aScaleData.AutoDateAxis = false;
+ if( aScaleData.AxisType == AxisType::DATE )
+ aScaleData.AxisType = AxisType::CATEGORY;
+ }
+ else if( nType == css::chart::ChartAxisType::DATE )
+ {
+ if( aScaleData.AxisType == AxisType::CATEGORY )
+ aScaleData.AxisType = AxisType::DATE;
+ }
+ bSetScaleData = true;
+ }
+ break;
+ }
+ case SCALE_PROP_DATE_INCREMENT:
+ {
+ TimeIncrement aTimeIncrement;
+ rOuterValue >>= aTimeIncrement;
+ aScaleData.TimeIncrement = aTimeIncrement;
+ bSetScaleData = true;
+ break;
+ }
+ case SCALE_PROP_EXPLICIT_DATE_INCREMENT:
+ //read only property
+ break;
+ case SCALE_PROP_LOGARITHMIC:
+ {
+ if( rOuterValue >>= bBool )
+ {
+ bool bWasLogarithm = AxisHelper::isLogarithmic( aScaleData.Scaling );
+
+ // safe comparison between sal_Bool and bool
+ if( (!bBool) != (!bWasLogarithm) )
+ {
+ if( bBool )
+ aScaleData.Scaling = AxisHelper::createLogarithmicScaling( 10.0 );
+ else
+ aScaleData.Scaling = nullptr;
+ bSetScaleData = true;
+ }
+ }
+ break;
+ }
+ case SCALE_PROP_REVERSEDIRECTION:
+ {
+ if( rOuterValue >>= bBool )
+ {
+ bool bWasReverse = ( aScaleData.Orientation == AxisOrientation_REVERSE );
+ if( (!bBool) != (!bWasReverse) ) // safe comparison between sal_Bool and bool
+ {
+ aScaleData.Orientation = bBool ? AxisOrientation_REVERSE : AxisOrientation_MATHEMATICAL;
+ bSetScaleData = true;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ OSL_FAIL("unknown scale property");
+ break;
+ }
+ }
+
+ if( bSetScaleData )
+ xAxis->setScaleData( aScaleData );
+}
+
+Any WrappedScaleProperty::getPropertyValue( tScaleProperty eScaleProperty, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Any aRet( m_aOuterValue );
+
+ rtl::Reference< Axis > xAxis = dynamic_cast<Axis*>(xInnerPropertySet.get());
+ OSL_ENSURE(xAxis.is(),"need an XAxis");
+ if(!xAxis.is())
+ return aRet;
+
+ chart2::ScaleData aScaleData( xAxis->getScaleData() );
+
+ ExplicitScaleData aExplicitScale;
+ ExplicitIncrementData aExplicitIncrement;
+
+ switch( eScaleProperty )
+ {
+ case SCALE_PROP_MAX:
+ {
+ aRet = aScaleData.Maximum;
+ if( !aRet.hasValue() )
+ {
+ m_spChart2ModelContact->getExplicitValuesForAxis(
+ xAxis, aExplicitScale, aExplicitIncrement );
+ aRet <<= aExplicitScale.Maximum;
+ }
+ break;
+ }
+ case SCALE_PROP_MIN:
+ {
+ aRet = aScaleData.Minimum;
+ if( !aRet.hasValue() )
+ {
+ m_spChart2ModelContact->getExplicitValuesForAxis(
+ xAxis, aExplicitScale, aExplicitIncrement );
+ aRet <<= aExplicitScale.Minimum;
+ }
+ break;
+ }
+
+ case SCALE_PROP_STEPMAIN:
+ {
+ aRet = aScaleData.IncrementData.Distance;
+ if( !aRet.hasValue() )
+ {
+ m_spChart2ModelContact->getExplicitValuesForAxis(
+ xAxis, aExplicitScale, aExplicitIncrement );
+ aRet <<= aExplicitIncrement.Distance;
+ }
+ break;
+ }
+ case SCALE_PROP_STEPHELP:
+ {
+ // todo: evaluate PostEquidistant
+ bool bNeedToCalculateExplicitValues = true;
+
+ bool bLogarithmic( AxisHelper::isLogarithmic(aScaleData.Scaling) );
+ Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements );
+ if( bLogarithmic )
+ {
+ if( rSubIncrements.hasElements() )
+ {
+ sal_Int32 nIntervalCount = 0;
+ rSubIncrements[ 0 ].IntervalCount >>= nIntervalCount;
+ aRet <<= double(nIntervalCount);
+ bNeedToCalculateExplicitValues = false;
+ }
+ }
+ else if( aScaleData.IncrementData.Distance.hasValue() )
+ {
+ if( rSubIncrements.hasElements() )
+ {
+ double fStepMain = 0;
+ sal_Int32 nIntervalCount = 0;
+ if( (aScaleData.IncrementData.Distance >>= fStepMain) &&
+ (rSubIncrements[ 0 ].IntervalCount >>= nIntervalCount) &&
+ nIntervalCount > 0 )
+ {
+ aRet <<= fStepMain / static_cast< double >( nIntervalCount );
+ bNeedToCalculateExplicitValues = false;
+ }
+ }
+ else
+ {
+ aRet = aScaleData.IncrementData.Distance;
+ bNeedToCalculateExplicitValues = false;
+ }
+ }
+
+ if( bNeedToCalculateExplicitValues )
+ {
+ m_spChart2ModelContact->getExplicitValuesForAxis(
+ xAxis, aExplicitScale, aExplicitIncrement );
+
+ if( !aExplicitIncrement.SubIncrements.empty() &&
+ aExplicitIncrement.SubIncrements[ 0 ].IntervalCount > 0 )
+ {
+ if( bLogarithmic )
+ {
+ if( rSubIncrements.hasElements() )
+ {
+ sal_Int32 nIntervalCount = aExplicitIncrement.SubIncrements[ 0 ].IntervalCount;
+ aRet <<= double(nIntervalCount);
+ }
+ }
+ else
+ aRet <<= aExplicitIncrement.Distance /
+ static_cast< double >(
+ aExplicitIncrement.SubIncrements[ 0 ].IntervalCount );
+ }
+ else
+ {
+ if( bLogarithmic )
+ aRet <<= 5.0;
+ else
+ aRet <<= aExplicitIncrement.Distance;
+ }
+ }
+ break;
+ }
+ case SCALE_PROP_STEPHELP_COUNT:
+ {
+ sal_Int32 nIntervalCount = 0;
+ bool bNeedToCalculateExplicitValues = true;
+ Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements );
+ if( rSubIncrements.hasElements() )
+ {
+ if( (rSubIncrements[ 0 ].IntervalCount >>= nIntervalCount) && (nIntervalCount > 0) )
+ bNeedToCalculateExplicitValues = false;
+ }
+ if( bNeedToCalculateExplicitValues )
+ {
+ m_spChart2ModelContact->getExplicitValuesForAxis( xAxis, aExplicitScale, aExplicitIncrement );
+ if( !aExplicitIncrement.SubIncrements.empty() )
+ nIntervalCount = aExplicitIncrement.SubIncrements[ 0 ].IntervalCount;
+ }
+ aRet <<= nIntervalCount;
+ break;
+ }
+ case SCALE_PROP_AUTO_MAX:
+ {
+ aRet <<= !aScaleData.Maximum.hasValue();
+ break;
+ }
+ case SCALE_PROP_AUTO_MIN:
+ {
+ aRet <<= !aScaleData.Minimum.hasValue();
+ break;
+ }
+ case SCALE_PROP_AUTO_STEPMAIN:
+ {
+ aRet <<= !aScaleData.IncrementData.Distance.hasValue();
+ break;
+ }
+ case SCALE_PROP_AUTO_STEPHELP:
+ {
+ Sequence< chart2::SubIncrement >& rSubIncrements( aScaleData.IncrementData.SubIncrements );
+ if( rSubIncrements.hasElements() )
+ aRet <<= !rSubIncrements[ 0 ].IntervalCount.hasValue();
+ else
+ aRet <<= true;
+ break;
+ }
+ case SCALE_PROP_ORIGIN:
+ {
+ aRet = aScaleData.Origin;
+ if( !aRet.hasValue() )
+ {
+ m_spChart2ModelContact->getExplicitValuesForAxis(
+ xAxis, aExplicitScale, aExplicitIncrement );
+ aRet <<= aExplicitScale.Origin;
+ }
+ break;
+ }
+ case SCALE_PROP_AUTO_ORIGIN:
+ {
+ aRet <<= !hasDoubleValue(aScaleData.Origin);
+ break;
+ }
+ case SCALE_PROP_AXIS_TYPE:
+ {
+ sal_Int32 nType = css::chart::ChartAxisType::AUTOMATIC;
+ if( aScaleData.AxisType == AxisType::DATE )
+ {
+ nType = css::chart::ChartAxisType::DATE;
+ }
+ else if( aScaleData.AxisType == AxisType::CATEGORY )
+ {
+ if( !aScaleData.AutoDateAxis )
+ nType = css::chart::ChartAxisType::CATEGORY;
+ }
+ aRet <<= nType;
+ break;
+ }
+ case SCALE_PROP_DATE_INCREMENT:
+ {
+ if( aScaleData.AxisType == AxisType::DATE || aScaleData.AutoDateAxis )
+ aRet <<= aScaleData.TimeIncrement;
+ break;
+ }
+ case SCALE_PROP_EXPLICIT_DATE_INCREMENT:
+ {
+ if( aScaleData.AxisType == AxisType::DATE || aScaleData.AutoDateAxis )
+ {
+ m_spChart2ModelContact->getExplicitValuesForAxis( xAxis, aExplicitScale, aExplicitIncrement );
+ if( aExplicitScale.AxisType == AxisType::DATE )
+ {
+ TimeIncrement aTimeIncrement;
+ aTimeIncrement.MajorTimeInterval <<= aExplicitIncrement.MajorTimeInterval;
+ aTimeIncrement.MinorTimeInterval <<= aExplicitIncrement.MinorTimeInterval;
+ aTimeIncrement.TimeResolution <<= aExplicitScale.TimeResolution;
+ aRet <<= aTimeIncrement;
+ }
+ else
+ aRet <<= aScaleData.TimeIncrement;
+ }
+
+ break;
+ }
+ case SCALE_PROP_LOGARITHMIC:
+ {
+ aRet <<= AxisHelper::isLogarithmic(aScaleData.Scaling);
+ break;
+ }
+ case SCALE_PROP_REVERSEDIRECTION:
+ {
+ aRet <<= aScaleData.Orientation == AxisOrientation_REVERSE;
+ break;
+ }
+ default:
+ {
+ OSL_FAIL("unknown scale property");
+ break;
+ }
+ }
+
+ return aRet;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedScaleProperty.hxx b/chart2/source/controller/chartapiwrapper/WrappedScaleProperty.hxx
new file mode 100644
index 0000000000..eca5295355
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedScaleProperty.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedProperty.hxx>
+
+#include <memory>
+#include <vector>
+
+namespace chart::wrapper { class Chart2ModelContact; }
+
+namespace chart::wrapper
+{
+
+class WrappedScaleProperty final : public WrappedProperty
+{
+public:
+ enum tScaleProperty
+ {
+ SCALE_PROP_MAX
+ , SCALE_PROP_MIN
+ , SCALE_PROP_ORIGIN
+ , SCALE_PROP_STEPMAIN
+ , SCALE_PROP_STEPHELP //deprecated property
+ , SCALE_PROP_STEPHELP_COUNT
+ , SCALE_PROP_AUTO_MAX
+ , SCALE_PROP_AUTO_MIN
+ , SCALE_PROP_AUTO_ORIGIN
+ , SCALE_PROP_AUTO_STEPMAIN
+ , SCALE_PROP_AUTO_STEPHELP
+ , SCALE_PROP_AXIS_TYPE
+ , SCALE_PROP_DATE_INCREMENT
+ , SCALE_PROP_EXPLICIT_DATE_INCREMENT
+ , SCALE_PROP_LOGARITHMIC
+ , SCALE_PROP_REVERSEDIRECTION
+ };
+
+ WrappedScaleProperty(tScaleProperty eScaleProperty, std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~WrappedScaleProperty() override;
+
+ static void addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList, const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+private:
+ /// @throws css::beans::UnknownPropertyException
+ /// @throws css::beans::PropertyVetoException
+ /// @throws css::lang::IllegalArgumentException
+ /// @throws css::lang::WrappedTargetException
+ /// @throws css::uno::RuntimeException
+ void setPropertyValue( tScaleProperty eScaleProperty, const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const;
+ /// @throws css::beans::UnknownPropertyException
+ /// @throws css::lang::WrappedTargetException
+ /// @throws css::uno::RuntimeException
+ css::uno::Any getPropertyValue( tScaleProperty eScaleProperty, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const;
+
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ tScaleProperty m_eScaleProperty;
+
+ mutable css::uno::Any m_aOuterValue;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.cxx
new file mode 100644
index 0000000000..6e11fbe021
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.cxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedScaleTextProperties.hxx"
+#include "Chart2ModelContact.hxx"
+#include <FastPropertyIdRanges.hxx>
+#include <WrappedProperty.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::beans::Property;
+
+namespace chart::wrapper
+{
+
+namespace {
+
+class WrappedScaleTextProperty : public WrappedProperty
+{
+public:
+ explicit WrappedScaleTextProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+
+ virtual void setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const override;
+ virtual Any getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const override;
+ virtual Any getPropertyDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+};
+
+}
+
+WrappedScaleTextProperty::WrappedScaleTextProperty(std::shared_ptr<Chart2ModelContact> spChart2ModelContact)
+ : ::chart::WrappedProperty( "ScaleText" , OUString() )
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+}
+
+void WrappedScaleTextProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ static constexpr OUString aRefSizeName = u"ReferencePageSize"_ustr;
+
+ if( !xInnerPropertySet.is() )
+ return;
+
+ bool bNewValue = false;
+ if( ! (rOuterValue >>= bNewValue) )
+ {
+ if( rOuterValue.hasValue() )
+ throw lang::IllegalArgumentException( "Property ScaleText requires value of type boolean", nullptr, 0 );
+ }
+
+ try
+ {
+ if( bNewValue )
+ {
+ awt::Size aRefSize( m_spChart2ModelContact->GetPageSize() );
+ xInnerPropertySet->setPropertyValue( aRefSizeName, uno::Any( aRefSize ) );
+ }
+ else
+ xInnerPropertySet->setPropertyValue( aRefSizeName, Any() );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+Any WrappedScaleTextProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Any aRet( getPropertyDefault( Reference< beans::XPropertyState >( xInnerPropertySet, uno::UNO_QUERY ) ) );
+ if( xInnerPropertySet.is() )
+ {
+ if( xInnerPropertySet->getPropertyValue( "ReferencePageSize" ).hasValue() )
+ aRet <<= true;
+ else
+ aRet <<= false;
+ }
+
+ return aRet;
+}
+
+Any WrappedScaleTextProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ Any aRet;
+ aRet <<= false;
+ return aRet;
+}
+
+namespace
+{
+enum
+{
+ PROP_CHART_SCALE_TEXT = FAST_PROPERTY_ID_START_SCALE_TEXT_PROP
+};
+
+}//anonymous namespace
+
+void WrappedScaleTextProperties::addProperties( std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "ScaleText",
+ PROP_CHART_SCALE_TEXT,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+void WrappedScaleTextProperties::addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ rList.emplace_back( new WrappedScaleTextProperty( spChart2ModelContact ) );
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.hxx b/chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.hxx
new file mode 100644
index 0000000000..958b5f55da
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedScaleTextProperties.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <memory>
+#include <vector>
+
+namespace chart { class WrappedProperty; }
+namespace chart::wrapper { class Chart2ModelContact; }
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart::wrapper
+{
+
+class WrappedScaleTextProperties
+{
+public:
+ static void addProperties( std::vector< css::beans::Property >& rOutProperties );
+ static void addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedSceneProperty.cxx b/chart2/source/controller/chartapiwrapper/WrappedSceneProperty.cxx
new file mode 100644
index 0000000000..1c8e6dc73e
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedSceneProperty.cxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedSceneProperty.hxx"
+#include "Chart2ModelContact.hxx"
+#include <DiagramHelper.hxx>
+#include <BaseGFXHelper.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+
+namespace chart::wrapper
+{
+
+void WrappedSceneProperty::addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ rList.emplace_back( new WrappedD3DTransformMatrixProperty( spChart2ModelContact ) );
+}
+
+WrappedD3DTransformMatrixProperty::WrappedD3DTransformMatrixProperty(
+ std::shared_ptr<Chart2ModelContact> spChart2ModelContact )
+ : WrappedProperty("D3DTransformMatrix","D3DTransformMatrix")
+ , m_spChart2ModelContact(std::move( spChart2ModelContact ))
+{
+}
+
+WrappedD3DTransformMatrixProperty::~WrappedD3DTransformMatrixProperty()
+{
+}
+
+void WrappedD3DTransformMatrixProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if( m_spChart2ModelContact->getDiagram()->isPieOrDonutChart() )
+ {
+ drawing::HomogenMatrix aHM;
+ if( rOuterValue >>= aHM )
+ {
+ ::basegfx::B3DTuple aRotation( BaseGFXHelper::GetRotationFromMatrix(
+ BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aHM ) ) );
+
+ ::basegfx::B3DHomMatrix aMatrix;
+ aMatrix.rotate( aRotation.getX(), aRotation.getY(), aRotation.getZ() );
+ ::basegfx::B3DHomMatrix aObjectMatrix;
+ ::basegfx::B3DHomMatrix aNewMatrix = aMatrix*aObjectMatrix;
+
+ aHM = BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aNewMatrix);
+
+ WrappedProperty::setPropertyValue( uno::Any(aHM), xInnerPropertySet );
+ return;
+ }
+ }
+
+ WrappedProperty::setPropertyValue( rOuterValue, xInnerPropertySet );
+}
+
+Any WrappedD3DTransformMatrixProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if( m_spChart2ModelContact->getDiagram()->isPieOrDonutChart() )
+ {
+ uno::Any aAMatrix( WrappedProperty::getPropertyValue( xInnerPropertySet ) );
+ drawing::HomogenMatrix aHM;
+ if( aAMatrix >>= aHM )
+ {
+ ::basegfx::B3DTuple aRotation( BaseGFXHelper::GetRotationFromMatrix(
+ BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aHM ) ) );
+
+ ::basegfx::B3DHomMatrix aMatrix;
+ aMatrix.rotate( aRotation.getX(), aRotation.getY(), aRotation.getZ() );
+ ::basegfx::B3DHomMatrix aObjectMatrix;
+ ::basegfx::B3DHomMatrix aNewMatrix = aMatrix*aObjectMatrix;
+
+ aHM = BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aNewMatrix);
+
+ return uno::Any(aHM);
+ }
+ }
+
+ return WrappedProperty::getPropertyValue( xInnerPropertySet );
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedSceneProperty.hxx b/chart2/source/controller/chartapiwrapper/WrappedSceneProperty.hxx
new file mode 100644
index 0000000000..31ef35abc5
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedSceneProperty.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedProperty.hxx>
+
+#include <memory>
+#include <vector>
+
+namespace chart::wrapper { class Chart2ModelContact; }
+
+namespace chart::wrapper
+{
+
+class WrappedSceneProperty
+{
+public:
+ static void addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+};
+
+class WrappedD3DTransformMatrixProperty : public WrappedProperty
+{
+public:
+ explicit WrappedD3DTransformMatrixProperty(
+ std::shared_ptr<Chart2ModelContact> spChart2ModelContact);
+ virtual ~WrappedD3DTransformMatrixProperty() override;
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+private:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.cxx b/chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.cxx
new file mode 100644
index 0000000000..5b073ca801
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.cxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <utility>
+
+#include "WrappedSeriesAreaOrLineProperty.hxx"
+#include "DataSeriesPointWrapper.hxx"
+
+namespace chart::wrapper
+{
+
+WrappedSeriesAreaOrLineProperty::WrappedSeriesAreaOrLineProperty(
+ const OUString& rOuterName
+ , OUString aInnerAreaTypeName
+ , OUString aInnerLineTypeName
+ , DataSeriesPointWrapper* pDataSeriesPointWrapper )
+ : WrappedProperty( rOuterName, OUString() )
+ , m_pDataSeriesPointWrapper( pDataSeriesPointWrapper )
+ , m_aInnerAreaTypeName(std::move( aInnerAreaTypeName ))
+ , m_aInnerLineTypeName(std::move( aInnerLineTypeName ))
+{
+}
+WrappedSeriesAreaOrLineProperty::~WrappedSeriesAreaOrLineProperty()
+{
+}
+
+//virtual
+OUString WrappedSeriesAreaOrLineProperty::getInnerName() const
+{
+ if( m_pDataSeriesPointWrapper && !m_pDataSeriesPointWrapper->isSupportingAreaProperties() )
+ return m_aInnerLineTypeName;
+ return m_aInnerAreaTypeName;
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.hxx b/chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.hxx
new file mode 100644
index 0000000000..f3561e7361
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedSeriesAreaOrLineProperty.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedProperty.hxx>
+
+namespace chart::wrapper
+{
+
+class DataSeriesPointWrapper;
+class WrappedSeriesAreaOrLineProperty : public WrappedProperty
+{
+public:
+ WrappedSeriesAreaOrLineProperty( const OUString& rOuterName
+ , OUString aInnerAreaTypeName, OUString aInnerLineTypeName
+ , DataSeriesPointWrapper* pDataSeriesPointWrapper );
+ virtual ~WrappedSeriesAreaOrLineProperty() override;
+
+ virtual OUString getInnerName() const override;
+
+private:
+ DataSeriesPointWrapper* m_pDataSeriesPointWrapper;
+ OUString m_aInnerAreaTypeName;
+ OUString m_aInnerLineTypeName;
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedSeriesOrDiagramProperty.hxx b/chart2/source/controller/chartapiwrapper/WrappedSeriesOrDiagramProperty.hxx
new file mode 100644
index 0000000000..82cd43eefb
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedSeriesOrDiagramProperty.hxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedProperty.hxx>
+#include "Chart2ModelContact.hxx"
+#include <DiagramHelper.hxx>
+#include <DataSeries.hxx>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace com::sun::star::chart2 { class XDataSeries; }
+
+namespace chart::wrapper
+{
+
+enum tSeriesOrDiagramPropertyType
+{
+ DATA_SERIES,
+ DIAGRAM
+};
+
+//PROPERTYTYPE is the type of the outer property
+
+template< typename PROPERTYTYPE >
+class WrappedSeriesOrDiagramProperty : public WrappedProperty
+{
+public:
+ virtual PROPERTYTYPE getValueFromSeries( const css::uno::Reference< css::beans::XPropertySet >& xSeriesPropertySet ) const =0;
+ virtual void setValueToSeries( const css::uno::Reference< css::beans::XPropertySet >& xSeriesPropertySet, const PROPERTYTYPE & aNewValue ) const =0;
+
+ explicit WrappedSeriesOrDiagramProperty( const OUString& rName, const css::uno::Any& rDefaulValue
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact
+ , tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedProperty(rName,OUString())
+ , m_spChart2ModelContact(std::move(spChart2ModelContact))
+ , m_aOuterValue(rDefaulValue)
+ , m_aDefaultValue(rDefaulValue)
+ , m_ePropertyType( ePropertyType )
+ {
+ }
+
+ bool detectInnerValue( PROPERTYTYPE& rValue, bool& rHasAmbiguousValue ) const
+ {
+ rHasAmbiguousValue = false;
+ if( m_ePropertyType != DIAGRAM || !m_spChart2ModelContact )
+ return false;
+ bool bHasDetectableInnerValue = false;
+ rtl::Reference<Diagram> xDiagram = m_spChart2ModelContact->getDiagram();
+ if (!xDiagram)
+ return false;
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector =
+ xDiagram->getDataSeries();
+ for (auto const& series : aSeriesVector)
+ {
+ PROPERTYTYPE aCurValue = getValueFromSeries( series );
+ if( !bHasDetectableInnerValue )
+ rValue = aCurValue;
+ else
+ {
+ if( rValue != aCurValue )
+ {
+ rHasAmbiguousValue = true;
+ break;
+ }
+ else
+ rValue = aCurValue;
+ }
+ bHasDetectableInnerValue = true;
+ }
+ return bHasDetectableInnerValue;
+ }
+ void setInnerValue( PROPERTYTYPE aNewValue ) const
+ {
+ if( m_ePropertyType == DIAGRAM &&
+ m_spChart2ModelContact )
+ {
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector =
+ m_spChart2ModelContact->getDiagram()->getDataSeries();
+ for (auto const& series : aSeriesVector)
+ {
+ setValueToSeries( series, aNewValue );
+ }
+ }
+ }
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override
+ {
+ PROPERTYTYPE aNewValue = PROPERTYTYPE();
+ if( ! (rOuterValue >>= aNewValue) )
+ throw css::lang::IllegalArgumentException( "statistic property requires different type", nullptr, 0 );
+
+ if( m_ePropertyType == DIAGRAM )
+ {
+ m_aOuterValue = rOuterValue;
+
+ bool bHasAmbiguousValue = false;
+ PROPERTYTYPE aOldValue = PROPERTYTYPE();
+ if( detectInnerValue( aOldValue, bHasAmbiguousValue ) )
+ {
+ if( bHasAmbiguousValue || aNewValue != aOldValue )
+ setInnerValue( aNewValue );
+ }
+ }
+ else
+ {
+ setValueToSeries( xInnerPropertySet, aNewValue );
+ }
+ }
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override
+ {
+ if( m_ePropertyType == DIAGRAM )
+ {
+ bool bHasAmbiguousValue = false;
+ PROPERTYTYPE aValue = PROPERTYTYPE();
+ if( detectInnerValue( aValue, bHasAmbiguousValue ) )
+ {
+ if(bHasAmbiguousValue)
+ m_aOuterValue = m_aDefaultValue;
+ else
+ m_aOuterValue <<= aValue;
+ }
+ return m_aOuterValue;
+ }
+ else
+ {
+ css::uno::Any aRet( m_aDefaultValue );
+ aRet <<= getValueFromSeries( xInnerPropertySet );
+ return aRet;
+ }
+ }
+
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& /* xInnerPropertyState */ ) const override
+ {
+ return m_aDefaultValue;
+ }
+
+protected:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable css::uno::Any m_aOuterValue;
+ css::uno::Any m_aDefaultValue;
+ tSeriesOrDiagramPropertyType m_ePropertyType;
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx
new file mode 100644
index 0000000000..d775dbdae6
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx
@@ -0,0 +1,286 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedSplineProperties.hxx"
+#include "Chart2ModelContact.hxx"
+#include <FastPropertyIdRanges.hxx>
+#include <ChartType.hxx>
+#include <DiagramHelper.hxx>
+#include <WrappedProperty.hxx>
+#include <unonames.hxx>
+
+#include <sal/log.hxx>
+
+#include <com/sun/star/chart2/CurveStyle.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <utility>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::beans::Property;
+
+namespace chart::wrapper
+{
+
+namespace
+{
+
+//PROPERTYTYPE is the type of the outer property
+
+template< typename PROPERTYTYPE >
+class WrappedSplineProperty : public WrappedProperty
+{
+public:
+ explicit WrappedSplineProperty( const OUString& rOuterName, OUString aInnerName
+ , const css::uno::Any& rDefaulValue
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact )
+ : WrappedProperty(rOuterName,OUString())
+ , m_spChart2ModelContact(std::move(spChart2ModelContact))
+ , m_aOuterValue(rDefaulValue)
+ , m_aDefaultValue(rDefaulValue)
+ , m_aOwnInnerName(std::move(aInnerName))
+ {
+ }
+
+ bool detectInnerValue( PROPERTYTYPE& rValue, bool& rHasAmbiguousValue ) const
+ {
+ rHasAmbiguousValue = false;
+ rtl::Reference<Diagram> xDiagram = m_spChart2ModelContact->getDiagram();
+ if (!xDiagram)
+ return false;
+ bool bHasDetectableInnerValue = false;
+ std::vector< rtl::Reference< ChartType > > aChartTypes = xDiagram->getChartTypes();
+ for( sal_Int32 nN = aChartTypes.size(); nN--; )
+ {
+ try
+ {
+ Any aSingleValue = convertInnerToOuterValue( aChartTypes[nN]->getPropertyValue(m_aOwnInnerName) );
+ PROPERTYTYPE aCurValue = PROPERTYTYPE();
+ aSingleValue >>= aCurValue;
+ if( !bHasDetectableInnerValue )
+ rValue = aCurValue;
+ else
+ {
+ if( rValue != aCurValue )
+ {
+ rHasAmbiguousValue = true;
+ break;
+ }
+ else
+ rValue = aCurValue;
+ }
+ bHasDetectableInnerValue = true;
+ }
+ catch( uno::Exception & ex )
+ {
+ //spline properties are not supported by all charttypes
+ //in that cases this exception is ok
+ ex.Context.is();//to have debug information without compilation warnings
+ }
+ }
+ return bHasDetectableInnerValue;
+ }
+ void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& /*xInnerPropertySet*/ ) const override
+ {
+ PROPERTYTYPE aNewValue;
+ if( ! (rOuterValue >>= aNewValue) )
+ throw css::lang::IllegalArgumentException( "spline property requires different type", nullptr, 0 );
+
+ m_aOuterValue = rOuterValue;
+
+ bool bHasAmbiguousValue = false;
+ PROPERTYTYPE aOldValue = PROPERTYTYPE();
+ if( !detectInnerValue( aOldValue, bHasAmbiguousValue ) )
+ return;
+
+ if( !(bHasAmbiguousValue || aNewValue != aOldValue) )
+ return;
+
+ std::vector< rtl::Reference< ChartType > > aChartTypes =
+ m_spChart2ModelContact->getDiagram()->getChartTypes();
+ for( sal_Int32 nN = aChartTypes.size(); nN--; )
+ {
+ try
+ {
+ aChartTypes[nN]->setPropertyValue(m_aOwnInnerName,convertOuterToInnerValue(uno::Any(aNewValue)));
+ }
+ catch( uno::Exception & ex )
+ {
+ //spline properties are not supported by all charttypes
+ //in that cases this exception is ok
+ ex.Context.is();//to have debug information without compilation warnings
+ }
+ }
+ }
+
+ css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& /*xInnerPropertySet*/ ) const override
+ {
+ bool bHasAmbiguousValue = false;
+ PROPERTYTYPE aValue;
+ if( detectInnerValue( aValue, bHasAmbiguousValue ) )
+ {
+ m_aOuterValue <<= aValue;
+ }
+ return m_aOuterValue;
+ }
+
+ css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& /*xInnerPropertyState*/ ) const override
+ {
+ return m_aDefaultValue;
+ }
+
+protected:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable css::uno::Any m_aOuterValue;
+ css::uno::Any m_aDefaultValue;
+ // this inner name is not set as inner name at the base class
+ const OUString m_aOwnInnerName;
+};
+
+class WrappedSplineTypeProperty : public WrappedSplineProperty< sal_Int32 >
+{
+public:
+ explicit WrappedSplineTypeProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact);
+
+ virtual css::uno::Any convertInnerToOuterValue( const css::uno::Any& rInnerValue ) const override;
+ virtual css::uno::Any convertOuterToInnerValue( const css::uno::Any& rOuterValue ) const override;
+};
+
+enum
+{
+ //spline properties
+ PROP_CHART_SPLINE_TYPE = FAST_PROPERTY_ID_START_CHART_SPLINE_PROP
+ , PROP_CHART_SPLINE_ORDER
+ , PROP_CHART_SPLINE_RESOLUTION
+};
+
+}//anonymous namespace
+
+void WrappedSplineProperties::addProperties( std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( CHART_UNONAME_SPLINE_TYPE,
+ PROP_CHART_SPLINE_TYPE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( CHART_UNONAME_SPLINE_ORDER,
+ PROP_CHART_SPLINE_ORDER,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( CHART_UNONAME_SPLINE_RESOLUTION,
+ PROP_CHART_SPLINE_RESOLUTION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+}
+
+void WrappedSplineProperties::addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ rList.emplace_back( new WrappedSplineTypeProperty( spChart2ModelContact ) );
+ rList.emplace_back(
+ new WrappedSplineProperty<sal_Int32>(
+ CHART_UNONAME_SPLINE_ORDER, CHART_UNONAME_SPLINE_ORDER,
+ uno::Any(sal_Int32(3)), spChart2ModelContact));
+ rList.emplace_back(
+ new WrappedSplineProperty<sal_Int32>(
+ CHART_UNONAME_SPLINE_RESOLUTION, CHART_UNONAME_CURVE_RESOLUTION,
+ uno::Any(sal_Int32(20)), spChart2ModelContact));
+}
+
+WrappedSplineTypeProperty::WrappedSplineTypeProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact)
+ : WrappedSplineProperty<sal_Int32>(CHART_UNONAME_SPLINE_TYPE, CHART_UNONAME_CURVE_STYLE, uno::Any(sal_Int32(0)), spChart2ModelContact )
+{
+}
+
+Any WrappedSplineTypeProperty::convertInnerToOuterValue( const Any& rInnerValue ) const
+{
+ chart2::CurveStyle aInnerValue = chart2::CurveStyle_LINES;
+ rInnerValue >>= aInnerValue;
+
+ sal_Int32 nOuterValue;
+ switch (aInnerValue)
+ {
+ case chart2::CurveStyle_CUBIC_SPLINES:
+ nOuterValue = 1;
+ break;
+ case chart2::CurveStyle_B_SPLINES:
+ nOuterValue = 2;
+ break;
+ case chart2::CurveStyle_STEP_START:
+ nOuterValue = 3;
+ break;
+ case chart2::CurveStyle_STEP_END:
+ nOuterValue = 4;
+ break;
+ case chart2::CurveStyle_STEP_CENTER_X:
+ nOuterValue = 5;
+ break;
+ case chart2::CurveStyle_STEP_CENTER_Y:
+ nOuterValue = 6;
+ break;
+ default:
+ nOuterValue = 0;
+ }
+
+ return uno::Any(nOuterValue);
+}
+Any WrappedSplineTypeProperty::convertOuterToInnerValue( const Any& rOuterValue ) const
+{
+ sal_Int32 nOuterValue=0;
+ rOuterValue >>= nOuterValue;
+
+ chart2::CurveStyle aInnerValue;
+
+ switch (nOuterValue)
+ {
+ case 1:
+ aInnerValue = chart2::CurveStyle_CUBIC_SPLINES;
+ break;
+ case 2:
+ aInnerValue = chart2::CurveStyle_B_SPLINES;
+ break;
+ case 3:
+ aInnerValue = chart2::CurveStyle_STEP_START;
+ break;
+ case 4:
+ aInnerValue = chart2::CurveStyle_STEP_END;
+ break;
+ case 5:
+ aInnerValue = chart2::CurveStyle_STEP_CENTER_X;
+ break;
+ case 6:
+ aInnerValue = chart2::CurveStyle_STEP_CENTER_Y;
+ break;
+ default:
+ SAL_WARN_IF(nOuterValue != 0, "chart2", "Unknown line style");
+ aInnerValue = chart2::CurveStyle_LINES;
+ }
+
+ return uno::Any(aInnerValue);
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.hxx b/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.hxx
new file mode 100644
index 0000000000..686a692979
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/types.h>
+#include <memory>
+#include <vector>
+
+namespace chart { class WrappedProperty; }
+namespace chart::wrapper { class Chart2ModelContact; }
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart::wrapper
+{
+
+class WrappedSplineProperties
+{
+public:
+ static void addProperties( std::vector< css::beans::Property > & rOutProperties );
+ static void addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx
new file mode 100644
index 0000000000..e5278bb5da
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.cxx
@@ -0,0 +1,1071 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedStatisticProperties.hxx"
+#include "WrappedSeriesOrDiagramProperty.hxx"
+#include <FastPropertyIdRanges.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <ErrorBar.hxx>
+#include <StatisticsHelper.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/chart/ChartErrorCategory.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/chart/ChartErrorIndicatorType.hpp>
+#include <com/sun/star/chart/ChartRegressionCurveType.hpp>
+#include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
+#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+#include <utility>
+
+namespace com::sun::star::chart2::data { class XDataProvider; }
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::beans::Property;
+
+namespace chart::wrapper
+{
+
+namespace
+{
+
+Any lcl_getRegressionDefault()
+{
+ Any aRet;
+ aRet <<= css::chart::ChartRegressionCurveType_NONE;
+ return aRet;
+}
+
+css::chart::ChartRegressionCurveType lcl_getRegressionCurveType(SvxChartRegress eRegressionType)
+{
+ css::chart::ChartRegressionCurveType eRet = css::chart::ChartRegressionCurveType_NONE;
+ switch(eRegressionType)
+ {
+ case SvxChartRegress::Linear:
+ eRet = css::chart::ChartRegressionCurveType_LINEAR;
+ break;
+ case SvxChartRegress::Log:
+ eRet = css::chart::ChartRegressionCurveType_LOGARITHM;
+ break;
+ case SvxChartRegress::Exp:
+ eRet = css::chart::ChartRegressionCurveType_EXPONENTIAL;
+ break;
+ case SvxChartRegress::Power:
+ eRet = css::chart::ChartRegressionCurveType_POWER;
+ break;
+ case SvxChartRegress::Polynomial:
+ eRet = css::chart::ChartRegressionCurveType_POLYNOMIAL;
+ break;
+ /*case SvxChartRegress::MovingAverage:
+ eRet = css::chart::ChartRegressionCurveType_MOVING_AVERAGE;
+ break;*/
+ default:
+ eRet = css::chart::ChartRegressionCurveType_NONE;
+ break;
+ }
+ return eRet;
+}
+
+SvxChartRegress lcl_getRegressionType( css::chart::ChartRegressionCurveType eRegressionCurveType )
+{
+ SvxChartRegress eRet;
+ switch (eRegressionCurveType)
+ {
+ case css::chart::ChartRegressionCurveType_LINEAR:
+ eRet = SvxChartRegress::Linear;
+ break;
+ case css::chart::ChartRegressionCurveType_LOGARITHM:
+ eRet = SvxChartRegress::Log;
+ break;
+ case css::chart::ChartRegressionCurveType_EXPONENTIAL:
+ eRet = SvxChartRegress::Exp;
+ break;
+ case css::chart::ChartRegressionCurveType_POLYNOMIAL:
+ //case css::chart::ChartRegressionCurveType_MOVING_AVERAGE:
+ case css::chart::ChartRegressionCurveType_POWER:
+ eRet = SvxChartRegress::Power;
+ break;
+ default:
+ eRet = SvxChartRegress::NONE;
+ break;
+ }
+ return eRet;
+}
+
+sal_Int32 lcl_getErrorBarStyle( const uno::Reference< beans::XPropertySet >& xErrorBarProperties )
+{
+ sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
+ if(xErrorBarProperties.is())
+ xErrorBarProperties->getPropertyValue( "ErrorBarStyle" ) >>= nStyle;
+ return nStyle;
+}
+
+uno::Reference< chart2::data::XDataProvider > lcl_getDataProviderFromContact(
+ const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ uno::Reference< chart2::data::XDataProvider > xResult;
+ if( spChart2ModelContact)
+ {
+ rtl::Reference< ChartModel > xChartDoc(
+ spChart2ModelContact->getDocumentModel());
+ if( xChartDoc.is())
+ xResult.set( xChartDoc->getDataProvider());
+ }
+ return xResult;
+}
+
+void lcl_ConvertRangeFromXML(
+ OUString & rInOutRange,
+ const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ if( !rInOutRange.isEmpty())
+ {
+ uno::Reference< chart2::data::XRangeXMLConversion > xConverter(
+ lcl_getDataProviderFromContact( spChart2ModelContact ), uno::UNO_QUERY );
+ if( xConverter.is())
+ {
+ rInOutRange = xConverter->convertRangeFromXML( rInOutRange );
+ }
+ }
+}
+
+void lcl_ConvertRangeToXML(
+ OUString & rInOutRange,
+ const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ if( !rInOutRange.isEmpty())
+ {
+ uno::Reference< chart2::data::XRangeXMLConversion > xConverter(
+ lcl_getDataProviderFromContact( spChart2ModelContact ), uno::UNO_QUERY );
+ if( xConverter.is())
+ {
+ rInOutRange = xConverter->convertRangeToXML( rInOutRange );
+ }
+ }
+}
+
+template< typename PROPERTYTYPE >
+class WrappedStatisticProperty : public WrappedSeriesOrDiagramProperty< PROPERTYTYPE >
+{
+public:
+ explicit WrappedStatisticProperty(
+ const OUString& rName, const Any& rDefaulValue,
+ const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType)
+ : WrappedSeriesOrDiagramProperty<PROPERTYTYPE>(rName, rDefaulValue, spChart2ModelContact,
+ ePropertyType)
+ {}
+
+protected:
+ static uno::Reference< beans::XPropertySet > getOrCreateErrorBarProperties( const Reference< beans::XPropertySet >& xSeriesPropertySet )
+ {
+ if(!xSeriesPropertySet.is())
+ return nullptr;
+ uno::Reference< beans::XPropertySet > xErrorBarProperties;
+ xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xErrorBarProperties;
+ if( !xErrorBarProperties.is() )
+ {
+ xErrorBarProperties = new ::chart::ErrorBar;
+ //default in new and old api are different
+ xErrorBarProperties->setPropertyValue( "ShowPositiveError" , uno::Any(false) );
+ xErrorBarProperties->setPropertyValue( "ShowNegativeError" , uno::Any(false) );
+ xErrorBarProperties->setPropertyValue( "ErrorBarStyle" , uno::Any(css::chart::ErrorBarStyle::NONE) );
+ xSeriesPropertySet->setPropertyValue( CHART_UNONAME_ERRORBAR_Y , uno::Any( xErrorBarProperties ) );
+ }
+ return xErrorBarProperties;
+ }
+
+};
+
+//PROP_CHART_STATISTIC_CONST_ERROR_LOW
+class WrappedConstantErrorLowProperty : public WrappedStatisticProperty< double >
+{
+public:
+ virtual double getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const double& aNewValue ) const override;
+
+ explicit WrappedConstantErrorLowProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+
+private:
+ mutable Any m_aOuterValue;
+};
+
+}//anonymous namespace
+
+WrappedConstantErrorLowProperty::WrappedConstantErrorLowProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< double >( "ConstantErrorLow"
+ , uno::Any( 0.0 ), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+double WrappedConstantErrorLowProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ double aRet = 0.0;
+ m_aDefaultValue >>= aRet;
+ uno::Reference< beans::XPropertySet > xErrorBarProperties;
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xErrorBarProperties ) && xErrorBarProperties.is())
+ {
+ if( lcl_getErrorBarStyle( xErrorBarProperties ) == css::chart::ErrorBarStyle::ABSOLUTE )
+ xErrorBarProperties->getPropertyValue( "NegativeError" ) >>= aRet;
+ else
+ m_aOuterValue >>= aRet;
+ }
+ return aRet;
+}
+
+void WrappedConstantErrorLowProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const double& aNewValue ) const
+{
+ uno::Reference< beans::XPropertySet > xErrorBarProperties( getOrCreateErrorBarProperties(xSeriesPropertySet) );
+ if( xErrorBarProperties.is() )
+ {
+ m_aOuterValue <<= aNewValue;
+ if( lcl_getErrorBarStyle( xErrorBarProperties ) == css::chart::ErrorBarStyle::ABSOLUTE )
+ {
+ xErrorBarProperties->setPropertyValue( "NegativeError", m_aOuterValue );
+ }
+ }
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_CONST_ERROR_HIGH
+class WrappedConstantErrorHighProperty : public WrappedStatisticProperty< double >
+{
+public:
+ virtual double getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const double& aNewValue ) const override;
+
+ explicit WrappedConstantErrorHighProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+
+private:
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedConstantErrorHighProperty::WrappedConstantErrorHighProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< double >( "ConstantErrorHigh"
+ , uno::Any( 0.0 ), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+double WrappedConstantErrorHighProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ double aRet = 0.0;
+ m_aDefaultValue >>= aRet;
+ uno::Reference< beans::XPropertySet > xErrorBarProperties;
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xErrorBarProperties ) && xErrorBarProperties.is())
+ {
+ if( lcl_getErrorBarStyle( xErrorBarProperties ) == css::chart::ErrorBarStyle::ABSOLUTE )
+ xErrorBarProperties->getPropertyValue( "PositiveError" ) >>= aRet;
+ else
+ m_aOuterValue >>= aRet;
+ }
+ return aRet;
+}
+
+void WrappedConstantErrorHighProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const double& aNewValue ) const
+{
+ uno::Reference< beans::XPropertySet > xErrorBarProperties( getOrCreateErrorBarProperties(xSeriesPropertySet) );
+ if( xErrorBarProperties.is() )
+ {
+ m_aOuterValue <<= aNewValue;
+ if( lcl_getErrorBarStyle( xErrorBarProperties ) == css::chart::ErrorBarStyle::ABSOLUTE )
+ {
+ xErrorBarProperties->setPropertyValue( "PositiveError" , m_aOuterValue );
+ }
+ }
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_MEAN_VALUE
+class WrappedMeanValueProperty : public WrappedStatisticProperty< bool >
+{
+public:
+ virtual bool getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const bool& aNewValue ) const override;
+
+ explicit WrappedMeanValueProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+};
+
+}
+
+WrappedMeanValueProperty::WrappedMeanValueProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< bool >( "MeanValue", uno::Any( false ), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+bool WrappedMeanValueProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ bool bRet = false;
+ uno::Reference< chart2::XRegressionCurveContainer > xRegCnt( xSeriesPropertySet, uno::UNO_QUERY );
+ if( xRegCnt.is() )
+ bRet = RegressionCurveHelper::hasMeanValueLine( xRegCnt );
+ return bRet;
+}
+
+void WrappedMeanValueProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const bool& aNewValue ) const
+{
+ uno::Reference< chart2::XRegressionCurveContainer > xRegCnt( xSeriesPropertySet, uno::UNO_QUERY );
+ if( xRegCnt.is() )
+ {
+ if(aNewValue)
+ RegressionCurveHelper::addMeanValueLine( xRegCnt, nullptr );
+ else
+ RegressionCurveHelper::removeMeanValueLine( xRegCnt );
+ }
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_ERROR_CATEGORY
+// deprecated, replaced by ErrorBarStyle
+class WrappedErrorCategoryProperty : public WrappedStatisticProperty< css::chart::ChartErrorCategory >
+{
+public:
+ virtual css::chart::ChartErrorCategory getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const css::chart::ChartErrorCategory& aNewValue ) const override;
+
+ explicit WrappedErrorCategoryProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+};
+
+}
+
+WrappedErrorCategoryProperty::WrappedErrorCategoryProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< css::chart::ChartErrorCategory >( "ErrorCategory"
+ , uno::Any( css::chart::ChartErrorCategory_NONE ), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+css::chart::ChartErrorCategory WrappedErrorCategoryProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ css::chart::ChartErrorCategory aRet = css::chart::ChartErrorCategory_NONE;
+ m_aDefaultValue >>= aRet;
+ uno::Reference< beans::XPropertySet > xErrorBarProperties;
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xErrorBarProperties ) && xErrorBarProperties.is())
+ {
+ sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
+ xErrorBarProperties->getPropertyValue( "ErrorBarStyle" ) >>= nStyle;
+ switch(nStyle)
+ {
+ case css::chart::ErrorBarStyle::NONE:
+ aRet = css::chart::ChartErrorCategory_NONE;
+ break;
+ case css::chart::ErrorBarStyle::VARIANCE:
+ aRet = css::chart::ChartErrorCategory_VARIANCE;
+ break;
+ case css::chart::ErrorBarStyle::STANDARD_DEVIATION:
+ aRet = css::chart::ChartErrorCategory_STANDARD_DEVIATION;
+ break;
+ case css::chart::ErrorBarStyle::ABSOLUTE:
+ aRet = css::chart::ChartErrorCategory_CONSTANT_VALUE;
+ break;
+ case css::chart::ErrorBarStyle::RELATIVE:
+ aRet = css::chart::ChartErrorCategory_PERCENT;
+ break;
+ case css::chart::ErrorBarStyle::ERROR_MARGIN:
+ aRet = css::chart::ChartErrorCategory_ERROR_MARGIN;
+ break;
+ case css::chart::ErrorBarStyle::STANDARD_ERROR:
+ break;
+ case css::chart::ErrorBarStyle::FROM_DATA:
+ break;
+ default:
+ break;
+ }
+ }
+ return aRet;
+}
+void WrappedErrorCategoryProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const css::chart::ChartErrorCategory& aNewValue ) const
+{
+ if( !xSeriesPropertySet.is() )
+ return;
+
+ uno::Reference< beans::XPropertySet > xErrorBarProperties( getOrCreateErrorBarProperties(xSeriesPropertySet) );
+ if( !xErrorBarProperties.is() )
+ return;
+
+ sal_Int32 nNewStyle = css::chart::ErrorBarStyle::NONE;
+ switch(aNewValue)
+ {
+ case css::chart::ChartErrorCategory_NONE:
+ nNewStyle = css::chart::ErrorBarStyle::NONE;
+ break;
+ case css::chart::ChartErrorCategory_VARIANCE:
+ nNewStyle = css::chart::ErrorBarStyle::VARIANCE;
+ break;
+ case css::chart::ChartErrorCategory_STANDARD_DEVIATION:
+ nNewStyle = css::chart::ErrorBarStyle::STANDARD_DEVIATION;
+ break;
+ case css::chart::ChartErrorCategory_CONSTANT_VALUE:
+ nNewStyle = css::chart::ErrorBarStyle::ABSOLUTE;
+ break;
+ case css::chart::ChartErrorCategory_PERCENT:
+ nNewStyle = css::chart::ErrorBarStyle::RELATIVE;
+ break;
+ case css::chart::ChartErrorCategory_ERROR_MARGIN:
+ nNewStyle = css::chart::ErrorBarStyle::ERROR_MARGIN;
+ break;
+ default:
+ break;
+ }
+ xErrorBarProperties->setPropertyValue( "ErrorBarStyle" , uno::Any(nNewStyle) );
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_PERCENT_ERROR
+class WrappedPercentageErrorProperty : public WrappedStatisticProperty< double >
+{
+public:
+ virtual double getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const double& aNewValue ) const override;
+
+ explicit WrappedPercentageErrorProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+
+private:
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedPercentageErrorProperty::WrappedPercentageErrorProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< double >( "PercentageError"
+ , uno::Any( 0.0 ), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+double WrappedPercentageErrorProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ double aRet = 0.0;
+ m_aDefaultValue >>= aRet;
+ uno::Reference< beans::XPropertySet > xErrorBarProperties;
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xErrorBarProperties ) && xErrorBarProperties.is())
+ {
+ if( lcl_getErrorBarStyle( xErrorBarProperties ) == css::chart::ErrorBarStyle::RELATIVE )
+ xErrorBarProperties->getPropertyValue( "PositiveError" ) >>= aRet;
+ else
+ m_aOuterValue >>= aRet;
+ }
+ return aRet;
+}
+void WrappedPercentageErrorProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const double& aNewValue ) const
+{
+ uno::Reference< beans::XPropertySet > xErrorBarProperties( getOrCreateErrorBarProperties(xSeriesPropertySet) );
+ if( xErrorBarProperties.is() )
+ {
+ m_aOuterValue <<= aNewValue;
+ if( lcl_getErrorBarStyle( xErrorBarProperties ) == css::chart::ErrorBarStyle::RELATIVE )
+ {
+ xErrorBarProperties->setPropertyValue( "PositiveError" , m_aOuterValue );
+ xErrorBarProperties->setPropertyValue( "NegativeError" , m_aOuterValue );
+ }
+ }
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_ERROR_MARGIN
+class WrappedErrorMarginProperty : public WrappedStatisticProperty< double >
+{
+public:
+ virtual double getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const double& aNewValue ) const override;
+
+ explicit WrappedErrorMarginProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+
+private:
+ mutable Any m_aOuterValue;
+};
+
+}
+
+WrappedErrorMarginProperty::WrappedErrorMarginProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< double >( "ErrorMargin"
+ , uno::Any( 0.0 ), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+double WrappedErrorMarginProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ double aRet = 0.0;
+ m_aDefaultValue >>= aRet;
+ uno::Reference< beans::XPropertySet > xErrorBarProperties;
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xErrorBarProperties ) && xErrorBarProperties.is())
+ {
+ if( lcl_getErrorBarStyle( xErrorBarProperties ) == css::chart::ErrorBarStyle::ERROR_MARGIN )
+ xErrorBarProperties->getPropertyValue( "PositiveError" ) >>= aRet;
+ else
+ m_aOuterValue >>= aRet;
+ }
+ return aRet;
+}
+void WrappedErrorMarginProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const double& aNewValue ) const
+{
+ uno::Reference< beans::XPropertySet > xErrorBarProperties( getOrCreateErrorBarProperties(xSeriesPropertySet) );
+ if( xErrorBarProperties.is() )
+ {
+ m_aOuterValue <<= aNewValue;
+ if( lcl_getErrorBarStyle( xErrorBarProperties ) == css::chart::ErrorBarStyle::ERROR_MARGIN )
+ {
+ xErrorBarProperties->setPropertyValue( "PositiveError" , m_aOuterValue );
+ xErrorBarProperties->setPropertyValue( "NegativeError" , m_aOuterValue );
+ }
+ }
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_ERROR_INDICATOR
+class WrappedErrorIndicatorProperty : public WrappedStatisticProperty< css::chart::ChartErrorIndicatorType >
+{
+public:
+ virtual css::chart::ChartErrorIndicatorType getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const css::chart::ChartErrorIndicatorType& aNewValue ) const override;
+
+ explicit WrappedErrorIndicatorProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+};
+
+}
+
+WrappedErrorIndicatorProperty::WrappedErrorIndicatorProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< css::chart::ChartErrorIndicatorType >( "ErrorIndicator"
+ , uno::Any( css::chart::ChartErrorIndicatorType_NONE ), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+css::chart::ChartErrorIndicatorType WrappedErrorIndicatorProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ css::chart::ChartErrorIndicatorType aRet = css::chart::ChartErrorIndicatorType_NONE;
+ m_aDefaultValue >>= aRet;
+ uno::Reference< beans::XPropertySet > xErrorBarProperties;
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xErrorBarProperties ) && xErrorBarProperties.is())
+ {
+ bool bPositive = false;
+ bool bNegative = false;
+ xErrorBarProperties->getPropertyValue( "ShowPositiveError" ) >>= bPositive;
+ xErrorBarProperties->getPropertyValue( "ShowNegativeError" ) >>= bNegative;
+
+ if( bPositive && bNegative )
+ aRet = css::chart::ChartErrorIndicatorType_TOP_AND_BOTTOM;
+ else if( bPositive && !bNegative )
+ aRet = css::chart::ChartErrorIndicatorType_UPPER;
+ else if( !bPositive && bNegative )
+ aRet = css::chart::ChartErrorIndicatorType_LOWER;
+ }
+ return aRet;
+}
+void WrappedErrorIndicatorProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const css::chart::ChartErrorIndicatorType& aNewValue ) const
+{
+ uno::Reference< beans::XPropertySet > xErrorBarProperties( getOrCreateErrorBarProperties(xSeriesPropertySet) );
+ if( !xErrorBarProperties.is() )
+ return;
+
+ bool bPositive = false;
+ bool bNegative = false;
+ switch( aNewValue )
+ {
+ case css::chart::ChartErrorIndicatorType_TOP_AND_BOTTOM:
+ bPositive = true;
+ bNegative = true;
+ break;
+ case css::chart::ChartErrorIndicatorType_UPPER:
+ bPositive = true;
+ break;
+ case css::chart::ChartErrorIndicatorType_LOWER:
+ bNegative = true;
+ break;
+ default:
+ break;
+ }
+
+ xErrorBarProperties->setPropertyValue( "ShowPositiveError" , uno::Any(bPositive) );
+ xErrorBarProperties->setPropertyValue( "ShowNegativeError" , uno::Any(bNegative) );
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_ERROR_BAR_STYLE
+// this is the new constant group that replaces the deprecated enum ChartErrorCategory
+class WrappedErrorBarStyleProperty : public WrappedStatisticProperty< sal_Int32 >
+{
+public:
+ virtual sal_Int32 getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const sal_Int32& nNewValue ) const override;
+
+ explicit WrappedErrorBarStyleProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact1,
+ tSeriesOrDiagramPropertyType ePropertyType );
+};
+
+}
+
+WrappedErrorBarStyleProperty::WrappedErrorBarStyleProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< sal_Int32 >( "ErrorBarStyle"
+ , uno::Any( css::chart::ErrorBarStyle::NONE ), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+sal_Int32 WrappedErrorBarStyleProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ sal_Int32 nRet = css::chart::ErrorBarStyle::NONE;
+ m_aDefaultValue >>= nRet;
+ uno::Reference< beans::XPropertySet > xErrorBarProperties;
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xErrorBarProperties ) && xErrorBarProperties.is())
+ {
+ xErrorBarProperties->getPropertyValue( "ErrorBarStyle" ) >>= nRet;
+ }
+ return nRet;
+}
+void WrappedErrorBarStyleProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const sal_Int32& nNewValue ) const
+{
+ if( !xSeriesPropertySet.is() )
+ return;
+
+ uno::Reference< beans::XPropertySet > xErrorBarProperties( getOrCreateErrorBarProperties(xSeriesPropertySet) );
+ if( xErrorBarProperties.is() )
+ {
+ xErrorBarProperties->setPropertyValue( "ErrorBarStyle" , uno::Any( nNewValue ));
+ }
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_ERROR_RANGE_POSITIVE
+class WrappedErrorBarRangePositiveProperty : public WrappedStatisticProperty< OUString >
+{
+public:
+ virtual OUString getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const OUString& aNewValue ) const override;
+
+ explicit WrappedErrorBarRangePositiveProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+};
+
+}
+
+WrappedErrorBarRangePositiveProperty::WrappedErrorBarRangePositiveProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< OUString >( "ErrorBarRangePositive"
+ , uno::Any( OUString() ), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+OUString WrappedErrorBarRangePositiveProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ OUString aRet;
+ m_aDefaultValue >>= aRet;
+ uno::Reference< chart2::data::XDataSource > xErrorBarDataSource;
+ if( xSeriesPropertySet.is() &&
+ ( xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xErrorBarDataSource ) &&
+ xErrorBarDataSource.is())
+ {
+ uno::Reference< chart2::data::XDataSequence > xSeq(
+ StatisticsHelper::getErrorDataSequenceFromDataSource(
+ xErrorBarDataSource, true /* positive */ ));
+ if( xSeq.is())
+ aRet = xSeq->getSourceRangeRepresentation();
+ else
+ m_aOuterValue >>= aRet;
+ }
+ lcl_ConvertRangeToXML( aRet, m_spChart2ModelContact );
+ return aRet;
+}
+
+void WrappedErrorBarRangePositiveProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const OUString& aNewValue ) const
+{
+ uno::Reference< beans::XPropertySet > xErrorBarProperties( getOrCreateErrorBarProperties(xSeriesPropertySet) );
+ if( !xErrorBarProperties.is() )
+ return;
+
+ uno::Reference< chart2::data::XDataProvider > xDataProvider(
+ lcl_getDataProviderFromContact( m_spChart2ModelContact ));
+ uno::Reference< chart2::data::XDataSource > xDataSource( xErrorBarProperties, uno::UNO_QUERY );
+ if( xDataSource.is() && xDataProvider.is())
+ {
+ OUString aTmp( aNewValue );
+ OUString aXMLRange( aNewValue );
+ lcl_ConvertRangeFromXML( aTmp, m_spChart2ModelContact );
+ StatisticsHelper::setErrorDataSequence(
+ xDataSource, xDataProvider, aTmp, true /* positive */, true /* y-error */, &aXMLRange );
+ m_aOuterValue <<= aTmp;
+ }
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_ERROR_RANGE_NEGATIVE
+class WrappedErrorBarRangeNegativeProperty : public WrappedStatisticProperty< OUString >
+{
+public:
+ virtual OUString getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const OUString& aNewValue ) const override;
+
+ explicit WrappedErrorBarRangeNegativeProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+};
+
+}
+
+WrappedErrorBarRangeNegativeProperty::WrappedErrorBarRangeNegativeProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< OUString >( "ErrorBarRangeNegative"
+ , uno::Any( OUString() ), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+OUString WrappedErrorBarRangeNegativeProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ OUString aRet;
+ m_aDefaultValue >>= aRet;
+ uno::Reference< chart2::data::XDataSource > xErrorBarDataSource;
+ if( xSeriesPropertySet.is() &&
+ ( xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xErrorBarDataSource ) &&
+ xErrorBarDataSource.is())
+ {
+ uno::Reference< chart2::data::XDataSequence > xSeq(
+ StatisticsHelper::getErrorDataSequenceFromDataSource(
+ xErrorBarDataSource, false /* positive */ ));
+ if( xSeq.is())
+ aRet = xSeq->getSourceRangeRepresentation();
+ else
+ m_aOuterValue >>= aRet;
+ }
+ lcl_ConvertRangeToXML( aRet, m_spChart2ModelContact );
+ return aRet;
+}
+
+void WrappedErrorBarRangeNegativeProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const OUString& aNewValue ) const
+{
+ uno::Reference< beans::XPropertySet > xErrorBarProperties( getOrCreateErrorBarProperties(xSeriesPropertySet) );
+ if( !xErrorBarProperties.is() )
+ return;
+
+ uno::Reference< chart2::data::XDataProvider > xDataProvider(
+ lcl_getDataProviderFromContact( m_spChart2ModelContact ));
+ uno::Reference< chart2::data::XDataSource > xDataSource( xErrorBarProperties, uno::UNO_QUERY );
+ if( xDataSource.is() && xDataProvider.is())
+ {
+ OUString aTmp( aNewValue );
+ OUString aXMLRange( aNewValue );
+ lcl_ConvertRangeFromXML( aTmp, m_spChart2ModelContact );
+ StatisticsHelper::setErrorDataSequence(
+ xDataSource, xDataProvider, aTmp, false /* positive */, true /* y-error */, &aXMLRange );
+ m_aOuterValue <<= aTmp;
+ }
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_REGRESSION_CURVES
+class WrappedRegressionCurvesProperty : public WrappedStatisticProperty< css::chart::ChartRegressionCurveType >
+{
+public:
+ virtual css::chart::ChartRegressionCurveType getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const css::chart::ChartRegressionCurveType & aNewValue ) const override;
+
+ explicit WrappedRegressionCurvesProperty( std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+};
+
+}
+
+WrappedRegressionCurvesProperty::WrappedRegressionCurvesProperty(
+ std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< css::chart::ChartRegressionCurveType >( "RegressionCurves"
+ , lcl_getRegressionDefault(), std::move(spChart2ModelContact), ePropertyType )
+{
+}
+
+css::chart::ChartRegressionCurveType WrappedRegressionCurvesProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ css::chart::ChartRegressionCurveType aRet;
+ m_aDefaultValue >>= aRet;
+ uno::Reference< chart2::XRegressionCurveContainer > xRegCnt( xSeriesPropertySet, uno::UNO_QUERY );
+ if( xRegCnt.is() )
+ {
+ aRet = lcl_getRegressionCurveType(
+ RegressionCurveHelper::getFirstRegressTypeNotMeanValueLine( xRegCnt ) );
+ }
+ return aRet;
+}
+void WrappedRegressionCurvesProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const css::chart::ChartRegressionCurveType& aNewValue ) const
+{
+ uno::Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xSeriesPropertySet, uno::UNO_QUERY );
+ if (!xRegressionCurveContainer)
+ return;
+ rtl::Reference< ::chart::RegressionCurveModel> xRegressionCurve = RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegressionCurveContainer );
+ if( xRegressionCurve.is() )
+ {
+ SvxChartRegress eNewRegressionType = lcl_getRegressionType( aNewValue );
+
+ RegressionCurveHelper::changeRegressionCurveType(
+ eNewRegressionType,
+ xRegressionCurveContainer,
+ xRegressionCurve);
+ }
+}
+
+namespace {
+
+//PROP_CHART_STATISTIC_REGRESSION_PROPERTIES
+//PROP_CHART_STATISTIC_ERROR_PROPERTIES
+//PROP_CHART_STATISTIC_MEAN_VALUE_PROPERTIES
+class WrappedStatisticPropertySetProperty : public WrappedStatisticProperty< Reference< beans::XPropertySet > >
+{
+public:
+ virtual Reference< beans::XPropertySet > getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ // properties are read-only, so this method should never be called
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const Reference< beans::XPropertySet > & xNewValue ) const override;
+
+ enum PropertySetType
+ {
+ PROPERTY_SET_TYPE_REGRESSION,
+ PROPERTY_SET_TYPE_ERROR_BAR,
+ PROPERTY_SET_TYPE_MEAN_VALUE
+ };
+
+ explicit WrappedStatisticPropertySetProperty(
+ PropertySetType ePropertySetType, std::shared_ptr< Chart2ModelContact > spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType );
+
+private:
+ PropertySetType m_eType;
+};
+
+}
+
+WrappedStatisticPropertySetProperty::WrappedStatisticPropertySetProperty(
+ PropertySetType ePropertySetType
+ , std::shared_ptr< Chart2ModelContact > spChart2ModelContact
+ , tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedStatisticProperty< Reference< beans::XPropertySet > >(
+ (ePropertySetType == PROPERTY_SET_TYPE_REGRESSION)
+ ? OUString("DataRegressionProperties")
+ : (ePropertySetType == PROPERTY_SET_TYPE_ERROR_BAR)
+ ? OUString("DataErrorProperties")
+ : OUString("DataMeanValueProperties")
+ , uno::Any(), std::move(spChart2ModelContact), ePropertyType )
+ , m_eType( ePropertySetType )
+{
+}
+
+Reference< beans::XPropertySet > WrappedStatisticPropertySetProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ Reference< beans::XPropertySet > xResult;
+ uno::Reference< chart2::XRegressionCurveContainer > xRegCnt( xSeriesPropertySet, uno::UNO_QUERY );
+
+ switch( m_eType )
+ {
+ case PROPERTY_SET_TYPE_REGRESSION:
+ if( xRegCnt.is() )
+ xResult = RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCnt );
+ break;
+ case PROPERTY_SET_TYPE_ERROR_BAR:
+ if( xSeriesPropertySet.is())
+ xSeriesPropertySet->getPropertyValue( CHART_UNONAME_ERRORBAR_Y ) >>= xResult;
+ break;
+ case PROPERTY_SET_TYPE_MEAN_VALUE:
+ if( xRegCnt.is() )
+ xResult = RegressionCurveHelper::getMeanValueLine( xRegCnt );
+ break;
+ }
+
+ return xResult;
+}
+
+void WrappedStatisticPropertySetProperty::setValueToSeries(
+ const Reference< beans::XPropertySet >& /* xSeriesPropertySet */
+ , const Reference< beans::XPropertySet >& /* xNewValue */ ) const
+{
+}
+
+namespace
+{
+enum
+{
+ //statistic properties
+ PROP_CHART_STATISTIC_CONST_ERROR_LOW = FAST_PROPERTY_ID_START_CHART_STATISTIC_PROP,
+ PROP_CHART_STATISTIC_CONST_ERROR_HIGH,
+ PROP_CHART_STATISTIC_MEAN_VALUE,
+ PROP_CHART_STATISTIC_ERROR_CATEGORY,
+ PROP_CHART_STATISTIC_ERROR_BAR_STYLE,
+ PROP_CHART_STATISTIC_PERCENT_ERROR,
+ PROP_CHART_STATISTIC_ERROR_MARGIN,
+ PROP_CHART_STATISTIC_ERROR_INDICATOR,
+ PROP_CHART_STATISTIC_ERROR_RANGE_POSITIVE,
+ PROP_CHART_STATISTIC_ERROR_RANGE_NEGATIVE,
+ PROP_CHART_STATISTIC_REGRESSION_CURVES,
+ PROP_CHART_STATISTIC_REGRESSION_PROPERTIES,
+ PROP_CHART_STATISTIC_ERROR_PROPERTIES,
+ PROP_CHART_STATISTIC_MEAN_VALUE_PROPERTIES
+};
+
+/** @parameter bDataSeriesProperty if true, this property is for a single data
+ series, if false, it is for the whole diagram, i.e. for all
+ series
+ */
+void lcl_addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact
+ , tSeriesOrDiagramPropertyType ePropertyType )
+{
+ rList.emplace_back( new WrappedConstantErrorLowProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedConstantErrorHighProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedMeanValueProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedErrorCategoryProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedErrorBarStyleProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedPercentageErrorProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedErrorMarginProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedErrorIndicatorProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedErrorBarRangePositiveProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedErrorBarRangeNegativeProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedRegressionCurvesProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedStatisticPropertySetProperty(
+ WrappedStatisticPropertySetProperty::PROPERTY_SET_TYPE_REGRESSION, spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedStatisticPropertySetProperty(
+ WrappedStatisticPropertySetProperty::PROPERTY_SET_TYPE_ERROR_BAR, spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedStatisticPropertySetProperty(
+ WrappedStatisticPropertySetProperty::PROPERTY_SET_TYPE_MEAN_VALUE, spChart2ModelContact, ePropertyType ) );
+}
+
+}//anonymous namespace
+
+void WrappedStatisticProperties::addProperties( std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "ConstantErrorLow",
+ PROP_CHART_STATISTIC_CONST_ERROR_LOW,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "ConstantErrorHigh",
+ PROP_CHART_STATISTIC_CONST_ERROR_HIGH,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "MeanValue",
+ PROP_CHART_STATISTIC_MEAN_VALUE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "ErrorCategory",
+ PROP_CHART_STATISTIC_ERROR_CATEGORY,
+ cppu::UnoType<css::chart::ChartErrorCategory>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "ErrorBarStyle",
+ PROP_CHART_STATISTIC_ERROR_BAR_STYLE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "PercentageError",
+ PROP_CHART_STATISTIC_PERCENT_ERROR,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "ErrorMargin",
+ PROP_CHART_STATISTIC_ERROR_MARGIN,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "ErrorIndicator",
+ PROP_CHART_STATISTIC_ERROR_INDICATOR,
+ cppu::UnoType<css::chart::ChartErrorIndicatorType>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "ErrorBarRangePositive",
+ PROP_CHART_STATISTIC_ERROR_RANGE_POSITIVE,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "ErrorBarRangeNegative",
+ PROP_CHART_STATISTIC_ERROR_RANGE_NEGATIVE,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "RegressionCurves",
+ PROP_CHART_STATISTIC_REGRESSION_CURVES,
+ cppu::UnoType<css::chart::ChartRegressionCurveType>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "DataRegressionProperties",
+ PROP_CHART_STATISTIC_REGRESSION_PROPERTIES,
+ cppu::UnoType<beans::XPropertySet>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "DataErrorProperties",
+ PROP_CHART_STATISTIC_ERROR_PROPERTIES,
+ cppu::UnoType<beans::XPropertySet>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "DataMeanValueProperties",
+ PROP_CHART_STATISTIC_MEAN_VALUE_PROPERTIES,
+ cppu::UnoType<beans::XPropertySet>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY
+ | beans::PropertyAttribute::MAYBEVOID );
+}
+
+void WrappedStatisticProperties::addWrappedPropertiesForSeries( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ lcl_addWrappedProperties( rList, spChart2ModelContact, DATA_SERIES );
+}
+
+void WrappedStatisticProperties::addWrappedPropertiesForDiagram( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ lcl_addWrappedProperties( rList, spChart2ModelContact, DIAGRAM );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.hxx b/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.hxx
new file mode 100644
index 0000000000..7831fccf4c
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedStatisticProperties.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/types.h>
+#include <memory>
+#include <vector>
+
+namespace chart { class WrappedProperty; }
+namespace chart::wrapper { class Chart2ModelContact; }
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart::wrapper
+{
+
+class WrappedStatisticProperties
+{
+public:
+ static void addProperties( std::vector< css::beans::Property > & rOutProperties );
+ static void addWrappedPropertiesForSeries( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+ static void addWrappedPropertiesForDiagram( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedStockProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedStockProperties.cxx
new file mode 100644
index 0000000000..837afa34c0
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedStockProperties.cxx
@@ -0,0 +1,284 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedStockProperties.hxx"
+#include "Chart2ModelContact.hxx"
+#include <FastPropertyIdRanges.hxx>
+#include <DataSeries.hxx>
+#include <DiagramHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <WrappedProperty.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::beans::Property;
+
+namespace chart::wrapper
+{
+
+namespace {
+
+class WrappedStockProperty : public WrappedProperty
+{
+public:
+ explicit WrappedStockProperty( const OUString& rOuterName
+ , css::uno::Any aDefaultValue
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact );
+
+ void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+ virtual rtl::Reference< ::chart::ChartTypeTemplate > getNewTemplate( bool bNewValue, const OUString& rCurrentTemplate, const rtl::Reference< ::chart::ChartTypeManager >& xFactory ) const = 0;
+
+protected:
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+ mutable css::uno::Any m_aOuterValue;
+ css::uno::Any m_aDefaultValue;
+};
+
+}
+
+WrappedStockProperty::WrappedStockProperty( const OUString& rOuterName
+ , css::uno::Any aDefaultValue
+ , std::shared_ptr<Chart2ModelContact> spChart2ModelContact )
+ : WrappedProperty(rOuterName,OUString())
+ , m_spChart2ModelContact(std::move(spChart2ModelContact))
+ , m_aDefaultValue(std::move(aDefaultValue))
+{
+}
+
+void WrappedStockProperty::setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ bool bNewValue = false;
+ if( ! (rOuterValue >>= bNewValue) )
+ throw lang::IllegalArgumentException( "stock properties require type sal_Bool", nullptr, 0 );
+
+ m_aOuterValue = rOuterValue;
+
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( !xChartDoc || !xDiagram )
+ return;
+ sal_Int32 nDimension = xDiagram->getDimension();
+ if( nDimension != 2 )
+ return;
+
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = xChartDoc->getTypeManager();
+ Diagram::tTemplateWithServiceName aTemplateAndService =
+ xDiagram->getTemplate( xChartTypeManager );
+
+ rtl::Reference< ::chart::ChartTypeTemplate > xTemplate =
+ getNewTemplate( bNewValue, aTemplateAndService.sServiceName, xChartTypeManager );
+
+ if(!xTemplate.is())
+ return;
+
+ try
+ {
+ // locked controllers
+ ControllerLockGuardUNO aCtrlLockGuard( m_spChart2ModelContact->getDocumentModel() );
+ xTemplate->changeDiagram( xDiagram );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+css::uno::Any WrappedStockProperty::getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ return m_aDefaultValue;
+}
+
+namespace {
+
+class WrappedVolumeProperty : public WrappedStockProperty
+{
+public:
+ explicit WrappedVolumeProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact);
+
+ css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ rtl::Reference< ::chart::ChartTypeTemplate > getNewTemplate( bool bNewValue, const OUString& rCurrentTemplate, const rtl::Reference< ::chart::ChartTypeManager >& xFactory ) const override;
+};
+
+}
+
+WrappedVolumeProperty::WrappedVolumeProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact)
+ : WrappedStockProperty( "Volume", uno::Any(false) , spChart2ModelContact )
+{
+}
+
+css::uno::Any WrappedVolumeProperty::getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() && xChartDoc.is() )
+ {
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector =
+ xDiagram->getDataSeries();
+ if( !aSeriesVector.empty() )
+ {
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = xChartDoc->getTypeManager();
+ Diagram::tTemplateWithServiceName aTemplateAndService =
+ xDiagram->getTemplate( xChartTypeManager );
+
+ if( aTemplateAndService.sServiceName == "com.sun.star.chart2.template.StockVolumeLowHighClose"
+ || aTemplateAndService.sServiceName == "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" )
+ m_aOuterValue <<= true;
+ else if( !aTemplateAndService.sServiceName.isEmpty() || !m_aOuterValue.hasValue() )
+ m_aOuterValue <<= false;
+ }
+ else if(!m_aOuterValue.hasValue())
+ m_aOuterValue <<= false;
+ }
+ return m_aOuterValue;
+}
+
+rtl::Reference< ::chart::ChartTypeTemplate > WrappedVolumeProperty::getNewTemplate( bool bNewValue, const OUString& rCurrentTemplate, const rtl::Reference< ::chart::ChartTypeManager >& xFactory ) const
+{
+ rtl::Reference< ::chart::ChartTypeTemplate > xTemplate;
+
+ if(!xFactory.is())
+ return xTemplate;
+
+ if( bNewValue ) //add volume
+ {
+ if( rCurrentTemplate == "com.sun.star.chart2.template.StockLowHighClose" )
+ xTemplate = xFactory->createTemplate( "com.sun.star.chart2.template.StockVolumeLowHighClose" );
+ else if( rCurrentTemplate == "com.sun.star.chart2.template.StockOpenLowHighClose" )
+ xTemplate = xFactory->createTemplate( "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" );
+ }
+ else //remove volume
+ {
+ if( rCurrentTemplate == "com.sun.star.chart2.template.StockVolumeLowHighClose" )
+ xTemplate = xFactory->createTemplate( "com.sun.star.chart2.template.StockLowHighClose" );
+ else if( rCurrentTemplate == "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" )
+ xTemplate = xFactory->createTemplate( "com.sun.star.chart2.template.StockOpenLowHighClose" );
+ }
+ return xTemplate;
+}
+
+namespace {
+
+class WrappedUpDownProperty : public WrappedStockProperty
+{
+public:
+ explicit WrappedUpDownProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact);
+
+ css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ rtl::Reference< ::chart::ChartTypeTemplate > getNewTemplate( bool bNewValue, const OUString& rCurrentTemplate, const rtl::Reference< ChartTypeManager >& xFactory ) const override;
+};
+
+}
+
+WrappedUpDownProperty::WrappedUpDownProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact)
+ : WrappedStockProperty( "UpDown", uno::Any(false) , spChart2ModelContact )
+{
+}
+
+css::uno::Any WrappedUpDownProperty::getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& /*xInnerPropertySet*/ ) const
+{
+ rtl::Reference< ChartModel > xChartDoc( m_spChart2ModelContact->getDocumentModel() );
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ if( xDiagram.is() && xChartDoc.is() )
+ {
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector =
+ xDiagram->getDataSeries();
+ if( !aSeriesVector.empty() )
+ {
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = xChartDoc->getTypeManager();
+ Diagram::tTemplateWithServiceName aTemplateAndService =
+ xDiagram->getTemplate( xChartTypeManager );
+
+ if( aTemplateAndService.sServiceName == "com.sun.star.chart2.template.StockOpenLowHighClose"
+ || aTemplateAndService.sServiceName == "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" )
+ m_aOuterValue <<= true;
+ else if( !aTemplateAndService.sServiceName.isEmpty() || !m_aOuterValue.hasValue() )
+ m_aOuterValue <<= false;
+ }
+ else if(!m_aOuterValue.hasValue())
+ m_aOuterValue <<= false;
+ }
+ return m_aOuterValue;
+}
+rtl::Reference< ::chart::ChartTypeTemplate > WrappedUpDownProperty::getNewTemplate( bool bNewValue, const OUString& rCurrentTemplate, const rtl::Reference< ChartTypeManager >& xFactory ) const
+{
+ rtl::Reference< ::chart::ChartTypeTemplate > xTemplate;
+ if( bNewValue ) //add open series
+ {
+ if( rCurrentTemplate == "com.sun.star.chart2.template.StockLowHighClose" )
+ xTemplate = xFactory->createTemplate( "com.sun.star.chart2.template.StockOpenLowHighClose" );
+ else if( rCurrentTemplate == "com.sun.star.chart2.template.StockVolumeLowHighClose" )
+ xTemplate = xFactory->createTemplate( "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" );
+ }
+ else //remove open series
+ {
+ if( rCurrentTemplate == "com.sun.star.chart2.template.StockOpenLowHighClose" )
+ xTemplate = xFactory->createTemplate( "com.sun.star.chart2.template.StockLowHighClose" );
+ else if( rCurrentTemplate == "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" )
+ xTemplate = xFactory->createTemplate( "com.sun.star.chart2.template.StockVolumeLowHighClose" );
+ }
+ return xTemplate;
+}
+
+namespace
+{
+enum
+{
+ //spline properties
+ PROP_CHART_STOCK_VOLUME = FAST_PROPERTY_ID_START_CHART_STOCK_PROP
+ , PROP_CHART_STOCK_UPDOWN
+};
+
+}//anonymous namespace
+
+void WrappedStockProperties::addProperties( std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "Volume",
+ PROP_CHART_STOCK_VOLUME,
+ cppu::UnoType<sal_Bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "UpDown",
+ PROP_CHART_STOCK_UPDOWN,
+ cppu::UnoType<sal_Bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+}
+
+void WrappedStockProperties::addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ rList.emplace_back( new WrappedVolumeProperty( spChart2ModelContact ) );
+ rList.emplace_back( new WrappedUpDownProperty( spChart2ModelContact ) );
+}
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedStockProperties.hxx b/chart2/source/controller/chartapiwrapper/WrappedStockProperties.hxx
new file mode 100644
index 0000000000..e460ba5873
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedStockProperties.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/types.h>
+#include <memory>
+#include <vector>
+
+namespace chart { class WrappedProperty; }
+namespace chart::wrapper { class Chart2ModelContact; }
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart::wrapper
+{
+
+class WrappedStockProperties
+{
+public:
+ static void addProperties( std::vector< css::beans::Property > & rOutProperties );
+ static void addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx
new file mode 100644
index 0000000000..79c45ea1d8
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.cxx
@@ -0,0 +1,531 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedSymbolProperties.hxx"
+#include "WrappedSeriesOrDiagramProperty.hxx"
+#include <FastPropertyIdRanges.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart2/SymbolStyle.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/chart/ChartSymbolType.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <vcl/GraphicLoader.hxx>
+
+#include <vcl/graph.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::beans::Property;
+
+namespace chart::wrapper
+{
+
+namespace
+{
+
+class WrappedSymbolTypeProperty : public WrappedSeriesOrDiagramProperty< sal_Int32 >
+{
+public:
+ virtual sal_Int32 getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const sal_Int32& aNewValue ) const override;
+
+ virtual Any getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const override;
+ virtual beans::PropertyState getPropertyState( const Reference< beans::XPropertyState >& xInnerPropertyState ) const override;
+
+ explicit WrappedSymbolTypeProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType);
+};
+
+class WrappedSymbolBitmapURLProperty : public WrappedSeriesOrDiagramProperty<OUString>
+{
+public:
+ virtual OUString getValueFromSeries(const Reference<beans::XPropertySet>& xSeriesPropertySet) const override;
+ virtual void setValueToSeries(const Reference<beans::XPropertySet> & xSeriesPropertySet, OUString const & xNewGraphicURL) const override;
+
+ explicit WrappedSymbolBitmapURLProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType);
+};
+
+class WrappedSymbolBitmapProperty : public WrappedSeriesOrDiagramProperty<uno::Reference<graphic::XGraphic>>
+{
+public:
+ virtual uno::Reference<graphic::XGraphic> getValueFromSeries(const Reference<beans::XPropertySet>& xSeriesPropertySet) const override;
+ virtual void setValueToSeries(const Reference<beans::XPropertySet> & xSeriesPropertySet, uno::Reference<graphic::XGraphic> const & xNewGraphic) const override;
+
+ explicit WrappedSymbolBitmapProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType);
+};
+
+class WrappedSymbolSizeProperty : public WrappedSeriesOrDiagramProperty< awt::Size >
+{
+public:
+ virtual awt::Size getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const awt::Size& aNewSize ) const override;
+ virtual beans::PropertyState getPropertyState( const Reference< beans::XPropertyState >& xInnerPropertyState ) const override;
+
+ explicit WrappedSymbolSizeProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType);
+};
+
+class WrappedSymbolAndLinesProperty : public WrappedSeriesOrDiagramProperty< bool >
+{
+public:
+ virtual bool getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const override;
+ virtual void setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const bool& bDrawLines ) const override;
+ virtual beans::PropertyState getPropertyState( const Reference< beans::XPropertyState >& xInnerPropertyState ) const override;
+
+ explicit WrappedSymbolAndLinesProperty(const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType);
+};
+
+enum
+{
+ //symbol properties
+ PROP_CHART_SYMBOL_TYPE = FAST_PROPERTY_ID_START_CHART_SYMBOL_PROP,
+ PROP_CHART_SYMBOL_BITMAP_URL,
+ PROP_CHART_SYMBOL_BITMAP,
+ PROP_CHART_SYMBOL_SIZE,
+ PROP_CHART_SYMBOL_AND_LINES
+};
+
+sal_Int32 lcl_getSymbolType( const css::chart2::Symbol& rSymbol )
+{
+ sal_Int32 nSymbol = css::chart::ChartSymbolType::NONE;
+ switch( rSymbol.Style )
+ {
+ case chart2::SymbolStyle_NONE:
+ break;
+ case chart2::SymbolStyle_AUTO:
+ nSymbol = css::chart::ChartSymbolType::AUTO;
+ break;
+ case chart2::SymbolStyle_STANDARD:
+ nSymbol = rSymbol.StandardSymbol%15;
+ break;
+ case chart2::SymbolStyle_POLYGON://new feature
+ nSymbol = css::chart::ChartSymbolType::AUTO;
+ break;
+ case chart2::SymbolStyle_GRAPHIC:
+ nSymbol = css::chart::ChartSymbolType::BITMAPURL;
+ break;
+ default:
+ nSymbol = css::chart::ChartSymbolType::AUTO;
+ break;
+ }
+ return nSymbol;
+}
+void lcl_setSymbolTypeToSymbol( sal_Int32 nSymbolType, chart2::Symbol& rSymbol )
+{
+ switch( nSymbolType )
+ {
+ case css::chart::ChartSymbolType::NONE:
+ rSymbol.Style = chart2::SymbolStyle_NONE;
+ break;
+ case css::chart::ChartSymbolType::AUTO:
+ rSymbol.Style = chart2::SymbolStyle_AUTO;
+ break;
+ case css::chart::ChartSymbolType::BITMAPURL:
+ rSymbol.Style = chart2::SymbolStyle_GRAPHIC;
+ break;
+ default:
+ rSymbol.Style = chart2::SymbolStyle_STANDARD;
+ rSymbol.StandardSymbol = nSymbolType;
+ break;
+ }
+}
+
+void lcl_addWrappedProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact
+ , tSeriesOrDiagramPropertyType ePropertyType )
+{
+ rList.emplace_back( new WrappedSymbolTypeProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedSymbolBitmapURLProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedSymbolBitmapProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedSymbolSizeProperty( spChart2ModelContact, ePropertyType ) );
+ rList.emplace_back( new WrappedSymbolAndLinesProperty( spChart2ModelContact, ePropertyType ) );
+}
+
+}//anonymous namespace
+
+void WrappedSymbolProperties::addProperties( std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "SymbolType",
+ PROP_CHART_SYMBOL_TYPE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "SymbolBitmapURL",
+ PROP_CHART_SYMBOL_BITMAP_URL,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "SymbolBitmap",
+ PROP_CHART_SYMBOL_BITMAP,
+ cppu::UnoType<graphic::XGraphic>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "SymbolSize",
+ PROP_CHART_SYMBOL_SIZE,
+ cppu::UnoType<awt::Size>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "Lines",
+ PROP_CHART_SYMBOL_AND_LINES,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+void WrappedSymbolProperties::addWrappedPropertiesForSeries( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ lcl_addWrappedProperties( rList, spChart2ModelContact, DATA_SERIES );
+}
+
+void WrappedSymbolProperties::addWrappedPropertiesForDiagram( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact )
+{
+ lcl_addWrappedProperties( rList, spChart2ModelContact, DIAGRAM );
+}
+
+WrappedSymbolTypeProperty::WrappedSymbolTypeProperty(
+ const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedSeriesOrDiagramProperty< sal_Int32 >( "SymbolType"
+ , uno::Any( css::chart::ChartSymbolType::NONE )
+ , spChart2ModelContact
+ , ePropertyType )
+{
+}
+
+sal_Int32 WrappedSymbolTypeProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ sal_Int32 aRet = 0;
+ m_aDefaultValue >>= aRet;
+ chart2::Symbol aSymbol;
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue("Symbol") >>= aSymbol ) )
+ aRet = lcl_getSymbolType( aSymbol );
+ return aRet;
+}
+
+void WrappedSymbolTypeProperty::setValueToSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet, const sal_Int32& nSymbolType ) const
+{
+ if(!xSeriesPropertySet.is())
+ return;
+
+ chart2::Symbol aSymbol;
+ xSeriesPropertySet->getPropertyValue("Symbol") >>= aSymbol;
+
+ lcl_setSymbolTypeToSymbol( nSymbolType, aSymbol );
+ xSeriesPropertySet->setPropertyValue( "Symbol", uno::Any( aSymbol ) );
+}
+
+Any WrappedSymbolTypeProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ //the old chart (< OOo 2.3) needs symbol-type="automatic" at the plot-area if any of the series should be able to have symbols
+ if( m_ePropertyType == DIAGRAM )
+ {
+ bool bHasAmbiguousValue = false;
+ sal_Int32 aValue = 0;
+ if( detectInnerValue( aValue, bHasAmbiguousValue ) )
+ {
+ if(bHasAmbiguousValue)
+ {
+ m_aOuterValue <<= css::chart::ChartSymbolType::AUTO;
+ }
+ else
+ {
+ if( aValue == css::chart::ChartSymbolType::NONE )
+ m_aOuterValue <<= css::chart::ChartSymbolType::NONE;
+ else
+ m_aOuterValue <<= css::chart::ChartSymbolType::AUTO;
+ }
+ }
+ return m_aOuterValue;
+ }
+ else
+ {
+ css::uno::Any aRet( m_aDefaultValue );
+ aRet <<= getValueFromSeries( xInnerPropertySet );
+ return aRet;
+ }
+}
+
+beans::PropertyState WrappedSymbolTypeProperty::getPropertyState( const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ //the special situation for this property here is that the diagram default can be
+ //different from the normal default and different from all singles series values
+ //so we need to return PropertyState_DIRECT_VALUE for more cases
+
+ if( m_ePropertyType == DATA_SERIES && //single series or point
+ m_spChart2ModelContact)
+ {
+ rtl::Reference< ::chart::Diagram > xDiagram( m_spChart2ModelContact->getDiagram() );
+ rtl::Reference< ::chart::DataSeries > xSeries( dynamic_cast<DataSeries*>(xInnerPropertyState.get()) );
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeOfSeries( xSeries ) );
+ if( ChartTypeHelper::isSupportingSymbolProperties( xChartType, 2 ) )
+ return beans::PropertyState_DIRECT_VALUE;
+ }
+ return WrappedProperty::getPropertyState( xInnerPropertyState );
+}
+
+WrappedSymbolBitmapURLProperty::WrappedSymbolBitmapURLProperty(
+ const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedSeriesOrDiagramProperty<OUString>("SymbolBitmapURL",
+ uno::Any(OUString()), spChart2ModelContact, ePropertyType)
+{
+}
+
+OUString WrappedSymbolBitmapURLProperty::getValueFromSeries(const Reference< beans::XPropertySet >& /*xSeriesPropertySet*/) const
+{
+ return OUString();
+}
+
+void WrappedSymbolBitmapURLProperty::setValueToSeries(
+ const Reference< beans::XPropertySet >& xSeriesPropertySet,
+ OUString const & xNewGraphicURL) const
+{
+ if (!xSeriesPropertySet.is())
+ return;
+
+ chart2::Symbol aSymbol;
+ if (xSeriesPropertySet->getPropertyValue("Symbol") >>= aSymbol)
+ {
+ if (!xNewGraphicURL.isEmpty())
+ {
+ Graphic aGraphic = vcl::graphic::loadFromURL(xNewGraphicURL);
+ aSymbol.Graphic.set(aGraphic.GetXGraphic());
+ xSeriesPropertySet->setPropertyValue("Symbol", uno::Any(aSymbol));
+ }
+ }
+}
+
+WrappedSymbolBitmapProperty::WrappedSymbolBitmapProperty(
+ const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedSeriesOrDiagramProperty<uno::Reference<graphic::XGraphic>>("SymbolBitmap",
+ uno::Any(uno::Reference<graphic::XGraphic>()), spChart2ModelContact, ePropertyType)
+{
+}
+
+uno::Reference<graphic::XGraphic> WrappedSymbolBitmapProperty::getValueFromSeries(const Reference< beans::XPropertySet >& xSeriesPropertySet) const
+{
+ uno::Reference<graphic::XGraphic> xGraphic;
+ m_aDefaultValue >>= xGraphic;
+
+ chart2::Symbol aSymbol;
+ if (xSeriesPropertySet.is() && (xSeriesPropertySet->getPropertyValue("Symbol") >>= aSymbol)
+ && aSymbol.Graphic.is())
+ {
+ xGraphic = aSymbol.Graphic;
+ }
+ return xGraphic;
+}
+
+void WrappedSymbolBitmapProperty::setValueToSeries(
+ const Reference< beans::XPropertySet >& xSeriesPropertySet,
+ uno::Reference<graphic::XGraphic> const & xNewGraphic) const
+{
+ if (!xSeriesPropertySet.is())
+ return;
+
+ chart2::Symbol aSymbol;
+ if (xSeriesPropertySet->getPropertyValue("Symbol") >>= aSymbol)
+ {
+ if (xNewGraphic.is())
+ {
+ aSymbol.Graphic.set(xNewGraphic);
+ xSeriesPropertySet->setPropertyValue("Symbol", uno::Any(aSymbol));
+ }
+ }
+}
+
+namespace
+{
+
+void lcl_correctSymbolSizeForBitmaps( chart2::Symbol& rSymbol )
+{
+ if( rSymbol.Style != chart2::SymbolStyle_GRAPHIC )
+ return;
+ if( rSymbol.Size.Width != -1 )
+ return;
+ if( rSymbol.Size.Height != -1 )
+ return;
+
+ //find a good automatic size
+ try
+ {
+ const awt::Size aDefaultSize(250,250);
+ awt::Size aSize = aDefaultSize;
+ uno::Reference< beans::XPropertySet > xProp( rSymbol.Graphic, uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ bool bFoundSize = false;
+ try
+ {
+ if( xProp->getPropertyValue( "Size100thMM" ) >>= aSize )
+ {
+ if( aSize.Width == 0 && aSize.Height == 0 )
+ aSize = aDefaultSize;
+ else
+ bFoundSize = true;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ if(!bFoundSize)
+ {
+ awt::Size aAWTPixelSize(10,10);
+ if( xProp->getPropertyValue( "SizePixel" ) >>= aAWTPixelSize )
+ {
+ Size aPixelSize(aAWTPixelSize.Width,aAWTPixelSize.Height);
+ Size aNewSize = o3tl::convert(aPixelSize, o3tl::Length::pt, o3tl::Length::mm100);
+
+ aSize = awt::Size( aNewSize.Width(), aNewSize.Height() );
+
+ if( aSize.Width == 0 && aSize.Height == 0 )
+ aSize = aDefaultSize;
+ }
+ }
+ }
+ rSymbol.Size = aSize;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+}//end anonymous namespace
+
+WrappedSymbolSizeProperty::WrappedSymbolSizeProperty(
+ const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedSeriesOrDiagramProperty< awt::Size >( "SymbolSize"
+ , uno::Any( awt::Size(250,250) ), spChart2ModelContact, ePropertyType )
+{
+}
+
+awt::Size WrappedSymbolSizeProperty::getValueFromSeries( const Reference< beans::XPropertySet >& xSeriesPropertySet ) const
+{
+ awt::Size aRet;
+ m_aDefaultValue >>= aRet;
+ chart2::Symbol aSymbol;
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue("Symbol") >>= aSymbol ))
+ aRet = aSymbol.Size;
+ return aRet;
+}
+
+void WrappedSymbolSizeProperty::setValueToSeries(
+ const Reference< beans::XPropertySet >& xSeriesPropertySet,
+ const awt::Size& aNewSize ) const
+{
+ if(!xSeriesPropertySet.is())
+ return;
+
+ chart2::Symbol aSymbol;
+ if( xSeriesPropertySet->getPropertyValue("Symbol") >>= aSymbol )
+ {
+ aSymbol.Size = aNewSize;
+ lcl_correctSymbolSizeForBitmaps(aSymbol);
+ xSeriesPropertySet->setPropertyValue( "Symbol", uno::Any( aSymbol ) );
+ }
+}
+
+beans::PropertyState WrappedSymbolSizeProperty::getPropertyState( const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ //only export symbol size if necessary
+ if( m_ePropertyType == DIAGRAM )
+ return beans::PropertyState_DEFAULT_VALUE;
+
+ try
+ {
+ chart2::Symbol aSymbol;
+ Reference< beans::XPropertySet > xSeriesPropertySet( xInnerPropertyState, uno::UNO_QUERY );
+ if( xSeriesPropertySet.is() && ( xSeriesPropertySet->getPropertyValue("Symbol") >>= aSymbol ))
+ {
+ if( aSymbol.Style != chart2::SymbolStyle_NONE )
+ return beans::PropertyState_DIRECT_VALUE;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return beans::PropertyState_DEFAULT_VALUE;
+}
+
+WrappedSymbolAndLinesProperty::WrappedSymbolAndLinesProperty(
+ const std::shared_ptr<Chart2ModelContact>& spChart2ModelContact,
+ tSeriesOrDiagramPropertyType ePropertyType )
+ : WrappedSeriesOrDiagramProperty< bool >( "Lines"
+ , uno::Any( true ), spChart2ModelContact, ePropertyType )
+{
+}
+
+bool WrappedSymbolAndLinesProperty::getValueFromSeries( const Reference< beans::XPropertySet >& /*xSeriesPropertySet*/ ) const
+{
+ //do not export this property anymore, instead use a linestyle none for no lines
+ return true;
+}
+
+void WrappedSymbolAndLinesProperty::setValueToSeries(
+ const Reference< beans::XPropertySet >& xSeriesPropertySet,
+ const bool& bDrawLines ) const
+{
+ if(!xSeriesPropertySet.is())
+ return;
+
+ drawing::LineStyle eOldLineStyle( drawing::LineStyle_SOLID );
+ xSeriesPropertySet->getPropertyValue( "LineStyle" ) >>= eOldLineStyle;
+ if( bDrawLines )
+ {
+ //#i114298# don't overwrite dashed lines with solid lines here
+ if( eOldLineStyle == drawing::LineStyle_NONE )
+ xSeriesPropertySet->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_SOLID ) );
+ }
+ else
+ {
+ if( eOldLineStyle != drawing::LineStyle_NONE )
+ xSeriesPropertySet->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE ) );
+ }
+}
+
+beans::PropertyState WrappedSymbolAndLinesProperty::getPropertyState( const Reference< beans::XPropertyState >& /*xInnerPropertyState*/ ) const
+{
+ //do not export this property anymore, instead use a linestyle none for no lines
+ return beans::PropertyState_DEFAULT_VALUE;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.hxx b/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.hxx
new file mode 100644
index 0000000000..f3a0fcd66e
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedSymbolProperties.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/types.h>
+#include <memory>
+#include <vector>
+
+namespace chart { class WrappedProperty; }
+namespace chart::wrapper { class Chart2ModelContact; }
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart::wrapper
+{
+
+class WrappedSymbolProperties
+{
+public:
+ static void addProperties( std::vector< css::beans::Property > & rOutProperties );
+ static void addWrappedPropertiesForSeries( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+ static void addWrappedPropertiesForDiagram( std::vector< std::unique_ptr<WrappedProperty> >& rList
+ , const std::shared_ptr< Chart2ModelContact >& spChart2ModelContact );
+};
+
+} //namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.cxx b/chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.cxx
new file mode 100644
index 0000000000..c35a75e31a
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WrappedTextRotationProperty.hxx"
+
+namespace com::sun::star::beans { class XPropertyState; }
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+
+namespace chart
+{
+
+WrappedTextRotationProperty::WrappedTextRotationProperty( bool bDirectState )
+ : ::chart::WrappedProperty( "TextRotation" , "TextRotation" )
+ , m_bDirectState( bDirectState )
+{
+}
+WrappedTextRotationProperty::~WrappedTextRotationProperty()
+{
+}
+
+beans::PropertyState WrappedTextRotationProperty::getPropertyState( const uno::Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ if( m_bDirectState )
+ return beans::PropertyState_DIRECT_VALUE;
+ return WrappedProperty::getPropertyState( xInnerPropertyState );
+}
+
+Any WrappedTextRotationProperty::convertInnerToOuterValue( const Any& rInnerValue ) const
+{
+ Any aRet;
+ double fVal = 0;
+ if( rInnerValue >>= fVal )
+ {
+ sal_Int32 n100thDegrees = static_cast< sal_Int32 >( fVal * 100.0 );
+ aRet <<= n100thDegrees;
+ }
+ return aRet;
+}
+Any WrappedTextRotationProperty::convertOuterToInnerValue( const Any& rOuterValue ) const
+{
+ Any aRet;
+ sal_Int32 nVal = 0;
+ if( rOuterValue >>= nVal )
+ {
+ double fDoubleDegrees = static_cast< double >( nVal ) / 100.0;
+ aRet <<= fDoubleDegrees;
+ }
+ return aRet;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.hxx b/chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.hxx
new file mode 100644
index 0000000000..48287dd592
--- /dev/null
+++ b/chart2/source/controller/chartapiwrapper/WrappedTextRotationProperty.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedProperty.hxx>
+
+namespace chart
+{
+class WrappedTextRotationProperty final : public WrappedProperty
+{
+public:
+ explicit WrappedTextRotationProperty(bool bDirectState = false);
+ virtual ~WrappedTextRotationProperty() override;
+
+ virtual css::beans::PropertyState getPropertyState(
+ const css::uno::Reference<css::beans::XPropertyState>& xInnerPropertyState) const override;
+
+private:
+ virtual css::uno::Any convertInnerToOuterValue(const css::uno::Any& rInnerValue) const override;
+ virtual css::uno::Any convertOuterToInnerValue(const css::uno::Any& rOuterValue) const override;
+
+ bool m_bDirectState;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/chartcontroller.component b/chart2/source/controller/chartcontroller.component
new file mode 100644
index 0000000000..ef8e748242
--- /dev/null
+++ b/chart2/source/controller/chartcontroller.component
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.chart.ElementSelectorToolbarController"
+ constructor="com_sun_star_comp_chart_ElementSelectorToolbarController_get_implementation">
+ <service name="com.sun.star.frame.ToolbarController"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.ChartDocumentWrapper"
+ constructor="com_sun_star_comp_chart2_ChartDocumentWrapper_get_implementation">
+ <service name="com.sun.star.beans.PropertySet"/>
+ <service name="com.sun.star.chart.ChartDocument"/>
+ <service name="com.sun.star.chart2.ChartDocumentWrapper"/>
+ <service name="com.sun.star.xml.UserDefinedAttributesSupplier"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.ChartFrameLoader"
+ constructor="com_sun_star_comp_chart2_ChartFrameLoader_get_implementation">
+ <service name="com.sun.star.frame.SynchronousFrameLoader"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.ChartTypeDialog"
+ constructor="com_sun_star_comp_chart2_ChartTypeDialog_get_implementation">
+ <service name="com.sun.star.chart2.ChartTypeDialog"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.chart2.WizardDialog"
+ constructor="com_sun_star_comp_chart2_WizardDialog_get_implementation">
+ <service name="com.sun.star.chart2.WizardDialog"/>
+ </implementation>
+ <implementation name="org.libreoffice.comp.chart2.sidebar.ChartPanelFactory"
+ constructor="org_libreoffice_comp_chart2_sidebar_ChartPanelFactory">
+ <service name="com.sun.star.ui.UIElementFactory"/>
+ </implementation>
+ <implementation name="org.libreoffice.chart2.Chart2ToolboxController"
+ constructor="org_libreoffice_chart2_Chart2ToolboxController">
+ <service name="com.sun.star.frame.ToolbarController"/>
+ </implementation>
+</component>
diff --git a/chart2/source/controller/dialogs/ChangingResource.cxx b/chart2/source/controller/dialogs/ChangingResource.cxx
new file mode 100644
index 0000000000..4cbbe569cc
--- /dev/null
+++ b/chart2/source/controller/dialogs/ChangingResource.cxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChangingResource.hxx>
+
+namespace chart
+{
+ResourceChangeListener::~ResourceChangeListener() {}
+
+ChangingResource::ChangingResource()
+ : m_pChangeListener(nullptr)
+{
+}
+ChangingResource::~ChangingResource() {}
+void ChangingResource::setChangeListener(ResourceChangeListener* pListener)
+{
+ m_pChangeListener = pListener;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/ChartResourceGroupDlgs.cxx b/chart2/source/controller/dialogs/ChartResourceGroupDlgs.cxx
new file mode 100644
index 0000000000..91307afaad
--- /dev/null
+++ b/chart2/source/controller/dialogs/ChartResourceGroupDlgs.cxx
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartResourceGroupDlgs.hxx>
+#include <ChartTypeDialogController.hxx>
+
+#include <strings.hrc>
+#include <ResId.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+const sal_uInt16 CUBIC_SPLINE_POS = 0;
+const sal_uInt16 B_SPLINE_POS = 1;
+
+SplinePropertiesDialog::SplinePropertiesDialog(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/schart/ui/smoothlinesdlg.ui", "SmoothLinesDialog")
+ , m_xLB_Spline_Type(m_xBuilder->weld_combo_box("SplineTypeComboBox"))
+ , m_xMF_SplineResolution(m_xBuilder->weld_spin_button("ResolutionSpinbutton"))
+ , m_xFT_SplineOrder(m_xBuilder->weld_label("PolynomialsLabel"))
+ , m_xMF_SplineOrder(m_xBuilder->weld_spin_button("PolynomialsSpinButton"))
+{
+ m_xDialog->set_title(SchResId(STR_DLG_SMOOTH_LINE_PROPERTIES));
+
+ m_xLB_Spline_Type->connect_changed(LINK(this, SplinePropertiesDialog, SplineTypeListBoxHdl));
+}
+
+void SplinePropertiesDialog::fillControls(const ChartTypeParameter& rParameter)
+{
+ switch (rParameter.eCurveStyle)
+ {
+ case CurveStyle_CUBIC_SPLINES:
+ m_xLB_Spline_Type->set_active(CUBIC_SPLINE_POS);
+ break;
+ case CurveStyle_B_SPLINES:
+ m_xLB_Spline_Type->set_active(B_SPLINE_POS);
+ break;
+ default:
+ m_xLB_Spline_Type->set_active(CUBIC_SPLINE_POS);
+ break;
+ }
+ m_xMF_SplineOrder->set_value(rParameter.nSplineOrder);
+ m_xMF_SplineResolution->set_value(rParameter.nCurveResolution);
+
+ //dis/enabling
+ m_xFT_SplineOrder->set_sensitive(m_xLB_Spline_Type->get_active() == B_SPLINE_POS);
+ m_xMF_SplineOrder->set_sensitive(m_xLB_Spline_Type->get_active() == B_SPLINE_POS);
+}
+
+void SplinePropertiesDialog::fillParameter(ChartTypeParameter& rParameter, bool bSmoothLines)
+{
+ if (!bSmoothLines)
+ rParameter.eCurveStyle = CurveStyle_LINES;
+ else if (m_xLB_Spline_Type->get_active() == CUBIC_SPLINE_POS)
+ rParameter.eCurveStyle = CurveStyle_CUBIC_SPLINES;
+ else if (m_xLB_Spline_Type->get_active() == B_SPLINE_POS)
+ rParameter.eCurveStyle = CurveStyle_B_SPLINES;
+
+ rParameter.nCurveResolution = m_xMF_SplineResolution->get_value();
+ rParameter.nSplineOrder = m_xMF_SplineOrder->get_value();
+}
+
+IMPL_LINK_NOARG(SplinePropertiesDialog, SplineTypeListBoxHdl, weld::ComboBox&, void)
+{
+ m_xFT_SplineOrder->set_sensitive(m_xLB_Spline_Type->get_active() == B_SPLINE_POS);
+ m_xMF_SplineOrder->set_sensitive(m_xLB_Spline_Type->get_active() == B_SPLINE_POS);
+}
+
+SteppedPropertiesDialog::SteppedPropertiesDialog(weld::Window* pParent)
+ : GenericDialogController(pParent, "modules/schart/ui/steppedlinesdlg.ui", "SteppedLinesDialog")
+ , m_xRB_Start(m_xBuilder->weld_radio_button("step_start_rb"))
+ , m_xRB_End(m_xBuilder->weld_radio_button("step_end_rb"))
+ , m_xRB_CenterX(m_xBuilder->weld_radio_button("step_center_x_rb"))
+ , m_xRB_CenterY(m_xBuilder->weld_radio_button("step_center_y_rb"))
+{
+ m_xDialog->set_title(SchResId(STR_DLG_STEPPED_LINE_PROPERTIES));
+}
+
+void SteppedPropertiesDialog::fillControls(const ChartTypeParameter& rParameter)
+{
+ switch (rParameter.eCurveStyle)
+ {
+ case CurveStyle_STEP_END:
+ m_xRB_End->set_active(true);
+ break;
+ case CurveStyle_STEP_CENTER_X:
+ m_xRB_CenterX->set_active(true);
+ break;
+ case CurveStyle_STEP_CENTER_Y:
+ m_xRB_CenterY->set_active(true);
+ break;
+ default: // includes CurveStyle_STEP_START
+ m_xRB_Start->set_active(true);
+ break;
+ }
+}
+void SteppedPropertiesDialog::fillParameter(ChartTypeParameter& rParameter, bool bSteppedLines)
+{
+ if (!bSteppedLines)
+ rParameter.eCurveStyle = CurveStyle_LINES;
+ else if (m_xRB_CenterY->get_active())
+ rParameter.eCurveStyle = CurveStyle_STEP_CENTER_Y;
+ else if (m_xRB_Start->get_active())
+ rParameter.eCurveStyle = CurveStyle_STEP_START;
+ else if (m_xRB_End->get_active())
+ rParameter.eCurveStyle = CurveStyle_STEP_END;
+ else if (m_xRB_CenterX->get_active())
+ rParameter.eCurveStyle = CurveStyle_STEP_CENTER_X;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/ChartResourceGroups.cxx b/chart2/source/controller/dialogs/ChartResourceGroups.cxx
new file mode 100644
index 0000000000..e1550d2766
--- /dev/null
+++ b/chart2/source/controller/dialogs/ChartResourceGroups.cxx
@@ -0,0 +1,383 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartResourceGroups.hxx>
+#include <ChartResourceGroupDlgs.hxx>
+
+#include <strings.hrc>
+#include <ResId.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+Dim3DLookResourceGroup::Dim3DLookResourceGroup(weld::Builder* pBuilder)
+ : m_xCB_3DLook(pBuilder->weld_check_button("3dlook"))
+ , m_xLB_Scheme(pBuilder->weld_combo_box("3dscheme"))
+{
+ m_xCB_3DLook->connect_toggled(LINK(this, Dim3DLookResourceGroup, Dim3DLookCheckHdl));
+ m_xLB_Scheme->connect_changed(LINK(this, Dim3DLookResourceGroup, SelectSchemeHdl));
+}
+
+void Dim3DLookResourceGroup::showControls(bool bShow)
+{
+ m_xCB_3DLook->set_visible(bShow);
+ m_xLB_Scheme->set_visible(bShow);
+}
+
+void Dim3DLookResourceGroup::fillControls(const ChartTypeParameter& rParameter)
+{
+ m_xCB_3DLook->set_active(rParameter.b3DLook);
+ m_xLB_Scheme->set_sensitive(rParameter.b3DLook);
+
+ // tdf#124295 - select always a 3D scheme
+ switch (rParameter.eThreeDLookScheme)
+ {
+ case ThreeDLookScheme::ThreeDLookScheme_Simple:
+ m_xLB_Scheme->set_active(POS_3DSCHEME_SIMPLE);
+ break;
+ case ThreeDLookScheme::ThreeDLookScheme_Realistic:
+ case ThreeDLookScheme::ThreeDLookScheme_Unknown:
+ m_xLB_Scheme->set_active(POS_3DSCHEME_REALISTIC);
+ break;
+ }
+}
+
+void Dim3DLookResourceGroup::fillParameter(ChartTypeParameter& rParameter)
+{
+ rParameter.b3DLook = m_xCB_3DLook->get_active();
+ // tdf#124295 - select always a 3D scheme
+ switch (m_xLB_Scheme->get_active())
+ {
+ case POS_3DSCHEME_SIMPLE:
+ rParameter.eThreeDLookScheme = ThreeDLookScheme::ThreeDLookScheme_Simple;
+ break;
+ default:
+ rParameter.eThreeDLookScheme = ThreeDLookScheme::ThreeDLookScheme_Realistic;
+ }
+}
+
+IMPL_LINK_NOARG(Dim3DLookResourceGroup, Dim3DLookCheckHdl, weld::Toggleable&, void)
+{
+ if (m_pChangeListener)
+ m_pChangeListener->stateChanged();
+}
+
+IMPL_LINK_NOARG(Dim3DLookResourceGroup, SelectSchemeHdl, weld::ComboBox&, void)
+{
+ if (m_pChangeListener)
+ m_pChangeListener->stateChanged();
+}
+
+SortByXValuesResourceGroup::SortByXValuesResourceGroup(weld::Builder* pBuilder)
+ : m_xCB_XValueSorting(pBuilder->weld_check_button("sort"))
+{
+ m_xCB_XValueSorting->connect_toggled(
+ LINK(this, SortByXValuesResourceGroup, SortByXValuesCheckHdl));
+}
+
+void SortByXValuesResourceGroup::showControls(bool bShow)
+{
+ m_xCB_XValueSorting->set_visible(bShow);
+}
+
+void SortByXValuesResourceGroup::fillControls(const ChartTypeParameter& rParameter)
+{
+ m_xCB_XValueSorting->set_active(rParameter.bSortByXValues);
+}
+
+void SortByXValuesResourceGroup::fillParameter(ChartTypeParameter& rParameter)
+{
+ rParameter.bSortByXValues = m_xCB_XValueSorting->get_active();
+}
+
+IMPL_LINK_NOARG(SortByXValuesResourceGroup, SortByXValuesCheckHdl, weld::Toggleable&, void)
+{
+ if (m_pChangeListener)
+ m_pChangeListener->stateChanged();
+}
+
+StackingResourceGroup::StackingResourceGroup(weld::Builder* pBuilder)
+ : m_xCB_Stacked(pBuilder->weld_check_button("stack"))
+ , m_xRB_Stack_Y(pBuilder->weld_radio_button("ontop"))
+ , m_xRB_Stack_Y_Percent(pBuilder->weld_radio_button("percent"))
+ , m_xRB_Stack_Z(pBuilder->weld_radio_button("deep"))
+{
+ m_xCB_Stacked->connect_toggled(LINK(this, StackingResourceGroup, StackingEnableHdl));
+ m_xRB_Stack_Y->connect_toggled(LINK(this, StackingResourceGroup, StackingChangeHdl));
+ m_xRB_Stack_Y_Percent->connect_toggled(LINK(this, StackingResourceGroup, StackingChangeHdl));
+ m_xRB_Stack_Z->connect_toggled(LINK(this, StackingResourceGroup, StackingChangeHdl));
+}
+
+void StackingResourceGroup::showControls(bool bShow)
+{
+ m_xCB_Stacked->set_visible(bShow);
+ m_xRB_Stack_Y->set_visible(bShow);
+ m_xRB_Stack_Y_Percent->set_visible(bShow);
+ m_xRB_Stack_Z->set_visible(false);
+}
+
+void StackingResourceGroup::fillControls(const ChartTypeParameter& rParameter)
+{
+ m_xCB_Stacked->set_active(
+ rParameter.eStackMode != GlobalStackMode_NONE
+ && rParameter.eStackMode
+ != GlobalStackMode_STACK_Z); //todo remove this condition if z stacking radio button is really used
+ switch (rParameter.eStackMode)
+ {
+ case GlobalStackMode_STACK_Y:
+ m_xRB_Stack_Y->set_active(true);
+ break;
+ case GlobalStackMode_STACK_Y_PERCENT:
+ m_xRB_Stack_Y_Percent->set_active(true);
+ break;
+ case GlobalStackMode_STACK_Z:
+ //todo uncomment this condition if z stacking radio button is really used
+ /*
+ if( rParameter.b3DLook )
+ m_xRB_Stack_Z->set_active(true);
+ else
+ */
+ m_xRB_Stack_Y->set_active(true);
+ break;
+ default:
+ m_xRB_Stack_Y->set_active(true);
+ break;
+ }
+ //dis/enabling
+ m_xCB_Stacked->set_sensitive(!rParameter.bXAxisWithValues);
+ m_xRB_Stack_Y->set_sensitive(m_xCB_Stacked->get_active() && !rParameter.bXAxisWithValues);
+ m_xRB_Stack_Y_Percent->set_sensitive(m_xCB_Stacked->get_active()
+ && !rParameter.bXAxisWithValues);
+ m_xRB_Stack_Z->set_sensitive(m_xCB_Stacked->get_active() && rParameter.b3DLook);
+}
+
+void StackingResourceGroup::fillParameter(ChartTypeParameter& rParameter)
+{
+ if (!m_xCB_Stacked->get_active())
+ rParameter.eStackMode = GlobalStackMode_NONE;
+ else if (m_xRB_Stack_Y->get_active())
+ rParameter.eStackMode = GlobalStackMode_STACK_Y;
+ else if (m_xRB_Stack_Y_Percent->get_active())
+ rParameter.eStackMode = GlobalStackMode_STACK_Y_PERCENT;
+ else if (m_xRB_Stack_Z->get_active())
+ rParameter.eStackMode = GlobalStackMode_STACK_Z;
+}
+
+IMPL_LINK(StackingResourceGroup, StackingChangeHdl, weld::Toggleable&, rRadio, void)
+{
+ //for each radio click there are coming two change events
+ //first uncheck of previous button -> ignore that call
+ //the second call gives the check of the new button
+ if (m_pChangeListener && rRadio.get_active())
+ m_pChangeListener->stateChanged();
+}
+
+IMPL_LINK_NOARG(StackingResourceGroup, StackingEnableHdl, weld::Toggleable&, void)
+{
+ if (m_pChangeListener)
+ m_pChangeListener->stateChanged();
+}
+
+SplineResourceGroup::SplineResourceGroup(weld::Builder* pBuilder, weld::Window* pParent)
+ : m_pParent(pParent)
+ , m_xFT_LineType(pBuilder->weld_label("linetypeft"))
+ , m_xLB_LineType(pBuilder->weld_combo_box("linetype"))
+ , m_xPB_DetailsDialog(pBuilder->weld_button("properties"))
+{
+ m_xLB_LineType->connect_changed(LINK(this, SplineResourceGroup, LineTypeChangeHdl));
+}
+
+std::shared_ptr<SplinePropertiesDialog> SplineResourceGroup::getSplinePropertiesDialog()
+{
+ if (!m_xSplinePropertiesDialog)
+ {
+ m_xSplinePropertiesDialog.reset(new SplinePropertiesDialog(m_pParent));
+ }
+ return m_xSplinePropertiesDialog;
+}
+
+std::shared_ptr<SteppedPropertiesDialog> SplineResourceGroup::getSteppedPropertiesDialog()
+{
+ if (!m_xSteppedPropertiesDialog)
+ {
+ m_xSteppedPropertiesDialog.reset(new SteppedPropertiesDialog(m_pParent));
+ }
+ return m_xSteppedPropertiesDialog;
+}
+
+void SplineResourceGroup::showControls(bool bShow)
+{
+ m_xFT_LineType->set_visible(bShow);
+ m_xLB_LineType->set_visible(bShow);
+ m_xPB_DetailsDialog->set_visible(bShow);
+}
+
+void SplineResourceGroup::fillControls(const ChartTypeParameter& rParameter)
+{
+ switch (rParameter.eCurveStyle)
+ {
+ case CurveStyle_LINES:
+ m_xLB_LineType->set_active(POS_LINETYPE_STRAIGHT);
+ m_xPB_DetailsDialog->set_sensitive(false);
+ break;
+ case CurveStyle_CUBIC_SPLINES:
+ case CurveStyle_B_SPLINES:
+ m_xLB_LineType->set_active(POS_LINETYPE_SMOOTH);
+ m_xPB_DetailsDialog->set_sensitive(true);
+ m_xPB_DetailsDialog->connect_clicked(
+ LINK(this, SplineResourceGroup, SplineDetailsDialogHdl));
+ m_xPB_DetailsDialog->set_tooltip_text(SchResId(STR_DLG_SMOOTH_LINE_PROPERTIES));
+ getSplinePropertiesDialog()->fillControls(rParameter);
+ break;
+ case CurveStyle_STEP_START:
+ case CurveStyle_STEP_END:
+ case CurveStyle_STEP_CENTER_X:
+ case CurveStyle_STEP_CENTER_Y:
+ m_xLB_LineType->set_active(POS_LINETYPE_STEPPED);
+ m_xPB_DetailsDialog->set_sensitive(true);
+ m_xPB_DetailsDialog->connect_clicked(
+ LINK(this, SplineResourceGroup, SteppedDetailsDialogHdl));
+ m_xPB_DetailsDialog->set_tooltip_text(SchResId(STR_DLG_STEPPED_LINE_PROPERTIES));
+ getSteppedPropertiesDialog()->fillControls(rParameter);
+ break;
+ default:
+ m_xLB_LineType->set_active(-1);
+ m_xPB_DetailsDialog->set_sensitive(false);
+ }
+}
+void SplineResourceGroup::fillParameter(ChartTypeParameter& rParameter)
+{
+ switch (m_xLB_LineType->get_active())
+ {
+ case POS_LINETYPE_SMOOTH:
+ getSplinePropertiesDialog()->fillParameter(rParameter, true);
+ break;
+ case POS_LINETYPE_STEPPED:
+ getSteppedPropertiesDialog()->fillParameter(rParameter, true);
+ break;
+ default: // includes POS_LINETYPE_STRAIGHT
+ rParameter.eCurveStyle = CurveStyle_LINES;
+ break;
+ }
+}
+
+IMPL_LINK_NOARG(SplineResourceGroup, LineTypeChangeHdl, weld::ComboBox&, void)
+{
+ if (m_pChangeListener)
+ m_pChangeListener->stateChanged();
+}
+
+IMPL_LINK_NOARG(SplineResourceGroup, SplineDetailsDialogHdl, weld::Button&, void)
+{
+ ChartTypeParameter aOldParameter;
+ std::shared_ptr<SplinePropertiesDialog> xDlg = getSplinePropertiesDialog();
+ xDlg->fillParameter(aOldParameter, m_xLB_LineType->get_active() == POS_LINETYPE_SMOOTH);
+
+ const sal_Int32 iOldLineTypePos = m_xLB_LineType->get_active();
+ m_xLB_LineType->set_active(POS_LINETYPE_SMOOTH);
+ weld::GenericDialogController::runAsync(xDlg, [this, xDlg, aOldParameter,
+ iOldLineTypePos](sal_Int32 nResult) {
+ m_xSplinePropertiesDialog = nullptr;
+ auto xNewDlg = getSplinePropertiesDialog();
+
+ if (nResult == RET_OK)
+ {
+ ChartTypeParameter aNewParameter;
+ xDlg->fillParameter(aNewParameter, m_xLB_LineType->get_active() == POS_LINETYPE_SMOOTH);
+ xNewDlg->fillControls(aNewParameter);
+
+ if (m_pChangeListener)
+ m_pChangeListener->stateChanged();
+ }
+ else
+ {
+ //restore old state:
+ m_xLB_LineType->set_active(iOldLineTypePos);
+ xNewDlg->fillControls(aOldParameter);
+ }
+ });
+}
+
+IMPL_LINK_NOARG(SplineResourceGroup, SteppedDetailsDialogHdl, weld::Button&, void)
+{
+ ChartTypeParameter aOldParameter;
+ std::shared_ptr<SteppedPropertiesDialog> xDlg = getSteppedPropertiesDialog();
+ xDlg->fillParameter(aOldParameter, m_xLB_LineType->get_active() == POS_LINETYPE_STEPPED);
+
+ const sal_Int32 iOldLineTypePos = m_xLB_LineType->get_active();
+ m_xLB_LineType->set_active(POS_LINETYPE_STEPPED);
+
+ weld::GenericDialogController::runAsync(
+ xDlg, [this, xDlg, aOldParameter, iOldLineTypePos](sal_Int32 nResult) {
+ m_xSteppedPropertiesDialog = nullptr;
+ auto xNewDlg = getSteppedPropertiesDialog();
+
+ if (nResult == RET_OK)
+ {
+ ChartTypeParameter aNewParameter;
+ xDlg->fillParameter(aNewParameter,
+ m_xLB_LineType->get_active() == POS_LINETYPE_STEPPED);
+ xNewDlg->fillControls(aNewParameter);
+
+ if (m_pChangeListener)
+ m_pChangeListener->stateChanged();
+ }
+ else
+ {
+ //restore old state:
+ m_xLB_LineType->set_active(iOldLineTypePos);
+ xDlg->fillControls(aOldParameter);
+ }
+ });
+}
+
+GeometryResourceGroup::GeometryResourceGroup(weld::Builder* pBuilder)
+ : m_aGeometryResources(pBuilder)
+{
+ m_aGeometryResources.connect_changed(LINK(this, GeometryResourceGroup, GeometryChangeHdl));
+}
+
+void GeometryResourceGroup::showControls(bool bShow) { m_aGeometryResources.set_visible(bShow); }
+
+void GeometryResourceGroup::fillControls(const ChartTypeParameter& rParameter)
+{
+ sal_uInt16 nGeometry3D = static_cast<sal_uInt16>(rParameter.nGeometry3D);
+ m_aGeometryResources.select(nGeometry3D);
+ m_aGeometryResources.set_sensitive(rParameter.b3DLook);
+}
+
+void GeometryResourceGroup::fillParameter(ChartTypeParameter& rParameter)
+{
+ rParameter.nGeometry3D = 1;
+ int nSelected = m_aGeometryResources.get_selected_index();
+ if (nSelected != -1)
+ rParameter.nGeometry3D = nSelected;
+}
+
+IMPL_LINK_NOARG(GeometryResourceGroup, GeometryChangeHdl, weld::TreeView&, void)
+{
+ if (m_pChangeListener)
+ m_pChangeListener->stateChanged();
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/ChartTypeDialogController.cxx b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx
new file mode 100644
index 0000000000..b52dbc2897
--- /dev/null
+++ b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx
@@ -0,0 +1,1254 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartTypeDialogController.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+#include <bitmaps.hlst>
+#include <ChartModelHelper.hxx>
+#include <DataSeries.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ControllerLockGuard.hxx>
+#include <AxisHelper.hxx>
+#include <unonames.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <ChartModel.hxx>
+
+#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
+
+#include <svtools/valueset.hxx>
+#include <vcl/image.hxx>
+#include <vcl/settings.hxx>
+
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+ChartTypeParameter::ChartTypeParameter()
+ : nSubTypeIndex( 1 )
+ , bXAxisWithValues( false )
+ , b3DLook( false )
+ , bSymbols( true )
+ , bLines( true )
+ , eStackMode( GlobalStackMode_NONE )
+ , eCurveStyle( CurveStyle_LINES )
+ , nCurveResolution(20)
+ , nSplineOrder(3)
+ , nGeometry3D(DataPointGeometry3D::CUBOID)
+ , eThreeDLookScheme(ThreeDLookScheme::ThreeDLookScheme_Realistic)
+ , bSortByXValues(false)
+ , mbRoundedEdge(false)
+{
+}
+
+ChartTypeParameter::ChartTypeParameter( sal_Int32 SubTypeIndex, bool HasXAxisWithValues
+ , bool Is3DLook, GlobalStackMode nStackMode
+ , bool HasSymbols, bool HasLines
+ , CurveStyle nCurveStyle )
+ : nSubTypeIndex( SubTypeIndex )
+ , bXAxisWithValues( HasXAxisWithValues )
+ , b3DLook( Is3DLook )
+ , bSymbols( HasSymbols )
+ , bLines( HasLines )
+ , eStackMode( nStackMode )
+ , eCurveStyle( nCurveStyle )
+ , nCurveResolution(20)
+ , nSplineOrder(3)
+ , nGeometry3D(DataPointGeometry3D::CUBOID)
+ , eThreeDLookScheme(ThreeDLookScheme::ThreeDLookScheme_Realistic)
+ , bSortByXValues(false)
+ , mbRoundedEdge(false)
+{
+}
+
+bool ChartTypeParameter::mapsToSameService( const ChartTypeParameter& rParameter ) const
+{
+ return mapsToSimilarService( rParameter, 0 );
+}
+bool ChartTypeParameter::mapsToSimilarService( const ChartTypeParameter& rParameter, sal_Int32 nTheHigherTheLess ) const
+{
+ sal_Int32 nMax=7;
+ if(nTheHigherTheLess>nMax)
+ return true;
+ if( bXAxisWithValues!=rParameter.bXAxisWithValues )
+ return nTheHigherTheLess>nMax-1;
+ if( b3DLook!=rParameter.b3DLook )
+ return nTheHigherTheLess>nMax-2;
+ if( eStackMode!=rParameter.eStackMode )
+ return nTheHigherTheLess>nMax-3;
+ if( nSubTypeIndex!=rParameter.nSubTypeIndex )
+ return nTheHigherTheLess>nMax-4;
+ if( bSymbols!=rParameter.bSymbols )
+ return nTheHigherTheLess>nMax-5;
+ if( bLines!=rParameter.bLines )
+ return nTheHigherTheLess>nMax-6;
+ return true;
+}
+
+ChartTypeDialogController::ChartTypeDialogController()
+ : bSupportsXAxisWithValues(false)
+ , bSupports3D(true)
+{
+}
+
+ChartTypeDialogController::~ChartTypeDialogController()
+{
+}
+
+bool ChartTypeDialogController::isSubType( const OUString& rServiceName )
+{
+ const tTemplateServiceChartTypeParameterMap& rTemplateMap = getTemplateMap();
+ tTemplateServiceChartTypeParameterMap::const_iterator aIt( rTemplateMap.find( rServiceName ));
+ return aIt != rTemplateMap.end();
+}
+ChartTypeParameter ChartTypeDialogController::getChartTypeParameterForService(
+ const OUString& rServiceName
+ , const uno::Reference< beans::XPropertySet >& xTemplateProps )
+{
+ ChartTypeParameter aRet;
+ const tTemplateServiceChartTypeParameterMap& rTemplateMap = getTemplateMap();
+ tTemplateServiceChartTypeParameterMap::const_iterator aIt( rTemplateMap.find( rServiceName ));
+ if( aIt != rTemplateMap.end())
+ aRet = (*aIt).second;
+ if( xTemplateProps.is() )
+ {
+ try
+ {
+ xTemplateProps->getPropertyValue( CHART_UNONAME_CURVE_STYLE ) >>= aRet.eCurveStyle;
+ xTemplateProps->getPropertyValue( CHART_UNONAME_CURVE_RESOLUTION ) >>= aRet.nCurveResolution;
+ xTemplateProps->getPropertyValue( CHART_UNONAME_SPLINE_ORDER ) >>= aRet.nSplineOrder;
+ }
+ catch( uno::Exception & ex )
+ {
+ //not all templates need to support CurveStyle, CurveResolution or SplineOrder
+ ex.Context.is();//to have debug information without compilation warnings
+ }
+
+ try
+ {
+ xTemplateProps->getPropertyValue( "Geometry3D" ) >>= aRet.nGeometry3D;
+ }
+ catch( uno::Exception& ex )
+ {
+ //not all templates need to support Geometry3D
+ ex.Context.is();//to have debug information without compilation warnings
+ }
+ }
+ return aRet;
+}
+void ChartTypeDialogController::adjustSubTypeAndEnableControls( ChartTypeParameter& /*rParameter*/ )
+{
+}
+void ChartTypeDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter )
+{
+ switch( rParameter.nSubTypeIndex )
+ {
+ case 2:
+ rParameter.eStackMode=GlobalStackMode_STACK_Y;
+ break;
+ case 3:
+ rParameter.eStackMode=GlobalStackMode_STACK_Y_PERCENT;
+ break;
+ case 4:
+ rParameter.eStackMode=GlobalStackMode_STACK_Z;
+ break;
+ default:
+ rParameter.eStackMode=GlobalStackMode_NONE;
+ break;
+ }
+}
+void ChartTypeDialogController::adjustParameterToMainType( ChartTypeParameter& rParameter )
+{
+ bool bFoundSomeMatch=false;
+
+ rParameter.bXAxisWithValues = bSupportsXAxisWithValues;
+ if( rParameter.b3DLook && !bSupports3D )
+ rParameter.b3DLook = false;
+ if(!rParameter.b3DLook && rParameter.eStackMode==GlobalStackMode_STACK_Z)
+ rParameter.eStackMode = GlobalStackMode_NONE;
+
+ const tTemplateServiceChartTypeParameterMap& rMap = getTemplateMap();
+ for( sal_Int32 nMatchPrecision=0; nMatchPrecision<7 && !bFoundSomeMatch; nMatchPrecision++ )
+ {
+ for (auto const& elem : rMap)
+ {
+ if( rParameter.mapsToSimilarService( elem.second, nMatchPrecision ) )
+ {
+ //remind some values
+ ThreeDLookScheme aScheme = rParameter.eThreeDLookScheme;
+ sal_Int32 nCurveResolution = rParameter.nCurveResolution;
+ sal_Int32 nSplineOrder = rParameter.nSplineOrder;
+ CurveStyle eCurveStyle = rParameter.eCurveStyle;
+ sal_Int32 nGeometry3D = rParameter.nGeometry3D;
+ bool bSortByXValues = rParameter.bSortByXValues;
+ bool bRoundedEdge = rParameter.mbRoundedEdge;
+
+ rParameter = elem.second;
+
+ //some values should not be changed with charttype
+ rParameter.eThreeDLookScheme = aScheme;
+ rParameter.nCurveResolution = nCurveResolution;
+ rParameter.nSplineOrder =nSplineOrder;
+ rParameter.eCurveStyle = eCurveStyle;
+ rParameter.nGeometry3D = nGeometry3D;
+ rParameter.bSortByXValues = bSortByXValues;
+ rParameter.mbRoundedEdge = bRoundedEdge;
+
+ bFoundSomeMatch = true;
+ break;
+ }
+ }
+ }
+ if(!bFoundSomeMatch)
+ {
+ if(!rMap.empty())
+ rParameter = (*rMap.begin()).second;
+ else
+ rParameter = ChartTypeParameter();
+ }
+}
+OUString ChartTypeDialogController::getServiceNameForParameter( const ChartTypeParameter& rParameter ) const
+{
+ ChartTypeParameter aParameter(rParameter);
+ if( aParameter.bXAxisWithValues )
+ aParameter.eStackMode = GlobalStackMode_NONE;
+ if(!aParameter.b3DLook && aParameter.eStackMode==GlobalStackMode_STACK_Z)
+ aParameter.eStackMode = GlobalStackMode_NONE;
+ const tTemplateServiceChartTypeParameterMap& rMap = getTemplateMap();
+ for (auto const& elem : rMap)
+ {
+ if( aParameter.mapsToSameService(elem.second) )
+ return elem.first;
+ }
+
+ OSL_FAIL( "ChartType not implemented yet - use fallback to similar type" );
+ for( sal_Int32 nMatchPrecision=1; nMatchPrecision<8; nMatchPrecision++ )
+ {
+ for (auto const& elem : rMap)
+ {
+ if( aParameter.mapsToSimilarService(elem.second, nMatchPrecision) )
+ return elem.first;
+ }
+ }
+ return OUString();
+}
+rtl::Reference< ChartTypeTemplate > ChartTypeDialogController::getCurrentTemplate(
+ const ChartTypeParameter& rParameter
+ , const rtl::Reference< ChartTypeManager >& xTemplateManager ) const
+{
+ rtl::Reference< ChartTypeTemplate > xTemplate;
+
+ OUString aServiceName( getServiceNameForParameter( rParameter ) );
+ if(!aServiceName.isEmpty())
+ {
+ xTemplate = xTemplateManager->createTemplate( aServiceName );
+ if(xTemplate.is())
+ {
+ uno::Reference< beans::XPropertySet > xTemplateProps( static_cast<cppu::OWeakObject*>(xTemplate.get()), uno::UNO_QUERY );
+ if(xTemplateProps.is())
+ {
+ try
+ {
+ xTemplateProps->setPropertyValue( CHART_UNONAME_CURVE_STYLE , uno::Any(rParameter.eCurveStyle) );
+ xTemplateProps->setPropertyValue( CHART_UNONAME_CURVE_RESOLUTION , uno::Any(rParameter.nCurveResolution) );
+ xTemplateProps->setPropertyValue( CHART_UNONAME_SPLINE_ORDER , uno::Any(rParameter.nSplineOrder) );
+ }
+ catch( uno::Exception & ex )
+ {
+ //not all templates need to support CurveStyle, CurveResolution or SplineOrder
+ ex.Context.is();//to have debug information without compilation warnings
+ }
+ try
+ {
+ xTemplateProps->setPropertyValue( "Geometry3D" , uno::Any(rParameter.nGeometry3D) );
+ }
+ catch( uno::Exception & ex )
+ {
+ //not all templates need to support Geometry3D
+ ex.Context.is();//to have debug information without compilation warnings
+ }
+
+ try
+ {
+ setTemplateProperties( xTemplateProps );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ }
+ return xTemplate;
+}
+
+void ChartTypeDialogController::commitToModel( const ChartTypeParameter& rParameter
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ rtl::Reference< ::chart::ChartTypeManager > xTemplateManager = xChartModel->getTypeManager();
+ rtl::Reference< ::chart::ChartTypeTemplate > xTemplate( getCurrentTemplate( rParameter, xTemplateManager ) );
+ if(!xTemplate.is())
+ return;
+
+ // locked controllers
+ ControllerLockGuardUNO aCtrlLockGuard( xChartModel );
+ rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
+ Diagram::tTemplateWithServiceName aTemplateWithService;
+ if (xDiagram)
+ aTemplateWithService = xDiagram->getTemplate( xTemplateManager );
+ if( aTemplateWithService.xChartTypeTemplate.is())
+ aTemplateWithService.xChartTypeTemplate->resetStyles2( xDiagram );
+ xTemplate->changeDiagram( xDiagram );
+ if( AllSettings::GetMathLayoutRTL() )
+ AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) );
+ if( rParameter.b3DLook )
+ xDiagram->setScheme( rParameter.eThreeDLookScheme );
+
+ if (xDiagram.is())
+ {
+ xDiagram->setPropertyValue(CHART_UNONAME_SORT_BY_XVALUES, uno::Any(rParameter.bSortByXValues));
+ }
+}
+void ChartTypeDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& /*rParameter*/ )
+{
+ rSubTypeList.Clear();
+}
+bool ChartTypeDialogController::shouldShow_3DLookControl() const
+{
+ return false;
+}
+bool ChartTypeDialogController::shouldShow_StackingControl() const
+{
+ return false;
+}
+bool ChartTypeDialogController::shouldShow_SplineControl() const
+{
+ return false;
+}
+bool ChartTypeDialogController::shouldShow_GeometryControl() const
+{
+ return false;
+}
+bool ChartTypeDialogController::shouldShow_SortByXValuesResourceGroup() const
+{
+ return false;
+}
+
+void ChartTypeDialogController::showExtraControls(weld::Builder* /*pBuilder*/)
+{
+}
+void ChartTypeDialogController::hideExtraControls() const
+{
+}
+void ChartTypeDialogController::fillExtraControls( const rtl::Reference<::chart::ChartModel>& /*xChartModel*/
+ , const uno::Reference< beans::XPropertySet >& /*xTemplateProps*/ ) const
+{
+}
+void ChartTypeDialogController::setTemplateProperties( const uno::Reference< beans::XPropertySet >& /*xTemplateProps*/ ) const
+{
+}
+
+ColumnOrBarChartDialogController_Base::ColumnOrBarChartDialogController_Base()
+{
+}
+ColumnOrBarChartDialogController_Base::~ColumnOrBarChartDialogController_Base()
+{
+}
+bool ColumnOrBarChartDialogController_Base::shouldShow_3DLookControl() const
+{
+ return true;
+}
+bool ColumnOrBarChartDialogController_Base::shouldShow_GeometryControl() const
+{
+ return true;
+}
+void ColumnOrBarChartDialogController_Base::adjustSubTypeAndEnableControls( ChartTypeParameter& rParameter )
+{
+ if(rParameter.nSubTypeIndex>3 && !rParameter.b3DLook)
+ {
+ rParameter.nSubTypeIndex=1;
+ }
+}
+ColumnChartDialogController::ColumnChartDialogController()
+{
+}
+ColumnChartDialogController::~ColumnChartDialogController()
+{
+}
+OUString ColumnChartDialogController::getName()
+{
+ return SchResId(STR_TYPE_COLUMN);
+}
+
+OUString ColumnChartDialogController::getImage()
+{
+ return BMP_TYPE_COLUMN;
+}
+
+const tTemplateServiceChartTypeParameterMap& ColumnChartDialogController::getTemplateMap() const
+{
+ static tTemplateServiceChartTypeParameterMap s_aTemplateMap{
+ {"com.sun.star.chart2.template.Column" , ChartTypeParameter(1,false,false,GlobalStackMode_NONE)},
+ {"com.sun.star.chart2.template.StackedColumn" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y)},
+ {"com.sun.star.chart2.template.PercentStackedColumn" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y_PERCENT)},
+ {"com.sun.star.chart2.template.ThreeDColumnFlat" , ChartTypeParameter(1,false,true,GlobalStackMode_NONE)},
+ {"com.sun.star.chart2.template.StackedThreeDColumnFlat" , ChartTypeParameter(2,false,true,GlobalStackMode_STACK_Y)},
+ {"com.sun.star.chart2.template.PercentStackedThreeDColumnFlat" , ChartTypeParameter(3,false,true,GlobalStackMode_STACK_Y_PERCENT)},
+ {"com.sun.star.chart2.template.ThreeDColumnDeep" , ChartTypeParameter(4,false,true,GlobalStackMode_STACK_Z)}};
+ return s_aTemplateMap;
+}
+void ColumnChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter )
+{
+ rSubTypeList.Clear();
+
+ if( rParameter.b3DLook )
+ {
+ switch(rParameter.nGeometry3D)
+ {
+ case DataPointGeometry3D::CYLINDER:
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_SAEULE_3D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_SAEULE_3D_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_SAEULE_3D_3));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_SAEULE_3D_4));
+ break;
+ case DataPointGeometry3D::CONE:
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_KEGEL_3D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_KEGEL_3D_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_KEGEL_3D_3));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_KEGEL_3D_4));
+ break;
+ case DataPointGeometry3D::PYRAMID:
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_PYRAMID_3D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_PYRAMID_3D_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_PYRAMID_3D_3));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_PYRAMID_3D_4));
+ break;
+ default: //DataPointGeometry3D::CUBOID:
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_COLUMNS_3D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_COLUMNS_3D_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_COLUMNS_3D_3));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_COLUMNS_3D));
+ break;
+ }
+ }
+ else
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_COLUMNS_2D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_COLUMNS_2D_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_COLUMNS_2D_3));
+ }
+
+ rSubTypeList.SetItemText( 1, SchResId( STR_NORMAL ) );
+ rSubTypeList.SetItemText( 2, SchResId( STR_STACKED ) );
+ rSubTypeList.SetItemText( 3, SchResId( STR_PERCENT ) );
+ rSubTypeList.SetItemText( 4, SchResId( STR_DEEP ) );
+}
+
+BarChartDialogController::BarChartDialogController()
+{
+}
+
+BarChartDialogController::~BarChartDialogController()
+{
+}
+
+OUString BarChartDialogController::getName()
+{
+ return SchResId(STR_TYPE_BAR);
+}
+
+OUString BarChartDialogController::getImage()
+{
+ return BMP_TYPE_BAR;
+}
+
+const tTemplateServiceChartTypeParameterMap& BarChartDialogController::getTemplateMap() const
+{
+ static tTemplateServiceChartTypeParameterMap s_aTemplateMap{
+ {"com.sun.star.chart2.template.Bar" , ChartTypeParameter(1,false,false,GlobalStackMode_NONE)},
+ {"com.sun.star.chart2.template.StackedBar" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y)},
+ {"com.sun.star.chart2.template.PercentStackedBar" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y_PERCENT)},
+ {"com.sun.star.chart2.template.ThreeDBarFlat" , ChartTypeParameter(1,false,true,GlobalStackMode_NONE)},
+ {"com.sun.star.chart2.template.StackedThreeDBarFlat" , ChartTypeParameter(2,false,true,GlobalStackMode_STACK_Y)},
+ {"com.sun.star.chart2.template.PercentStackedThreeDBarFlat" , ChartTypeParameter(3,false,true,GlobalStackMode_STACK_Y_PERCENT)},
+ {"com.sun.star.chart2.template.ThreeDBarDeep" , ChartTypeParameter(4,false,true,GlobalStackMode_STACK_Z)}};
+ return s_aTemplateMap;
+}
+void BarChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter )
+{
+ rSubTypeList.Clear();
+
+ if( rParameter.b3DLook )
+ {
+ switch(rParameter.nGeometry3D)
+ {
+ case DataPointGeometry3D::CYLINDER:
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_ROEHRE_3D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_ROEHRE_3D_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_ROEHRE_3D_3));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_ROEHRE_3D_4));
+ break;
+ case DataPointGeometry3D::CONE:
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_KEGELQ_3D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_KEGELQ_3D_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_KEGELQ_3D_3));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_KEGELQ_3D_4));
+ break;
+ case DataPointGeometry3D::PYRAMID:
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_PYRAMIDQ_3D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_PYRAMIDQ_3D_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_PYRAMIDQ_3D_3));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_PYRAMIDQ_3D_4));
+ break;
+ default: //DataPointGeometry3D::CUBOID:
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_BARS_3D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_BARS_3D_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_BARS_3D_3));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_BARS_3D));
+ break;
+ }
+ }
+ else
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_BARS_2D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_BARS_2D_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_BARS_2D_3));
+ }
+ rSubTypeList.SetItemText( 1, SchResId( STR_NORMAL ) );
+ rSubTypeList.SetItemText( 2, SchResId( STR_STACKED ) );
+ rSubTypeList.SetItemText( 3, SchResId( STR_PERCENT ) );
+ rSubTypeList.SetItemText( 4, SchResId( STR_DEEP ) );
+}
+
+PieChartDialogController::PieChartDialogController()
+{
+}
+
+PieChartDialogController::~PieChartDialogController()
+{
+}
+
+OUString PieChartDialogController::getName()
+{
+ return SchResId(STR_TYPE_PIE);
+}
+
+OUString PieChartDialogController::getImage()
+{
+ return BMP_TYPE_PIE;
+}
+
+const tTemplateServiceChartTypeParameterMap& PieChartDialogController::getTemplateMap() const
+{
+ static tTemplateServiceChartTypeParameterMap s_aTemplateMap{
+ {"com.sun.star.chart2.template.Pie" , ChartTypeParameter(1,false,false)},
+ {"com.sun.star.chart2.template.PieAllExploded" , ChartTypeParameter(2,false,false)},
+ {"com.sun.star.chart2.template.Donut" , ChartTypeParameter(3,false,false)},
+ {"com.sun.star.chart2.template.DonutAllExploded" , ChartTypeParameter(4,false,false)},
+ {"com.sun.star.chart2.template.ThreeDPie" , ChartTypeParameter(1,false,true)},
+ {"com.sun.star.chart2.template.ThreeDPieAllExploded" , ChartTypeParameter(2,false,true)},
+ {"com.sun.star.chart2.template.ThreeDDonut" , ChartTypeParameter(3,false,true)},
+ {"com.sun.star.chart2.template.ThreeDDonutAllExploded" , ChartTypeParameter(4,false,true)}};
+ return s_aTemplateMap;
+}
+void PieChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter )
+{
+ rSubTypeList.Clear();
+
+ if( rParameter.b3DLook )
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_CIRCLES_3D));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_CIRCLES_3D_EXPLODED));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_DONUT_3D));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_DONUT_3D_EXPLODED));
+ }
+ else
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_CIRCLES_2D));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_CIRCLES_2D_EXPLODED));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_DONUT_2D));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_DONUT_2D_EXPLODED));
+ }
+ rSubTypeList.SetItemText( 1, SchResId( STR_NORMAL ) );
+ rSubTypeList.SetItemText( 2, SchResId( STR_PIE_EXPLODED ) );
+ rSubTypeList.SetItemText( 3, SchResId( STR_DONUT ) );
+ rSubTypeList.SetItemText( 4, SchResId( STR_DONUT_EXPLODED ) );
+}
+
+bool PieChartDialogController::shouldShow_3DLookControl() const
+{
+ return true;
+}
+
+void PieChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter )
+{
+ if(rParameter.eStackMode==GlobalStackMode_STACK_Z)
+ rParameter.eStackMode = GlobalStackMode_NONE;
+}
+
+LineChartDialogController::LineChartDialogController()
+{
+}
+
+LineChartDialogController::~LineChartDialogController()
+{
+}
+
+OUString LineChartDialogController::getName()
+{
+ return SchResId(STR_TYPE_LINE);
+}
+
+OUString LineChartDialogController::getImage()
+{
+ return BMP_TYPE_LINE;
+}
+
+const tTemplateServiceChartTypeParameterMap& LineChartDialogController::getTemplateMap() const
+{
+ static tTemplateServiceChartTypeParameterMap s_aTemplateMap{
+ {"com.sun.star.chart2.template.Symbol" , ChartTypeParameter(1,false,false,GlobalStackMode_NONE,true,false)},
+ {"com.sun.star.chart2.template.StackedSymbol" , ChartTypeParameter(1,false,false,GlobalStackMode_STACK_Y,true,false)},
+ {"com.sun.star.chart2.template.PercentStackedSymbol" , ChartTypeParameter(1,false,false,GlobalStackMode_STACK_Y_PERCENT,true,false)},
+ {"com.sun.star.chart2.template.LineSymbol" , ChartTypeParameter(2,false,false,GlobalStackMode_NONE,true,true)},
+ {"com.sun.star.chart2.template.StackedLineSymbol" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y,true,true)},
+ {"com.sun.star.chart2.template.PercentStackedLineSymbol" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y_PERCENT,true,true)},
+ {"com.sun.star.chart2.template.Line" , ChartTypeParameter(3,false,false,GlobalStackMode_NONE,false,true)},
+ {"com.sun.star.chart2.template.StackedLine" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y,false,true)},
+ {"com.sun.star.chart2.template.PercentStackedLine" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y_PERCENT,false,true)},
+ {"com.sun.star.chart2.template.StackedThreeDLine" , ChartTypeParameter(4,false,true,GlobalStackMode_STACK_Y,false,true)},
+ {"com.sun.star.chart2.template.PercentStackedThreeDLine" , ChartTypeParameter(4,false,true,GlobalStackMode_STACK_Y_PERCENT,false,true)},
+ {"com.sun.star.chart2.template.ThreeDLineDeep" , ChartTypeParameter(4,false,true,GlobalStackMode_STACK_Z,false,true)}};
+ return s_aTemplateMap;
+}
+void LineChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter )
+{
+ rSubTypeList.Clear();
+
+ switch( rParameter.eCurveStyle )
+ {
+ case CurveStyle_CUBIC_SPLINES:
+ case CurveStyle_B_SPLINES:
+ if( rParameter.eStackMode == GlobalStackMode_NONE || rParameter.eStackMode == GlobalStackMode_STACK_Z )
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XCATEGORY));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XCATEGORY_SMOOTH));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XCATEGORY_SMOOTH));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XCATEGORY_SMOOTH));
+ }
+ else
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_STACKED));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_STACKED_SMOOTH));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_STACKED_SMOOTH));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_STACKED_SMOOTH));
+ }
+ break;
+ case CurveStyle_STEP_START:
+ case CurveStyle_STEP_END:
+ case CurveStyle_STEP_CENTER_X:
+ case CurveStyle_STEP_CENTER_Y:
+ if( rParameter.eStackMode == GlobalStackMode_NONE || rParameter.eStackMode == GlobalStackMode_STACK_Z )
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XCATEGORY));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XCATEGORY_STEPPED));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XCATEGORY_STEPPED));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XCATEGORY_STEPPED));
+ }
+ else
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_STACKED));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_STACKED_STEPPED));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_STACKED_STEPPED));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_STACKED_STEPPED));
+ }
+ break;
+ default: // includes CurveStyle_LINES
+ //direct lines
+ if( rParameter.eStackMode == GlobalStackMode_NONE || rParameter.eStackMode == GlobalStackMode_STACK_Z )
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XCATEGORY));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XCATEGORY));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XCATEGORY));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XCATEGORY));
+ }
+ else
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_STACKED));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_STACKED));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_STACKED));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_STACKED));
+ }
+ }
+
+ rSubTypeList.SetItemText( 1, SchResId( STR_POINTS_ONLY ) );
+ rSubTypeList.SetItemText( 2, SchResId( STR_POINTS_AND_LINES ) );
+ rSubTypeList.SetItemText( 3, SchResId( STR_LINES_ONLY ) );
+ rSubTypeList.SetItemText( 4, SchResId( STR_LINES_3D ) );
+}
+bool LineChartDialogController::shouldShow_StackingControl() const
+{
+ return true;
+}
+bool LineChartDialogController::shouldShow_SplineControl() const
+{
+ return true;
+}
+void LineChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter )
+{
+ rParameter.b3DLook = false;
+
+ switch( rParameter.nSubTypeIndex )
+ {
+ case 2:
+ rParameter.bSymbols = true;
+ rParameter.bLines = true;
+ break;
+ case 3:
+ rParameter.bSymbols = false;
+ rParameter.bLines = true;
+ break;
+ case 4:
+ rParameter.bSymbols = false;
+ rParameter.bLines = true;
+ rParameter.b3DLook = true;
+ if( rParameter.eStackMode == GlobalStackMode_NONE )
+ rParameter.eStackMode = GlobalStackMode_STACK_Z;
+ break;
+ default:
+ rParameter.bSymbols = true;
+ rParameter.bLines = false;
+ break;
+ }
+
+ if(!rParameter.b3DLook && rParameter.eStackMode == GlobalStackMode_STACK_Z )
+ rParameter.eStackMode = GlobalStackMode_NONE;
+}
+void LineChartDialogController::adjustParameterToMainType( ChartTypeParameter& rParameter )
+{
+ if( rParameter.b3DLook && rParameter.eStackMode == GlobalStackMode_NONE )
+ rParameter.eStackMode = GlobalStackMode_STACK_Z;
+
+ ChartTypeDialogController::adjustParameterToMainType( rParameter );
+}
+
+XYChartDialogController::XYChartDialogController()
+{
+ bSupportsXAxisWithValues = true;
+}
+
+XYChartDialogController::~XYChartDialogController()
+{
+}
+
+OUString XYChartDialogController::getName()
+{
+ return SchResId(STR_TYPE_XY);
+}
+
+OUString XYChartDialogController::getImage()
+{
+ return BMP_TYPE_XY;
+}
+
+const tTemplateServiceChartTypeParameterMap& XYChartDialogController::getTemplateMap() const
+{
+ static tTemplateServiceChartTypeParameterMap s_aTemplateMap{
+ {"com.sun.star.chart2.template.ScatterSymbol" , ChartTypeParameter(1,true,false,GlobalStackMode_NONE,true,false)},
+ {"com.sun.star.chart2.template.ScatterLineSymbol" , ChartTypeParameter(2,true,false,GlobalStackMode_NONE,true,true)},
+ {"com.sun.star.chart2.template.ScatterLine" , ChartTypeParameter(3,true,false,GlobalStackMode_NONE,false,true)},
+ {"com.sun.star.chart2.template.ThreeDScatter" , ChartTypeParameter(4,true,true,GlobalStackMode_NONE,false,true)}};
+ return s_aTemplateMap;
+}
+
+void XYChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter )
+{
+ rSubTypeList.Clear();
+
+ switch (rParameter.eCurveStyle)
+ {
+ case CurveStyle_CUBIC_SPLINES:
+ case CurveStyle_B_SPLINES:
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XVALUES));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XVALUES_SMOOTH));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XVALUES_SMOOTH));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XVALUES_SMOOTH));
+ break;
+ }
+ case CurveStyle_STEP_START:
+ case CurveStyle_STEP_END:
+ case CurveStyle_STEP_CENTER_X:
+ case CurveStyle_STEP_CENTER_Y:
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XVALUES));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XVALUES_STEPPED));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XVALUES_STEPPED));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XVALUES_STEPPED));
+ break;
+ }
+ default: // includes CurveStyle_LINES
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XVALUES));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XVALUES));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XVALUES));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XVALUES));
+ }
+
+ rSubTypeList.SetItemText( 1, SchResId( STR_POINTS_ONLY ) );
+ rSubTypeList.SetItemText( 2, SchResId( STR_POINTS_AND_LINES ) );
+ rSubTypeList.SetItemText( 3, SchResId( STR_LINES_ONLY ) );
+ rSubTypeList.SetItemText( 4, SchResId( STR_LINES_3D ) );
+}
+bool XYChartDialogController::shouldShow_SplineControl() const
+{
+ return true;
+}
+bool XYChartDialogController::shouldShow_SortByXValuesResourceGroup() const
+{
+ return true;
+}
+void XYChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter )
+{
+ rParameter.eStackMode=GlobalStackMode_NONE;
+ rParameter.b3DLook = false;
+ rParameter.bXAxisWithValues = true;
+
+ switch( rParameter.nSubTypeIndex )
+ {
+ case 2:
+ rParameter.bSymbols = true;
+ rParameter.bLines = true;
+ break;
+ case 3:
+ rParameter.bSymbols = false;
+ rParameter.bLines = true;
+ break;
+ case 4:
+ rParameter.bSymbols = false;
+ rParameter.bLines = true;
+ rParameter.b3DLook = true;
+ rParameter.eStackMode=GlobalStackMode_STACK_Z;
+ break;
+ default:
+ rParameter.bSymbols = true;
+ rParameter.bLines = false;
+ break;
+ }
+}
+
+AreaChartDialogController::AreaChartDialogController()
+{
+}
+
+AreaChartDialogController::~AreaChartDialogController()
+{
+}
+
+OUString AreaChartDialogController::getName()
+{
+ return SchResId(STR_TYPE_AREA);
+}
+
+OUString AreaChartDialogController::getImage()
+{
+ return BMP_TYPE_AREA;
+}
+
+bool AreaChartDialogController::shouldShow_3DLookControl() const
+{
+ return true;
+}
+
+const tTemplateServiceChartTypeParameterMap& AreaChartDialogController::getTemplateMap() const
+{
+ static tTemplateServiceChartTypeParameterMap s_aTemplateMap{
+ {"com.sun.star.chart2.template.Area" , ChartTypeParameter(1,false,false,GlobalStackMode_NONE)},
+ {"com.sun.star.chart2.template.ThreeDArea" , ChartTypeParameter(1,false,true,GlobalStackMode_STACK_Z)},
+ {"com.sun.star.chart2.template.StackedArea" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y)},
+ {"com.sun.star.chart2.template.StackedThreeDArea" , ChartTypeParameter(2,false,true,GlobalStackMode_STACK_Y)},
+ {"com.sun.star.chart2.template.PercentStackedArea" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y_PERCENT)},
+ {"com.sun.star.chart2.template.PercentStackedThreeDArea" , ChartTypeParameter(3,false,true,GlobalStackMode_STACK_Y_PERCENT)}};
+ return s_aTemplateMap;
+}
+
+void AreaChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter )
+{
+ rSubTypeList.Clear();
+
+ if( rParameter.b3DLook )
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_AREAS_3D));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_AREAS_3D_1));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_AREAS_3D_2));
+ }
+ else
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_AREAS_2D_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_AREAS_2D));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_AREAS_2D_3));
+ }
+
+ rSubTypeList.SetItemText( 1, SchResId( rParameter.b3DLook ? STR_DEEP : STR_NORMAL ) );
+ rSubTypeList.SetItemText( 2, SchResId( STR_STACKED ) );
+ rSubTypeList.SetItemText( 3, SchResId( STR_PERCENT ) );
+}
+void AreaChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter )
+{
+ rParameter.eCurveStyle = CurveStyle_LINES;
+
+ if( rParameter.nSubTypeIndex>3 )
+ rParameter.nSubTypeIndex = 1;
+ switch( rParameter.nSubTypeIndex )
+ {
+ case 2:
+ rParameter.eStackMode=GlobalStackMode_STACK_Y;
+ break;
+ case 3:
+ rParameter.eStackMode=GlobalStackMode_STACK_Y_PERCENT;
+ break;
+ default:
+ if( rParameter.b3DLook )
+ rParameter.eStackMode=GlobalStackMode_STACK_Z;
+ else
+ rParameter.eStackMode=GlobalStackMode_NONE;
+ break;
+ }
+}
+void AreaChartDialogController::adjustParameterToMainType( ChartTypeParameter& rParameter )
+{
+ if( rParameter.b3DLook && rParameter.eStackMode == GlobalStackMode_NONE )
+ rParameter.eStackMode = GlobalStackMode_STACK_Z;
+
+ ChartTypeDialogController::adjustParameterToMainType( rParameter );
+}
+
+NetChartDialogController::NetChartDialogController()
+{
+ bSupports3D = false;
+}
+
+NetChartDialogController::~NetChartDialogController()
+{
+}
+
+OUString NetChartDialogController::getName()
+{
+ return SchResId(STR_TYPE_NET);
+}
+
+OUString NetChartDialogController::getImage()
+{
+ return BMP_TYPE_NET;
+}
+
+bool NetChartDialogController::shouldShow_StackingControl() const
+{
+ return true;
+}
+
+const tTemplateServiceChartTypeParameterMap& NetChartDialogController::getTemplateMap() const
+{
+ static tTemplateServiceChartTypeParameterMap s_aTemplateMap{
+ //@todo need templates with symbols only
+ {"com.sun.star.chart2.template.NetSymbol" , ChartTypeParameter(1,false,false,GlobalStackMode_NONE,true,false)},
+ {"com.sun.star.chart2.template.StackedNetSymbol" , ChartTypeParameter(1,false,false,GlobalStackMode_STACK_Y,true,false)},
+ {"com.sun.star.chart2.template.PercentStackedNetSymbol" ,ChartTypeParameter(1,false,false,GlobalStackMode_STACK_Y_PERCENT,true,false)},
+
+ {"com.sun.star.chart2.template.Net" , ChartTypeParameter(2,false,false,GlobalStackMode_NONE,true,true)},
+ {"com.sun.star.chart2.template.StackedNet" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y,true,true)},
+ {"com.sun.star.chart2.template.PercentStackedNet" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y_PERCENT,true,true)},
+
+ {"com.sun.star.chart2.template.NetLine" , ChartTypeParameter(3,false,false,GlobalStackMode_NONE,false,true)},
+ {"com.sun.star.chart2.template.StackedNetLine" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y,false,true)},
+ {"com.sun.star.chart2.template.PercentStackedNetLine" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y_PERCENT,false,true)},
+
+ {"com.sun.star.chart2.template.FilledNet" , ChartTypeParameter(4,false,false,GlobalStackMode_NONE,false,false)},
+ {"com.sun.star.chart2.template.StackedFilledNet" , ChartTypeParameter(4,false,false,GlobalStackMode_STACK_Y,false,false)},
+ {"com.sun.star.chart2.template.PercentStackedFilledNet" ,ChartTypeParameter(4,false,false,GlobalStackMode_STACK_Y_PERCENT,false,false)}};
+ return s_aTemplateMap;
+}
+void NetChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter )
+{
+ rSubTypeList.Clear();
+
+ if( rParameter.eStackMode == GlobalStackMode_NONE )
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_NET_SYMB));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_NET_LINESYMB));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_NET));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_NET_FILL));
+ }
+ else
+ {
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_NET_SYMB_STACK));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_NET_LINESYMB_STACK));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_NET_STACK));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_NET_FILL_STACK));
+ }
+
+ rSubTypeList.SetItemText( 1, SchResId( STR_POINTS_ONLY ) );
+ rSubTypeList.SetItemText( 2, SchResId( STR_POINTS_AND_LINES ) );
+ rSubTypeList.SetItemText( 3, SchResId( STR_LINES_ONLY ) );
+ rSubTypeList.SetItemText( 4, SchResId( STR_FILLED ) );
+}
+void NetChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter )
+{
+ rParameter.b3DLook = false;
+ if(rParameter.eStackMode==GlobalStackMode_STACK_Z)
+ rParameter.eStackMode = GlobalStackMode_NONE;
+
+ switch( rParameter.nSubTypeIndex )
+ {
+ case 2:
+ rParameter.bSymbols = true;
+ rParameter.bLines = true;
+ break;
+ case 3:
+ rParameter.bSymbols = false;
+ rParameter.bLines = true;
+ break;
+ case 4:
+ rParameter.bSymbols = false;
+ rParameter.bLines = false;
+ break;
+ default:
+ rParameter.bSymbols = true;
+ rParameter.bLines = false;
+ break;
+ }
+}
+StockChartDialogController::StockChartDialogController()
+{
+ bSupports3D = false;
+}
+
+StockChartDialogController::~StockChartDialogController()
+{
+}
+
+OUString StockChartDialogController::getName()
+{
+ return SchResId(STR_TYPE_STOCK);
+}
+
+OUString StockChartDialogController::getImage()
+{
+ return BMP_TYPE_STOCK;
+}
+
+const tTemplateServiceChartTypeParameterMap& StockChartDialogController::getTemplateMap() const
+{
+ static tTemplateServiceChartTypeParameterMap s_aTemplateMap{
+ {"com.sun.star.chart2.template.StockLowHighClose" , ChartTypeParameter(1)},
+ {"com.sun.star.chart2.template.StockOpenLowHighClose" , ChartTypeParameter(2)},
+ {"com.sun.star.chart2.template.StockVolumeLowHighClose" , ChartTypeParameter(3)},
+ {"com.sun.star.chart2.template.StockVolumeOpenLowHighClose" ,ChartTypeParameter(4)}};
+ return s_aTemplateMap;
+}
+
+void StockChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& /*rParameter*/ )
+{
+ rSubTypeList.Clear();
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_STOCK_1));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_STOCK_2));
+ rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_STOCK_3));
+ rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_STOCK_4));
+
+ rSubTypeList.SetItemText( 1, SchResId(STR_STOCK_1) );
+ rSubTypeList.SetItemText( 2, SchResId(STR_STOCK_2) );
+ rSubTypeList.SetItemText( 3, SchResId(STR_STOCK_3) );
+ rSubTypeList.SetItemText( 4, SchResId(STR_STOCK_4) );
+}
+
+void StockChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter )
+{
+ rParameter.b3DLook = false;
+ rParameter.eStackMode = GlobalStackMode_NONE;
+}
+
+CombiColumnLineChartDialogController::CombiColumnLineChartDialogController()
+{
+ bSupports3D = false;
+}
+
+OUString CombiColumnLineChartDialogController::getName()
+{
+ return SchResId(STR_TYPE_COMBI_COLUMN_LINE);
+}
+
+OUString CombiColumnLineChartDialogController::getImage()
+{
+ return BMP_TYPE_COLUMN_LINE;
+}
+
+const tTemplateServiceChartTypeParameterMap& CombiColumnLineChartDialogController::getTemplateMap() const
+{
+ static tTemplateServiceChartTypeParameterMap s_aTemplateMap{
+ {"com.sun.star.chart2.template.ColumnWithLine" , ChartTypeParameter(1)},
+ {"com.sun.star.chart2.template.StackedColumnWithLine" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y)}};
+ return s_aTemplateMap;
+}
+
+void CombiColumnLineChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& /*rParameter*/ )
+{
+ rSubTypeList.Clear();
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_COLUMN_LINE));
+ rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_COLUMN_LINE_STACKED));
+
+ rSubTypeList.SetItemText(1, SchResId(STR_LINE_COLUMN));
+ rSubTypeList.SetItemText(2, SchResId(STR_LINE_STACKEDCOLUMN));
+}
+
+void CombiColumnLineChartDialogController::showExtraControls(weld::Builder* pBuilder)
+{
+ if (!m_xFT_NumberOfLines)
+ {
+ m_xFT_NumberOfLines = pBuilder->weld_label("nolinesft");
+ }
+ if (!m_xMF_NumberOfLines)
+ {
+ m_xMF_NumberOfLines = pBuilder->weld_spin_button("nolines");
+
+ m_xMF_NumberOfLines->set_increments(1, 10);
+ m_xMF_NumberOfLines->set_range(1, 100);
+
+ m_xMF_NumberOfLines->connect_value_changed( LINK( this, CombiColumnLineChartDialogController, ChangeLineCountHdl ) );
+ }
+
+ m_xFT_NumberOfLines->show();
+ m_xMF_NumberOfLines->show();
+}
+
+void CombiColumnLineChartDialogController::hideExtraControls() const
+{
+ if (m_xFT_NumberOfLines)
+ m_xFT_NumberOfLines->hide();
+ if (m_xMF_NumberOfLines)
+ m_xMF_NumberOfLines->hide();
+}
+
+void CombiColumnLineChartDialogController::fillExtraControls(
+ const rtl::Reference<::chart::ChartModel>& xChartModel
+ , const uno::Reference< beans::XPropertySet >& xTemplateProps ) const
+{
+ if (!m_xMF_NumberOfLines)
+ return;
+
+ rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
+ if(!xDiagram.is())
+ return;
+
+ sal_Int32 nNumLines = 0;
+
+ if(xTemplateProps.is())
+ {
+ try
+ {
+ xTemplateProps->getPropertyValue( "NumberOfLines" ) >>= nNumLines;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ if( nNumLines < 0 )
+ nNumLines = 0;
+ m_xMF_NumberOfLines->set_value(nNumLines);
+
+ sal_Int32 nMaxLines = ChartModelHelper::getDataSeries( xChartModel ).size() - 1;
+ if( nMaxLines < 0 )
+ nMaxLines = 0;
+ m_xMF_NumberOfLines->set_max(nMaxLines);
+}
+void CombiColumnLineChartDialogController::setTemplateProperties( const uno::Reference< beans::XPropertySet >& xTemplateProps ) const
+{
+ if( xTemplateProps.is() )
+ {
+ sal_Int32 nNumLines = m_xMF_NumberOfLines->get_value();
+ xTemplateProps->setPropertyValue( "NumberOfLines" , uno::Any(nNumLines) );
+ }
+}
+
+IMPL_LINK_NOARG(CombiColumnLineChartDialogController, ChangeLineCountHdl, weld::SpinButton&, void)
+{
+ if( m_pChangeListener )
+ m_pChangeListener->stateChanged();
+}
+void CombiColumnLineChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter )
+{
+ rParameter.b3DLook = false;
+ if(rParameter.eStackMode==GlobalStackMode_STACK_Z)
+ rParameter.eStackMode = GlobalStackMode_NONE;
+
+ switch( rParameter.nSubTypeIndex )
+ {
+ case 2:
+ rParameter.eStackMode=GlobalStackMode_STACK_Y;
+ break;
+ default:
+ rParameter.eStackMode=GlobalStackMode_NONE;
+ break;
+ }
+}
+
+BubbleChartDialogController::BubbleChartDialogController()
+{
+}
+
+BubbleChartDialogController::~BubbleChartDialogController()
+{
+}
+
+OUString BubbleChartDialogController::getName()
+{
+ return SchResId(STR_TYPE_BUBBLE);
+}
+
+OUString BubbleChartDialogController::getImage()
+{
+ return BMP_TYPE_BUBBLE;
+}
+
+const tTemplateServiceChartTypeParameterMap& BubbleChartDialogController::getTemplateMap() const
+{
+ static tTemplateServiceChartTypeParameterMap s_aTemplateMap{
+ {"com.sun.star.chart2.template.Bubble" , ChartTypeParameter(1,true)}};
+ return s_aTemplateMap;
+}
+void BubbleChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& /*rParameter*/ )
+{
+ rSubTypeList.Clear();
+ rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_BUBBLE_1));
+
+ rSubTypeList.SetItemText( 1, SchResId(STR_BUBBLE_1) );
+}
+void BubbleChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter )
+{
+ rParameter.b3DLook = false;
+ rParameter.eStackMode = GlobalStackMode_NONE;
+}
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/DataBrowser.cxx b/chart2/source/controller/dialogs/DataBrowser.cxx
new file mode 100644
index 0000000000..30182b95ee
--- /dev/null
+++ b/chart2/source/controller/dialogs/DataBrowser.cxx
@@ -0,0 +1,1376 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/zforlist.hxx>
+
+#include "DataBrowser.hxx"
+#include "DataBrowserModel.hxx"
+#include <strings.hrc>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <CommonConverters.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <servicenames_charttypes.hxx>
+#include <ResId.hxx>
+#include <bitmaps.hlst>
+#include <helpids.h>
+#include <ChartModel.hxx>
+#include <ChartType.hxx>
+
+#include <vcl/weld.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <svl/numformat.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <com/sun/star/container/XIndexReplace.hpp>
+
+#include <algorithm>
+#include <limits>
+
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+
+using namespace ::svt;
+
+namespace
+{
+/* BrowserMode::COLUMNSELECTION : single cells may be selected rather than only
+ entire rows
+ BrowserMode::(H|V)LINES : show horizontal or vertical grid-lines
+ BrowserMode::AUTO_(H|V)SCROLL : scroll automated horizontally or vertically when
+ cursor is moved beyond the edge of the dialog
+ BrowserMode::HIDESELECT : Do not mark the current row with selection color
+ (usually blue)
+ ! BrowserMode::HIDECURSOR would prevent flickering in edit fields, but navigating
+ with shift up/down, and entering non-editable cells would be problematic,
+ e.g. the first cell, or when being in read-only mode
+*/
+const BrowserMode BrowserStdFlags = BrowserMode::COLUMNSELECTION |
+ BrowserMode::HLINES | BrowserMode::VLINES |
+ BrowserMode::AUTO_HSCROLL | BrowserMode::AUTO_VSCROLL |
+ BrowserMode::HIDESELECT;
+
+sal_Int32 lcl_getColumnInData( sal_uInt16 nCol )
+{
+ return static_cast< sal_Int32 >( nCol ) - 1;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+namespace impl
+{
+
+class SeriesHeaderEdit
+{
+public:
+ explicit SeriesHeaderEdit(std::unique_ptr<weld::Entry> xControl);
+
+ void setStartColumn( sal_Int32 nStartColumn );
+ sal_Int32 getStartColumn() const { return m_nStartColumn;}
+ void SetShowWarningBox( bool bShowWarning );
+
+ OUString GetText() const { return m_xControl->get_text(); }
+ void SetText(const OUString& rText) { m_xControl->set_text(rText); }
+
+ bool HasFocus() const { return m_xControl->has_focus(); }
+
+ void set_size_request(int nWidth, int nHeight) { m_xControl->set_size_request(nWidth, nHeight); }
+ void set_margin_start(int nLeft) { m_xControl->set_margin_start(nLeft); }
+
+ void SetModifyHdl(const Link<SeriesHeaderEdit&,void>& rLink) { m_aModifyHdl = rLink; }
+ void SetGetFocusHdl(const Link<SeriesHeaderEdit&,void>& rLink) { m_aFocusInHdl = rLink; }
+
+private:
+ DECL_LINK(NameEdited, weld::Entry&, void);
+ DECL_LINK(NameFocusIn, weld::Widget&, void);
+ DECL_LINK(MousePressHdl, const MouseEvent&, bool);
+
+ std::unique_ptr<weld::Entry> m_xControl;
+ Link<SeriesHeaderEdit&,void> m_aModifyHdl;
+ Link<SeriesHeaderEdit&,void> m_aFocusInHdl;
+ sal_Int32 m_nStartColumn;
+ bool m_bShowWarningBox;
+};
+
+SeriesHeaderEdit::SeriesHeaderEdit(std::unique_ptr<weld::Entry> xControl)
+ : m_xControl(std::move(xControl))
+ , m_nStartColumn(0)
+ , m_bShowWarningBox(false)
+{
+ m_xControl->set_help_id(HID_SCH_DATA_SERIES_LABEL);
+ m_xControl->connect_changed(LINK(this, SeriesHeaderEdit, NameEdited));
+ m_xControl->connect_focus_in(LINK(this, SeriesHeaderEdit, NameFocusIn));
+ m_xControl->connect_mouse_press(LINK(this, SeriesHeaderEdit, MousePressHdl));
+}
+
+IMPL_LINK_NOARG(SeriesHeaderEdit, NameEdited, weld::Entry&, void)
+{
+ m_aModifyHdl.Call(*this);
+}
+
+IMPL_LINK_NOARG(SeriesHeaderEdit, NameFocusIn, weld::Widget&, void)
+{
+ m_aFocusInHdl.Call(*this);
+}
+
+void SeriesHeaderEdit::setStartColumn( sal_Int32 nStartColumn )
+{
+ m_nStartColumn = nStartColumn;
+}
+
+void SeriesHeaderEdit::SetShowWarningBox( bool bShowWarning )
+{
+ m_bShowWarningBox = bShowWarning;
+}
+
+IMPL_LINK_NOARG(SeriesHeaderEdit, MousePressHdl, const MouseEvent&, bool)
+{
+ if (m_bShowWarningBox)
+ {
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(m_xControl.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ SchResId(STR_INVALID_NUMBER)));
+ xWarn->run();
+ }
+
+ return false;
+}
+
+class SeriesHeader
+{
+public:
+ explicit SeriesHeader(weld::Container* pParent, weld::Container* pColorParent);
+ ~SeriesHeader();
+
+ void SetColor( const Color & rCol );
+ void SetPos();
+ void SetWidth( sal_Int32 nWidth );
+ void SetChartType( const rtl::Reference< ::chart::ChartType > & xChartType,
+ bool bSwapXAndYAxis );
+ void SetSeriesName( const OUString & rName );
+ void SetRange( sal_Int32 nStartCol, sal_Int32 nEndCol );
+
+ void SetPixelWidth( sal_Int32 nWidth );
+
+ sal_Int32 GetStartColumn() const { return m_nStartCol;}
+ sal_Int32 GetEndColumn() const { return m_nEndCol;}
+
+ static const sal_Int32 nSymbolHeight = 10;
+ static const sal_Int32 nSymbolDistance = 2;
+
+ static sal_Int32 GetRelativeAppFontXPosForNameField() { return nSymbolHeight + nSymbolDistance; }
+
+ void Show();
+ void Hide();
+
+ /** call this before destroying the class. This notifies the listeners to
+ changes of the edit field for the series name.
+ */
+ void applyChanges();
+
+ void SetGetFocusHdl(const Link<SeriesHeaderEdit&,void>& rLink);
+
+ void SetEditChangedHdl( const Link<SeriesHeaderEdit&,void> & rLink );
+
+ bool HasFocus() const;
+
+private:
+ Timer m_aUpdateDataTimer;
+
+ std::unique_ptr<weld::Builder> m_xBuilder1;
+ std::unique_ptr<weld::Builder> m_xBuilder2;
+
+ weld::Container* m_pParent;
+ weld::Container* m_pColorParent;
+
+ std::unique_ptr<weld::Container> m_xContainer1;
+ std::unique_ptr<weld::Container> m_xContainer2;
+ std::unique_ptr<weld::Image> m_spSymbol;
+ std::unique_ptr<SeriesHeaderEdit> m_spSeriesName;
+ std::unique_ptr<weld::Image> m_spColorBar;
+ VclPtr< OutputDevice> m_xDevice;
+ Link<SeriesHeaderEdit&,void> m_aChangeLink;
+ Color m_aColor;
+
+ void notifyChanges();
+ DECL_LINK( ImplUpdateDataHdl, Timer*, void );
+ DECL_LINK( SeriesNameEdited, SeriesHeaderEdit&, void );
+
+ static OUString GetChartTypeImage(
+ const rtl::Reference< ::chart::ChartType > & xChartType,
+ bool bSwapXAndYAxis
+ );
+
+ sal_Int32 m_nStartCol, m_nEndCol;
+ sal_Int32 m_nWidth;
+ bool m_bSeriesNameChangePending;
+};
+
+SeriesHeader::SeriesHeader(weld::Container* pParent, weld::Container* pColorParent)
+ : m_aUpdateDataTimer( "SeriesHeader UpdateDataTimer" )
+ , m_xBuilder1(Application::CreateBuilder(pParent, "modules/schart/ui/columnfragment.ui"))
+ , m_xBuilder2(Application::CreateBuilder(pColorParent, "modules/schart/ui/imagefragment.ui"))
+ , m_pParent(pParent)
+ , m_pColorParent(pColorParent)
+ , m_xContainer1(m_xBuilder1->weld_container("container"))
+ , m_xContainer2(m_xBuilder2->weld_container("container"))
+ , m_spSymbol(m_xBuilder1->weld_image("image"))
+ , m_spSeriesName(new SeriesHeaderEdit(m_xBuilder1->weld_entry("entry")))
+ , m_spColorBar(m_xBuilder2->weld_image("image"))
+ , m_xDevice(Application::GetDefaultDevice())
+ , m_nStartCol( 0 )
+ , m_nEndCol( 0 )
+ , m_nWidth( 42 )
+ , m_bSeriesNameChangePending( false )
+{
+ m_aUpdateDataTimer.SetInvokeHandler(LINK(this, SeriesHeader, ImplUpdateDataHdl));
+ m_aUpdateDataTimer.SetTimeout(4 * EDIT_UPDATEDATA_TIMEOUT);
+
+ m_spSeriesName->SetModifyHdl(LINK(this, SeriesHeader, SeriesNameEdited));
+ Show();
+}
+
+SeriesHeader::~SeriesHeader()
+{
+ m_aUpdateDataTimer.Stop();
+ m_pParent->move(m_xContainer1.get(), nullptr);
+ m_pColorParent->move(m_xContainer2.get(), nullptr);
+}
+
+void SeriesHeader::notifyChanges()
+{
+ m_aChangeLink.Call(*m_spSeriesName);
+ m_bSeriesNameChangePending = false;
+}
+
+void SeriesHeader::applyChanges()
+{
+ if( m_bSeriesNameChangePending )
+ {
+ notifyChanges();
+ }
+}
+
+void SeriesHeader::SetColor( const Color & rCol )
+{
+ m_aColor = rCol;
+}
+
+void SeriesHeader::SetPos()
+{
+ // chart type symbol
+ Size aSize( nSymbolHeight, nSymbolHeight );
+ aSize = m_xDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont));
+ m_spSymbol->set_size_request(aSize.Width(), aSize.Height());
+
+ // series name edit field
+ m_spSeriesName->set_margin_start(2);
+
+ sal_Int32 nHeightPx = m_xDevice->LogicToPixel(Size(0, 12), MapMode(MapUnit::MapAppFont)).Height();
+ m_spSeriesName->set_size_request(m_nWidth - aSize.Width() - 2, nHeightPx);
+
+ // color bar
+ nHeightPx = m_xDevice->LogicToPixel(Size(0, 3), MapMode(MapUnit::MapAppFont)).Height();
+ m_spColorBar->set_size_request(m_nWidth, nHeightPx);
+
+ ScopedVclPtr<VirtualDevice> xVirDev(m_spColorBar->create_virtual_device());
+ xVirDev->SetOutputSizePixel(Size(m_nWidth, nHeightPx));
+ xVirDev->SetFillColor(m_aColor);
+ xVirDev->SetLineColor(m_aColor);
+ xVirDev->DrawRect(tools::Rectangle(Point(0, 0), aSize));
+ m_spColorBar->set_image(xVirDev.get());
+}
+
+void SeriesHeader::SetWidth( sal_Int32 nWidth )
+{
+ m_nWidth = nWidth;
+ SetPos();
+}
+
+void SeriesHeader::SetPixelWidth( sal_Int32 nWidth )
+{
+ SetWidth(nWidth);
+}
+
+void SeriesHeader::SetChartType(
+ const rtl::Reference< ChartType > & xChartType,
+ bool bSwapXAndYAxis
+)
+{
+ m_spSymbol->set_from_icon_name( GetChartTypeImage( xChartType, bSwapXAndYAxis ) );
+}
+
+void SeriesHeader::SetSeriesName( const OUString & rName )
+{
+ m_spSeriesName->SetText(rName);
+}
+
+void SeriesHeader::SetRange( sal_Int32 nStartCol, sal_Int32 nEndCol )
+{
+ m_nStartCol = nStartCol;
+ m_nEndCol = std::max(nEndCol, nStartCol);
+ m_spSeriesName->setStartColumn( nStartCol );
+}
+
+void SeriesHeader::Show()
+{
+ m_xContainer1->show();
+ m_xContainer2->show();
+}
+
+void SeriesHeader::Hide()
+{
+ m_xContainer1->hide();
+ m_xContainer2->hide();
+}
+
+void SeriesHeader::SetEditChangedHdl( const Link<SeriesHeaderEdit&,void> & rLink )
+{
+ m_aChangeLink = rLink;
+}
+
+IMPL_LINK_NOARG(SeriesHeader, ImplUpdateDataHdl, Timer*, void)
+{
+ notifyChanges();
+}
+
+IMPL_LINK_NOARG(SeriesHeader, SeriesNameEdited, SeriesHeaderEdit&, void)
+{
+ m_bSeriesNameChangePending = true;
+ m_aUpdateDataTimer.Start();
+}
+
+void SeriesHeader::SetGetFocusHdl( const Link<SeriesHeaderEdit&,void>& rLink )
+{
+ m_spSeriesName->SetGetFocusHdl( rLink );
+}
+
+bool SeriesHeader::HasFocus() const
+{
+ return m_spSeriesName->HasFocus();
+}
+
+OUString SeriesHeader::GetChartTypeImage(
+ const rtl::Reference< ChartType > & xChartType,
+ bool bSwapXAndYAxis
+)
+{
+ OUString aResult;
+ if( !xChartType.is())
+ return aResult;
+ OUString aChartTypeName( xChartType->getChartType());
+
+ if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_AREA )
+ {
+ aResult = BMP_TYPE_AREA;
+ }
+ else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_COLUMN )
+ {
+ if( bSwapXAndYAxis )
+ aResult = BMP_TYPE_BAR;
+ else
+ aResult = BMP_TYPE_COLUMN;
+ }
+ else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_LINE )
+ {
+ aResult = BMP_TYPE_LINE;
+ }
+ else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_SCATTER )
+ {
+ aResult = BMP_TYPE_XY;
+ }
+ else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_PIE )
+ {
+ aResult = BMP_TYPE_PIE;
+ }
+ else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_NET
+ || aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET )
+ {
+ aResult = BMP_TYPE_NET;
+ }
+ else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK )
+ {
+ // @todo: correct image for candle-stick type
+ aResult = BMP_TYPE_STOCK;
+ }
+ else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE )
+ {
+ aResult = BMP_TYPE_BUBBLE;
+ }
+
+ return aResult;
+}
+
+} // namespace impl
+
+namespace
+{
+
+/** returns false, if no header as the focus.
+
+ If a header has the focus, true is returned and the index of the header
+ with focus is set at pIndex if pOutIndex is not 0.
+*/
+bool lcl_SeriesHeaderHasFocus(
+ const std::vector< std::shared_ptr< ::chart::impl::SeriesHeader > > & rSeriesHeader,
+ sal_Int32 * pOutIndex = nullptr )
+{
+ sal_Int32 nIndex = 0;
+ for (auto const& elem : rSeriesHeader)
+ {
+ if(elem->HasFocus())
+ {
+ if( pOutIndex )
+ *pOutIndex = nIndex;
+ return true;
+ }
+ ++nIndex;
+ }
+ return false;
+}
+
+sal_Int32 lcl_getColumnInDataOrHeader(
+ sal_uInt16 nCol, const std::vector< std::shared_ptr< ::chart::impl::SeriesHeader > > & rSeriesHeader )
+{
+ sal_Int32 nColIdx = 0;
+ bool bHeaderHasFocus( lcl_SeriesHeaderHasFocus( rSeriesHeader, &nColIdx ));
+
+ if( bHeaderHasFocus )
+ nColIdx = lcl_getColumnInData( static_cast< sal_uInt16 >( rSeriesHeader[nColIdx]->GetStartColumn()));
+ else
+ nColIdx = lcl_getColumnInData( nCol );
+
+ return nColIdx;
+}
+
+} // anonymous namespace
+
+DataBrowser::DataBrowser(const css::uno::Reference<css::awt::XWindow> &rParent,
+ weld::Container* pColumns, weld::Container* pColors) :
+ ::svt::EditBrowseBox(VCLUnoHelper::GetWindow(rParent),
+ EditBrowseBoxFlags::SMART_TAB_TRAVEL | EditBrowseBoxFlags::HANDLE_COLUMN_TEXT,
+ WB_BORDER | WB_TABSTOP, BrowserStdFlags ),
+ m_nSeekRow( 0 ),
+ m_bIsReadOnly( false ),
+ m_bDataValid( true ),
+ m_aNumberEditField(VclPtr<FormattedControl>::Create(&EditBrowseBox::GetDataWindow(), false)),
+ m_aTextEditField(VclPtr<EditControl>::Create(&EditBrowseBox::GetDataWindow())),
+ m_pColumnsWin(pColumns),
+ m_pColorsWin(pColors),
+ m_rNumberEditController( new ::svt::FormattedFieldCellController( m_aNumberEditField.get() )),
+ m_rTextEditController( new ::svt::EditCellController( m_aTextEditField.get() ))
+{
+ Formatter& rFormatter = m_aNumberEditField->get_formatter();
+ rFormatter.SetDefaultValue( std::numeric_limits<double>::quiet_NaN() );
+ rFormatter.TreatAsNumber( true );
+ RenewTable();
+}
+
+DataBrowser::~DataBrowser()
+{
+ disposeOnce();
+}
+
+void DataBrowser::dispose()
+{
+ m_aSeriesHeaders.clear();
+ m_aNumberEditField.disposeAndClear();
+ m_aTextEditField.disposeAndClear();
+ ::svt::EditBrowseBox::dispose();
+}
+
+bool DataBrowser::MayInsertRow() const
+{
+ return ! IsReadOnly()
+ && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ));
+}
+
+bool DataBrowser::MayInsertColumn() const
+{
+ return ! IsReadOnly();
+}
+
+bool DataBrowser::MayDeleteRow() const
+{
+ return ! IsReadOnly()
+ && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
+ && ( GetCurRow() >= 0 )
+ && ( GetRowCount() > 1 );
+}
+
+bool DataBrowser::MayDeleteColumn() const
+{
+ // if a series header has the focus
+ if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
+ return true;
+
+ return ! IsReadOnly()
+ && ( GetCurColumnId() > 1 )
+ && ( ColCount() > 2 );
+}
+
+bool DataBrowser::MayMoveUpRows() const
+{
+ return ! IsReadOnly()
+ && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
+ && ( GetCurRow() > 0 )
+ && ( GetCurRow() <= GetRowCount() - 1 );
+}
+
+bool DataBrowser::MayMoveDownRows() const
+{
+ return ! IsReadOnly()
+ && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
+ && ( GetCurRow() >= 0 )
+ && ( GetCurRow() < GetRowCount() - 1 );
+}
+
+bool DataBrowser::MayMoveLeftColumns() const
+{
+ // if a series header (except the last one) has the focus
+ {
+ sal_Int32 nColIndex(0);
+ if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders, &nColIndex ))
+ return (o3tl::make_unsigned( nColIndex ) <= (m_aSeriesHeaders.size() - 1)) && (static_cast< sal_uInt32 >( nColIndex ) != 0);
+ }
+
+ sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
+ return ! IsReadOnly()
+ && ( nColIdx > 1 )
+ && ( nColIdx <= ColCount() - 2 )
+ && m_apDataBrowserModel
+ && !m_apDataBrowserModel->isCategoriesColumn( nColIdx );
+}
+
+bool DataBrowser::MayMoveRightColumns() const
+{
+ // if a series header (except the last one) has the focus
+ {
+ sal_Int32 nColIndex(0);
+ if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders, &nColIndex ))
+ return (o3tl::make_unsigned( nColIndex ) < (m_aSeriesHeaders.size() - 1));
+ }
+
+ sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
+ return ! IsReadOnly()
+ && ( nColIdx > 0 )
+ && ( nColIdx < ColCount()-2 )
+ && m_apDataBrowserModel
+ && !m_apDataBrowserModel->isCategoriesColumn( nColIdx );
+}
+
+void DataBrowser::clearHeaders()
+{
+ for( const auto& spHeader : m_aSeriesHeaders )
+ spHeader->applyChanges();
+ m_aSeriesHeaders.clear();
+}
+
+void DataBrowser::RenewTable()
+{
+ if (!m_apDataBrowserModel)
+ return;
+
+ sal_Int32 nOldRow = GetCurRow();
+ sal_uInt16 nOldColId = GetCurColumnId();
+
+ bool bLastUpdateMode = GetUpdateMode();
+ SetUpdateMode( false );
+
+ if( IsModified() )
+ SaveModified();
+
+ DeactivateCell();
+
+ RemoveColumns();
+ RowRemoved( 1, GetRowCount() );
+
+ // for row numbers
+ InsertHandleColumn( static_cast< sal_uInt16 >(
+ GetDataWindow().LogicToPixel( Size( 42, 0 )).getWidth() ));
+
+ OUString aDefaultSeriesName(SchResId(STR_COLUMN_LABEL));
+ replaceParamterInString( aDefaultSeriesName, u"%COLUMNNUMBER", OUString::number( 24 ) );
+ sal_Int32 nColumnWidth = GetDataWindow().GetTextWidth( aDefaultSeriesName )
+ + GetDataWindow().LogicToPixel(Point(8 + impl::SeriesHeader::GetRelativeAppFontXPosForNameField(), 0), MapMode(MapUnit::MapAppFont)).X();
+ sal_Int32 nColumnCount = m_apDataBrowserModel->getColumnCount();
+ // nRowCount is a member of a base class
+ sal_Int32 nRowCountLocal = m_apDataBrowserModel->getMaxRowCount();
+ for( sal_Int32 nColIdx=1; nColIdx<=nColumnCount; ++nColIdx )
+ {
+ InsertDataColumn( static_cast< sal_uInt16 >( nColIdx ), GetColString( nColIdx ), nColumnWidth );
+ }
+
+ RowInserted( 1, nRowCountLocal );
+ GoToRow( std::min( nOldRow, GetRowCount() - 1 ));
+ GoToColumnId( std::min( nOldColId, static_cast< sal_uInt16 >( ColCount() - 1 )));
+
+ // fill series headers
+ clearHeaders();
+ const DataBrowserModel::tDataHeaderVector& aHeaders( m_apDataBrowserModel->getDataHeaders());
+ Link<impl::SeriesHeaderEdit&,void> aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus ));
+ Link<impl::SeriesHeaderEdit&,void> aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged ));
+
+ for (auto const& elemHeader : aHeaders)
+ {
+ auto spHeader = std::make_shared<impl::SeriesHeader>( m_pColumnsWin, m_pColorsWin );
+ Color nColor;
+ // @todo: Set "DraftColor", i.e. interpolated colors for gradients, bitmaps, etc.
+ if( elemHeader.m_xDataSeries.is() &&
+ ( elemHeader.m_xDataSeries->getPropertyValue( "Color" ) >>= nColor ))
+ spHeader->SetColor( nColor );
+ spHeader->SetChartType( elemHeader.m_xChartType, elemHeader.m_bSwapXAndYAxis );
+ spHeader->SetSeriesName(
+ elemHeader.m_xDataSeries->getLabelForRole(
+ elemHeader.m_xChartType.is() ?
+ elemHeader.m_xChartType->getRoleOfSequenceForSeriesLabel() :
+ OUString("values-y")));
+ // index is 1-based, as 0 is for the column that contains the row-numbers
+ spHeader->SetRange( elemHeader.m_nStartColumn + 1, elemHeader.m_nEndColumn + 1 );
+ spHeader->SetGetFocusHdl( aFocusLink );
+ spHeader->SetEditChangedHdl( aSeriesHeaderChangedLink );
+ m_aSeriesHeaders.push_back( spHeader );
+ }
+
+ ImplAdjustHeaderControls();
+ SetUpdateMode( bLastUpdateMode );
+ ActivateCell();
+ Invalidate();
+}
+
+OUString DataBrowser::GetColString( sal_Int32 nColumnId ) const
+{
+ OSL_ASSERT(m_apDataBrowserModel);
+ if( nColumnId > 0 )
+ return m_apDataBrowserModel->getRoleOfColumn( nColumnId - 1 );
+ return OUString();
+}
+
+OUString DataBrowser::GetCellText( sal_Int32 nRow, sal_uInt16 nColumnId ) const
+{
+ OUString aResult;
+
+ if( nColumnId == 0 )
+ {
+ aResult = OUString::number(nRow + 1);
+ }
+ else if( nRow >= 0 && m_apDataBrowserModel)
+ {
+ sal_Int32 nColIndex = static_cast< sal_Int32 >( nColumnId ) - 1;
+
+ if( m_apDataBrowserModel->getCellType( nColIndex ) == DataBrowserModel::NUMBER )
+ {
+ double fData( m_apDataBrowserModel->getCellNumber( nColIndex, nRow ));
+
+ if( ! std::isnan( fData ) &&
+ m_spNumberFormatterWrapper )
+ {
+ bool bColorChanged = false;
+ Color nLabelColor;
+ aResult = m_spNumberFormatterWrapper->getFormattedString(
+ GetNumberFormatKey( nColumnId ),
+ fData, nLabelColor, bColorChanged );
+ }
+ }
+ else if( m_apDataBrowserModel->getCellType( nColIndex ) == DataBrowserModel::TEXTORDATE )
+ {
+ uno::Any aAny = m_apDataBrowserModel->getCellAny( nColIndex, nRow );
+ OUString aText;
+ double fDouble=0.0;
+ if( aAny>>=aText )
+ aResult = aText;
+ else if( aAny>>=fDouble )
+ {
+ if( ! std::isnan( fDouble ) && m_spNumberFormatterWrapper )
+ {
+ // If a numberformat was available here we could directly
+ // obtain the corresponding edit format in
+ // getDateTimeInputNumberFormat() instead of doing the
+ // guess work.
+ sal_Int32 nNumberFormat = DiagramHelper::getDateTimeInputNumberFormat(
+ m_xChartDoc, fDouble );
+ Color nLabelColor;
+ bool bColorChanged = false;
+ aResult = m_spNumberFormatterWrapper->getFormattedString(
+ nNumberFormat, fDouble, nLabelColor, bColorChanged );
+ }
+ }
+ }
+ else
+ {
+ OSL_ASSERT( m_apDataBrowserModel->getCellType( nColIndex ) == DataBrowserModel::TEXT );
+ aResult = m_apDataBrowserModel->getCellText( nColIndex, nRow );
+ }
+ }
+
+ return aResult;
+}
+
+double DataBrowser::GetCellNumber( sal_Int32 nRow, sal_uInt16 nColumnId ) const
+{
+ if(( nColumnId >= 1 ) && ( nRow >= 0 ) && m_apDataBrowserModel)
+ {
+ return m_apDataBrowserModel->getCellNumber(
+ static_cast< sal_Int32 >( nColumnId ) - 1, nRow );
+ }
+
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+void DataBrowser::Resize()
+{
+ bool bLastUpdateMode = GetUpdateMode();
+ SetUpdateMode( false );
+
+ ::svt::EditBrowseBox::Resize();
+ ImplAdjustHeaderControls();
+ SetUpdateMode( bLastUpdateMode );
+}
+
+void DataBrowser::SetReadOnly( bool bNewState )
+{
+ if( m_bIsReadOnly != bNewState )
+ {
+ m_bIsReadOnly = bNewState;
+ Invalidate();
+ DeactivateCell();
+ }
+}
+
+void DataBrowser::CursorMoved()
+{
+ EditBrowseBox::CursorMoved();
+
+ if( GetUpdateMode() )
+ m_aCursorMovedHdlLink.Call( this );
+}
+
+void DataBrowser::MouseButtonDown( const BrowserMouseEvent& rEvt )
+{
+ if( !m_bDataValid )
+ ShowWarningBox();
+ else
+ EditBrowseBox::MouseButtonDown( rEvt );
+}
+
+void DataBrowser::ShowWarningBox()
+{
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ SchResId(STR_INVALID_NUMBER)));
+ xWarn->run();
+}
+
+bool DataBrowser::ShowQueryBox()
+{
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ SchResId(STR_DATA_EDITOR_INCORRECT_INPUT)));
+ return xQueryBox->run() == RET_YES;
+}
+
+bool DataBrowser::IsDataValid() const
+{
+ bool bValid = true;
+ const sal_Int32 nCol = lcl_getColumnInData( GetCurColumnId());
+
+ if( m_apDataBrowserModel->getCellType( nCol ) == DataBrowserModel::NUMBER )
+ {
+ sal_uInt32 nDummy = 0;
+ double fDummy = 0.0;
+ OUString aText(m_aNumberEditField->get_widget().get_text());
+
+ if( !aText.isEmpty() &&
+ m_spNumberFormatterWrapper &&
+ m_spNumberFormatterWrapper->getSvNumberFormatter() &&
+ ! m_spNumberFormatterWrapper->getSvNumberFormatter()->IsNumberFormat(
+ aText, nDummy, fDummy ))
+ {
+ bValid = false;
+ }
+ }
+
+ return bValid;
+}
+
+void DataBrowser::CellModified()
+{
+ m_bDataValid = IsDataValid();
+ m_aCursorMovedHdlLink.Call( this );
+}
+
+void DataBrowser::SetDataFromModel(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc )
+{
+ m_xChartDoc = xChartDoc;
+
+ m_apDataBrowserModel.reset( new DataBrowserModel( m_xChartDoc ));
+ m_spNumberFormatterWrapper =
+ std::make_shared<NumberFormatterWrapper>(m_xChartDoc);
+
+ Formatter& rFormatter = m_aNumberEditField->get_formatter();
+ rFormatter.SetFormatter( m_spNumberFormatterWrapper->getSvNumberFormatter() );
+
+ RenewTable();
+
+ const sal_Int32 nColCnt = m_apDataBrowserModel->getColumnCount();
+ const sal_Int32 nRowCnt = m_apDataBrowserModel->getMaxRowCount();
+ if( nRowCnt && nColCnt )
+ {
+ GoToRow( 0 );
+ GoToColumnId( 1 );
+ }
+}
+
+void DataBrowser::InsertColumn()
+{
+ sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
+
+ if( nColIdx >= 0 && m_apDataBrowserModel)
+ {
+ // save changes made to edit-field
+ if( IsModified() )
+ SaveModified();
+
+ m_apDataBrowserModel->insertDataSeries( nColIdx );
+ RenewTable();
+ }
+}
+
+void DataBrowser::InsertTextColumn()
+{
+ sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
+
+ if( nColIdx >= 0 && m_apDataBrowserModel)
+ {
+ // save changes made to edit-field
+ if( IsModified() )
+ SaveModified();
+
+ m_apDataBrowserModel->insertComplexCategoryLevel( nColIdx );
+ RenewTable();
+ }
+}
+
+void DataBrowser::RemoveColumn()
+{
+ sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
+
+ if( nColIdx >= 0 && m_apDataBrowserModel)
+ {
+ // save changes made to edit-field
+ if( IsModified() )
+ SaveModified();
+
+ m_bDataValid = true;
+ m_apDataBrowserModel->removeDataSeriesOrComplexCategoryLevel( nColIdx );
+ RenewTable();
+ }
+}
+
+void DataBrowser::InsertRow()
+{
+ sal_Int32 nRowIdx = GetCurRow();
+
+ if( nRowIdx >= 0 && m_apDataBrowserModel)
+ {
+ // save changes made to edit-field
+ if( IsModified() )
+ SaveModified();
+
+ m_apDataBrowserModel->insertDataPointForAllSeries( nRowIdx );
+ RenewTable();
+ }
+}
+
+void DataBrowser::RemoveRow()
+{
+ sal_Int32 nRowIdx = GetCurRow();
+
+ if( nRowIdx >= 0 && m_apDataBrowserModel)
+ {
+ // save changes made to edit-field
+ if( IsModified() )
+ SaveModified();
+
+ m_bDataValid = true;
+ m_apDataBrowserModel->removeDataPointForAllSeries( nRowIdx );
+ RenewTable();
+ }
+}
+
+void DataBrowser::MoveLeftColumn()
+{
+ sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
+
+ if( !(nColIdx > 0 && m_apDataBrowserModel))
+ return;
+
+ // save changes made to edit-field
+ if( IsModified() )
+ SaveModified();
+
+ m_apDataBrowserModel->swapDataSeries( nColIdx - 1 );
+
+ // keep cursor in swapped column
+ if(( 0 < GetCurColumnId() ) && ( GetCurColumnId() <= ColCount() - 1 ))
+ {
+ Dispatch( BROWSER_CURSORLEFT );
+ }
+ RenewTable();
+}
+
+void DataBrowser::MoveRightColumn()
+{
+ sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
+
+ if( !(nColIdx >= 0 && m_apDataBrowserModel))
+ return;
+
+ // save changes made to edit-field
+ if( IsModified() )
+ SaveModified();
+
+ m_apDataBrowserModel->swapDataSeries( nColIdx );
+
+ // keep cursor in swapped column
+ if( GetCurColumnId() < ColCount() - 1 )
+ {
+ Dispatch( BROWSER_CURSORRIGHT );
+ }
+ RenewTable();
+}
+
+void DataBrowser::MoveUpRow()
+{
+ sal_Int32 nRowIdx = GetCurRow();
+
+ if( !(nRowIdx > 0 && m_apDataBrowserModel))
+ return;
+
+ // save changes made to edit-field
+ if( IsModified() )
+ SaveModified();
+
+ m_apDataBrowserModel->swapDataPointForAllSeries( nRowIdx - 1 );
+
+ // keep cursor in swapped row
+ if(( 0 < GetCurRow() ) && ( GetCurRow() <= GetRowCount() - 1 ))
+ {
+ Dispatch( BROWSER_CURSORUP );
+ }
+ RenewTable();
+}
+
+void DataBrowser::MoveDownRow()
+{
+ sal_Int32 nRowIdx = GetCurRow();
+
+ if( !(nRowIdx >= 0 && m_apDataBrowserModel))
+ return;
+
+ // save changes made to edit-field
+ if( IsModified() )
+ SaveModified();
+
+ m_apDataBrowserModel->swapDataPointForAllSeries( nRowIdx );
+
+ // keep cursor in swapped row
+ if( GetCurRow() < GetRowCount() - 1 )
+ {
+ Dispatch( BROWSER_CURSORDOWN );
+ }
+ RenewTable();
+}
+
+void DataBrowser::SetCursorMovedHdl( const Link<DataBrowser*,void>& rLink )
+{
+ m_aCursorMovedHdlLink = rLink;
+}
+
+// implementations for ::svt::EditBrowseBox (pure virtual methods)
+void DataBrowser::PaintCell(
+ OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId ) const
+{
+ Point aPos( rRect.TopLeft());
+ aPos.AdjustX(1 );
+
+ OUString aText = GetCellText( m_nSeekRow, nColumnId );
+ Size TxtSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight());
+
+ // clipping
+ if( aPos.X() < rRect.Right() || aPos.X() + TxtSize.Width() > rRect.Right() ||
+ aPos.Y() < rRect.Top() || aPos.Y() + TxtSize.Height() > rRect.Bottom())
+ rDev.SetClipRegion(vcl::Region(rRect));
+
+ // allow for a disabled control ...
+ bool bEnabled = IsEnabled();
+ Color aOriginalColor = rDev.GetTextColor();
+ if( ! bEnabled )
+ rDev.SetTextColor( GetSettings().GetStyleSettings().GetDisableColor() );
+
+ // draw the text
+ rDev.DrawText( aPos, aText );
+
+ // reset the color (if necessary)
+ if( ! bEnabled )
+ rDev.SetTextColor( aOriginalColor );
+
+ if( rDev.IsClipRegion())
+ rDev.SetClipRegion();
+}
+
+bool DataBrowser::SeekRow( sal_Int32 nRow )
+{
+ if( ! EditBrowseBox::SeekRow( nRow ))
+ return false;
+
+ if( nRow < 0 )
+ m_nSeekRow = - 1;
+ else
+ m_nSeekRow = nRow;
+
+ return true;
+}
+
+bool DataBrowser::IsTabAllowed( bool bForward ) const
+{
+ sal_Int32 nRow = GetCurRow();
+ sal_Int32 nCol = GetCurColumnId();
+
+ // column 0 is header-column
+ sal_Int32 nBadCol = bForward
+ ? GetColumnCount() - 1
+ : 1;
+ sal_Int32 nBadRow = bForward
+ ? GetRowCount() - 1
+ : 0;
+
+ if( !m_bDataValid )
+ {
+ const_cast< DataBrowser* >( this )->ShowWarningBox();
+ return false;
+ }
+
+ return ( nRow != nBadRow ||
+ nCol != nBadCol );
+}
+
+::svt::CellController* DataBrowser::GetController( sal_Int32 /*nRow*/, sal_uInt16 nCol )
+{
+ if( m_bIsReadOnly )
+ return nullptr;
+
+ if( CellContainsNumbers( nCol ))
+ {
+ Formatter& rFormatter = m_aNumberEditField->get_formatter();
+ rFormatter.UseInputStringForFormatting();
+ rFormatter.SetFormatKey( GetNumberFormatKey( nCol ));
+ return m_rNumberEditController.get();
+ }
+
+ return m_rTextEditController.get();
+}
+
+void DataBrowser::InitController(
+ ::svt::CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol )
+{
+ if( rController == m_rTextEditController )
+ {
+ OUString aText( GetCellText( nRow, nCol ) );
+ weld::Entry& rEntry = m_aTextEditField->get_widget();
+ rEntry.set_text(aText);
+ rEntry.select_region(0, -1);
+ }
+ else if( rController == m_rNumberEditController )
+ {
+ // treat invalid and empty text as Nan
+ Formatter& rFormatter = m_aNumberEditField->get_formatter();
+ rFormatter.EnableNotANumber( true );
+ if( std::isnan( GetCellNumber( nRow, nCol )))
+ rFormatter.SetTextValue( OUString());
+ else
+ rFormatter.SetValue( GetCellNumber( nRow, nCol ) );
+ weld::Entry& rEntry = m_aNumberEditField->get_widget();
+ rEntry.select_region(0, -1);
+ }
+ else
+ {
+ OSL_FAIL( "Invalid Controller" );
+ }
+}
+
+bool DataBrowser::CellContainsNumbers( sal_uInt16 nCol ) const
+{
+ if (!m_apDataBrowserModel)
+ return false;
+ return m_apDataBrowserModel->getCellType( lcl_getColumnInData( nCol )) == DataBrowserModel::NUMBER;
+}
+
+sal_uInt32 DataBrowser::GetNumberFormatKey( sal_uInt16 nCol ) const
+{
+ if (!m_apDataBrowserModel)
+ return 0;
+ return m_apDataBrowserModel->getNumberFormatKey( lcl_getColumnInData( nCol ) );
+}
+
+bool DataBrowser::isDateTimeString( const OUString& aInputString, double& fOutDateTimeValue )
+{
+ sal_uInt32 nNumberFormat=0;
+ SvNumberFormatter* pSvNumberFormatter = m_spNumberFormatterWrapper ? m_spNumberFormatterWrapper->getSvNumberFormatter() : nullptr;
+ if( !aInputString.isEmpty() && pSvNumberFormatter && pSvNumberFormatter->IsNumberFormat( aInputString, nNumberFormat, fOutDateTimeValue ) )
+ {
+ SvNumFormatType nType = pSvNumberFormatter->GetType( nNumberFormat);
+ return (nType & SvNumFormatType::DATE) || (nType & SvNumFormatType::TIME);
+ }
+ return false;
+}
+
+bool DataBrowser::SaveModified()
+{
+ if( ! IsModified() )
+ return true;
+
+ bool bChangeValid = true;
+
+ const sal_Int32 nRow = GetCurRow();
+ const sal_Int32 nCol = lcl_getColumnInData( GetCurColumnId());
+
+ OSL_ENSURE( nRow >= 0 || nCol >= 0, "This cell should not be modified!" );
+
+ SvNumberFormatter* pSvNumberFormatter = m_spNumberFormatterWrapper ? m_spNumberFormatterWrapper->getSvNumberFormatter() : nullptr;
+ switch( m_apDataBrowserModel->getCellType( nCol ))
+ {
+ case DataBrowserModel::NUMBER:
+ {
+ sal_uInt32 nDummy = 0;
+ double fDummy = 0.0;
+ OUString aText(m_aNumberEditField->get_widget().get_text());
+ // an empty string is valid, if no numberformatter exists, all
+ // values are treated as valid
+ if( !aText.isEmpty() && pSvNumberFormatter &&
+ ! pSvNumberFormatter->IsNumberFormat( aText, nDummy, fDummy ) )
+ {
+ bChangeValid = false;
+ }
+ else
+ {
+ Formatter& rFormatter = m_aNumberEditField->get_formatter();
+ double fData = rFormatter.GetValue();
+ bChangeValid = m_apDataBrowserModel->setCellNumber( nCol, nRow, fData );
+ }
+ }
+ break;
+ case DataBrowserModel::TEXTORDATE:
+ {
+ weld::Entry& rEntry = m_aTextEditField->get_widget();
+ OUString aText(rEntry.get_text());
+ double fValue = 0.0;
+ bChangeValid = false;
+ if( isDateTimeString( aText, fValue ) )
+ bChangeValid = m_apDataBrowserModel->setCellAny( nCol, nRow, uno::Any( fValue ) );
+ if(!bChangeValid)
+ bChangeValid = m_apDataBrowserModel->setCellAny( nCol, nRow, uno::Any( aText ) );
+ }
+ break;
+ case DataBrowserModel::TEXT:
+ {
+ weld::Entry& rEntry = m_aTextEditField->get_widget();
+ OUString aText(rEntry.get_text());
+ bChangeValid = m_apDataBrowserModel->setCellText( nCol, nRow, aText );
+ }
+ break;
+ }
+
+ // the first valid change changes this to true
+ if( bChangeValid )
+ {
+ RowModified( GetCurRow(), GetCurColumnId());
+ ::svt::CellController* pCtrl = GetController( GetCurRow(), GetCurColumnId());
+ if( pCtrl )
+ pCtrl->SaveValue();
+ }
+
+ return bChangeValid;
+}
+
+bool DataBrowser::EndEditing()
+{
+ SaveModified();
+
+ // apply changes made to series headers
+ for( const auto& spHeader : m_aSeriesHeaders )
+ spHeader->applyChanges();
+
+ if( m_bDataValid )
+ return true;
+ else
+ return ShowQueryBox();
+}
+
+void DataBrowser::ColumnResized( sal_uInt16 nColId )
+{
+ bool bLastUpdateMode = GetUpdateMode();
+ SetUpdateMode( false );
+
+ EditBrowseBox::ColumnResized( nColId );
+ ImplAdjustHeaderControls();
+ SetUpdateMode( bLastUpdateMode );
+}
+
+void DataBrowser::EndScroll()
+{
+ bool bLastUpdateMode = GetUpdateMode();
+ SetUpdateMode( false );
+
+ EditBrowseBox::EndScroll();
+ RenewSeriesHeaders();
+
+ SetUpdateMode( bLastUpdateMode );
+}
+
+void DataBrowser::RenewSeriesHeaders()
+{
+ clearHeaders();
+ DataBrowserModel::tDataHeaderVector aHeaders( m_apDataBrowserModel->getDataHeaders());
+ Link<impl::SeriesHeaderEdit&,void> aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus ));
+ Link<impl::SeriesHeaderEdit&,void> aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged ));
+
+ for (auto const& elemHeader : aHeaders)
+ {
+ auto spHeader = std::make_shared<impl::SeriesHeader>( m_pColumnsWin, m_pColorsWin );
+ Color nColor;
+ if( elemHeader.m_xDataSeries.is() &&
+ ( elemHeader.m_xDataSeries->getPropertyValue( "Color" ) >>= nColor ))
+ spHeader->SetColor( nColor );
+ spHeader->SetChartType( elemHeader.m_xChartType, elemHeader.m_bSwapXAndYAxis );
+ spHeader->SetSeriesName(
+ elemHeader.m_xDataSeries->getLabelForRole(
+ elemHeader.m_xChartType.is() ?
+ elemHeader.m_xChartType->getRoleOfSequenceForSeriesLabel() :
+ OUString( "values-y")));
+ spHeader->SetRange( elemHeader.m_nStartColumn + 1, elemHeader.m_nEndColumn + 1 );
+ spHeader->SetGetFocusHdl( aFocusLink );
+ spHeader->SetEditChangedHdl( aSeriesHeaderChangedLink );
+ m_aSeriesHeaders.push_back( spHeader );
+ }
+
+ ImplAdjustHeaderControls();
+}
+
+void DataBrowser::ImplAdjustHeaderControls()
+{
+ sal_uInt16 nColCount = GetColumnCount();
+ sal_uInt32 nCurrentPos = GetPosPixel().getX();
+ sal_uInt32 nMaxPos = nCurrentPos + GetOutputSizePixel().getWidth();
+ sal_uInt32 nStartPos = nCurrentPos;
+
+ // width of header column
+ nCurrentPos += GetColumnWidth( 0 );
+
+ weld::Container* pWin = m_pColumnsWin;
+ weld::Container* pColorWin = m_pColorsWin;
+ pWin->set_margin_start(nCurrentPos);
+ pColorWin->set_margin_start(nCurrentPos);
+
+ tSeriesHeaderContainer::iterator aIt( m_aSeriesHeaders.begin());
+ sal_uInt16 i = GetFirstVisibleColNumber();
+ while( (aIt != m_aSeriesHeaders.end()) && ((*aIt)->GetStartColumn() < i) )
+ {
+ (*aIt)->Hide();
+ ++aIt;
+ }
+ for( ; i < nColCount && aIt != m_aSeriesHeaders.end(); ++i )
+ {
+ if( (*aIt)->GetStartColumn() == i )
+ nStartPos = nCurrentPos;
+
+ nCurrentPos += (GetColumnWidth( i ));
+
+ if( (*aIt)->GetEndColumn() == i )
+ {
+ if( nStartPos < nMaxPos )
+ {
+ (*aIt)->SetPixelWidth( nCurrentPos - nStartPos );
+ (*aIt)->Show();
+
+ if (pWin)
+ {
+ pWin->set_margin_start(nStartPos);
+ pColorWin->set_margin_start(nStartPos);
+ pWin = pColorWin = nullptr;
+ }
+
+ }
+ else
+ (*aIt)->Hide();
+ ++aIt;
+ }
+ }
+}
+
+IMPL_LINK( DataBrowser, SeriesHeaderGotFocus, impl::SeriesHeaderEdit&, rEdit, void )
+{
+ rEdit.SetShowWarningBox( !m_bDataValid );
+
+ if( !m_bDataValid )
+ GoToCell( 0, 0 );
+ else
+ {
+ MakeFieldVisible( GetCurRow(), static_cast< sal_uInt16 >( rEdit.getStartColumn()) );
+ ActivateCell();
+ m_aCursorMovedHdlLink.Call( this );
+ }
+}
+
+IMPL_LINK( DataBrowser, SeriesHeaderChanged, impl::SeriesHeaderEdit&, rEdit, void )
+{
+ rtl::Reference< DataSeries > xSeries =
+ m_apDataBrowserModel->getDataSeriesByColumn( rEdit.getStartColumn() - 1 );
+ if( !xSeries.is())
+ return;
+
+ rtl::Reference< ChartType > xChartType(
+ m_apDataBrowserModel->getHeaderForSeries( xSeries ).m_xChartType );
+ if( xChartType.is())
+ {
+ uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq =
+ DataSeriesHelper::getDataSequenceByRole( xSeries, xChartType->getRoleOfSequenceForSeriesLabel());
+ if( xLabeledSeq.is())
+ {
+ Reference< container::XIndexReplace > xIndexReplace( xLabeledSeq->getLabel(), uno::UNO_QUERY );
+ if( xIndexReplace.is())
+ xIndexReplace->replaceByIndex(
+ 0, uno::Any( rEdit.GetText()));
+ }
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/DataBrowser.hxx b/chart2/source/controller/dialogs/DataBrowser.hxx
new file mode 100644
index 0000000000..c1d6a72e6c
--- /dev/null
+++ b/chart2/source/controller/dialogs/DataBrowser.hxx
@@ -0,0 +1,187 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svtools/editbrowsebox.hxx>
+#include <vcl/weld.hxx>
+
+#include <memory>
+#include <vector>
+
+namespace com::sun::star {
+ namespace awt {
+ class XWindow;
+ }
+ namespace chart2 {
+ class XChartDocument;
+ }
+}
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+class OutputDevice;
+
+namespace chart
+{
+
+class DataBrowserModel;
+class NumberFormatterWrapper;
+class ChartModel;
+
+namespace impl
+{
+class SeriesHeader;
+class SeriesHeaderEdit;
+}
+
+class DataBrowser : public ::svt::EditBrowseBox
+{
+protected:
+ // EditBrowseBox overridables
+ virtual void PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId ) const override;
+ virtual bool SeekRow( sal_Int32 nRow ) override;
+ virtual bool IsTabAllowed( bool bForward ) const override;
+ virtual ::svt::CellController* GetController( sal_Int32 nRow, sal_uInt16 nCol ) override;
+ virtual void InitController( ::svt::CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol ) override;
+ virtual bool SaveModified() override;
+ virtual void CursorMoved() override;
+ // called whenever the control of the current cell has been modified
+ virtual void CellModified() override;
+ virtual void ColumnResized( sal_uInt16 nColId ) override;
+ virtual void EndScroll() override;
+ virtual void MouseButtonDown( const BrowserMouseEvent& rEvt ) override;
+
+public:
+ DataBrowser(const css::uno::Reference<css::awt::XWindow> &rParent,
+ weld::Container* pColumns, weld::Container* pColors);
+
+ virtual ~DataBrowser() override;
+ virtual void dispose() override;
+
+ /** GetCellText returns the text at the given position
+ @param nRow
+ the number of the row
+ @param nColId
+ the ID of the column
+ @return
+ the text out of the cell
+ */
+ virtual OUString GetCellText(sal_Int32 nRow, sal_uInt16 nColId) const override;
+
+ /** returns the number in the given cell. If a cell is empty or contains a
+ string, the result will be Nan
+ */
+ double GetCellNumber( sal_Int32 nRow, sal_uInt16 nColumnId ) const;
+
+ bool isDateTimeString( const OUString& aInputString, double& fOutDateTimeValue );
+
+ // Window
+ virtual void Resize() override;
+
+ void SetReadOnly( bool bNewState );
+ bool IsReadOnly() const { return m_bIsReadOnly;}
+
+ void SetDataFromModel( const rtl::Reference<::chart::ChartModel> & xChartDoc );
+
+ // predicates to determine what actions are possible at the current cursor
+ // position. This depends on the implementation of the according mutators
+ // below. (They are used for enabling toolbar icons)
+ bool MayInsertRow() const;
+ bool MayInsertColumn() const;
+ bool MayDeleteRow() const;
+ bool MayDeleteColumn() const;
+
+ bool MayMoveUpRows() const;
+ bool MayMoveDownRows() const;
+ bool MayMoveRightColumns() const;
+ bool MayMoveLeftColumns() const;
+
+ // mutators mutating data
+ void InsertRow();
+ void InsertColumn();
+ void InsertTextColumn();
+ void RemoveRow();
+ void RemoveColumn();
+
+ using BrowseBox::RemoveColumn;
+ using BrowseBox::MouseButtonDown;
+
+ void MoveUpRow();
+ void MoveDownRow();
+ void MoveLeftColumn();
+ void MoveRightColumn();
+
+ void SetCursorMovedHdl( const Link<DataBrowser*,void>& rLink );
+
+ /// confirms all pending changes to be ready to be closed
+ bool EndEditing();
+
+ bool CellContainsNumbers( sal_uInt16 nCol ) const;
+
+ sal_uInt32 GetNumberFormatKey( sal_uInt16 nCol ) const;
+
+ bool IsEnableItem() const { return m_bDataValid;}
+ bool IsDataValid() const;
+ void ShowWarningBox();
+ bool ShowQueryBox();
+
+ void RenewSeriesHeaders();
+
+private:
+ rtl::Reference<::chart::ChartModel> m_xChartDoc;
+ std::unique_ptr< DataBrowserModel > m_apDataBrowserModel;
+
+ typedef std::vector< std::shared_ptr< impl::SeriesHeader > > tSeriesHeaderContainer;
+ tSeriesHeaderContainer m_aSeriesHeaders;
+
+ std::shared_ptr< NumberFormatterWrapper > m_spNumberFormatterWrapper;
+
+ /// the row that is currently painted
+ sal_Int32 m_nSeekRow;
+ bool m_bIsReadOnly;
+ bool m_bDataValid;
+
+ VclPtr<svt::FormattedControl> m_aNumberEditField;
+ VclPtr<svt::EditControl> m_aTextEditField;
+ weld::Container* m_pColumnsWin;
+ weld::Container* m_pColorsWin;
+
+ /// note: m_aNumberEditField must precede this member!
+ ::svt::CellControllerRef m_rNumberEditController;
+ /// note: m_aTextEditField must precede this member!
+ ::svt::CellControllerRef m_rTextEditController;
+
+ Link<DataBrowser*,void> m_aCursorMovedHdlLink;
+
+ void clearHeaders();
+ void RenewTable();
+ void ImplAdjustHeaderControls();
+
+ OUString GetColString( sal_Int32 nColumnId ) const;
+
+ DECL_LINK( SeriesHeaderGotFocus, impl::SeriesHeaderEdit&, void );
+ DECL_LINK( SeriesHeaderChanged, impl::SeriesHeaderEdit&, void );
+
+ DataBrowser( const DataBrowser & ) = delete;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/DataBrowserModel.cxx b/chart2/source/controller/dialogs/DataBrowserModel.cxx
new file mode 100644
index 0000000000..63ec6f31fc
--- /dev/null
+++ b/chart2/source/controller/dialogs/DataBrowserModel.cxx
@@ -0,0 +1,935 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DataBrowserModel.hxx"
+#include "DialogModel.hxx"
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeManager.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <StatisticsHelper.hxx>
+#include <ChartTypeHelper.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <ChartModel.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
+#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+#include <o3tl/safeint.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/property.hxx>
+
+#include <algorithm>
+#include <cstddef>
+#include <limits>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart {
+
+namespace {
+
+OUString lcl_getRole(
+ const Reference< chart2::data::XDataSequence > & xSeq )
+{
+ OUString aResult;
+ Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ try
+ {
+ xProp->getPropertyValue( "Role" ) >>= aResult;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ return aResult;
+}
+
+OUString lcl_getUIRoleName(
+ const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
+{
+ OUString aResult = DataSeriesHelper::getRole(xLSeq);
+ if( !aResult.isEmpty())
+ aResult = DialogModel::ConvertRoleFromInternalToUI(aResult);
+ return aResult;
+}
+
+void lcl_copyDataSequenceProperties(
+ const Reference< chart2::data::XDataSequence > & xOldSequence,
+ const Reference< chart2::data::XDataSequence > & xNewSequence )
+{
+ Reference< beans::XPropertySet > xOldSeqProp( xOldSequence, uno::UNO_QUERY );
+ Reference< beans::XPropertySet > xNewSeqProp( xNewSequence, uno::UNO_QUERY );
+ comphelper::copyProperties( xOldSeqProp, xNewSeqProp );
+}
+
+bool lcl_SequenceOfSeriesIsShared(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ const Reference< chart2::data::XDataSequence > & xValues )
+{
+ bool bResult = false;
+ if( !xValues.is())
+ return bResult;
+ try
+ {
+ OUString aValuesRole( lcl_getRole( xValues ));
+ OUString aValuesRep( xValues->getSourceRangeRepresentation());
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aLSeq( xSeries->getDataSequences2());
+ for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : aLSeq )
+ if (labeledDataSeq.is() && DataSeriesHelper::getRole(labeledDataSeq) == aValuesRole)
+ {
+ // getValues().is(), because lcl_getRole checked that already
+ bResult = (aValuesRep == labeledDataSeq->getValues()->getSourceRangeRepresentation());
+ // assumption: a role appears only once in a series
+ break;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return bResult;
+}
+
+typedef std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > lcl_tSharedSeqVec;
+
+lcl_tSharedSeqVec lcl_getSharedSequences( const std::vector< rtl::Reference< DataSeries > > & rSeries )
+{
+ // @todo: if only some series share a sequence, those have to be duplicated
+ // and made unshared for all series
+ lcl_tSharedSeqVec aResult;
+ // if we have only one series, we don't want any shared sequences
+ if( rSeries.size() <= 1 )
+ return aResult;
+
+ for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : rSeries[0]->getDataSequences2() )
+ {
+ Reference< chart2::data::XDataSequence > xValues( labeledDataSeq->getValues());
+ bool bShared = true;
+ for( std::size_t nSeriesIdx=1; nSeriesIdx<rSeries.size(); ++nSeriesIdx )
+ {
+ bShared = lcl_SequenceOfSeriesIsShared( rSeries[nSeriesIdx], xValues );
+ if( !bShared )
+ break;
+ }
+ if( bShared )
+ aResult.push_back( labeledDataSeq );
+ }
+
+ return aResult;
+}
+
+sal_Int32 lcl_getValuesRepresentationIndex(
+ const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
+{
+ sal_Int32 nResult = -1;
+ if( xLSeq.is())
+ {
+ Reference< chart2::data::XDataSequence > xSeq( xLSeq->getValues());
+ if( xSeq.is())
+ {
+ OUString aRep( xSeq->getSourceRangeRepresentation());
+ nResult = aRep.toInt32();
+ }
+ }
+ return nResult;
+}
+
+struct lcl_RepresentationsOfLSeqMatch
+{
+ explicit lcl_RepresentationsOfLSeqMatch( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) :
+ m_aValuesRep( xLSeq.is() ?
+ (xLSeq->getValues().is() ? xLSeq->getValues()->getSourceRangeRepresentation() : OUString())
+ : OUString() )
+ {}
+ bool operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq )
+ {
+ if (!xLSeq.is() || !xLSeq->getValues().is())
+ return false;
+
+ return xLSeq->getValues()->getSourceRangeRepresentation() == m_aValuesRep;
+ }
+private:
+ OUString m_aValuesRep;
+};
+
+struct lcl_RolesOfLSeqMatch
+{
+ explicit lcl_RolesOfLSeqMatch( const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq ) :
+ m_aRole(DataSeriesHelper::getRole(xLSeq)) {}
+
+ bool operator() ( const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq )
+ {
+ return DataSeriesHelper::getRole(xLSeq) == m_aRole;
+ }
+private:
+ OUString m_aRole;
+};
+
+bool lcl_ShowCategoriesAsDataLabel( const rtl::Reference< ::chart::Diagram > & xDiagram )
+{
+ return !xDiagram->isCategory();
+}
+
+} // anonymous namespace
+
+struct DataBrowserModel::tDataColumn
+{
+ rtl::Reference<DataSeries> m_xDataSeries;
+ OUString m_aUIRoleName;
+ uno::Reference<chart2::data::XLabeledDataSequence> m_xLabeledDataSequence;
+ eCellType m_eCellType;
+ sal_Int32 m_nNumberFormatKey;
+
+ // default CTOR
+ tDataColumn() : m_eCellType( TEXT ), m_nNumberFormatKey( 0 ) {}
+ // "full" CTOR
+ tDataColumn(
+ rtl::Reference<DataSeries> xDataSeries,
+ OUString aUIRoleName,
+ uno::Reference<chart2::data::XLabeledDataSequence> xLabeledDataSequence,
+ eCellType aCellType,
+ sal_Int32 nNumberFormatKey ) :
+ m_xDataSeries(std::move( xDataSeries )),
+ m_aUIRoleName(std::move( aUIRoleName )),
+ m_xLabeledDataSequence(std::move( xLabeledDataSequence )),
+ m_eCellType( aCellType ),
+ m_nNumberFormatKey( nNumberFormatKey )
+ {}
+};
+
+struct DataBrowserModel::implColumnLess
+{
+ bool operator() ( const DataBrowserModel::tDataColumn & rLeft, const DataBrowserModel::tDataColumn & rRight )
+ {
+ if( rLeft.m_xLabeledDataSequence.is() && rRight.m_xLabeledDataSequence.is())
+ {
+ return DialogModel::GetRoleIndexForSorting(DataSeriesHelper::getRole(rLeft.m_xLabeledDataSequence)) <
+ DialogModel::GetRoleIndexForSorting(DataSeriesHelper::getRole(rRight.m_xLabeledDataSequence));
+ }
+ return true;
+ }
+};
+
+DataBrowserModel::DataBrowserModel(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc ) :
+ m_xChartDocument( xChartDoc ),
+ m_apDialogModel( new DialogModel( xChartDoc ))
+{
+ updateFromModel();
+}
+
+DataBrowserModel::~DataBrowserModel()
+{}
+
+namespace
+{
+struct lcl_DataSeriesOfHeaderMatches
+{
+ explicit lcl_DataSeriesOfHeaderMatches(
+ rtl::Reference< ::chart::DataSeries > xSeriesToCompareWith ) :
+ m_xSeries(std::move( xSeriesToCompareWith ))
+ {}
+ bool operator() ( const ::chart::DataBrowserModel::tDataHeader & rHeader )
+ {
+ return (m_xSeries == rHeader.m_xDataSeries);
+ }
+private:
+ rtl::Reference< ::chart::DataSeries > m_xSeries;
+};
+}
+
+void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex )
+{
+ OSL_ASSERT(m_apDialogModel);
+ Reference< chart2::XInternalDataProvider > xDataProvider(
+ m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
+
+ if (!xDataProvider.is())
+ return;
+
+ if( isCategoriesColumn(nAfterColumnIndex) )
+ // Move to the last category column.
+ nAfterColumnIndex = getCategoryColumnCount()-1;
+
+ sal_Int32 nStartCol = 0;
+ rtl::Reference< Diagram > xDiagram = m_xChartDocument->getFirstChartDiagram();
+ rtl::Reference<ChartType> xChartType;
+ rtl::Reference<DataSeries> xSeries;
+ if (o3tl::make_unsigned(nAfterColumnIndex) < m_aColumns.size())
+ // Get the data series at specific column position (if available).
+ xSeries = m_aColumns[nAfterColumnIndex].m_xDataSeries;
+
+ sal_Int32 nSeriesNumberFormat = 0;
+ if( xSeries.is())
+ {
+ // Use the chart type of the currently selected data series.
+ xChartType = xDiagram->getChartTypeOfSeries( xSeries );
+
+ // Find the corresponding header and determine the last column of this
+ // data series.
+ tDataHeaderVector::const_iterator aIt(
+ std::find_if( m_aHeaders.begin(), m_aHeaders.end(),
+ lcl_DataSeriesOfHeaderMatches( xSeries )));
+ if( aIt != m_aHeaders.end())
+ nStartCol = aIt->m_nEndColumn;
+
+ // Get the number format too.
+ if( xSeries.is() )
+ xSeries->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nSeriesNumberFormat;
+ }
+ else
+ {
+ // No data series at specified column position. Use the first chart type.
+ xChartType = xDiagram->getChartTypeByIndex( 0 );
+ nStartCol = nAfterColumnIndex;
+ }
+
+ if (!xChartType.is())
+ return;
+
+ // Get shared sequences of current series. Normally multiple data series
+ // only share "values-x" sequences. (TODO: simplify this logic).
+ lcl_tSharedSeqVec aSharedSequences = lcl_getSharedSequences( xChartType->getDataSeries2());
+
+ rtl::Reference<::chart::DataSeries> xNewSeries =
+ m_apDialogModel->insertSeriesAfter(xSeries, xChartType, true);
+
+ if (!xNewSeries.is())
+ // Failed to insert new data series to the model. Bail out.
+ return;
+
+ const std::vector<uno::Reference<chart2::data::XLabeledDataSequence> > & aLSequences = xNewSeries->getDataSequences2();
+ sal_Int32 nSeqIdx = 0;
+ sal_Int32 nSeqSize = aLSequences.size();
+ for (sal_Int32 nIndex = nStartCol; nSeqIdx < nSeqSize; ++nSeqIdx)
+ {
+ lcl_tSharedSeqVec::const_iterator aSharedIt(
+ std::find_if( aSharedSequences.begin(), aSharedSequences.end(),
+ lcl_RolesOfLSeqMatch( aLSequences[nSeqIdx] )));
+
+ if( aSharedIt != aSharedSequences.end())
+ {
+ // Shared sequence. Most likely "values-x" sequence. Copy it from existing sequence.
+ aLSequences[nSeqIdx]->setValues( (*aSharedIt)->getValues());
+ aLSequences[nSeqIdx]->setLabel( (*aSharedIt)->getLabel());
+ }
+ else
+ {
+ // Insert a new column in the internal data for the new sequence.
+ xDataProvider->insertSequence( nIndex - 1 );
+
+ // values
+ Reference< chart2::data::XDataSequence > xNewSeq(
+ xDataProvider->createDataSequenceByRangeRepresentation(
+ OUString::number( nIndex )));
+ lcl_copyDataSequenceProperties(
+ aLSequences[nSeqIdx]->getValues(), xNewSeq );
+ aLSequences[nSeqIdx]->setValues( xNewSeq );
+
+ // labels
+ Reference< chart2::data::XDataSequence > xNewLabelSeq(
+ xDataProvider->createDataSequenceByRangeRepresentation(
+ "label " +
+ OUString::number( nIndex )));
+ lcl_copyDataSequenceProperties(
+ aLSequences[nSeqIdx]->getLabel(), xNewLabelSeq );
+ aLSequences[nSeqIdx]->setLabel( xNewLabelSeq );
+ ++nIndex;
+ }
+ }
+
+ if( nSeriesNumberFormat != 0 )
+ {
+ //give the new series the same number format as the former series especially for bubble charts thus the bubble size values can be edited with same format immediately
+ xNewSeries->setPropertyValue(CHART_UNONAME_NUMFMT , uno::Any(nSeriesNumberFormat));
+ }
+
+ updateFromModel();
+}
+
+void DataBrowserModel::insertComplexCategoryLevel( sal_Int32 nAfterColumnIndex )
+{
+ //create a new text column for complex categories
+
+ OSL_ASSERT(m_apDialogModel);
+ Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
+ if (!xDataProvider.is())
+ return;
+
+ if( !isCategoriesColumn(nAfterColumnIndex) )
+ nAfterColumnIndex = getCategoryColumnCount()-1;
+
+ if(nAfterColumnIndex<0)
+ {
+ OSL_FAIL( "wrong index for category level insertion" );
+ return;
+ }
+
+ m_apDialogModel->startControllerLockTimer();
+ ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
+ xDataProvider->insertComplexCategoryLevel( nAfterColumnIndex+1 );
+ updateFromModel();
+}
+
+void DataBrowserModel::removeComplexCategoryLevel( sal_Int32 nAtColumnIndex )
+{
+ //delete a category column if there is more than one level (in case of a single column we do not get here)
+ OSL_ENSURE(nAtColumnIndex>0, "wrong index for categories deletion" );
+
+ Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
+ if (!xDataProvider.is())
+ return;
+
+ m_apDialogModel->startControllerLockTimer();
+ ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
+ xDataProvider->deleteComplexCategoryLevel( nAtColumnIndex );
+
+ updateFromModel();
+}
+
+void DataBrowserModel::removeDataSeriesOrComplexCategoryLevel( sal_Int32 nAtColumnIndex )
+{
+ OSL_ASSERT(m_apDialogModel);
+ if (nAtColumnIndex < 0 || o3tl::make_unsigned(nAtColumnIndex) >= m_aColumns.size())
+ // Out of bound.
+ return;
+
+ if (isCategoriesColumn(nAtColumnIndex))
+ {
+ removeComplexCategoryLevel(nAtColumnIndex);
+ return;
+ }
+
+ const rtl::Reference<DataSeries>& xSeries = m_aColumns[nAtColumnIndex].m_xDataSeries;
+
+ m_apDialogModel->deleteSeries(xSeries, getHeaderForSeries(xSeries).m_xChartType);
+
+ //delete sequences from internal data provider that are not used anymore
+ //but do not delete sequences that are still in use by the remaining series
+
+ Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
+ if (!xDataProvider.is() || !xSeries.is())
+ {
+ // Something went wrong. Bail out.
+ updateFromModel();
+ return;
+ }
+
+ rtl::Reference<ChartType> xSeriesCnt(getHeaderForSeries(xSeries).m_xChartType);
+ if (!xSeriesCnt.is())
+ {
+ // Unexpected happened. Bail out.
+ updateFromModel();
+ return;
+ }
+
+ // Collect all the remaining data sequences in the same chart type. The
+ // deleted data series is already gone by this point.
+ std::vector<uno::Reference<chart2::data::XLabeledDataSequence> > aAllDataSeqs =
+ DataSeriesHelper::getAllDataSequences(xSeriesCnt->getDataSeries2());
+
+ // Check if the sequences to be deleted are still referenced by any of
+ // the other data series. If not, mark them for deletion.
+ std::vector<sal_Int32> aSequenceIndexesToDelete;
+ const std::vector<uno::Reference<chart2::data::XLabeledDataSequence> > & aSequencesOfDeleted = xSeries->getDataSequences2();
+ for (auto const & labeledDataSeq : aSequencesOfDeleted)
+ {
+ // if not used by the remaining series this sequence can be deleted
+ if( std::none_of( aAllDataSeqs.begin(), aAllDataSeqs.end(),
+ lcl_RepresentationsOfLSeqMatch( labeledDataSeq )) )
+ aSequenceIndexesToDelete.push_back( lcl_getValuesRepresentationIndex( labeledDataSeq ) );
+ }
+
+ // delete unnecessary sequences of the internal data
+ // iterate using greatest index first, so that deletion does not
+ // shift other sequences that will be deleted later
+ std::sort( aSequenceIndexesToDelete.begin(), aSequenceIndexesToDelete.end());
+ for( std::vector< sal_Int32 >::reverse_iterator aIt(
+ aSequenceIndexesToDelete.rbegin()); aIt != aSequenceIndexesToDelete.rend(); ++aIt )
+ {
+ if( *aIt != -1 )
+ xDataProvider->deleteSequence( *aIt );
+ }
+
+ updateFromModel();
+}
+
+void DataBrowserModel::swapDataSeries( sal_Int32 nFirstColumnIndex )
+{
+ OSL_ASSERT(m_apDialogModel);
+ if( o3tl::make_unsigned( nFirstColumnIndex ) < m_aColumns.size() - 1 )
+ {
+ rtl::Reference< DataSeries > xSeries( m_aColumns[nFirstColumnIndex].m_xDataSeries );
+ if( xSeries.is())
+ {
+ m_apDialogModel->moveSeries( xSeries, DialogModel::MoveDirection::Down );
+ updateFromModel();
+ }
+ }
+}
+
+void DataBrowserModel::swapDataPointForAllSeries( sal_Int32 nFirstIndex )
+{
+ OSL_ASSERT(m_apDialogModel);
+ Reference< chart2::XInternalDataProvider > xDataProvider(
+ m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
+ // lockControllers
+ ControllerLockGuardUNO aGuard( m_apDialogModel->getChartModel());
+ if( xDataProvider.is())
+ xDataProvider->swapDataPointWithNextOneForAllSequences( nFirstIndex );
+ // unlockControllers
+}
+
+void DataBrowserModel::insertDataPointForAllSeries( sal_Int32 nAfterIndex )
+{
+ Reference< chart2::XInternalDataProvider > xDataProvider(
+ m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
+ // lockControllers
+ ControllerLockGuardUNO aGuard( m_apDialogModel->getChartModel());
+ if( xDataProvider.is())
+ xDataProvider->insertDataPointForAllSequences( nAfterIndex );
+ // unlockControllers
+}
+
+void DataBrowserModel::removeDataPointForAllSeries( sal_Int32 nAtIndex )
+{
+ Reference< chart2::XInternalDataProvider > xDataProvider(
+ m_apDialogModel->getDataProvider(), uno::UNO_QUERY );
+ // lockControllers
+ ControllerLockGuardUNO aGuard( m_apDialogModel->getChartModel());
+ if( xDataProvider.is())
+ xDataProvider->deleteDataPointForAllSequences( nAtIndex );
+ // unlockControllers
+}
+
+DataBrowserModel::tDataHeader DataBrowserModel::getHeaderForSeries(
+ const Reference< chart2::XDataSeries > & xSeries ) const
+{
+ rtl::Reference<DataSeries> pSeries = dynamic_cast<DataSeries*>(xSeries.get());
+ assert(!xSeries || pSeries);
+ for (auto const& elemHeader : m_aHeaders)
+ {
+ if( elemHeader.m_xDataSeries == pSeries )
+ return elemHeader;
+ }
+ return tDataHeader();
+}
+
+rtl::Reference< DataSeries >
+ DataBrowserModel::getDataSeriesByColumn( sal_Int32 nColumn ) const
+{
+ tDataColumnVector::size_type nIndex( nColumn );
+ if( nIndex < m_aColumns.size())
+ return m_aColumns[nIndex].m_xDataSeries;
+ return nullptr;
+}
+
+DataBrowserModel::eCellType DataBrowserModel::getCellType( sal_Int32 nAtColumn ) const
+{
+ eCellType eResult = TEXT;
+ tDataColumnVector::size_type nIndex( nAtColumn );
+ if( nIndex < m_aColumns.size())
+ eResult = m_aColumns[nIndex].m_eCellType;
+ return eResult;
+}
+
+double DataBrowserModel::getCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow )
+{
+ tDataColumnVector::size_type nIndex( nAtColumn );
+ if( nIndex < m_aColumns.size() &&
+ m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
+ {
+ Reference< chart2::data::XNumericalDataSequence > xData(
+ m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY );
+ if( xData.is())
+ {
+ Sequence< double > aValues( xData->getNumericalData());
+ if( nAtRow < aValues.getLength())
+ return aValues[nAtRow];
+ }
+ }
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+uno::Any DataBrowserModel::getCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow )
+{
+ uno::Any aResult;
+
+ tDataColumnVector::size_type nIndex( nAtColumn );
+ if( nIndex < m_aColumns.size() &&
+ m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
+ {
+ Reference< chart2::data::XDataSequence > xData(
+ m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues() );
+ if( xData.is() )
+ {
+ Sequence< uno::Any > aValues( xData->getData());
+ if( nAtRow < aValues.getLength())
+ aResult = aValues[nAtRow];
+ }
+ }
+ return aResult;
+}
+
+OUString DataBrowserModel::getCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow )
+{
+ OUString aResult;
+
+ tDataColumnVector::size_type nIndex( nAtColumn );
+ if( nIndex < m_aColumns.size() &&
+ m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
+ {
+ Reference< chart2::data::XTextualDataSequence > xData(
+ m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY );
+ if( xData.is())
+ {
+ Sequence< OUString > aValues( xData->getTextualData());
+ if( nAtRow < aValues.getLength())
+ aResult = aValues[nAtRow];
+ }
+ }
+ return aResult;
+}
+
+sal_uInt32 DataBrowserModel::getNumberFormatKey( sal_Int32 nAtColumn )
+{
+ tDataColumnVector::size_type nIndex( nAtColumn );
+ if( nIndex < m_aColumns.size())
+ return m_aColumns[ nIndex ].m_nNumberFormatKey;
+ return 0;
+}
+
+bool DataBrowserModel::setCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow, const uno::Any & rValue )
+{
+ bool bResult = false;
+ tDataColumnVector::size_type nIndex( nAtColumn );
+ if( nIndex < m_aColumns.size() &&
+ m_aColumns[ nIndex ].m_xLabeledDataSequence.is())
+ {
+ bResult = true;
+ try
+ {
+ ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
+
+ // label
+ if( nAtRow == -1 )
+ {
+ Reference< container::XIndexReplace > xIndexReplace(
+ m_aColumns[ nIndex ].m_xLabeledDataSequence->getLabel(), uno::UNO_QUERY_THROW );
+ xIndexReplace->replaceByIndex( 0, rValue );
+ }
+ else
+ {
+ Reference< container::XIndexReplace > xIndexReplace(
+ m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY_THROW );
+ xIndexReplace->replaceByIndex( nAtRow, rValue );
+ }
+
+ m_apDialogModel->startControllerLockTimer();
+ //notify change directly to the model (this is necessary here as sequences for complex categories not known directly to the chart model so they do not notify their changes) (for complex categories see issue #i82971#)
+ if( m_xChartDocument.is() )
+ m_xChartDocument->setModified(true);
+ }
+ catch( const uno::Exception & )
+ {
+ bResult = false;
+ }
+ }
+ return bResult;
+}
+
+bool DataBrowserModel::setCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow, double fValue )
+{
+ return (getCellType( nAtColumn ) == NUMBER) &&
+ setCellAny( nAtColumn, nAtRow, uno::Any( fValue ));
+}
+
+bool DataBrowserModel::setCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow, const OUString & rText )
+{
+ return (getCellType( nAtColumn ) == TEXT) &&
+ setCellAny( nAtColumn, nAtRow, uno::Any( rText ));
+}
+
+sal_Int32 DataBrowserModel::getColumnCount() const
+{
+ return static_cast< sal_Int32 >( m_aColumns.size());
+}
+
+sal_Int32 DataBrowserModel::getMaxRowCount() const
+{
+ sal_Int32 nResult = 0;
+ for (auto const& column : m_aColumns)
+ {
+ if( column.m_xLabeledDataSequence.is())
+ {
+ Reference< chart2::data::XDataSequence > xSeq(
+ column.m_xLabeledDataSequence->getValues());
+ if( !xSeq.is())
+ continue;
+ sal_Int32 nLength( xSeq->getData().getLength());
+ if( nLength > nResult )
+ nResult = nLength;
+ }
+ }
+
+ return nResult;
+}
+
+OUString DataBrowserModel::getRoleOfColumn( sal_Int32 nColumnIndex ) const
+{
+ if( nColumnIndex != -1 &&
+ o3tl::make_unsigned( nColumnIndex ) < m_aColumns.size())
+ return m_aColumns[ nColumnIndex ].m_aUIRoleName;
+ return OUString();
+}
+
+bool DataBrowserModel::isCategoriesColumn( sal_Int32 nColumnIndex ) const
+{
+ if (nColumnIndex < 0)
+ return false;
+
+ if (o3tl::make_unsigned(nColumnIndex) >= m_aColumns.size())
+ return false;
+
+ // A column is a category when it doesn't have an associated data series.
+ return !m_aColumns[nColumnIndex].m_xDataSeries.is();
+}
+
+sal_Int32 DataBrowserModel::getCategoryColumnCount()
+{
+ sal_Int32 nLastTextColumnIndex = -1;
+ for (auto const& column : m_aColumns)
+ {
+ if( !column.m_xDataSeries.is() )
+ nLastTextColumnIndex++;
+ else
+ break;
+ }
+ return nLastTextColumnIndex+1;
+}
+
+void DataBrowserModel::updateFromModel()
+{
+ if( !m_xChartDocument.is())
+ return;
+ m_aColumns.clear();
+ m_aHeaders.clear();
+
+ rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram());
+ if( !xDiagram.is())
+ return;
+
+ // set template at DialogModel
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = m_xChartDocument->getTypeManager();
+ Diagram::tTemplateWithServiceName aTemplateAndService =
+ xDiagram->getTemplate( xChartTypeManager );
+ if( aTemplateAndService.xChartTypeTemplate.is())
+ m_apDialogModel->setTemplate( aTemplateAndService.xChartTypeTemplate );
+
+ sal_Int32 nHeaderStart = 0;
+ sal_Int32 nHeaderEnd = 0;
+ {
+ ExplicitCategoriesProvider aExplicitCategoriesProvider( ChartModelHelper::getFirstCoordinateSystem(m_xChartDocument), *m_xChartDocument );
+
+ const std::vector< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList = aExplicitCategoriesProvider.getSplitCategoriesList();
+ sal_Int32 nLevelCount = rSplitCategoriesList.size();
+ for( sal_Int32 nL = 0; nL<nLevelCount; nL++ )
+ {
+ Reference< chart2::data::XLabeledDataSequence > xCategories( rSplitCategoriesList[nL] );
+ if( !xCategories.is() )
+ continue;
+
+ tDataColumn aCategories;
+ aCategories.m_xLabeledDataSequence = xCategories;
+ if( lcl_ShowCategoriesAsDataLabel( xDiagram ))
+ aCategories.m_aUIRoleName = DialogModel::GetRoleDataLabel();
+ else
+ aCategories.m_aUIRoleName = lcl_getUIRoleName( xCategories );
+ aCategories.m_eCellType = TEXTORDATE;
+ m_aColumns.push_back( aCategories );
+ ++nHeaderStart;
+ }
+ }
+
+ if( !xDiagram.is())
+ return;
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > aCooSysSeq( xDiagram->getBaseCoordinateSystems());
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : aCooSysSeq )
+ {
+ const std::vector< rtl::Reference< ChartType > > aChartTypes( coords->getChartTypes2());
+ sal_Int32 nXAxisNumberFormat = DataSeriesHelper::getNumberFormatKeyFromAxis( nullptr, coords, 0, 0 );
+
+ for( auto const & CT: aChartTypes )
+ {
+ rtl::Reference< ChartType > xSeriesCnt( CT );
+ OUString aRoleForDataLabelNumberFormat = ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( CT );
+
+ const std::vector< rtl::Reference< DataSeries > > & aSeries( xSeriesCnt->getDataSeries2());
+ lcl_tSharedSeqVec aSharedSequences( lcl_getSharedSequences( aSeries ));
+ for (auto const& sharedSequence : aSharedSequences)
+ {
+ tDataColumn aSharedSequence;
+ aSharedSequence.m_xLabeledDataSequence = sharedSequence;
+ aSharedSequence.m_aUIRoleName = lcl_getUIRoleName(sharedSequence);
+ aSharedSequence.m_eCellType = NUMBER;
+ // as the sequences are shared it should be ok to take the first series
+ // @todo: dimension index 0 for x-values used here. This is just a guess.
+ // Also, the axis index is 0, as there is usually only one x-axis
+ aSharedSequence.m_nNumberFormatKey = nXAxisNumberFormat;
+ m_aColumns.push_back( aSharedSequence );
+ ++nHeaderStart;
+ }
+ for( rtl::Reference< DataSeries > const & dataSeries : aSeries )
+ {
+ tDataColumnVector::size_type nStartColIndex = m_aColumns.size();
+ rtl::Reference< DataSeries > xSeries( dataSeries );
+ if( xSeries.is())
+ {
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aLSeqs( xSeries->getDataSequences2());
+ if( aLSeqs.empty() )
+ continue;
+ nHeaderEnd = nHeaderStart;
+
+ // @todo: dimension index 1 for y-values used here. This is just a guess
+ sal_Int32 nYAxisNumberFormatKey =
+ DataSeriesHelper::getNumberFormatKeyFromAxis(
+ dataSeries, coords, 1 );
+
+ sal_Int32 nSeqIdx=0;
+ for( ; nSeqIdx<static_cast<sal_Int32>(aLSeqs.size()); ++nSeqIdx )
+ {
+ sal_Int32 nSequenceNumberFormatKey = nYAxisNumberFormatKey;
+ OUString aRole = DataSeriesHelper::getRole(aLSeqs[nSeqIdx]);
+
+ if( aRole == aRoleForDataLabelNumberFormat )
+ {
+ nSequenceNumberFormatKey = ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
+ xSeries);
+ }
+ else if( aRole == "values-x" )
+ nSequenceNumberFormatKey = nXAxisNumberFormat;
+
+ if( std::none_of( aSharedSequences.begin(), aSharedSequences.end(),
+ lcl_RepresentationsOfLSeqMatch( aLSeqs[nSeqIdx] )) )
+ {
+ // no shared sequence
+ m_aColumns.emplace_back(
+ dataSeries,
+ lcl_getUIRoleName( aLSeqs[nSeqIdx] ),
+ aLSeqs[nSeqIdx],
+ NUMBER,
+ nSequenceNumberFormatKey );
+ ++nHeaderEnd;
+ }
+ // else skip
+ }
+ bool bSwapXAndYAxis = false;
+ try
+ {
+ coords->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndYAxis;
+ }
+ catch( const beans::UnknownPropertyException & ) {}
+
+ // add ranges for error bars if present for a series
+ if( StatisticsHelper::usesErrorBarRanges( dataSeries ))
+ addErrorBarRanges( dataSeries, nYAxisNumberFormatKey, nSeqIdx, nHeaderEnd, true );
+
+ if( StatisticsHelper::usesErrorBarRanges( dataSeries, /* bYError = */ false ))
+ addErrorBarRanges( dataSeries, nYAxisNumberFormatKey, nSeqIdx, nHeaderEnd, false );
+
+ m_aHeaders.emplace_back(
+ dataSeries,
+ CT,
+ bSwapXAndYAxis,
+ nHeaderStart,
+ nHeaderEnd - 1 );
+
+ nHeaderStart = nHeaderEnd;
+
+ std::sort( m_aColumns.begin() + nStartColIndex, m_aColumns.end(), implColumnLess() );
+ }
+ }
+ }
+ }
+}
+
+void DataBrowserModel::addErrorBarRanges(
+ const rtl::Reference< DataSeries > & xDataSeries,
+ sal_Int32 nNumberFormatKey,
+ sal_Int32 & rInOutSequenceIndex,
+ sal_Int32 & rInOutHeaderEnd, bool bYError )
+{
+ try
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences;
+
+ Reference< chart2::data::XDataSource > xErrorSource(
+ StatisticsHelper::getErrorBars( xDataSeries, bYError ), uno::UNO_QUERY );
+
+ uno::Reference< chart2::data::XLabeledDataSequence > xErrorLSequence =
+ StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
+ xErrorSource,
+ /* bPositiveValue = */ true,
+ bYError );
+ if( xErrorLSequence.is())
+ aSequences.push_back( xErrorLSequence );
+
+ xErrorLSequence =
+ StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
+ xErrorSource,
+ /* bPositiveValue = */ false,
+ bYError );
+ if( xErrorLSequence.is())
+ aSequences.push_back( xErrorLSequence );
+
+ for (uno::Reference<chart2::data::XLabeledDataSequence> const & rDataSequence : aSequences)
+ {
+ m_aColumns.emplace_back(xDataSeries, lcl_getUIRoleName(rDataSequence),
+ rDataSequence, NUMBER, nNumberFormatKey);
+ ++rInOutSequenceIndex;
+ ++rInOutHeaderEnd;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/DataBrowserModel.hxx b/chart2/source/controller/dialogs/DataBrowserModel.hxx
new file mode 100644
index 0000000000..e3254851d0
--- /dev/null
+++ b/chart2/source/controller/dialogs/DataBrowserModel.hxx
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <DataSeries.hxx>
+#include <ChartType.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <rtl/ref.hxx>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace com::sun::star::chart2 {
+ class XDataSeries;
+ class XChartType;
+}
+
+namespace chart
+{
+
+class DialogModel;
+class ChartModel;
+class ChartType;
+class DataSeries;
+
+class DataBrowserModel final
+{
+public:
+ explicit DataBrowserModel(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc );
+ ~DataBrowserModel();
+
+ /** Inserts a new data series after the data series to which the data column
+ with index nAfterColumnIndex belongs.
+ */
+ void insertDataSeries( sal_Int32 nAfterColumnIndex );
+
+ /** Inserts a new text column for complex categories.
+ */
+ void insertComplexCategoryLevel( sal_Int32 nAfterColumnIndex );
+
+ /** Removes a data series to which the data column with index nAtColumnIndex
+ belongs.
+ */
+ void removeDataSeriesOrComplexCategoryLevel( sal_Int32 nAtColumnIndex );
+
+ /** Swaps the series to which the data column with index nFirstIndex belongs
+ with the next series (which starts at an index >= nFirstIndex + 1)
+ */
+ void swapDataSeries( sal_Int32 nFirstIndex );
+ void swapDataPointForAllSeries( sal_Int32 nFirstIndex );
+
+ void insertDataPointForAllSeries( sal_Int32 nAfterIndex );
+ void removeDataPointForAllSeries( sal_Int32 nAtIndex );
+
+ enum eCellType
+ {
+ NUMBER,
+ TEXT,
+ TEXTORDATE
+ };
+
+ eCellType getCellType( sal_Int32 nAtColumn ) const;
+ /// If getCellType( nAtColumn, nAtRow ) returns TEXT, the result will be Nan
+ double getCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow );
+ OUString getCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow );
+ css::uno::Any getCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow );
+ sal_uInt32 getNumberFormatKey( sal_Int32 nAtColumn );
+
+ /// returns </sal_True> if the number could successfully be set at the given position
+ bool setCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow, double fValue );
+ /// returns </sal_True> if the text could successfully be set at the given position
+ bool setCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow, const OUString & rText );
+ bool setCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow, const css::uno::Any & aValue );
+
+ sal_Int32 getColumnCount() const;
+ sal_Int32 getMaxRowCount() const;
+
+ // returns the UI string of the corresponding role
+ OUString getRoleOfColumn( sal_Int32 nColumnIndex ) const;
+ bool isCategoriesColumn( sal_Int32 nColumnIndex ) const;
+
+ struct tDataHeader
+ {
+ rtl::Reference< ::chart::DataSeries > m_xDataSeries;
+ rtl::Reference< ::chart::ChartType > m_xChartType;
+ bool m_bSwapXAndYAxis;
+ sal_Int32 m_nStartColumn;
+ sal_Int32 m_nEndColumn;
+
+ // default CTOR
+ tDataHeader() :
+ m_bSwapXAndYAxis( false ),
+ m_nStartColumn( -1 ),
+ m_nEndColumn( -1 )
+ {}
+ // "full" CTOR
+ tDataHeader(
+ rtl::Reference< ::chart::DataSeries > xDataSeries,
+ rtl::Reference< ::chart::ChartType > xChartType,
+ bool bSwapXAndYAxis,
+ sal_Int32 nStartColumn,
+ sal_Int32 nEndColumn ) :
+ m_xDataSeries(std::move( xDataSeries )),
+ m_xChartType(std::move( xChartType )),
+ m_bSwapXAndYAxis( bSwapXAndYAxis ),
+ m_nStartColumn( nStartColumn ),
+ m_nEndColumn( nEndColumn )
+ {}
+ };
+
+ typedef std::vector< tDataHeader > tDataHeaderVector;
+
+ const tDataHeaderVector& getDataHeaders() const { return m_aHeaders;}
+
+ tDataHeader getHeaderForSeries(
+ const css::uno::Reference< css::chart2::XDataSeries > &xSeries ) const;
+
+ rtl::Reference< ::chart::DataSeries >
+ getDataSeriesByColumn( sal_Int32 nColumn ) const;
+
+private:
+ void updateFromModel();
+
+ void removeComplexCategoryLevel( sal_Int32 nAtColumnIndex );
+
+ void addErrorBarRanges(
+ const rtl::Reference<::chart::DataSeries > & xDataSeries,
+ sal_Int32 nNumberFormatKey,
+ sal_Int32 & rInOutSequenceIndex,
+ sal_Int32 & rInOutHeaderEnd, bool bYError );
+
+ sal_Int32 getCategoryColumnCount();
+
+ rtl::Reference<::chart::ChartModel> m_xChartDocument;
+ std::unique_ptr< DialogModel > m_apDialogModel;
+
+ struct tDataColumn;
+ struct implColumnLess;
+
+ typedef std::vector< tDataColumn > tDataColumnVector;
+
+ tDataColumnVector m_aColumns;
+ tDataHeaderVector m_aHeaders;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/DialogModel.cxx b/chart2/source/controller/dialogs/DialogModel.cxx
new file mode 100644
index 0000000000..edd00184e6
--- /dev/null
+++ b/chart2/source/controller/dialogs/DialogModel.cxx
@@ -0,0 +1,849 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DialogModel.hxx"
+#include <RangeSelectionHelper.hxx>
+#include <DataInterpreter.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DataSourceHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <strings.hrc>
+#include <ResId.hxx>
+#include <ControllerLockGuard.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <ThreeDHelper.hxx>
+#include <ChartModel.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <LabeledDataSequence.hxx>
+
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <rtl/ustring.hxx>
+
+#include <utility>
+#include <algorithm>
+#include <cstddef>
+#include <iterator>
+#include <numeric>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+constexpr OUString lcl_aLabelRole( u"label"_ustr );
+
+
+OUString lcl_ConvertRole( const OUString & rRoleString )
+{
+ OUString aResult( rRoleString );
+
+ typedef std::map< OUString, OUString > tTranslationMap;
+ static const tTranslationMap aTranslationMap =
+ {
+ { "categories", ::chart::SchResId( STR_DATA_ROLE_CATEGORIES ) },
+ { "error-bars-x", ::chart::SchResId( STR_DATA_ROLE_X_ERROR ) },
+ { "error-bars-x-positive", ::chart::SchResId( STR_DATA_ROLE_X_ERROR_POSITIVE ) },
+ { "error-bars-x-negative", ::chart::SchResId( STR_DATA_ROLE_X_ERROR_NEGATIVE ) },
+ { "error-bars-y", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR ) },
+ { "error-bars-y-positive", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_POSITIVE ) },
+ { "error-bars-y-negative", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_NEGATIVE ) },
+ { "label", ::chart::SchResId( STR_DATA_ROLE_LABEL ) },
+ { "values-first", ::chart::SchResId( STR_DATA_ROLE_FIRST ) },
+ { "values-last", ::chart::SchResId( STR_DATA_ROLE_LAST ) },
+ { "values-max", ::chart::SchResId( STR_DATA_ROLE_MAX ) },
+ { "values-min", ::chart::SchResId( STR_DATA_ROLE_MIN ) },
+ { "values-x", ::chart::SchResId( STR_DATA_ROLE_X ) },
+ { "values-y", ::chart::SchResId( STR_DATA_ROLE_Y ) },
+ { "values-size", ::chart::SchResId( STR_DATA_ROLE_SIZE ) },
+ { "FillColor", ::chart::SchResId( STR_PROPERTY_ROLE_FILLCOLOR ) },
+ { "BorderColor", ::chart::SchResId( STR_PROPERTY_ROLE_BORDERCOLOR ) },
+ };
+
+ tTranslationMap::const_iterator aIt( aTranslationMap.find( rRoleString ));
+ if( aIt != aTranslationMap.end())
+ {
+ aResult = (*aIt).second;
+ }
+ return aResult;
+}
+
+typedef std::map< OUString, sal_Int32 > lcl_tRoleIndexMap;
+
+lcl_tRoleIndexMap lcl_createRoleIndexMap()
+{
+ lcl_tRoleIndexMap aMap;
+ sal_Int32 nIndex = 0;
+
+ aMap[ "label" ] = ++nIndex;
+ aMap[ "categories" ] = ++nIndex;
+ aMap[ "values-x" ] = ++nIndex;
+ aMap[ "values-y" ] = ++nIndex;
+ aMap[ "error-bars-x" ] = ++nIndex;
+ aMap[ "error-bars-x-positive" ] = ++nIndex;
+ aMap[ "error-bars-x-negative" ] = ++nIndex;
+ aMap[ "error-bars-y" ] = ++nIndex;
+ aMap[ "error-bars-y-positive" ] = ++nIndex;
+ aMap[ "error-bars-y-negative" ] = ++nIndex;
+ aMap[ "values-first" ] = ++nIndex;
+ aMap[ "values-min" ] = ++nIndex;
+ aMap[ "values-max" ] = ++nIndex;
+ aMap[ "values-last" ] = ++nIndex;
+ aMap[ "values-size" ] = ++nIndex;
+
+ return aMap;
+}
+
+
+struct lcl_RolesWithRangeAppend
+{
+ typedef Reference< data::XLabeledDataSequence > value_type;
+ typedef ::chart::DialogModel::tRolesWithRanges tContainerType;
+
+ explicit lcl_RolesWithRangeAppend( tContainerType * rCnt,
+ OUString aLabelRole )
+ : m_rDestCnt( rCnt ),
+ m_aRoleForLabelSeq(std::move( aLabelRole ))
+ {}
+
+ lcl_RolesWithRangeAppend & operator= ( const value_type & xVal )
+ {
+ try
+ {
+ if( xVal.is())
+ {
+ // data sequence
+ Reference< data::XDataSequence > xSeq( xVal->getValues());
+ if( xSeq.is())
+ {
+ OUString aRole;
+ Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
+ if( xProp->getPropertyValue( "Role" ) >>= aRole )
+ {
+ m_rDestCnt->emplace(aRole, xSeq->getSourceRangeRepresentation());
+ // label
+ if( aRole == m_aRoleForLabelSeq )
+ {
+ Reference< data::XDataSequence > xLabelSeq( xVal->getLabel());
+ if( xLabelSeq.is())
+ {
+ m_rDestCnt->emplace(
+ lcl_aLabelRole, xLabelSeq->getSourceRangeRepresentation());
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return *this;
+ }
+
+ // Implement output operator requirements as required by std::copy (and
+ // implement prefix increment in terms of postfix increment to avoid unused
+ // member function warnings for the latter in the common case where
+ // std::copy would not actually need it):
+ lcl_RolesWithRangeAppend & operator* () { return *this; }
+ lcl_RolesWithRangeAppend & operator++ () { return operator++(0); }
+ lcl_RolesWithRangeAppend & operator++ (int) { return *this; }
+
+private:
+ tContainerType * m_rDestCnt;
+ OUString m_aRoleForLabelSeq;
+};
+
+}
+
+namespace std
+{
+ template<> struct iterator_traits<lcl_RolesWithRangeAppend>
+ {
+ typedef std::output_iterator_tag iterator_category;
+ typedef Reference< data::XLabeledDataSequence > value_type;
+ typedef value_type& reference;
+ };
+}
+
+namespace {
+
+void lcl_SetSequenceRole(
+ const Reference< data::XDataSequence > & xSeq,
+ const OUString & rRole )
+{
+ Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
+ if( xProp.is())
+ xProp->setPropertyValue( "Role" , uno::Any( rRole ));
+}
+
+Sequence< OUString > lcl_CopyExcludingValuesFirst(
+ Sequence< OUString > const & i_aInput )
+{
+ Sequence< OUString > aOutput( i_aInput.getLength());
+ auto pOutput = aOutput.getArray();
+ int nSourceIndex, nDestIndex;
+ for( nSourceIndex = nDestIndex = 0; nSourceIndex < i_aInput.getLength(); nSourceIndex++ )
+ {
+ if( i_aInput[nSourceIndex] == "values-first" )
+ {
+ aOutput.realloc( aOutput.getLength() - 1 );
+ pOutput = aOutput.getArray();
+ }
+ else
+ {
+ pOutput[nDestIndex] = i_aInput[nSourceIndex];
+ nDestIndex++;
+ }
+ }
+ return aOutput;
+}
+
+rtl::Reference< ::chart::DataSeries > lcl_CreateNewSeries(
+ const rtl::Reference< ::chart::ChartType > & xChartType,
+ sal_Int32 nNewSeriesIndex,
+ sal_Int32 nTotalNumberOfSeriesInCTGroup,
+ const rtl::Reference< ::chart::Diagram > & xDiagram,
+ const rtl::Reference< ::chart::ChartTypeTemplate > & xTemplate,
+ bool bCreateDataCachedSequences )
+{
+ // create plain series
+ rtl::Reference< ::chart::DataSeries > xResult = new ::chart::DataSeries();
+ if( xTemplate.is())
+ {
+ // @deprecated: correct default color should be found by view
+ // without setting it as hard attribute
+ Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
+ if( xColorScheme.is())
+ xResult->setPropertyValue( "Color" , uno::Any( xColorScheme->getColorByIndex( nNewSeriesIndex )));
+ std::size_t nGroupIndex=0;
+ if( xChartType.is())
+ {
+ std::vector< rtl::Reference< ::chart::ChartType > > aCTs =
+ xDiagram->getChartTypes();
+ for( ; nGroupIndex < aCTs.size(); ++nGroupIndex)
+ if( aCTs[nGroupIndex] == xChartType )
+ break;
+ if( nGroupIndex == aCTs.size())
+ nGroupIndex = 0;
+ }
+ xTemplate->applyStyle2( xResult, nGroupIndex, nNewSeriesIndex, nTotalNumberOfSeriesInCTGroup );
+ }
+
+ if( bCreateDataCachedSequences )
+ {
+ // set chart type specific roles
+ if( xChartType.is() )
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences;
+ const OUString aRoleOfSeqForSeriesLabel = xChartType->getRoleOfSequenceForSeriesLabel();
+ const OUString aLabel(::chart::SchResId(STR_DATA_UNNAMED_SERIES));
+ Sequence< OUString > aPossibleRoles( xChartType->getSupportedMandatoryRoles());
+ Sequence< OUString > aPossibleOptRoles( xChartType->getSupportedOptionalRoles());
+
+ //special handling for candlestick type
+ if( xTemplate.is())
+ {
+ rtl::Reference< ::chart::DataInterpreter > xInterpreter( xTemplate->getDataInterpreter2());
+ if( xInterpreter.is())
+ {
+ sal_Int32 nStockVariant;
+ if( xInterpreter->getChartTypeSpecificData("stock variant") >>= nStockVariant )
+ {
+ if( nStockVariant == 0 || nStockVariant == 2) {
+ //delete "values-first" role
+ aPossibleRoles = lcl_CopyExcludingValuesFirst(aPossibleRoles);
+ aPossibleOptRoles = lcl_CopyExcludingValuesFirst(aPossibleOptRoles);
+ }
+ }
+ }
+ }
+
+ const Sequence< OUString > aRoles( aPossibleRoles );
+ const Sequence< OUString > aOptRoles( aPossibleOptRoles );
+
+ for(OUString const & role : aRoles)
+ {
+ if( role == lcl_aLabelRole )
+ continue;
+ Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence() );
+ lcl_SetSequenceRole( xSeq, role );
+ // assert that aRoleOfSeqForSeriesLabel is part of the mandatory roles
+ if( role == aRoleOfSeqForSeriesLabel )
+ {
+ Reference< data::XDataSequence > xLabel( ::chart::DataSourceHelper::createCachedDataSequence( aLabel ));
+ lcl_SetSequenceRole( xLabel, lcl_aLabelRole );
+ aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq, xLabel ));
+ }
+ else
+ aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq ));
+ }
+
+ for(OUString const & role : aOptRoles)
+ {
+ if( role == lcl_aLabelRole )
+ continue;
+ Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence());
+ lcl_SetSequenceRole( xSeq, role );
+ aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq ));
+ }
+
+ xResult->setData( aNewSequences );
+ }
+ }
+
+ return xResult;
+}
+
+struct lcl_addSeriesNumber
+{
+ sal_Int32 operator() ( sal_Int32 nCurrentNumber, const Reference< XDataSeriesContainer > & xCnt ) const
+ {
+ if( xCnt.is())
+ return nCurrentNumber + (xCnt->getDataSeries().getLength());
+ return nCurrentNumber;
+ }
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+DialogModelTimeBasedInfo::DialogModelTimeBasedInfo():
+ bTimeBased(false),
+ nStart(0),
+ nEnd(0)
+{
+}
+
+DialogModel::DialogModel(
+ rtl::Reference<::chart::ChartModel> xChartDocument ) :
+ m_xChartDocument(std::move( xChartDocument )),
+ m_aTimerTriggeredControllerLock( m_xChartDocument )
+{
+}
+
+DialogModel::~DialogModel()
+{
+ if(maTimeBasedInfo.bTimeBased)
+ {
+ getModel().setTimeBasedRange(maTimeBasedInfo.nStart, maTimeBasedInfo.nEnd);
+ }
+}
+
+void DialogModel::setTemplate(
+ const rtl::Reference< ChartTypeTemplate > & xTemplate )
+{
+ m_xTemplate = xTemplate;
+}
+
+std::shared_ptr< RangeSelectionHelper > const &
+ DialogModel::getRangeSelectionHelper() const
+{
+ if( ! m_spRangeSelectionHelper)
+ m_spRangeSelectionHelper =
+ std::make_shared<RangeSelectionHelper>( m_xChartDocument );
+
+ return m_spRangeSelectionHelper;
+}
+
+const rtl::Reference<::chart::ChartModel> & DialogModel::getChartModel() const
+{
+ return m_xChartDocument;
+}
+
+Reference< data::XDataProvider > DialogModel::getDataProvider() const
+{
+ Reference< data::XDataProvider > xResult;
+ if( m_xChartDocument.is())
+ xResult.set( m_xChartDocument->getDataProvider());
+ return xResult;
+}
+
+std::vector< rtl::Reference< ChartType > >
+ DialogModel::getAllDataSeriesContainers() const
+{
+ std::vector< rtl::Reference< ChartType > > aResult;
+
+ try
+ {
+ if( !m_xChartDocument )
+ return {};
+ rtl::Reference< Diagram > xDiagram = m_xChartDocument->getFirstChartDiagram();
+ if( xDiagram.is())
+ {
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq(
+ xDiagram->getBaseCoordinateSystems());
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : aCooSysSeq )
+ {
+
+ for (const auto & rxChartType : coords->getChartTypes2())
+ aResult.push_back(rxChartType);
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return aResult;
+}
+
+std::vector< DialogModel::tSeriesWithChartTypeByName >
+ DialogModel::getAllDataSeriesWithLabel() const
+{
+ std::vector< tSeriesWithChartTypeByName > aResult;
+ std::vector< rtl::Reference< ChartType > > aContainers(
+ getAllDataSeriesContainers());
+
+ for (const auto & rxChartType : aContainers )
+ {
+ try
+ {
+ const std::vector< rtl::Reference< DataSeries > > & aSeq = rxChartType->getDataSeries2();
+ OUString aRole = rxChartType->getRoleOfSequenceForSeriesLabel();
+ for( rtl::Reference< DataSeries > const & dataSeries : aSeq )
+ {
+ aResult.push_back(
+ ::chart::DialogModel::tSeriesWithChartTypeByName(
+ dataSeries->getLabelForRole( aRole ),
+ std::make_pair( dataSeries, rxChartType )));
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return aResult;
+}
+
+namespace {
+
+void addMissingRoles(DialogModel::tRolesWithRanges& rResult, const uno::Sequence<OUString>& rRoles)
+{
+ for(OUString const & role : rRoles)
+ {
+ if(rResult.find(role) == rResult.end())
+ rResult.emplace(role, OUString());
+ }
+}
+
+/**
+ * Insert a new data series to chart type at position after specified series
+ * position.
+ *
+ * @param xChartType chart type that contains data series.
+ * @param xSeries insertion position. The new series will be inserted after
+ * this one.
+ * @param xNewSeries new data series to insert.
+ */
+void addNewSeriesToContainer(
+ const rtl::Reference<ChartType>& xChartType,
+ const rtl::Reference<DataSeries>& xSeries,
+ const rtl::Reference<DataSeries>& xNewSeries )
+{
+ auto aSeries = xChartType->getDataSeries2();
+
+ auto aIt = std::find( aSeries.begin(), aSeries.end(), xSeries);
+
+ if( aIt == aSeries.end())
+ // if we have no series we insert at the first position.
+ aIt = aSeries.begin();
+ else
+ // vector::insert inserts before, so we have to advance
+ ++aIt;
+
+ aSeries.insert(aIt, xNewSeries);
+ xChartType->setDataSeries(aSeries);
+}
+
+}
+
+DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges(
+ const Reference< XDataSeries > & xSeries,
+ const OUString & aRoleOfSequenceForLabel,
+ const rtl::Reference< ::chart::ChartType > & xChartType )
+{
+ DialogModel::tRolesWithRanges aResult;
+ try
+ {
+ Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW );
+ const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
+ std::copy( aSeq.begin(), aSeq.end(),
+ lcl_RolesWithRangeAppend( &aResult, aRoleOfSequenceForLabel ));
+ if( xChartType.is())
+ {
+ // add missing mandatory roles
+ Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles());
+ addMissingRoles(aResult, aRoles);
+
+ // add missing optional roles
+ aRoles = xChartType->getSupportedOptionalRoles();
+ addMissingRoles(aResult, aRoles);
+
+ // add missing property roles
+ aRoles = xChartType->getSupportedPropertyRoles();
+ addMissingRoles(aResult, aRoles);
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return aResult;
+}
+
+void DialogModel::moveSeries(
+ const rtl::Reference< DataSeries > & xSeries,
+ MoveDirection eDirection )
+{
+ m_aTimerTriggeredControllerLock.startTimer();
+ ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
+
+ rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram());
+ xDiagram->moveSeries( xSeries, eDirection==MoveDirection::Down );
+}
+
+rtl::Reference< ::chart::DataSeries > DialogModel::insertSeriesAfter(
+ const Reference< XDataSeries > & xUnoSeries,
+ const rtl::Reference< ::chart::ChartType > & xChartType,
+ bool bCreateDataCachedSequences /* = false */ )
+{
+ m_aTimerTriggeredControllerLock.startTimer();
+ ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
+ rtl::Reference< ::chart::DataSeries > xNewSeries;
+ rtl::Reference<DataSeries> xSeries = dynamic_cast<DataSeries*>(xUnoSeries.get());
+ assert(xSeries || !xUnoSeries);
+
+ try
+ {
+ rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram() );
+ ThreeDLookScheme e3DScheme = xDiagram->detectScheme();
+
+ sal_Int32 nSeriesInChartType = 0;
+ const sal_Int32 nTotalSeries = countSeries();
+ if( xChartType.is())
+ {
+ nSeriesInChartType = xChartType->getDataSeries().getLength();
+ }
+
+ // create new series
+ xNewSeries =
+ lcl_CreateNewSeries(
+ xChartType,
+ nTotalSeries, // new series' index
+ nSeriesInChartType,
+ xDiagram,
+ m_xTemplate,
+ bCreateDataCachedSequences );
+
+ // add new series to container
+ if( xNewSeries.is())
+ addNewSeriesToContainer(xChartType, xSeries, xNewSeries);
+
+ xDiagram->setScheme( e3DScheme );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return xNewSeries;
+}
+
+void DialogModel::deleteSeries(
+ const rtl::Reference< DataSeries > & xSeries,
+ const rtl::Reference< ChartType > & xChartType )
+{
+ m_aTimerTriggeredControllerLock.startTimer();
+ ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
+
+ DataSeriesHelper::deleteSeries( xSeries, xChartType );
+}
+
+uno::Reference< chart2::data::XLabeledDataSequence > DialogModel::getCategories() const
+{
+ uno::Reference< chart2::data::XLabeledDataSequence > xResult;
+ try
+ {
+ if( m_xChartDocument.is())
+ {
+ rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram());
+ if (xDiagram.is())
+ xResult = xDiagram->getCategories();
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return xResult;
+}
+
+void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories )
+{
+ if( !m_xChartDocument.is())
+ return;
+
+ rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram());
+ if( !xDiagram.is())
+ return;
+
+ // categories
+ bool bSupportsCategories = true;
+
+ rtl::Reference< ChartType > xFirstChartType( xDiagram->getChartTypeByIndex( 0 ) );
+ if( xFirstChartType.is() )
+ {
+ sal_Int32 nAxisType = ChartTypeHelper::getAxisType( xFirstChartType, 0 ); // x-axis
+ bSupportsCategories = (nAxisType == AxisType::CATEGORY);
+ }
+ xDiagram->setCategories( xCategories, true, bSupportsCategories );
+}
+
+OUString DialogModel::getCategoriesRange() const
+{
+ OUString aRange;
+ try
+ {
+ uno::Reference< chart2::data::XLabeledDataSequence > xLSeq( getCategories());
+ if( xLSeq.is())
+ {
+ Reference< data::XDataSequence > xSeq( xLSeq->getValues());
+ if( xSeq.is())
+ aRange = xSeq->getSourceRangeRepresentation();
+ }
+ }
+ catch (const lang::DisposedException&)
+ {
+ TOOLS_WARN_EXCEPTION( "chart2", "unexpected exception caught" );
+ }
+ return aRange;
+}
+
+bool DialogModel::isCategoryDiagram() const
+{
+ bool bRet = false;
+ if( m_xChartDocument.is() && m_xChartDocument->getFirstChartDiagram())
+ bRet = m_xChartDocument->getFirstChartDiagram()->isCategory();
+ return bRet;
+}
+
+void DialogModel::detectArguments(
+ OUString & rOutRangeString,
+ bool & rOutUseColumns,
+ bool & rOutFirstCellAsLabel,
+ bool & rOutHasCategories ) const
+{
+ try
+ {
+ uno::Sequence< sal_Int32 > aSequenceMapping;//todo YYYX
+
+ // Note: unused data is currently not supported in being passed to detectRangeSegmentation
+ if( m_xChartDocument.is())
+ {
+ (void)DataSourceHelper::detectRangeSegmentation(
+ m_xChartDocument,
+ rOutRangeString, aSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+bool DialogModel::allArgumentsForRectRangeDetected() const
+{
+ return DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument );
+}
+
+void DialogModel::startControllerLockTimer()
+{
+ m_aTimerTriggeredControllerLock.startTimer();
+}
+
+void DialogModel::setData(
+ const Sequence< beans::PropertyValue > & rArguments )
+{
+ m_aTimerTriggeredControllerLock.startTimer();
+ ControllerLockGuardUNO aLockedControllers( m_xChartDocument );
+
+ Reference< data::XDataProvider > xDataProvider( getDataProvider());
+ if( ! xDataProvider.is() ||
+ ! m_xTemplate.is() )
+ {
+ OSL_FAIL( "Model objects missing" );
+ return;
+ }
+
+ try
+ {
+ Reference< chart2::data::XDataSource > xDataSource(
+ xDataProvider->createDataSource( rArguments ) );
+
+ rtl::Reference< ::chart::DataInterpreter > xInterpreter(
+ m_xTemplate->getDataInterpreter2());
+ if( xInterpreter.is())
+ {
+ rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram() );
+ ThreeDLookScheme e3DScheme = xDiagram->detectScheme();
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesToReUse =
+ xDiagram->getDataSeries();
+ applyInterpretedData(
+ xInterpreter->interpretDataSource(
+ xDataSource, rArguments,
+ aSeriesToReUse ),
+ aSeriesToReUse);
+
+ xDiagram->setScheme( e3DScheme );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void DialogModel::setTimeBasedRange( bool bTimeBased, sal_Int32 nStart, sal_Int32 nEnd) const
+{
+ maTimeBasedInfo.nStart = nStart;
+ maTimeBasedInfo.nEnd = nEnd;
+ maTimeBasedInfo.bTimeBased = bTimeBased;
+}
+
+OUString DialogModel::ConvertRoleFromInternalToUI( const OUString & rRoleString )
+{
+ return lcl_ConvertRole( rRoleString );
+}
+
+OUString DialogModel::GetRoleDataLabel()
+{
+ return ::chart::SchResId(STR_OBJECT_DATALABELS);
+}
+
+sal_Int32 DialogModel::GetRoleIndexForSorting( const OUString & rInternalRoleString )
+{
+ static lcl_tRoleIndexMap aRoleIndexMap = lcl_createRoleIndexMap();
+
+ lcl_tRoleIndexMap::const_iterator aIt( aRoleIndexMap.find( rInternalRoleString ));
+ if( aIt != aRoleIndexMap.end())
+ return aIt->second;
+
+ return 0;
+}
+
+// private methods
+
+void DialogModel::applyInterpretedData(
+ const InterpretedData & rNewData,
+ const std::vector< rtl::Reference< DataSeries > > & rSeriesToReUse )
+{
+ if( ! m_xChartDocument.is())
+ return;
+
+ m_aTimerTriggeredControllerLock.startTimer();
+ rtl::Reference< Diagram > xDiagram( m_xChartDocument->getFirstChartDiagram());
+ if( !xDiagram.is())
+ return;
+
+ // styles
+ if( m_xTemplate.is() )
+ {
+ sal_Int32 nGroup = 0;
+ sal_Int32 nSeriesCounter = 0;
+ sal_Int32 nNewSeriesIndex = static_cast< sal_Int32 >( rSeriesToReUse.size());
+ const sal_Int32 nOuterSize=rNewData.Series.size();
+
+ for(; nGroup < nOuterSize; ++nGroup)
+ {
+ const std::vector< rtl::Reference< DataSeries > > & aSeries( rNewData.Series[ nGroup ] );
+ const sal_Int32 nSeriesInGroup = aSeries.size();
+ for( sal_Int32 nSeries=0; nSeries<nSeriesInGroup; ++nSeries, ++nSeriesCounter )
+ {
+ if( std::find( rSeriesToReUse.begin(), rSeriesToReUse.end(), aSeries[nSeries] )
+ == rSeriesToReUse.end())
+ {
+ if( aSeries[nSeries].is())
+ {
+ // @deprecated: correct default color should be found by view
+ // without setting it as hard attribute
+ Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
+ if( xColorScheme.is())
+ aSeries[nSeries]->setPropertyValue( "Color" ,
+ uno::Any( xColorScheme->getColorByIndex( nSeriesCounter )));
+ }
+ m_xTemplate->applyStyle2( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup );
+ }
+ }
+ }
+ }
+
+ // data series
+ std::vector< rtl::Reference< ChartType > > aSeriesCnt = getAllDataSeriesContainers();
+
+ OSL_ASSERT( aSeriesCnt.size() == rNewData.Series.size());
+
+ auto aSrcIt = rNewData.Series.begin();
+ auto aDestIt = aSeriesCnt.begin();
+ for(; aSrcIt != rNewData.Series.end() && aDestIt != aSeriesCnt.end();
+ ++aSrcIt, ++aDestIt )
+ {
+ try
+ {
+ OSL_ASSERT( (*aDestIt).is());
+ (*aDestIt)->setDataSeries( *aSrcIt );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ DialogModel::setCategories(rNewData.Categories);
+}
+
+sal_Int32 DialogModel::countSeries() const
+{
+ std::vector< rtl::Reference< ChartType > > aCnt( getAllDataSeriesContainers());
+ return std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber());
+}
+
+ChartModel& DialogModel::getModel() const
+{
+ return *m_xChartDocument;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/DialogModel.hxx b/chart2/source/controller/dialogs/DialogModel.hxx
new file mode 100644
index 0000000000..325cffe067
--- /dev/null
+++ b/chart2/source/controller/dialogs/DialogModel.hxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <TimerTriggeredControllerLock.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+
+#include <map>
+#include <memory>
+#include <vector>
+
+namespace chart { class ChartModel; }
+namespace com::sun::star::beans { struct PropertyValue; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::uno { template <class E> class Sequence; }
+
+namespace com::sun::star::chart2 {
+ class XDataSeriesContainer;
+ class XDataSeries;
+ class XChartType;
+ namespace data {
+ class XDataProvider;
+ class XLabeledDataSequence;
+ }
+}
+
+namespace chart
+{
+class ChartType;
+class ChartTypeTemplate;
+class DataSeries;
+struct InterpretedData;
+class LabeledDataSequence;
+class RangeSelectionHelper;
+
+struct DialogModelTimeBasedInfo
+{
+ DialogModelTimeBasedInfo();
+
+ bool bTimeBased;
+ sal_Int32 nStart;
+ sal_Int32 nEnd;
+};
+
+class DialogModel
+{
+public:
+ explicit DialogModel( rtl::Reference<::chart::ChartModel> xChartDocument );
+ ~DialogModel();
+
+ typedef std::pair<
+ OUString,
+ std::pair< rtl::Reference< ::chart::DataSeries >,
+ rtl::Reference< ::chart::ChartType > > >
+ tSeriesWithChartTypeByName;
+
+ typedef std::map< OUString, OUString >
+ tRolesWithRanges;
+
+ void setTemplate(
+ const rtl::Reference< ::chart::ChartTypeTemplate > & xTemplate );
+
+ std::shared_ptr< RangeSelectionHelper > const &
+ getRangeSelectionHelper() const;
+
+ const rtl::Reference<::chart::ChartModel> &
+ getChartModel() const;
+
+ css::uno::Reference< css::chart2::data::XDataProvider >
+ getDataProvider() const;
+
+ std::vector< rtl::Reference< ::chart::ChartType > >
+ getAllDataSeriesContainers() const;
+
+ std::vector< tSeriesWithChartTypeByName >
+ getAllDataSeriesWithLabel() const;
+
+ static tRolesWithRanges getRolesWithRanges(
+ const css::uno::Reference< css::chart2::XDataSeries > & xSeries,
+ const OUString & aRoleOfSequenceForLabel,
+ const rtl::Reference< ::chart::ChartType > & xChartType );
+
+ enum class MoveDirection
+ {
+ Down, Up
+ };
+
+ void moveSeries( const rtl::Reference< DataSeries > & xSeries,
+ MoveDirection eDirection );
+
+ /// @return the newly inserted series
+ rtl::Reference<
+ ::chart::DataSeries > insertSeriesAfter(
+ const css::uno::Reference< css::chart2::XDataSeries > & xSeries,
+ const rtl::Reference< ::chart::ChartType > & xChartType,
+ bool bCreateDataCachedSequences = false );
+
+ void deleteSeries(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ const rtl::Reference< ::chart::ChartType > & xChartType );
+
+ css::uno::Reference< css::chart2::data::XLabeledDataSequence >
+ getCategories() const;
+
+ void setCategories( const css::uno::Reference< css::chart2::data::XLabeledDataSequence > & xCategories );
+
+ OUString getCategoriesRange() const;
+
+ bool isCategoryDiagram() const;
+
+ void detectArguments(
+ OUString & rOutRangeString,
+ bool & rOutUseColumns, bool & rOutFirstCellAsLabel, bool & rOutHasCategories ) const;
+
+ bool allArgumentsForRectRangeDetected() const;
+
+ void setData( const css::uno::Sequence< css::beans::PropertyValue > & rArguments );
+
+ void setTimeBasedRange( bool bTimeBased, sal_Int32 nStart, sal_Int32 nEnd) const;
+
+ const DialogModelTimeBasedInfo& getTimeBasedInfo() const { return maTimeBasedInfo; }
+
+ void startControllerLockTimer();
+
+ static OUString ConvertRoleFromInternalToUI( const OUString & rRoleString );
+ static OUString GetRoleDataLabel();
+
+ // pass a role string (not translated) and get an index that serves for
+ // relative ordering, to get e.g. x-values and y-values in the right order
+ static sal_Int32 GetRoleIndexForSorting( const OUString & rInternalRoleString );
+
+ ChartModel& getModel() const;
+
+private:
+ rtl::Reference<::chart::ChartModel>
+ m_xChartDocument;
+
+ rtl::Reference< ::chart::ChartTypeTemplate > m_xTemplate;
+
+ mutable std::shared_ptr< RangeSelectionHelper >
+ m_spRangeSelectionHelper;
+
+ TimerTriggeredControllerLock m_aTimerTriggeredControllerLock;
+
+private:
+ void applyInterpretedData(
+ const InterpretedData & rNewData,
+ const std::vector< rtl::Reference< ::chart::DataSeries > > & rSeriesToReUse );
+
+ sal_Int32 countSeries() const;
+
+ mutable DialogModelTimeBasedInfo maTimeBasedInfo;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/ObjectNameProvider.cxx b/chart2/source/controller/dialogs/ObjectNameProvider.cxx
new file mode 100644
index 0000000000..2097e43c21
--- /dev/null
+++ b/chart2/source/controller/dialogs/ObjectNameProvider.cxx
@@ -0,0 +1,868 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <ObjectNameProvider.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <TitleHelper.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <CommonConverters.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <RegressionCurveModel.hxx>
+#include <rtl/math.hxx>
+#include <rtl/ustring.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/localedatawrapper.hxx>
+
+#include <com/sun/star/chart2/XTitle.hpp>
+#include <com/sun/star/chart2/MovingAverageType.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <o3tl/string_view.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+namespace
+{
+
+OUString lcl_getDataSeriesName( std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ OUString aRet;
+
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel );
+ if( xDiagram.is() && xSeries.is() )
+ {
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeOfSeries( xSeries ) );
+ if( xChartType.is() )
+ {
+ aRet = xSeries->getLabelForRole(
+ xChartType->getRoleOfSequenceForSeriesLabel() ) ;
+ }
+ }
+
+ return aRet;
+}
+
+OUString lcl_getFullSeriesName( std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ OUString aRet(SchResId(STR_TIP_DATASERIES));
+ OUString aWildcard( "%SERIESNAME" );
+ sal_Int32 nIndex = aRet.indexOf( aWildcard );
+ if( nIndex != -1 )
+ aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataSeriesName( rObjectCID, xChartModel ) );
+ return aRet;
+}
+
+void lcl_addText( OUString& rOut, std::u16string_view rSeparator, std::u16string_view rNext )
+{
+ if( !(rOut.isEmpty() || rNext.empty()) )
+ rOut+=rSeparator;
+ if( !rNext.empty() )
+ rOut+=rNext;
+}
+
+OUString lcl_getDataPointValueText( const rtl::Reference< DataSeries >& xSeries, sal_Int32 nPointIndex,
+ const rtl::Reference< BaseCoordinateSystem >& xCooSys,
+ const Reference< frame::XModel >& xChartModel )
+{
+
+ OUString aRet;
+
+ if(!xSeries.is())
+ return aRet;
+
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aDataSequences = xSeries->getDataSequences2();
+
+ OUString aX, aY, aY_Min, aY_Max, aY_First, aY_Last, a_Size;
+ double fValue = 0;
+
+ uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY );
+ NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
+ Color nLabelColor;//dummy
+ bool bColorChanged;//dummy
+
+ for(sal_Int32 nN = aDataSequences.size();nN--;)
+ {
+ uno::Reference<data::XDataSequence> xDataSequence( aDataSequences[nN]->getValues());
+ if( !xDataSequence.is() )
+ continue;
+
+ try
+ {
+ Sequence< Any > aData( xDataSequence->getData() );
+
+ if( nPointIndex >= aData.getLength() )
+ continue;
+ uno::Reference<beans::XPropertySet> xProp(xDataSequence, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ uno::Any aARole = xProp->getPropertyValue( "Role" );
+ OUString aRole;
+ aARole >>= aRole;
+
+ if( aRole == "values-x" )
+ {
+ aData[nPointIndex]>>= fValue;
+ sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
+ aX = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
+ }
+ else if( aRole == "values-y")
+ {
+ aData[nPointIndex]>>= fValue;
+ sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
+ aY = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
+ }
+ else if( aRole == "values-first" )
+ {
+ aData[nPointIndex]>>= fValue;
+ sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
+ aY_First = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
+ }
+ else if( aRole == "values-min" )
+ {
+ aData[nPointIndex]>>= fValue;
+ sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
+ aY_Min = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
+ }
+ else if( aRole == "values-max" )
+ {
+ aData[nPointIndex]>>= fValue;
+ sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
+ aY_Max = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
+ }
+ else if( aRole == "values-last" )
+ {
+ aData[nPointIndex]>>= fValue;
+ sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
+ aY_Last = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
+ }
+ else if( aRole == "values-size" )
+ {
+ aData[nPointIndex]>>= fValue;
+ sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
+ a_Size = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
+ }
+ }
+ }
+ catch (const lang::DisposedException&)
+ {
+ TOOLS_WARN_EXCEPTION( "chart2", "unexpected exception caught" );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+
+ if( aX.isEmpty() )
+ {
+ ChartModel& rModel = dynamic_cast<ChartModel&>(*xChartModel);
+ aRet = ExplicitCategoriesProvider::getCategoryByIndex( xCooSys, rModel, nPointIndex );
+ }
+ else
+ {
+ aRet = aX;
+ }
+
+ OUString aSeparator( " " );
+
+ lcl_addText( aRet, aSeparator, aY );
+ lcl_addText( aRet, aSeparator, aY_First );
+ lcl_addText( aRet, aSeparator, aY_Min );
+ lcl_addText( aRet, aSeparator, aY_Max );
+ lcl_addText( aRet, aSeparator, aY_Last );
+ lcl_addText( aRet, aSeparator, a_Size );
+
+ return aRet;
+}
+
+} //end anonymous namespace
+
+OUString ObjectNameProvider::getName( ObjectType eObjectType, bool bPlural )
+{
+ OUString aRet;
+ switch( eObjectType )
+ {
+ case OBJECTTYPE_PAGE:
+ aRet=SchResId(STR_OBJECT_PAGE);
+ break;
+ case OBJECTTYPE_TITLE:
+ {
+ if(bPlural)
+ aRet=SchResId(STR_OBJECT_TITLES);
+ else
+ aRet=SchResId(STR_OBJECT_TITLE);
+ }
+ break;
+ case OBJECTTYPE_LEGEND:
+ aRet=SchResId(STR_OBJECT_LEGEND);
+ break;
+ case OBJECTTYPE_LEGEND_ENTRY:
+ aRet=SchResId(STR_OBJECT_LEGEND_SYMBOL);//@todo change string if we do differentiate symbol and legend entry in future
+ break;
+ case OBJECTTYPE_DIAGRAM:
+ aRet=SchResId(STR_OBJECT_DIAGRAM);
+ break;
+ case OBJECTTYPE_DIAGRAM_WALL:
+ aRet=SchResId(STR_OBJECT_DIAGRAM_WALL);
+ break;
+ case OBJECTTYPE_DIAGRAM_FLOOR:
+ aRet=SchResId(STR_OBJECT_DIAGRAM_FLOOR);
+ break;
+ case OBJECTTYPE_AXIS:
+ {
+ if(bPlural)
+ aRet=SchResId(STR_OBJECT_AXES);
+ else
+ aRet=SchResId(STR_OBJECT_AXIS);
+ }
+ break;
+ case OBJECTTYPE_AXIS_UNITLABEL:
+ aRet=SchResId(STR_OBJECT_LABEL);//@todo maybe a more concrete name
+ break;
+ case OBJECTTYPE_GRID:
+ case OBJECTTYPE_SUBGRID: //maybe todo: different names for subgrids
+ {
+ if(bPlural)
+ aRet=SchResId(STR_OBJECT_GRIDS);
+ else
+ aRet=SchResId(STR_OBJECT_GRID);
+ }
+ break;
+ case OBJECTTYPE_DATA_SERIES:
+ {
+ if(bPlural)
+ aRet=SchResId(STR_OBJECT_DATASERIES_PLURAL);
+ else
+ aRet=SchResId(STR_OBJECT_DATASERIES);
+ }
+ break;
+ case OBJECTTYPE_DATA_POINT:
+ {
+ if(bPlural)
+ aRet=SchResId(STR_OBJECT_DATAPOINTS);
+ else
+ aRet=SchResId(STR_OBJECT_DATAPOINT);
+ }
+ break;
+ case OBJECTTYPE_DATA_LABELS:
+ aRet=SchResId(STR_OBJECT_DATALABELS);
+ break;
+ case OBJECTTYPE_DATA_LABEL:
+ aRet=SchResId(STR_OBJECT_LABEL);
+ break;
+ case OBJECTTYPE_DATA_ERRORS_X:
+ aRet=SchResId(STR_OBJECT_ERROR_BARS_X);
+ break;
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ aRet=SchResId(STR_OBJECT_ERROR_BARS_Y);
+ break;
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ aRet=SchResId(STR_OBJECT_ERROR_BARS_Z);
+ break;
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ aRet=SchResId(STR_OBJECT_AVERAGE_LINE);
+ break;
+ case OBJECTTYPE_DATA_CURVE:
+ {
+ if(bPlural)
+ aRet=SchResId(STR_OBJECT_CURVES);
+ else
+ aRet=SchResId(STR_OBJECT_CURVE);
+ }
+ break;
+ case OBJECTTYPE_DATA_STOCK_RANGE:
+ break;
+ case OBJECTTYPE_DATA_STOCK_LOSS:
+ aRet=SchResId(STR_OBJECT_STOCK_LOSS);
+ break;
+ case OBJECTTYPE_DATA_STOCK_GAIN:
+ aRet=SchResId(STR_OBJECT_STOCK_GAIN);
+ break;
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ aRet=SchResId(STR_OBJECT_CURVE_EQUATION);
+ break;
+ case OBJECTTYPE_DATA_TABLE:
+ aRet=SchResId(STR_DATA_TABLE);
+ break;
+ default: //OBJECTTYPE_UNKNOWN
+ ;
+ }
+ return aRet;
+}
+
+OUString ObjectNameProvider::getAxisName( std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ OUString aRet;
+
+ rtl::Reference< ::chart::Axis > xAxis =
+ dynamic_cast<::chart::Axis*>(ObjectIdentifier::getObjectPropertySet( rObjectCID , xChartModel ).get());
+
+ sal_Int32 nCooSysIndex = 0;
+ sal_Int32 nDimensionIndex = 0;
+ sal_Int32 nAxisIndex = 0;
+ AxisHelper::getIndicesForAxis( xAxis, xChartModel->getFirstChartDiagram(), nCooSysIndex, nDimensionIndex, nAxisIndex );
+
+ switch(nDimensionIndex)
+ {
+ case 0://x-axis
+ if( nAxisIndex == 0 )
+ aRet=SchResId(STR_OBJECT_AXIS_X);
+ else
+ aRet=SchResId(STR_OBJECT_SECONDARY_X_AXIS);
+ break;
+ case 1://y-axis
+ if( nAxisIndex == 0 )
+ aRet=SchResId(STR_OBJECT_AXIS_Y);
+ else
+ aRet=SchResId(STR_OBJECT_SECONDARY_Y_AXIS);
+ break;
+ case 2://z-axis
+ aRet=SchResId(STR_OBJECT_AXIS_Z);
+ break;
+ default://axis
+ aRet=SchResId(STR_OBJECT_AXIS);
+ break;
+ }
+
+ return aRet;
+}
+
+OUString ObjectNameProvider::getTitleNameByType( TitleHelper::eTitleType eType )
+{
+ OUString aRet;
+
+ switch(eType)
+ {
+ case TitleHelper::MAIN_TITLE:
+ aRet=SchResId(STR_OBJECT_TITLE_MAIN);
+ break;
+ case TitleHelper::SUB_TITLE:
+ aRet=SchResId(STR_OBJECT_TITLE_SUB);
+ break;
+ case TitleHelper::X_AXIS_TITLE:
+ aRet=SchResId(STR_OBJECT_TITLE_X_AXIS);
+ break;
+ case TitleHelper::Y_AXIS_TITLE:
+ aRet=SchResId(STR_OBJECT_TITLE_Y_AXIS);
+ break;
+ case TitleHelper::Z_AXIS_TITLE:
+ aRet=SchResId(STR_OBJECT_TITLE_Z_AXIS);
+ break;
+ case TitleHelper::SECONDARY_X_AXIS_TITLE:
+ aRet=SchResId(STR_OBJECT_TITLE_SECONDARY_X_AXIS);
+ break;
+ case TitleHelper::SECONDARY_Y_AXIS_TITLE:
+ aRet=SchResId(STR_OBJECT_TITLE_SECONDARY_Y_AXIS);
+ break;
+ default:
+ OSL_FAIL("unknown title type");
+ break;
+ }
+
+ if( aRet.isEmpty() )
+ aRet=SchResId(STR_OBJECT_TITLE);
+
+ return aRet;
+}
+
+OUString ObjectNameProvider::getTitleName( std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ OUString aRet;
+
+ rtl::Reference<Title> xTitle =
+ dynamic_cast<Title*>(ObjectIdentifier::getObjectPropertySet( rObjectCID , xChartModel ).get());
+ if( xTitle )
+ {
+ TitleHelper::eTitleType eType;
+ if( TitleHelper::getTitleType( eType, xTitle, xChartModel ) )
+ aRet = ObjectNameProvider::getTitleNameByType( eType );
+ }
+ if( aRet.isEmpty() )
+ aRet=SchResId(STR_OBJECT_TITLE);
+
+ return aRet;
+}
+
+OUString ObjectNameProvider::getGridName( std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ OUString aRet;
+
+ sal_Int32 nCooSysIndex = -1;
+ sal_Int32 nDimensionIndex = -1;
+ sal_Int32 nAxisIndex = -1;
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( rObjectCID , xChartModel );
+ AxisHelper::getIndicesForAxis( xAxis, xChartModel->getFirstChartDiagram()
+ , nCooSysIndex , nDimensionIndex, nAxisIndex );
+
+ bool bMainGrid = (ObjectIdentifier::getObjectType( rObjectCID ) == OBJECTTYPE_GRID);
+
+ if( bMainGrid )
+ {
+ switch(nDimensionIndex)
+ {
+ case 0://x-axis
+ aRet=SchResId(STR_OBJECT_GRID_MAJOR_X);
+ break;
+ case 1://y-axis
+ aRet=SchResId(STR_OBJECT_GRID_MAJOR_Y);
+ break;
+ case 2://z-axis
+ aRet=SchResId(STR_OBJECT_GRID_MAJOR_Z);
+ break;
+ default://axis
+ aRet=SchResId(STR_OBJECT_GRID);
+ break;
+ }
+ }
+ else
+ {
+ switch(nDimensionIndex)
+ {
+ case 0://x-axis
+ aRet=SchResId(STR_OBJECT_GRID_MINOR_X);
+ break;
+ case 1://y-axis
+ aRet=SchResId(STR_OBJECT_GRID_MINOR_Y);
+ break;
+ case 2://z-axis
+ aRet=SchResId(STR_OBJECT_GRID_MINOR_Z);
+ break;
+ default://axis
+ aRet=SchResId(STR_OBJECT_GRID);
+ break;
+ }
+ }
+ return aRet;
+}
+
+OUString ObjectNameProvider::getHelpText( std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel>& xChartModel, bool bVerbose )
+{
+ OUString aRet;
+ ObjectType eObjectType( ObjectIdentifier::getObjectType(rObjectCID) );
+ if( eObjectType == OBJECTTYPE_AXIS )
+ {
+ aRet=ObjectNameProvider::getAxisName( rObjectCID, xChartModel );
+ }
+ else if( eObjectType == OBJECTTYPE_GRID
+ || eObjectType == OBJECTTYPE_SUBGRID )
+ {
+ aRet=ObjectNameProvider::getGridName( rObjectCID, xChartModel );
+ }
+ else if( eObjectType == OBJECTTYPE_TITLE )
+ {
+ aRet=ObjectNameProvider::getTitleName( rObjectCID, xChartModel );
+ }
+ else if( eObjectType == OBJECTTYPE_DATA_SERIES )
+ {
+ aRet = lcl_getFullSeriesName( rObjectCID, xChartModel );
+ }
+ else if( eObjectType == OBJECTTYPE_DATA_POINT )
+ {
+ if( bVerbose )
+ {
+ aRet= SchResId(STR_TIP_DATAPOINT_INDEX) + "\n"
+ + SchResId(STR_TIP_DATASERIES) + "\n"
+ + SchResId(STR_TIP_DATAPOINT_VALUES);
+ }
+ else
+ aRet=SchResId(STR_TIP_DATAPOINT);
+
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel );
+ if( xDiagram.is() && xSeries.is() )
+ {
+ sal_Int32 nPointIndex = o3tl::toInt32(ObjectIdentifier::getParticleID(rObjectCID));
+
+ //replace data point index
+ OUString aWildcard( "%POINTNUMBER" );
+ sal_Int32 nIndex = aRet.indexOf( aWildcard );
+ if( nIndex != -1 )
+ {
+ aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), OUString::number(nPointIndex+1) );
+ }
+
+ //replace data series index
+ aWildcard = "%SERIESNUMBER";
+ nIndex = aRet.indexOf( aWildcard );
+ if( nIndex != -1 )
+ {
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector =
+ xDiagram->getDataSeries();
+ sal_Int32 nSeriesIndex = -1;
+ for( nSeriesIndex=aSeriesVector.size();nSeriesIndex--;)
+ {
+ if( aSeriesVector[nSeriesIndex] == xSeries )
+ {
+ break;
+ }
+ }
+
+ OUString aReplacement( OUString::number(nSeriesIndex+1) );
+ aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), aReplacement );
+ }
+
+ //replace point values
+ aWildcard = "%POINTVALUES";
+ nIndex = aRet.indexOf( aWildcard );
+ if( nIndex != -1 )
+ aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataPointValueText(
+ xSeries,nPointIndex, DataSeriesHelper::getCoordinateSystemOfSeries(xSeries, xDiagram), xChartModel ) );
+
+ //replace series name
+ aWildcard = "%SERIESNAME";
+ nIndex = aRet.indexOf( aWildcard );
+ if( nIndex != -1 )
+ aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataSeriesName( rObjectCID, xChartModel ) );
+ }
+ }
+ else if( eObjectType == OBJECTTYPE_DATA_CURVE )
+ {
+ if( bVerbose )
+ {
+ aRet = SchResId( STR_OBJECT_CURVE_WITH_PARAMETERS );
+ rtl::Reference< DataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ));
+
+ if( xSeries.is())
+ {
+ sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID );
+ rtl::Reference< RegressionCurveModel > xCurve = RegressionCurveHelper::getRegressionCurveAtIndex(xSeries, nCurveIndex);
+ if( xCurve.is())
+ {
+ try
+ {
+ Reference< chart2::XRegressionCurveCalculator > xCalculator( xCurve->getCalculator(), uno::UNO_SET_THROW );
+ sal_Int32 aDegree = 2;
+ sal_Int32 aPeriod = 2;
+ sal_Int32 aMovingType = css::chart2::MovingAverageType::Prior;
+ bool bForceIntercept = false;
+ double aInterceptValue = 0.0;
+ OUString aXName ("x"), aYName ("f(x)");
+ const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
+ const OUString& aNumDecimalSep = rLocaleDataWrapper.getNumDecimalSep();
+ sal_Unicode cDecSeparator = aNumDecimalSep[0];
+
+ xCurve->getPropertyValue( "PolynomialDegree") >>= aDegree;
+ xCurve->getPropertyValue( "MovingAveragePeriod") >>= aPeriod;
+ xCurve->getPropertyValue( "MovingAverageType") >>= aMovingType;
+ xCurve->getPropertyValue( "ForceIntercept") >>= bForceIntercept;
+ if (bForceIntercept)
+ xCurve->getPropertyValue( "InterceptValue") >>= aInterceptValue;
+ uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties());
+ if( xEqProp.is())
+ {
+ if ( !(xEqProp->getPropertyValue( "XName") >>= aXName) )
+ aXName = "x";
+ if ( !(xEqProp->getPropertyValue( "YName") >>= aYName) )
+ aYName = "f(x)";
+ }
+ xCalculator->setRegressionProperties(aDegree, bForceIntercept, aInterceptValue, aPeriod, aMovingType);
+ xCalculator->setXYNames ( aXName, aYName );
+ RegressionCurveHelper::initializeCurveCalculator( xCalculator, xSeries, xChartModel );
+
+ // change text for Moving Average
+ if ( RegressionCurveHelper::getRegressionType( xCurve ) == SvxChartRegress::MovingAverage )
+ {
+ aRet = xCalculator->getRepresentation();
+ }
+ else
+ {
+ // replace formula
+ OUString aWildcard = "%FORMULA";
+ sal_Int32 nIndex = aRet.indexOf( aWildcard );
+ if( nIndex != -1 )
+ {
+ OUString aFormula ( xCalculator->getRepresentation() );
+ if ( cDecSeparator != '.' )
+ {
+ aFormula = aFormula.replace( '.', cDecSeparator );
+ }
+ aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), aFormula );
+ }
+
+ // replace r^2
+ aWildcard = "%RSQUARED";
+ nIndex = aRet.indexOf( aWildcard );
+ if( nIndex != -1 )
+ {
+ double fR( xCalculator->getCorrelationCoefficient());
+ aRet = aRet.replaceAt(
+ nIndex, aWildcard.getLength(),
+ ::rtl::math::doubleToUString(
+ fR*fR, rtl_math_StringFormat_G, 4, cDecSeparator, true ));
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ }
+ else
+ {
+ rtl::Reference< DataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID(rObjectCID , xChartModel));
+ aRet += getName(eObjectType);
+
+ if( xSeries.is())
+ {
+ sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID );
+ rtl::Reference< RegressionCurveModel > xCurve( RegressionCurveHelper::getRegressionCurveAtIndex(xSeries, nCurveIndex) );
+ if( xCurve.is())
+ {
+ aRet += " (" + RegressionCurveHelper::getRegressionCurveName(xCurve) + " )";
+ }
+ }
+ }
+ }
+ else if( eObjectType == OBJECTTYPE_DATA_AVERAGE_LINE )
+ {
+ if( bVerbose )
+ {
+ aRet = SchResId(STR_OBJECT_AVERAGE_LINE_WITH_PARAMETERS);
+ rtl::Reference< DataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ));
+ if( xSeries.is())
+ {
+ rtl::Reference< RegressionCurveModel > xCurve( RegressionCurveHelper::getMeanValueLine( xSeries ));
+ if( xCurve.is())
+ {
+ try
+ {
+ Reference< chart2::XRegressionCurveCalculator > xCalculator( xCurve->getCalculator(), uno::UNO_SET_THROW );
+ RegressionCurveHelper::initializeCurveCalculator( xCalculator, xSeries, xChartModel );
+
+ const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
+ const OUString& aNumDecimalSep = rLocaleDataWrapper.getNumDecimalSep();
+ sal_Unicode cDecSeparator = aNumDecimalSep[0];
+
+ OUString aWildcard( "%AVERAGE_VALUE" );
+ sal_Int32 nIndex = aRet.indexOf( aWildcard );
+ // as the curve is constant, the value at any x-value is ok
+ if( nIndex != -1 )
+ {
+ const double fMeanValue( xCalculator->getCurveValue( 0.0 ));
+ aRet = aRet.replaceAt(
+ nIndex, aWildcard.getLength(),
+ ::rtl::math::doubleToUString(
+ fMeanValue, rtl_math_StringFormat_G, 4, cDecSeparator, true ));
+ }
+
+ // replace standard deviation
+ aWildcard = "%STD_DEVIATION";
+ nIndex = aRet.indexOf( aWildcard );
+ if( nIndex != -1 )
+ {
+ const double fStdDev( xCalculator->getCorrelationCoefficient());
+ aRet = aRet.replaceAt(
+ nIndex, aWildcard.getLength(),
+ ::rtl::math::doubleToUString(
+ fStdDev, rtl_math_StringFormat_G, 4, cDecSeparator, true ));
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ }
+ else
+ {
+ // non-verbose
+ aRet = ObjectNameProvider::getName( eObjectType );
+ }
+ }
+ else
+ {
+ aRet = ObjectNameProvider::getName( eObjectType );
+ }
+ return aRet;
+}
+
+OUString ObjectNameProvider::getSelectedObjectText( std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel>& xChartDocument )
+{
+ OUString aRet;
+ ObjectType eObjectType( ObjectIdentifier::getObjectType(rObjectCID) );
+
+ if( eObjectType == OBJECTTYPE_DATA_POINT )
+ {
+ aRet = SchResId( STR_STATUS_DATAPOINT_MARKED );
+
+ rtl::Reference< Diagram > xDiagram( xChartDocument->getFirstChartDiagram() );
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartDocument );
+ if( xDiagram.is() && xSeries.is() )
+ {
+ sal_Int32 nPointIndex = o3tl::toInt32( ObjectIdentifier::getParticleID(rObjectCID) );
+
+ // replace data point index
+ replaceParamterInString( aRet, u"%POINTNUMBER", OUString::number( nPointIndex + 1 ));
+
+ // replace data series index
+ {
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector(
+ xDiagram->getDataSeries() );
+ sal_Int32 nSeriesIndex = -1;
+ for( nSeriesIndex=aSeriesVector.size();nSeriesIndex--;)
+ {
+ if( aSeriesVector[nSeriesIndex] == xSeries )
+ break;
+ }
+ replaceParamterInString( aRet, u"%SERIESNUMBER", OUString::number( nSeriesIndex + 1 ) );
+ }
+
+ // replace point value
+ replaceParamterInString( aRet, u"%POINTVALUES", lcl_getDataPointValueText(
+ xSeries, nPointIndex, DataSeriesHelper::getCoordinateSystemOfSeries(xSeries, xDiagram), xChartDocument ) );
+ }
+ }
+ else
+ {
+ // use the verbose text including the formula for trend lines
+ const bool bVerbose( eObjectType == OBJECTTYPE_DATA_CURVE || eObjectType == OBJECTTYPE_DATA_AVERAGE_LINE );
+ const OUString aHelpText( getHelpText( rObjectCID, xChartDocument, bVerbose ));
+ if( !aHelpText.isEmpty())
+ {
+ aRet = SchResId( STR_STATUS_OBJECT_MARKED );
+ replaceParamterInString( aRet, u"%OBJECTNAME", aHelpText );
+ }
+ }
+
+ return aRet;
+}
+
+OUString ObjectNameProvider::getNameForCID(
+ std::u16string_view rObjectCID,
+ const rtl::Reference<::chart::ChartModel>& xChartDocument )
+{
+ ObjectType eType( ObjectIdentifier::getObjectType( rObjectCID ));
+
+ switch( eType )
+ {
+ case OBJECTTYPE_AXIS:
+ return getAxisName( rObjectCID, xChartDocument );
+ case OBJECTTYPE_TITLE:
+ return getTitleName( rObjectCID, xChartDocument );
+ case OBJECTTYPE_GRID:
+ case OBJECTTYPE_SUBGRID:
+ return getGridName( rObjectCID, xChartDocument );
+ case OBJECTTYPE_DATA_SERIES:
+ return lcl_getFullSeriesName( rObjectCID, xChartDocument );
+ case OBJECTTYPE_DATA_POINT:
+ case OBJECTTYPE_DATA_LABELS:
+ case OBJECTTYPE_DATA_LABEL:
+ case OBJECTTYPE_DATA_ERRORS_X:
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ case OBJECTTYPE_DATA_CURVE:
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ {
+ OUString aRet = lcl_getFullSeriesName( rObjectCID, xChartDocument ) + " ";
+ if( eType == OBJECTTYPE_DATA_POINT || eType == OBJECTTYPE_DATA_LABEL )
+ {
+ aRet += getName( OBJECTTYPE_DATA_POINT );
+ sal_Int32 nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID );
+ aRet += " " + OUString::number(nPointIndex+1);
+ if( eType == OBJECTTYPE_DATA_LABEL )
+ {
+ aRet += " " + getName( OBJECTTYPE_DATA_LABEL );
+ }
+ }
+ else if (eType == OBJECTTYPE_DATA_CURVE || eType == OBJECTTYPE_DATA_CURVE_EQUATION)
+ {
+ rtl::Reference< DataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartDocument ));
+
+ aRet += " " + getName(eType);
+
+ if( xSeries.is())
+ {
+ sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID );
+ rtl::Reference< RegressionCurveModel > xCurve( RegressionCurveHelper::getRegressionCurveAtIndex(xSeries, nCurveIndex) );
+ if( xCurve.is())
+ {
+ aRet += " (" + RegressionCurveHelper::getRegressionCurveName(xCurve) + ")";
+ }
+ }
+ }
+ else
+ {
+ aRet += getName( eType );
+ }
+ return aRet;
+ }
+ default:
+ break;
+ }
+
+ return getName( eType );
+}
+
+OUString ObjectNameProvider::getName_ObjectForSeries(
+ ObjectType eObjectType,
+ std::u16string_view rSeriesCID,
+ const rtl::Reference<::chart::ChartModel>& xChartDocument )
+{
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rSeriesCID , xChartDocument );
+ if( xSeries.is() )
+ {
+ OUString aRet = SchResId(STR_OBJECT_FOR_SERIES);
+ replaceParamterInString( aRet, u"%OBJECTNAME", getName( eObjectType ) );
+ replaceParamterInString( aRet, u"%SERIESNAME", lcl_getDataSeriesName( rSeriesCID, xChartDocument ) );
+ return aRet;
+ }
+ else
+ return ObjectNameProvider::getName_ObjectForAllSeries( eObjectType );
+}
+
+OUString ObjectNameProvider::getName_ObjectForAllSeries( ObjectType eObjectType )
+{
+ OUString aRet = SchResId(STR_OBJECT_FOR_ALL_SERIES);
+ replaceParamterInString( aRet, u"%OBJECTNAME", getName( eObjectType, true /*bPlural*/ ) );
+ return aRet;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/RangeSelectionHelper.cxx b/chart2/source/controller/dialogs/RangeSelectionHelper.cxx
new file mode 100644
index 0000000000..00e9a3cc8a
--- /dev/null
+++ b/chart2/source/controller/dialogs/RangeSelectionHelper.cxx
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RangeSelectionHelper.hxx>
+#include <RangeSelectionListener.hxx>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/chart2/data/XDataProvider.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <ChartModel.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+RangeSelectionHelper::RangeSelectionHelper(
+ rtl::Reference<::chart::ChartModel> xChartDocument ) :
+ m_xChartDocument(std::move( xChartDocument ))
+{}
+
+RangeSelectionHelper::~RangeSelectionHelper()
+{}
+
+bool RangeSelectionHelper::hasRangeSelection()
+{
+ return getRangeSelection().is();
+}
+
+Reference< sheet::XRangeSelection > const & RangeSelectionHelper::getRangeSelection()
+{
+ if( !m_xRangeSelection.is() &&
+ m_xChartDocument.is() )
+ {
+ try
+ {
+ Reference< chart2::data::XDataProvider > xDataProvider( m_xChartDocument->getDataProvider());
+ if( xDataProvider.is())
+ m_xRangeSelection.set( xDataProvider->getRangeSelection());
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+
+ m_xRangeSelection.clear();
+ }
+ }
+
+ return m_xRangeSelection;
+}
+
+void RangeSelectionHelper::raiseRangeSelectionDocument()
+{
+ Reference< sheet::XRangeSelection > xRangeSel( getRangeSelection());
+ if( !xRangeSel.is())
+ return;
+
+ try
+ {
+ // bring document to front
+ Reference< frame::XController > xCtrl( xRangeSel, uno::UNO_QUERY );
+ if( xCtrl.is())
+ {
+ Reference< frame::XFrame > xFrame( xCtrl->getFrame());
+ if( xFrame.is())
+ {
+ Reference< awt::XTopWindow > xWin( xFrame->getContainerWindow(),
+ uno::UNO_QUERY_THROW );
+ xWin->toFront();
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+bool RangeSelectionHelper::chooseRange(
+ const OUString & aCurrentRange,
+ const OUString & aUIString,
+ RangeSelectionListenerParent & rListenerParent )
+{
+ ControllerLockGuardUNO aGuard( m_xChartDocument );
+
+ bool bResult = true;
+ raiseRangeSelectionDocument();
+
+ try
+ {
+ Reference< sheet::XRangeSelection > xRangeSel( getRangeSelection());
+ if( xRangeSel.is())
+ {
+ Sequence< beans::PropertyValue > aArgs{
+ beans::PropertyValue(
+ "InitialValue", -1, uno::Any( aCurrentRange ),
+ beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "Title", -1,
+ uno::Any( aUIString ),
+ beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "CloseOnMouseRelease", -1, uno::Any( true ),
+ beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "MultiSelectionMode", -1, uno::Any( true ),
+ beans::PropertyState_DIRECT_VALUE )
+ };
+ if( m_xRangeSelectionListener.is() )
+ stopRangeListening();
+ m_xRangeSelectionListener.set( Reference< sheet::XRangeSelectionListener >(
+ new RangeSelectionListener( rListenerParent, aCurrentRange, m_xChartDocument )));
+
+ xRangeSel->addRangeSelectionListener( m_xRangeSelectionListener );
+ xRangeSel->startRangeSelection( aArgs );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ bResult = false;
+ }
+
+ return bResult;
+}
+
+void RangeSelectionHelper::stopRangeListening( bool bRemoveListener /* = true */ )
+{
+ if( bRemoveListener &&
+ m_xRangeSelectionListener.is() &&
+ m_xRangeSelection.is() )
+ {
+ m_xRangeSelection->removeRangeSelectionListener( m_xRangeSelectionListener );
+ }
+
+ m_xRangeSelectionListener = nullptr;
+}
+
+bool RangeSelectionHelper::verifyCellRange( const OUString & rRangeStr )
+{
+ Reference< chart2::data::XDataProvider > xDataProvider( m_xChartDocument->getDataProvider());
+ if( ! xDataProvider.is())
+ return false;
+
+ return xDataProvider->createDataSequenceByRangeRepresentationPossible( rRangeStr );
+}
+
+bool RangeSelectionHelper::verifyArguments( const Sequence< beans::PropertyValue > & rArguments )
+{
+ Reference< chart2::data::XDataProvider > xDataProvider( m_xChartDocument->getDataProvider());
+ if( ! xDataProvider.is())
+ return false;
+
+ return xDataProvider->createDataSourcePossible( rArguments );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/RangeSelectionListener.cxx b/chart2/source/controller/dialogs/RangeSelectionListener.cxx
new file mode 100644
index 0000000000..e4974ab30d
--- /dev/null
+++ b/chart2/source/controller/dialogs/RangeSelectionListener.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RangeSelectionListener.hxx>
+#include <ChartModel.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+RangeSelectionListener::RangeSelectionListener(
+ RangeSelectionListenerParent & rParent,
+ OUString aInitialRange,
+ const rtl::Reference<::chart::ChartModel>& xModelToLockController ) :
+ m_rParent( rParent ),
+ m_aRange(std::move( aInitialRange )),
+ m_aControllerLockGuard( xModelToLockController )
+{}
+
+RangeSelectionListener::~RangeSelectionListener()
+{}
+
+// ____ XRangeSelectionListener ____
+void SAL_CALL RangeSelectionListener::done( const sheet::RangeSelectionEvent& aEvent )
+{
+ m_aRange = aEvent.RangeDescriptor;
+ m_rParent.listeningFinished( m_aRange );
+}
+
+void SAL_CALL RangeSelectionListener::aborted( const sheet::RangeSelectionEvent& /*aEvent*/ )
+{
+ m_rParent.listeningFinished( m_aRange );
+}
+
+// ____ XEventListener ____
+void SAL_CALL RangeSelectionListener::disposing( const lang::EventObject& /*Source*/ )
+{
+ m_rParent.disposingRangeSelection();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/TextDirectionListBox.cxx b/chart2/source/controller/dialogs/TextDirectionListBox.cxx
new file mode 100644
index 0000000000..68181fdfc7
--- /dev/null
+++ b/chart2/source/controller/dialogs/TextDirectionListBox.cxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TextDirectionListBox.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+
+namespace chart
+{
+TextDirectionListBox::TextDirectionListBox(std::unique_ptr<weld::ComboBox> pControl)
+ : svx::FrameDirectionListBox(std::move(pControl))
+{
+ append(SvxFrameDirection::Horizontal_LR_TB, SchResId(STR_TEXT_DIRECTION_LTR));
+ append(SvxFrameDirection::Horizontal_RL_TB, SchResId(STR_TEXT_DIRECTION_RTL));
+ append(SvxFrameDirection::Environment, SchResId(STR_TEXT_DIRECTION_SUPER));
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/TimerTriggeredControllerLock.cxx b/chart2/source/controller/dialogs/TimerTriggeredControllerLock.cxx
new file mode 100644
index 0000000000..cee4af1fb0
--- /dev/null
+++ b/chart2/source/controller/dialogs/TimerTriggeredControllerLock.cxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TimerTriggeredControllerLock.hxx>
+#include <ControllerLockGuard.hxx>
+#include <ChartModel.hxx>
+#include <utility>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+TimerTriggeredControllerLock::TimerTriggeredControllerLock(
+ rtl::Reference<::chart::ChartModel> xModel)
+ : m_xModel(std::move(xModel))
+ , m_aTimer("chart2 TimerTriggeredControllerLock")
+{
+ m_aTimer.SetTimeout(4 * EDIT_UPDATEDATA_TIMEOUT);
+ m_aTimer.SetInvokeHandler(LINK(this, TimerTriggeredControllerLock, TimerTimeout));
+}
+TimerTriggeredControllerLock::~TimerTriggeredControllerLock() { m_aTimer.Stop(); }
+
+void TimerTriggeredControllerLock::startTimer()
+{
+ if (!m_apControllerLockGuard)
+ m_apControllerLockGuard.reset(new ControllerLockGuardUNO(m_xModel));
+ m_aTimer.Start();
+}
+IMPL_LINK_NOARG(TimerTriggeredControllerLock, TimerTimeout, Timer*, void)
+{
+ m_apControllerLockGuard.reset();
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/TitleDialogData.cxx b/chart2/source/controller/dialogs/TitleDialogData.cxx
new file mode 100644
index 0000000000..f110b3d520
--- /dev/null
+++ b/chart2/source/controller/dialogs/TitleDialogData.cxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <TitleDialogData.hxx>
+#include <TitleHelper.hxx>
+#include <ChartModelHelper.hxx>
+#include <Diagram.hxx>
+#include <AxisHelper.hxx>
+#include <ChartModel.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+TitleDialogData::TitleDialogData( std::unique_ptr<ReferenceSizeProvider> pRefSizeProvider )
+ : aPossibilityList{ true, true, true, true, true, true, true }
+ , aExistenceList{ false, false, false, false, false, false, false }
+ , aTextList(7)
+ , apReferenceSizeProvider( std::move(pRefSizeProvider) )
+{
+}
+
+void TitleDialogData::readFromModel( const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
+
+ //get possibilities
+ uno::Sequence< sal_Bool > aAxisPossibilityList;
+ AxisHelper::getAxisOrGridPossibilities( aAxisPossibilityList, xDiagram );
+ sal_Bool* pPossibilityList = aPossibilityList.getArray();
+ pPossibilityList[2]=aAxisPossibilityList[0];//x axis title
+ pPossibilityList[3]=aAxisPossibilityList[1];//y axis title
+ pPossibilityList[4]=aAxisPossibilityList[2];//z axis title
+ pPossibilityList[5]=aAxisPossibilityList[3];//secondary x axis title
+ pPossibilityList[6]=aAxisPossibilityList[4];//secondary y axis title
+
+ sal_Bool* pExistenceList = aExistenceList.getArray();
+ auto pTextList = aTextList.getArray();
+ //find out which title exists and get their text
+ //main title:
+ for( auto nTitleIndex = +TitleHelper::TITLE_BEGIN;
+ nTitleIndex < +TitleHelper::NORMAL_TITLE_END;
+ nTitleIndex++)
+ {
+ rtl::Reference< Title > xTitle = TitleHelper::getTitle(
+ static_cast< TitleHelper::eTitleType >( nTitleIndex ), xChartModel );
+ pExistenceList[nTitleIndex] = xTitle.is();
+ pTextList[nTitleIndex]=TitleHelper::getCompleteString( xTitle );
+ }
+}
+
+bool TitleDialogData::writeDifferenceToModel(
+ const rtl::Reference<::chart::ChartModel>& xChartModel
+ , const uno::Reference< uno::XComponentContext >& xContext
+ , const TitleDialogData* pOldState )
+{
+ bool bChanged = false;
+ for( auto nN = +TitleHelper::TITLE_BEGIN;
+ nN < +TitleHelper::NORMAL_TITLE_END;
+ nN++)
+ {
+ if( !pOldState || ( pOldState->aExistenceList[nN] != aExistenceList[nN] ) )
+ {
+ if(aExistenceList[nN])
+ {
+ TitleHelper::createTitle(
+ static_cast< TitleHelper::eTitleType >( nN ), aTextList[nN], xChartModel, xContext,
+ apReferenceSizeProvider.get() );
+ bChanged = true;
+ }
+ else
+ {
+ TitleHelper::removeTitle( static_cast< TitleHelper::eTitleType >( nN ), xChartModel );
+ bChanged = true;
+ }
+ }
+ else if( !pOldState || ( pOldState->aTextList[nN] != aTextList[nN] ) )
+ {
+ //change content
+ rtl::Reference< Title > xTitle(
+ TitleHelper::getTitle( static_cast< TitleHelper::eTitleType >( nN ), xChartModel ) );
+ if(xTitle.is())
+ {
+ TitleHelper::setCompleteString( aTextList[nN], xTitle, xContext );
+ bChanged = true;
+ }
+ }
+ }
+ return bChanged;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_ChartType.cxx b/chart2/source/controller/dialogs/dlg_ChartType.cxx
new file mode 100644
index 0000000000..e6e88dae42
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_ChartType.cxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_ChartType.hxx>
+#include "tp_ChartType.hxx"
+#include <ChartModel.hxx>
+#include <utility>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+ChartTypeDialog::ChartTypeDialog(weld::Window* pParent,
+ rtl::Reference<::chart::ChartModel> xChartModel)
+ : GenericDialogController(pParent, "modules/schart/ui/charttypedialog.ui", "ChartTypeDialog")
+ , m_xChartModel(std::move(xChartModel))
+ , m_xContentArea(m_xBuilder->weld_container("content"))
+{
+ m_xChartTypeTabPage = std::make_unique<ChartTypeTabPage>(
+ m_xContentArea.get(), this, m_xChartModel, false /*don't show title description*/);
+
+ m_xChartTypeTabPage->initializePage();
+}
+
+ChartTypeDialog::~ChartTypeDialog() { m_xChartTypeTabPage.reset(); }
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_ChartType_UNO.cxx b/chart2/source/controller/dialogs/dlg_ChartType_UNO.cxx
new file mode 100644
index 0000000000..0e95cd75c4
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_ChartType_UNO.cxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_ChartType_UNO.hxx>
+#include <dlg_ChartType.hxx>
+#include <ChartModel.hxx>
+#include <servicenames.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+namespace com::sun::star::awt { class XWindow; }
+
+namespace chart
+{
+using namespace ::com::sun::star;
+ChartTypeUnoDlg::ChartTypeUnoDlg( const uno::Reference< uno::XComponentContext >& _xContext )
+ : ChartTypeUnoDlg_BASE( _xContext )
+{
+}
+ChartTypeUnoDlg::~ChartTypeUnoDlg()
+{
+ // we do this here cause the base class' call to destroyDialog won't reach us anymore: we're within a dtor,
+ // so this virtual-method-call the base class does not work, we're already dead then...
+ if (m_xDialog)
+ {
+ ::osl::MutexGuard aGuard(m_aMutex);
+ if (m_xDialog)
+ destroyDialog();
+ }
+}
+// lang::XServiceInfo
+OUString SAL_CALL ChartTypeUnoDlg::getImplementationName()
+{
+ return CHART_TYPE_DIALOG_SERVICE_IMPLEMENTATION_NAME;
+}
+
+css::uno::Sequence<OUString> SAL_CALL ChartTypeUnoDlg::getSupportedServiceNames()
+{
+ return { CHART_TYPE_DIALOG_SERVICE_NAME };
+}
+uno::Sequence< sal_Int8 > SAL_CALL ChartTypeUnoDlg::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+void ChartTypeUnoDlg::implInitialize(const uno::Any& _rValue)
+{
+ beans::PropertyValue aProperty;
+ if (_rValue >>= aProperty)
+ {
+ if (aProperty.Name == "ChartModel")
+ {
+ uno::Reference<XInterface> xInt;
+ aProperty.Value >>= xInt;
+ assert(dynamic_cast<::chart::ChartModel*>(xInt.get()));
+ m_xChartModel = dynamic_cast<::chart::ChartModel*>(xInt.get());
+ }
+ else
+ ChartTypeUnoDlg_BASE::implInitialize(_rValue);
+ }
+ else
+ ChartTypeUnoDlg_BASE::implInitialize(_rValue);
+}
+
+std::unique_ptr<weld::DialogController> ChartTypeUnoDlg::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+{
+ ChartModel* pChartModel = dynamic_cast<ChartModel*>(rParent.get());
+ assert(pChartModel);
+ return std::make_unique<ChartTypeDialog>(Application::GetFrameWeld(rParent), pChartModel);
+}
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL ChartTypeUnoDlg::getPropertySetInfo()
+{
+ return createPropertySetInfo( getInfoHelper() );
+}
+
+::cppu::IPropertyArrayHelper& ChartTypeUnoDlg::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* ChartTypeUnoDlg::createArrayHelper( ) const
+{
+ uno::Sequence< beans::Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+} //namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_ChartTypeDialog_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new chart::ChartTypeUnoDlg(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_CreationWizard.cxx b/chart2/source/controller/dialogs/dlg_CreationWizard.cxx
new file mode 100644
index 0000000000..12d2280579
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_CreationWizard.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_CreationWizard.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+#include <helpids.h>
+#include <ChartModel.hxx>
+
+#include "tp_ChartType.hxx"
+#include "tp_RangeChooser.hxx"
+#include "tp_Wizard_TitlesAndObjects.hxx"
+#include "tp_DataSource.hxx"
+#include <ChartTypeTemplateProvider.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <utility>
+#include "DialogModel.hxx"
+
+using namespace css;
+
+using vcl::RoadmapWizardTypes::WizardPath;
+
+namespace chart
+{
+#define PATH_FULL 1
+#define STATE_FIRST 0
+#define STATE_CHARTTYPE STATE_FIRST
+#define STATE_SIMPLE_RANGE 1
+#define STATE_DATA_SERIES 2
+#define STATE_OBJECTS 3
+#define STATE_LAST STATE_OBJECTS
+
+CreationWizard::CreationWizard(weld::Window* pParent, const rtl::Reference<::chart::ChartModel>& xChartModel,
+ uno::Reference<uno::XComponentContext> xContext)
+ : vcl::RoadmapWizardMachine(pParent)
+ , m_xChartModel(xChartModel,uno::UNO_QUERY)
+ , m_xComponentContext(std::move(xContext))
+ , m_pTemplateProvider(nullptr)
+ , m_aTimerTriggeredControllerLock(xChartModel)
+ , m_bCanTravel(true)
+{
+ m_pDialogModel.reset(new DialogModel(m_xChartModel));
+ defaultButton(WizardButtonFlags::FINISH);
+
+ setTitleBase(SchResId(STR_DLG_CHART_WIZARD));
+
+ // tdf#134386 set m_pTemplateProvider before creating any other pages
+ m_pTemplateProvider = static_cast<ChartTypeTabPage*>(GetOrCreatePage(STATE_CHARTTYPE));
+ assert(m_pTemplateProvider && "must exist");
+ m_pDialogModel->setTemplate(m_pTemplateProvider->getCurrentTemplate());
+
+ WizardPath aPath = {
+ STATE_CHARTTYPE,
+ STATE_SIMPLE_RANGE,
+ STATE_DATA_SERIES,
+ STATE_OBJECTS
+ };
+
+ declarePath(PATH_FULL, aPath);
+
+ // tdf#135935 ensure help ID is set when no element is clicked in the dialog
+ m_xAssistant->set_help_id(HID_SCH_WIZARD_ROADMAP);
+
+ if (!m_pDialogModel->getModel().isDataFromSpreadsheet())
+ {
+ enableState(STATE_SIMPLE_RANGE, false);
+ enableState(STATE_DATA_SERIES, false);
+ }
+
+ // Call ActivatePage, to create and activate the first page
+ ActivatePage();
+
+ m_xAssistant->set_current_page(0);
+}
+
+CreationWizard::~CreationWizard() = default;
+
+std::unique_ptr<BuilderPage> CreationWizard::createPage(WizardState nState)
+{
+ std::unique_ptr<vcl::OWizardPage> xRet;
+
+ OUString sIdent(OUString::number(nState));
+ weld::Container* pPageContainer = m_xAssistant->append_page(sIdent);
+
+ switch( nState )
+ {
+ case STATE_CHARTTYPE:
+ {
+ m_aTimerTriggeredControllerLock.startTimer();
+ xRet = std::make_unique<ChartTypeTabPage>(pPageContainer, this, m_xChartModel);
+ break;
+ }
+ case STATE_SIMPLE_RANGE:
+ {
+ m_aTimerTriggeredControllerLock.startTimer();
+ xRet = std::make_unique<RangeChooserTabPage>(pPageContainer, this, *m_pDialogModel, m_pTemplateProvider);
+ break;
+ }
+ case STATE_DATA_SERIES:
+ {
+ m_aTimerTriggeredControllerLock.startTimer();
+ xRet = std::make_unique<DataSourceTabPage>(pPageContainer, this, *m_pDialogModel, m_pTemplateProvider);
+ break;
+ }
+ case STATE_OBJECTS:
+ {
+ xRet = std::make_unique<TitlesAndObjectsTabPage>(pPageContainer, this, m_xChartModel, m_xComponentContext);
+ m_aTimerTriggeredControllerLock.startTimer();
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (xRet)
+ xRet->SetPageTitle(OUString()); //remove title of pages to not get them in the wizard title
+
+ return xRet;
+}
+
+bool CreationWizard::leaveState( WizardState /*_nState*/ )
+{
+ return m_bCanTravel;
+}
+
+vcl::WizardTypes::WizardState CreationWizard::determineNextState( WizardState nCurrentState ) const
+{
+ if( !m_bCanTravel )
+ return WZS_INVALID_STATE;
+ if( nCurrentState == STATE_LAST )
+ return WZS_INVALID_STATE;
+ vcl::WizardTypes::WizardState nNextState = nCurrentState + 1;
+ while( !isStateEnabled( nNextState ) && nNextState <= STATE_LAST )
+ ++nNextState;
+ return (nNextState==STATE_LAST+1) ? WZS_INVALID_STATE : nNextState;
+}
+
+void CreationWizard::enterState(WizardState nState)
+{
+ m_aTimerTriggeredControllerLock.startTimer();
+ enableButtons( WizardButtonFlags::PREVIOUS, nState > STATE_FIRST );
+ enableButtons( WizardButtonFlags::NEXT, nState < STATE_LAST );
+ if( isStateEnabled( nState ))
+ vcl::RoadmapWizardMachine::enterState(nState);
+}
+
+void CreationWizard::setInvalidPage(BuilderPage* pTabPage)
+{
+ if (pTabPage == m_pCurTabPage)
+ m_bCanTravel = false;
+}
+
+void CreationWizard::setValidPage(BuilderPage* pTabPage)
+{
+ if (pTabPage == m_pCurTabPage)
+ m_bCanTravel = true;
+}
+
+OUString CreationWizard::getStateDisplayName( WizardState nState ) const
+{
+ TranslateId pResId;
+ switch( nState )
+ {
+ case STATE_CHARTTYPE:
+ pResId = STR_PAGE_CHARTTYPE;
+ break;
+ case STATE_SIMPLE_RANGE:
+ pResId = STR_PAGE_DATA_RANGE;
+ break;
+ case STATE_DATA_SERIES:
+ pResId = STR_OBJECT_DATASERIES_PLURAL;
+ break;
+ case STATE_OBJECTS:
+ pResId = STR_PAGE_CHART_ELEMENTS;
+ break;
+ default:
+ break;
+ }
+ if (!pResId)
+ return OUString();
+ return SchResId(pResId);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx b/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx
new file mode 100644
index 0000000000..3a1fa1386f
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx
@@ -0,0 +1,362 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_CreationWizard_UNO.hxx>
+#include <dlg_CreationWizard.hxx>
+#include <ChartModel.hxx>
+#include <servicenames.hxx>
+#include <TimerTriggeredControllerLock.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <vcl/weldutils.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <sfx2/viewsh.hxx>
+
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+CreationWizardUnoDlg::CreationWizardUnoDlg(uno::Reference<uno::XComponentContext> xContext)
+ : OComponentHelper(m_aMutex)
+ , m_xCC(std::move(xContext))
+ , m_bUnlockControllersOnExecute(false)
+{
+ uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(m_xCC);
+ uno::Reference< frame::XTerminateListener > xListener( this );
+ xDesktop->addTerminateListener( xListener );
+}
+
+CreationWizardUnoDlg::~CreationWizardUnoDlg()
+{
+ SolarMutexGuard aSolarGuard;
+ m_xDialog.reset();
+}
+
+// lang::XServiceInfo
+OUString SAL_CALL CreationWizardUnoDlg::getImplementationName()
+{
+ return CHART_WIZARD_DIALOG_SERVICE_IMPLEMENTATION_NAME;
+}
+
+sal_Bool SAL_CALL CreationWizardUnoDlg::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL CreationWizardUnoDlg::getSupportedServiceNames()
+{
+ return { CHART_WIZARD_DIALOG_SERVICE_NAME };
+}
+
+// XInterface
+uno::Any SAL_CALL CreationWizardUnoDlg::queryInterface( const uno::Type& aType )
+{
+ return OComponentHelper::queryInterface( aType );
+}
+void SAL_CALL CreationWizardUnoDlg::acquire() noexcept
+{
+ OComponentHelper::acquire();
+}
+void SAL_CALL CreationWizardUnoDlg::release() noexcept
+{
+ OComponentHelper::release();
+}
+uno::Any SAL_CALL CreationWizardUnoDlg::queryAggregation( uno::Type const & rType )
+{
+ if (rType == cppu::UnoType<ui::dialogs::XAsynchronousExecutableDialog>::get())
+ {
+ void * p = static_cast< ui::dialogs::XAsynchronousExecutableDialog * >( this );
+ return uno::Any( &p, rType );
+ }
+ else if (rType == cppu::UnoType<lang::XServiceInfo>::get())
+ {
+ void * p = static_cast< lang::XServiceInfo * >( this );
+ return uno::Any( &p, rType );
+ }
+ else if (rType == cppu::UnoType<lang::XInitialization>::get())
+ {
+ void * p = static_cast< lang::XInitialization * >( this );
+ return uno::Any( &p, rType );
+ }
+ else if (rType == cppu::UnoType<frame::XTerminateListener>::get())
+ {
+ void * p = static_cast< frame::XTerminateListener * >( this );
+ return uno::Any( &p, rType );
+ }
+ else if (rType == cppu::UnoType<beans::XPropertySet>::get())
+ {
+ void * p = static_cast< beans::XPropertySet * >( this );
+ return uno::Any( &p, rType );
+ }
+ return OComponentHelper::queryAggregation( rType );
+}
+
+uno::Sequence< uno::Type > CreationWizardUnoDlg::getTypes()
+{
+ static uno::Sequence<uno::Type> aTypeList{ cppu::UnoType<lang::XComponent>::get(),
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<uno::XAggregation>::get(),
+ cppu::UnoType<uno::XWeak>::get(),
+ cppu::UnoType<lang::XServiceInfo>::get(),
+ cppu::UnoType<lang::XInitialization>::get(),
+ cppu::UnoType<frame::XTerminateListener>::get(),
+ cppu::UnoType<ui::dialogs::XAsynchronousExecutableDialog>::get(),
+ cppu::UnoType<beans::XPropertySet>::get() };
+ return aTypeList;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL CreationWizardUnoDlg::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XTerminateListener
+void SAL_CALL CreationWizardUnoDlg::queryTermination( const lang::EventObject& /*Event*/ )
+{
+}
+
+void SAL_CALL CreationWizardUnoDlg::notifyTermination( const lang::EventObject& /*Event*/ )
+{
+ // we are going down, so dispose us!
+ dispose();
+}
+
+void SAL_CALL CreationWizardUnoDlg::disposing( const lang::EventObject& /*Source*/ )
+{
+ //Listener should deregister himself and release all references to the closing object.
+}
+
+void SAL_CALL CreationWizardUnoDlg::setDialogTitle( const OUString& /*rTitle*/ )
+{
+}
+void CreationWizardUnoDlg::createDialogOnDemand()
+{
+ SolarMutexGuard aSolarGuard;
+ if (m_xDialog)
+ return;
+
+ if( !m_xParentWindow.is() && m_xChartModel.is() )
+ {
+ uno::Reference< frame::XController > xController(
+ m_xChartModel->getCurrentController() );
+ if( xController.is() )
+ {
+ uno::Reference< frame::XFrame > xFrame(
+ xController->getFrame() );
+ if(xFrame.is())
+ m_xParentWindow = xFrame->getContainerWindow();
+ }
+ }
+
+ weld::Window* pParent(Application::GetFrameWeld(m_xParentWindow));
+ if (!pParent)
+ {
+ if (weld::TransportAsXWindow* pTunnel = dynamic_cast<weld::TransportAsXWindow*>(m_xParentWindow.get()))
+ pParent = dynamic_cast<weld::Window*>(pTunnel->getWidget());
+ }
+
+ uno::Reference< XComponent > xKeepAlive( this );
+ if( m_xChartModel.is() )
+ {
+ m_xDialog = std::make_shared<CreationWizard>(pParent, m_xChartModel, m_xCC);
+ }
+}
+
+IMPL_STATIC_LINK_NOARG(CreationWizardUnoDlg, InstallLOKNotifierHdl, void*, vcl::ILibreOfficeKitNotifier*)
+{
+ return SfxViewShell::Current();
+}
+
+void SAL_CALL CreationWizardUnoDlg::startExecuteModal( const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& xListener )
+{
+ SolarMutexGuard aSolarGuard;
+ createDialogOnDemand();
+
+ if( !m_xDialog )
+ return;
+
+ m_xDialog->getDialog()->SetInstallLOKNotifierHdl(
+ LINK(this, CreationWizardUnoDlg, InstallLOKNotifierHdl));
+
+ TimerTriggeredControllerLock aTimerTriggeredControllerLock( m_xChartModel );
+ if( m_bUnlockControllersOnExecute && m_xChartModel.is() )
+ m_xChartModel->unlockControllers();
+
+ CreationWizardUnoDlg* xThat = this;
+ weld::DialogController::runAsync(m_xDialog, [xListener, xThat](sal_Int32 nResult){
+ if( xListener.is() )
+ {
+ ::css::uno::Reference< ::css::uno::XInterface > xSource;
+ // Notify UNO listener to perform correct action depending on the result
+ css::ui::dialogs::DialogClosedEvent aEvent( xSource, nResult );
+ xListener->dialogClosed( aEvent );
+ }
+ xThat->m_xDialog.reset();
+ });
+}
+
+void SAL_CALL CreationWizardUnoDlg::initialize( const uno::Sequence< uno::Any >& aArguments )
+{
+ for(const uno::Any& rArgument : aArguments)
+ {
+ beans::PropertyValue aProperty;
+ if(rArgument >>= aProperty)
+ {
+ if( aProperty.Name == "ParentWindow" )
+ {
+ aProperty.Value >>= m_xParentWindow;
+ }
+ else if( aProperty.Name == "ChartModel" )
+ {
+ uno::Reference<XInterface> xInt;
+ aProperty.Value >>= xInt;
+ m_xChartModel = dynamic_cast<::chart::ChartModel*>(xInt.get());
+ assert(m_xChartModel);
+ }
+ }
+ }
+}
+
+// ____ OComponentHelper ____
+/// Called in dispose method after the listeners were notified.
+void SAL_CALL CreationWizardUnoDlg::disposing()
+{
+ m_xChartModel.clear();
+ m_xParentWindow.clear();
+
+ SolarMutexGuard aSolarGuard;
+ m_xDialog.reset();
+
+ try
+ {
+ uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(m_xCC);
+ uno::Reference< frame::XTerminateListener > xListener( this );
+ xDesktop->removeTerminateListener( xListener );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+//XPropertySet
+uno::Reference< beans::XPropertySetInfo > SAL_CALL CreationWizardUnoDlg::getPropertySetInfo()
+{
+ OSL_FAIL("not implemented");
+ return nullptr;
+}
+
+void SAL_CALL CreationWizardUnoDlg::setPropertyValue(const OUString& rPropertyName,
+ const uno::Any& rValue)
+{
+ if( rPropertyName == "Position" )
+ {
+ SolarMutexGuard aSolarGuard;
+ createDialogOnDemand();
+
+ //read only property, do nothing else
+ }
+ else if( rPropertyName == "Size")
+ {
+ //read only property, do nothing
+ }
+ else if( rPropertyName == "UnlockControllersOnExecute" )
+ {
+ if( ! (rValue >>= m_bUnlockControllersOnExecute) )
+ throw lang::IllegalArgumentException( "Property 'UnlockControllers' requires value of type boolean" , nullptr, 0 );
+ }
+ else
+ throw beans::UnknownPropertyException( "unknown property was tried to set to chart wizard" , nullptr );
+}
+
+uno::Any SAL_CALL CreationWizardUnoDlg::getPropertyValue( const OUString& rPropertyName )
+{
+ uno::Any aRet;
+ if( rPropertyName == "Position" )
+ {
+ //get left upper outer corner relative to screen
+ //pixels, screen position
+ SolarMutexGuard aSolarGuard;
+ createDialogOnDemand();
+ if (m_xDialog)
+ {
+ Point aPos(m_xDialog->getDialog()->get_position());
+ awt::Point aPoint(aPos.X(), aPos.Y());
+ aRet <<= aPoint;
+ }
+ }
+ else if( rPropertyName == "Size" )
+ {
+ //get outer size inclusive decoration
+ //pixels, screen position
+ SolarMutexGuard aSolarGuard;
+ createDialogOnDemand();
+ if (m_xDialog)
+ {
+ Size aRect(m_xDialog->getDialog()->get_size());
+ awt::Size aSize(aRect.Width(), aRect.Height());
+ aRet <<= aSize;
+ }
+ }
+ else if( rPropertyName == "UnlockControllersOnExecute" )
+ {
+ aRet <<= m_bUnlockControllersOnExecute;
+ }
+ else
+ throw beans::UnknownPropertyException( "unknown property was tried to get from chart wizard" , nullptr );
+ return aRet;
+}
+
+void SAL_CALL CreationWizardUnoDlg::addPropertyChangeListener(
+ const OUString& /* aPropertyName */, const uno::Reference< beans::XPropertyChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL CreationWizardUnoDlg::removePropertyChangeListener(
+ const OUString& /* aPropertyName */, const uno::Reference< beans::XPropertyChangeListener >& /* aListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL CreationWizardUnoDlg::addVetoableChangeListener( const OUString& /* PropertyName */, const uno::Reference< beans::XVetoableChangeListener >& /* aListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL CreationWizardUnoDlg::removeVetoableChangeListener( const OUString& /* PropertyName */, const uno::Reference< beans::XVetoableChangeListener >& /* aListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+} //namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_WizardDialog_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new chart::CreationWizardUnoDlg(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_DataEditor.cxx b/chart2/source/controller/dialogs/dlg_DataEditor.cxx
new file mode 100644
index 0000000000..367b1d183a
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_DataEditor.cxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_DataEditor.hxx>
+#include "DataBrowser.hxx"
+#include <ChartModel.hxx>
+#include <comphelper/stl_types.hxx>
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <utility>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+DataEditor::DataEditor(weld::Window* pParent,
+ rtl::Reference<::chart::ChartModel> xChartDoc,
+ const Reference< uno::XComponentContext > & xContext)
+ : GenericDialogController(pParent, "modules/schart/ui/chartdatadialog.ui", "ChartDataDialog")
+ , m_bReadOnly(false)
+ , m_xChartDoc(std::move(xChartDoc))
+ , m_xContext(xContext)
+ , m_xTbxData(m_xBuilder->weld_toolbar("toolbar"))
+ , m_xCloseBtn(m_xBuilder->weld_button("close"))
+ , m_xTable(m_xBuilder->weld_container("datawindow"))
+ , m_xColumns(m_xBuilder->weld_container("columns"))
+ , m_xColors(m_xBuilder->weld_container("colorcolumns"))
+ , m_xTableCtrlParent(m_xTable->CreateChildFrame())
+ , m_xBrwData(VclPtr<DataBrowser>::Create(m_xTableCtrlParent, m_xColumns.get(), m_xColors.get()))
+{
+ m_xCloseBtn->connect_clicked(LINK(this, DataEditor, CloseHdl));
+
+ Size aSize(m_xTable->get_approximate_digit_width() * 75, m_xTable->get_text_height() * 15);
+ m_xTable->set_size_request(aSize.Width(), aSize.Height());
+
+ m_xBrwData->Show();
+
+ m_xTbxData->connect_clicked(LINK(this, DataEditor, ToolboxHdl));
+
+ m_xBrwData->SetCursorMovedHdl( LINK( this, DataEditor, BrowserCursorMovedHdl ));
+
+ m_xBrwData->SetDataFromModel( m_xChartDoc );
+ m_xBrwData->GrabFocus();
+
+ bool bReadOnly = true;
+ if( m_xChartDoc.is())
+ bReadOnly = m_xChartDoc->isReadonly();
+ SetReadOnly( bReadOnly );
+}
+
+DataEditor::~DataEditor()
+{
+ m_xBrwData.disposeAndClear();
+ m_xTableCtrlParent->dispose();
+ m_xTableCtrlParent.clear();
+}
+
+// react on click (or keypress) on toolbar icon
+IMPL_LINK(DataEditor, ToolboxHdl, const OUString&, rId, void)
+{
+ if (rId == "InsertRow")
+ m_xBrwData->InsertRow();
+ else if (rId == "InsertColumn")
+ m_xBrwData->InsertColumn();
+ else if (rId == "InsertTextColumn")
+ m_xBrwData->InsertTextColumn();
+ else if (rId == "RemoveRow")
+ m_xBrwData->RemoveRow();
+ else if (rId == "RemoveColumn")
+ m_xBrwData->RemoveColumn();
+ else if (rId == "MoveLeftColumn")
+ m_xBrwData->MoveLeftColumn();
+ else if (rId == "MoveRightColumn")
+ m_xBrwData->MoveRightColumn();
+ else if (rId == "MoveUpRow")
+ m_xBrwData->MoveUpRow();
+ else if (rId == "MoveDownRow")
+ m_xBrwData->MoveDownRow();
+}
+
+// refresh toolbar icons according to currently selected cell in browse box
+IMPL_LINK_NOARG(DataEditor, BrowserCursorMovedHdl, DataBrowser*, void)
+{
+ if( m_bReadOnly )
+ return;
+
+ bool bIsDataValid = m_xBrwData->IsEnableItem();
+
+ m_xTbxData->set_item_sensitive("InsertRow", bIsDataValid && m_xBrwData->MayInsertRow() );
+ m_xTbxData->set_item_sensitive("InsertColumn", bIsDataValid && m_xBrwData->MayInsertColumn() );
+ m_xTbxData->set_item_sensitive("InsertTextColumn", bIsDataValid && m_xBrwData->MayInsertColumn() );
+ m_xTbxData->set_item_sensitive("RemoveRow", m_xBrwData->MayDeleteRow() );
+ m_xTbxData->set_item_sensitive("RemoveColumn", m_xBrwData->MayDeleteColumn() );
+
+ m_xTbxData->set_item_sensitive("MoveLeftColumn", bIsDataValid && m_xBrwData->MayMoveLeftColumns() );
+ m_xTbxData->set_item_sensitive("MoveRightColumn", bIsDataValid && m_xBrwData->MayMoveRightColumns() );
+ m_xTbxData->set_item_sensitive("MoveDownRow", bIsDataValid && m_xBrwData->MayMoveDownRows() );
+ m_xTbxData->set_item_sensitive("MoveUpRow", bIsDataValid && m_xBrwData->MayMoveUpRows() );
+}
+
+// disable all modifying controls
+void DataEditor::SetReadOnly( bool bReadOnly )
+{
+ m_bReadOnly = bReadOnly;
+ if( m_bReadOnly )
+ {
+ m_xTbxData->set_item_sensitive("InsertRow", false);
+ m_xTbxData->set_item_sensitive("InsertColumn", false);
+ m_xTbxData->set_item_sensitive("InsertTextColumn", false);
+ m_xTbxData->set_item_sensitive("RemoveRow", false);
+ m_xTbxData->set_item_sensitive("RemoveColumn", false);
+ m_xTbxData->set_item_sensitive("MoveLeftColumn", false);
+ m_xTbxData->set_item_sensitive("MoveRightColumn", false);
+ m_xTbxData->set_item_sensitive("MoveUpRow", false);
+ m_xTbxData->set_item_sensitive("MoveDownRow", false);
+ }
+
+ m_xBrwData->SetReadOnly( m_bReadOnly );
+}
+
+IMPL_LINK_NOARG(DataEditor, CloseHdl, weld::Button&, void)
+{
+ bool bApplied = m_xBrwData->EndEditing(); // apply changes to model
+ if (bApplied)
+ m_xDialog->response(RET_CLOSE);
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_DataSource.cxx b/chart2/source/controller/dialogs/dlg_DataSource.cxx
new file mode 100644
index 0000000000..1eb6202deb
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_DataSource.cxx
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/chart2/XChartDocument.hpp>
+
+#include <dlg_DataSource.hxx>
+#include <ChartTypeTemplateProvider.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include "DialogModel.hxx"
+#include <ChartModel.hxx>
+
+#include "tp_RangeChooser.hxx"
+#include "tp_DataSource.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart;
+
+namespace chart
+{
+
+namespace {
+
+class DocumentChartTypeTemplateProvider : public ChartTypeTemplateProvider
+{
+public:
+ explicit DocumentChartTypeTemplateProvider(
+ const rtl::Reference<::chart::ChartModel> & xDoc );
+
+ // ____ ChartTypeTemplateProvider ____
+ virtual rtl::Reference< ::chart::ChartTypeTemplate > getCurrentTemplate() const override;
+
+private:
+ rtl::Reference< ::chart::ChartTypeTemplate > m_xTemplate;
+};
+
+}
+
+DocumentChartTypeTemplateProvider::DocumentChartTypeTemplateProvider(
+ const rtl::Reference<::chart::ChartModel> & xDoc )
+{
+ if( !xDoc.is())
+ return;
+
+ rtl::Reference< Diagram > xDia( xDoc->getFirstChartDiagram());
+ if( xDia.is())
+ {
+ Diagram::tTemplateWithServiceName aResult(
+ xDia->getTemplate( xDoc->getTypeManager() ));
+ m_xTemplate = aResult.xChartTypeTemplate;
+ }
+}
+
+rtl::Reference< ::chart::ChartTypeTemplate > DocumentChartTypeTemplateProvider::getCurrentTemplate() const
+{
+ return m_xTemplate;
+}
+
+sal_uInt16 DataSourceDialog::m_nLastPageId = 0;
+
+DataSourceDialog::DataSourceDialog(weld::Window * pParent,
+ const rtl::Reference<::chart::ChartModel> & xChartDocument)
+ : GenericDialogController(pParent, "modules/schart/ui/datarangedialog.ui",
+ "DataRangeDialog")
+ , m_apDocTemplateProvider(new DocumentChartTypeTemplateProvider(xChartDocument))
+ , m_apDialogModel(new DialogModel(xChartDocument))
+ , m_bRangeChooserTabIsValid(true)
+ , m_bDataSourceTabIsValid(true)
+ , m_bTogglingEnabled(true)
+ , m_xTabControl(m_xBuilder->weld_notebook("tabcontrol"))
+ , m_xBtnOK(m_xBuilder->weld_button("ok"))
+{
+ m_xRangeChooserTabPage = std::make_unique<RangeChooserTabPage>(m_xTabControl->get_page("range"), this,
+ *m_apDialogModel,
+ m_apDocTemplateProvider.get(), true /* bHideDescription */ );
+ m_xDataSourceTabPage = std::make_unique<DataSourceTabPage>(m_xTabControl->get_page("series"), this,
+ *m_apDialogModel,
+ m_apDocTemplateProvider.get(), true /* bHideDescription */ );
+ m_xTabControl->connect_enter_page(LINK(this, DataSourceDialog, ActivatePageHdl));
+ m_xTabControl->connect_leave_page(LINK(this, DataSourceDialog, DeactivatePageHdl));
+ ActivatePageHdl(m_xTabControl->get_current_page_ident());
+ if (m_nLastPageId != 0)
+ {
+ m_xTabControl->set_current_page(m_nLastPageId);
+ ActivatePageHdl(m_xTabControl->get_current_page_ident());
+ }
+}
+
+DataSourceDialog::~DataSourceDialog()
+{
+ m_xRangeChooserTabPage.reset();
+ m_xDataSourceTabPage.reset();
+ m_nLastPageId = m_xTabControl->get_current_page();
+}
+
+short DataSourceDialog::run()
+{
+ short nResult = GenericDialogController::run();
+ if( nResult == RET_OK )
+ {
+ if( m_xRangeChooserTabPage )
+ m_xRangeChooserTabPage->commitPage();
+ if( m_xDataSourceTabPage )
+ m_xDataSourceTabPage->commitPage();
+ }
+ return nResult;
+}
+
+IMPL_LINK(DataSourceDialog, ActivatePageHdl, const OUString&, rPage, void)
+{
+ if (rPage == "range")
+ m_xRangeChooserTabPage->Activate();
+ else if (rPage == "series")
+ m_xDataSourceTabPage->Activate();
+}
+
+// allow/disallow user to leave page
+IMPL_LINK_NOARG(DataSourceDialog, DeactivatePageHdl, const OUString&, bool)
+{
+ return m_bTogglingEnabled;
+}
+
+void DataSourceDialog::setInvalidPage(BuilderPage* pTabPage)
+{
+ if (pTabPage == m_xRangeChooserTabPage.get())
+ m_bRangeChooserTabIsValid = false;
+ else if (pTabPage == m_xDataSourceTabPage.get())
+ m_bDataSourceTabIsValid = false;
+
+ if (!(m_bRangeChooserTabIsValid && m_bDataSourceTabIsValid))
+ {
+ m_xBtnOK->set_sensitive(false);
+ // note: there seems to be no suitable mechanism to address pages by
+ // identifier, at least it is unclear what the page identifiers are.
+ // @todo: change the fixed numbers to identifiers
+ if( m_bRangeChooserTabIsValid )
+ m_xTabControl->set_current_page(1);
+ else if( m_bDataSourceTabIsValid )
+ m_xTabControl->set_current_page(0);
+ m_bTogglingEnabled = false;
+ }
+}
+
+void DataSourceDialog::setValidPage(BuilderPage* pTabPage)
+{
+ if( pTabPage == m_xRangeChooserTabPage.get() )
+ m_bRangeChooserTabIsValid = true;
+ else if( pTabPage == m_xDataSourceTabPage.get() )
+ m_bDataSourceTabIsValid = true;
+
+ if (m_bRangeChooserTabIsValid && m_bDataSourceTabIsValid)
+ {
+ m_xBtnOK->set_sensitive(true);
+ m_bTogglingEnabled = true;
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx b/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx
new file mode 100644
index 0000000000..6a79bac4a4
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_InsertAxis_Grid.hxx>
+
+namespace chart
+{
+
+InsertAxisOrGridDialogData::InsertAxisOrGridDialogData()
+ : aPossibilityList{ true, true, true, true, true, true }
+ , aExistenceList{ false, false, false, false, false, false }
+{
+}
+
+// SchAxisDlg
+
+SchAxisDlg::SchAxisDlg(weld::Window* pWindow,
+ const InsertAxisOrGridDialogData& rInput, bool bAxisDlg)
+ : GenericDialogController(pWindow,
+ bAxisDlg ?
+ OUString("modules/schart/ui/insertaxisdlg.ui") :
+ OUString("modules/schart/ui/insertgriddlg.ui"),
+ bAxisDlg ?
+ OUString("InsertAxisDialog") :
+ OUString("InsertGridDialog"))
+ , m_xCbPrimaryX(m_xBuilder->weld_check_button("primaryX"))
+ , m_xCbPrimaryY(m_xBuilder->weld_check_button("primaryY"))
+ , m_xCbPrimaryZ(m_xBuilder->weld_check_button("primaryZ"))
+ , m_xCbSecondaryX(m_xBuilder->weld_check_button("secondaryX"))
+ , m_xCbSecondaryY(m_xBuilder->weld_check_button("secondaryY"))
+ , m_xCbSecondaryZ(m_xBuilder->weld_check_button("secondaryZ"))
+{
+ if (bAxisDlg)
+ {
+ //todo: remove if secondary z axis are possible somewhere
+ m_xCbSecondaryZ->hide();
+ }
+
+ m_xCbPrimaryX->set_active( rInput.aExistenceList[0] );
+ m_xCbPrimaryY->set_active( rInput.aExistenceList[1] );
+ m_xCbPrimaryZ->set_active( rInput.aExistenceList[2] );
+ m_xCbSecondaryX->set_active( rInput.aExistenceList[3] );
+ m_xCbSecondaryY->set_active( rInput.aExistenceList[4] );
+ m_xCbSecondaryZ->set_active( rInput.aExistenceList[5] );
+
+ m_xCbPrimaryX->set_sensitive( rInput.aPossibilityList[0] );
+ m_xCbPrimaryY->set_sensitive( rInput.aPossibilityList[1] );
+ m_xCbPrimaryZ->set_sensitive( rInput.aPossibilityList[2] );
+ m_xCbSecondaryX->set_sensitive( rInput.aPossibilityList[3] );
+ m_xCbSecondaryY->set_sensitive( rInput.aPossibilityList[4] );
+ m_xCbSecondaryZ->set_sensitive( rInput.aPossibilityList[5] );
+}
+
+void SchAxisDlg::getResult( InsertAxisOrGridDialogData& rOutput )
+{
+ sal_Bool* pExistenceList = rOutput.aExistenceList.getArray();
+ pExistenceList[0]=m_xCbPrimaryX->get_active();
+ pExistenceList[1]=m_xCbPrimaryY->get_active();
+ pExistenceList[2]=m_xCbPrimaryZ->get_active();
+ pExistenceList[3]=m_xCbSecondaryX->get_active();
+ pExistenceList[4]=m_xCbSecondaryY->get_active();
+ pExistenceList[5]=m_xCbSecondaryZ->get_active();
+}
+
+SchGridDlg::SchGridDlg(weld::Window* pParent, const InsertAxisOrGridDialogData& rInput)
+ : SchAxisDlg(pParent, rInput, false) //rInAttrs, b3D, bNet, bSecondaryX, bSecondaryY, false )
+{
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_InsertDataLabel.cxx b/chart2/source/controller/dialogs/dlg_InsertDataLabel.cxx
new file mode 100644
index 0000000000..57817d883d
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_InsertDataLabel.cxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_InsertDataLabel.hxx>
+#include "res_DataLabel.hxx"
+
+namespace chart
+{
+
+DataLabelsDialog::DataLabelsDialog(weld::Window* pWindow, const SfxItemSet& rInAttrs, SvNumberFormatter* pFormatter)
+ : GenericDialogController(pWindow, "modules/schart/ui/dlg_DataLabel.ui", "dlg_DataLabels")
+ , m_apDataLabelResources(new DataLabelResources(m_xBuilder.get(), pWindow, rInAttrs))
+{
+ m_apDataLabelResources->SetNumberFormatter( pFormatter );
+ m_apDataLabelResources->Reset(rInAttrs);
+}
+
+DataLabelsDialog::~DataLabelsDialog() = default;
+
+void DataLabelsDialog::FillItemSet(SfxItemSet& rOutAttrs)
+{
+ m_apDataLabelResources->FillItemSet(&rOutAttrs);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_InsertDataTable.cxx b/chart2/source/controller/dialogs/dlg_InsertDataTable.cxx
new file mode 100644
index 0000000000..4b5e928db0
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_InsertDataTable.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <dlg_InsertDataTable.hxx>
+
+namespace chart
+{
+InsertDataTableDialog::InsertDataTableDialog(weld::Window* pWindow)
+ : GenericDialogController(pWindow, "modules/schart/ui/dlg_InsertDataTable.ui",
+ "InsertDataTableDialog")
+ , m_aDataTablePropertiesResources(*m_xBuilder)
+ , m_xCbShowDataTable(m_xBuilder->weld_check_button("showDataTable"))
+{
+ m_xCbShowDataTable->connect_toggled(LINK(this, InsertDataTableDialog, ShowDataTableToggle));
+ init(m_aData);
+}
+
+IMPL_LINK_NOARG(InsertDataTableDialog, ShowDataTableToggle, weld::Toggleable&, void)
+{
+ changeEnabled();
+}
+
+void InsertDataTableDialog::changeEnabled()
+{
+ bool bEnable = m_xCbShowDataTable->get_active();
+ m_aDataTablePropertiesResources.setChecksSensitive(bEnable);
+ m_aData.mbShow = bEnable;
+}
+
+void InsertDataTableDialog::init(DataTableDialogData const& rData)
+{
+ m_aData = rData;
+ m_aDataTablePropertiesResources.setHorizontalBorder(m_aData.mbHorizontalBorders);
+ m_aDataTablePropertiesResources.setVerticalBorder(m_aData.mbVerticalBorders);
+ m_aDataTablePropertiesResources.setOutline(m_aData.mbOutline);
+ m_aDataTablePropertiesResources.setKeys(m_aData.mbKeys);
+ m_xCbShowDataTable->set_active(m_aData.mbShow);
+ changeEnabled();
+}
+
+DataTableDialogData& InsertDataTableDialog::getDataTableDialogData()
+{
+ m_aData.mbShow = m_xCbShowDataTable->get_active();
+
+ m_aData.mbHorizontalBorders = m_aDataTablePropertiesResources.getHorizontalBorder();
+ m_aData.mbVerticalBorders = m_aDataTablePropertiesResources.getVerticalBorder();
+ m_aData.mbOutline = m_aDataTablePropertiesResources.getOutline();
+ m_aData.mbKeys = m_aDataTablePropertiesResources.getKeys();
+
+ return m_aData;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_InsertErrorBars.cxx b/chart2/source/controller/dialogs/dlg_InsertErrorBars.cxx
new file mode 100644
index 0000000000..807e902856
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_InsertErrorBars.cxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_InsertErrorBars.hxx>
+#include <res_ErrorBar.hxx>
+#include <chartview/ExplicitScaleValues.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <ChartView.hxx>
+#include <ObjectIdentifier.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <ObjectNameProvider.hxx>
+#include <DataSeries.hxx>
+
+#include <comphelper/servicehelper.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+namespace chart
+{
+
+InsertErrorBarsDialog::InsertErrorBarsDialog(
+ weld::Window* pParent, const SfxItemSet& rMyAttrs,
+ const rtl::Reference<::chart::ChartModel> & xChartDocument,
+ ErrorBarResources::tErrorBarType eType /* = ErrorBarResources::ERROR_BAR_Y */ )
+ : GenericDialogController(pParent, "modules/schart/ui/dlg_InsertErrorBars.ui", "dlg_InsertErrorBars")
+ , m_apErrorBarResources( new ErrorBarResources(
+ m_xBuilder.get(), this, rMyAttrs,
+ /* bNoneAvailable = */ true, eType ))
+{
+ ObjectType objType = eType == ErrorBarResources::ERROR_BAR_Y ? OBJECTTYPE_DATA_ERRORS_Y : OBJECTTYPE_DATA_ERRORS_X;
+
+ m_xDialog->set_title(ObjectNameProvider::getName_ObjectForAllSeries(objType));
+
+ m_apErrorBarResources->SetChartDocumentForRangeChoosing( xChartDocument );
+}
+
+void InsertErrorBarsDialog::FillItemSet(SfxItemSet& rOutAttrs)
+{
+ m_apErrorBarResources->FillItemSet(rOutAttrs);
+}
+
+void InsertErrorBarsDialog::SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth )
+{
+ m_apErrorBarResources->SetAxisMinorStepWidthForErrorBarDecimals( fMinorStepWidth );
+}
+
+double InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals(
+ const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const rtl::Reference<::chart::ChartView>& xChartView,
+ std::u16string_view rSelectedObjectCID )
+{
+ double fStepWidth = 0.001;
+
+ ExplicitValueProvider* pExplicitValueProvider( xChartView.get() );
+ if( pExplicitValueProvider )
+ {
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rSelectedObjectCID, xChartModel );
+ rtl::Reference< Axis > xAxis = xDiagram->getAttachedAxis( xSeries );
+ if(!xAxis.is())
+ xAxis = AxisHelper::getAxis( 1/*nDimensionIndex*/, true/*bMainAxis*/, xDiagram );
+ if(xAxis.is())
+ {
+ ExplicitScaleData aExplicitScale;
+ ExplicitIncrementData aExplicitIncrement;
+ pExplicitValueProvider->getExplicitValuesForAxis( xAxis,aExplicitScale, aExplicitIncrement );
+
+ fStepWidth = aExplicitIncrement.Distance;
+ if( !aExplicitIncrement.SubIncrements.empty() && aExplicitIncrement.SubIncrements[0].IntervalCount>0 )
+ fStepWidth=fStepWidth/double(aExplicitIncrement.SubIncrements[0].IntervalCount);
+ else
+ fStepWidth/=10;
+ }
+ }
+
+ return fStepWidth;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_InsertLegend.cxx b/chart2/source/controller/dialogs/dlg_InsertLegend.cxx
new file mode 100644
index 0000000000..c55ecc3e88
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_InsertLegend.cxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_InsertLegend.hxx>
+#include <res_LegendPosition.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+SchLegendDlg::SchLegendDlg(weld::Window* pWindow, const uno::Reference<uno::XComponentContext>& xCC)
+ : GenericDialogController(pWindow, "modules/schart/ui/dlg_InsertLegend.ui", "dlg_InsertLegend")
+ , m_xLegendPositionResources(new LegendPositionResources(*m_xBuilder, xCC))
+{
+}
+
+void SchLegendDlg::init(const rtl::Reference<::chart::ChartModel>& xChartModel)
+{
+ m_xLegendPositionResources->writeToResources(xChartModel);
+}
+
+void SchLegendDlg::writeToModel(const rtl::Reference<::chart::ChartModel>& xChartModel) const
+{
+ m_xLegendPositionResources->writeToModel(xChartModel);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_InsertTitle.cxx b/chart2/source/controller/dialogs/dlg_InsertTitle.cxx
new file mode 100644
index 0000000000..03f9429458
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_InsertTitle.cxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_InsertTitle.hxx>
+#include <res_Titles.hxx>
+#include <ObjectNameProvider.hxx>
+
+namespace chart
+{
+SchTitleDlg::SchTitleDlg(weld::Window* pWindow, const TitleDialogData& rInput)
+ : GenericDialogController(pWindow, "modules/schart/ui/inserttitledlg.ui", "InsertTitleDialog")
+ , m_xTitleResources(new TitleResources(*m_xBuilder, true))
+{
+ m_xDialog->set_title(ObjectNameProvider::getName(OBJECTTYPE_TITLE, true));
+ m_xTitleResources->writeToResources(rInput);
+}
+
+void SchTitleDlg::getResult(TitleDialogData& rOutput)
+{
+ m_xTitleResources->readFromResources(rOutput);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_NumberFormat.cxx b/chart2/source/controller/dialogs/dlg_NumberFormat.cxx
new file mode 100644
index 0000000000..f5cfe8e3bd
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_NumberFormat.cxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "dlg_NumberFormat.hxx"
+
+#include <svl/itemset.hxx>
+#include <svx/dialogs.hrc>
+#include <svx/svxids.hrc>
+#include <sfx2/tabdlg.hxx>
+#include <sfx2/sfxdlg.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+NumberFormatDialog::NumberFormatDialog(weld::Window* pParent, const SfxItemSet& rSet)
+ : SfxSingleTabDialogController(pParent, &rSet, "cui/ui/formatnumberdialog.ui", "FormatNumberDialog")
+ , m_xContent( m_xBuilder->weld_container("content") )
+{
+ SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
+ ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SVXPAGE_NUMBERFORMAT );
+ if (fnCreatePage)
+ {
+ std::unique_ptr<SfxTabPage> xTabPage = (*fnCreatePage)(m_xContent.get(), this, &rSet);
+ xTabPage->PageCreated(rSet);
+ SetTabPage(std::move(xTabPage));
+ }
+}
+
+SfxItemSet NumberFormatDialog::CreateEmptyItemSetForNumberFormatDialog( SfxItemPool& rItemPool )
+{
+ return SfxItemSet( rItemPool, svl::Items<
+ SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO,
+ SID_ATTR_NUMBERFORMAT_ONE_AREA, SID_ATTR_NUMBERFORMAT_ONE_AREA,
+ SID_ATTR_NUMBERFORMAT_NOLANGUAGE, SID_ATTR_NUMBERFORMAT_NOLANGUAGE,
+ SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE> );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_NumberFormat.hxx b/chart2/source/controller/dialogs/dlg_NumberFormat.hxx
new file mode 100644
index 0000000000..be02edeb62
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_NumberFormat.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/basedlgs.hxx>
+
+namespace weld
+{
+class Window;
+class Container;
+}
+class SfxItemSet;
+class SfxItemPool;
+
+namespace chart
+{
+class NumberFormatDialog : public SfxSingleTabDialogController
+{
+ std::unique_ptr<weld::Container> m_xContent;
+
+public:
+ NumberFormatDialog(weld::Window* pParent, const SfxItemSet& rSet);
+
+ static SfxItemSet CreateEmptyItemSetForNumberFormatDialog(SfxItemPool& rItemPool);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx b/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx
new file mode 100644
index 0000000000..e885fdaef3
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx
@@ -0,0 +1,638 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cstddef>
+
+#include <dlg_ObjectProperties.hxx>
+#include <strings.hrc>
+#include "tp_AxisLabel.hxx"
+#include "tp_DataLabel.hxx"
+#include "tp_LegendPosition.hxx"
+#include "tp_PointGeometry.hxx"
+#include "tp_Scale.hxx"
+#include "tp_AxisPositions.hxx"
+#include "tp_ErrorBars.hxx"
+#include "tp_Trendline.hxx"
+#include "tp_SeriesToAxis.hxx"
+#include "tp_TitleRotation.hxx"
+#include "tp_PolarOptions.hxx"
+#include "tp_DataPointOption.hxx"
+#include "tp_DataTable.hxx"
+#include <ResId.hxx>
+#include <ViewElementListProvider.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ObjectNameProvider.hxx>
+#include <DataSeries.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <ChartModel.hxx>
+#include <CommonConverters.hxx>
+#include <RegressionCalculationHelper.hxx>
+#include <BaseCoordinateSystem.hxx>
+
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/XAxis.hpp>
+#include <svl/intitem.hxx>
+#include <svl/ctloptions.hxx>
+
+#include <svx/svxids.hrc>
+
+#include <svx/drawitem.hxx>
+#include <svx/ofaitem.hxx>
+#include <svx/svxgraphicitem.hxx>
+
+#include <svx/dialogs.hrc>
+#include <editeng/flstitem.hxx>
+
+#include <svx/flagsdef.hxx>
+#include <svx/numinf.hxx>
+
+#include <svl/cjkoptions.hxx>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace com::sun::star::chart2 { class XChartType; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::beans::XPropertySet;
+
+ObjectPropertiesDialogParameter::ObjectPropertiesDialogParameter( OUString aObjectCID )
+ : m_aObjectCID(std::move( aObjectCID ))
+ , m_eObjectType( ObjectIdentifier::getObjectType( m_aObjectCID ) )
+ , m_bAffectsMultipleObjects(false)
+ , m_bHasGeometryProperties(false)
+ , m_bHasStatisticProperties(false)
+ , m_bProvidesSecondaryYAxis(false)
+ , m_bProvidesOverlapAndGapWidth(false)
+ , m_bProvidesBarConnectors(false)
+ , m_bHasAreaProperties(false)
+ , m_bHasSymbolProperties(false)
+ , m_bHasNumberProperties(false)
+ , m_bProvidesStartingAngle(false)
+ , m_bProvidesMissingValueTreatments(false)
+ , m_bIsPieChartDataPoint(false)
+ , m_bHasScaleProperties(false)
+ , m_bCanAxisLabelsBeStaggered(false)
+ , m_bSupportingAxisPositioning(false)
+ , m_bShowAxisOrigin(false)
+ , m_bIsCrossingAxisIsCategoryAxis(false)
+ , m_bSupportingCategoryPositioning(false)
+ , m_bComplexCategoriesAxis( false )
+ , m_nNbPoints( 0 )
+{
+ std::u16string_view aParticleID = ObjectIdentifier::getParticleID( m_aObjectCID );
+ m_bAffectsMultipleObjects = (aParticleID == u"ALLELEMENTS");
+}
+ObjectPropertiesDialogParameter::~ObjectPropertiesDialogParameter()
+{
+}
+
+void ObjectPropertiesDialogParameter::init( const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ m_xChartDocument = xChartModel;
+ rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aObjectCID, xChartModel );
+ rtl::Reference< ChartType > xChartType = ChartModelHelper::getChartTypeOfSeries( xChartModel, xSeries );
+ sal_Int32 nDimensionCount = 0;
+ if (xDiagram)
+ nDimensionCount = xDiagram->getDimension();
+
+ bool bHasSeriesProperties = (m_eObjectType==OBJECTTYPE_DATA_SERIES);
+ bool bHasDataPointproperties = (m_eObjectType==OBJECTTYPE_DATA_POINT);
+
+ if( bHasSeriesProperties || bHasDataPointproperties )
+ {
+ m_bHasGeometryProperties = ChartTypeHelper::isSupportingGeometryProperties( xChartType, nDimensionCount );
+ m_bHasAreaProperties = ChartTypeHelper::isSupportingAreaProperties( xChartType, nDimensionCount );
+ m_bHasSymbolProperties = ChartTypeHelper::isSupportingSymbolProperties( xChartType, nDimensionCount );
+ m_bIsPieChartDataPoint = bHasDataPointproperties && ChartTypeHelper::isSupportingStartingAngle( xChartType );
+
+ if( bHasSeriesProperties )
+ {
+ m_bHasStatisticProperties = ChartTypeHelper::isSupportingStatisticProperties( xChartType, nDimensionCount );
+ m_bProvidesSecondaryYAxis = ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount );
+ m_bProvidesOverlapAndGapWidth = ChartTypeHelper::isSupportingOverlapAndGapWidthProperties( xChartType, nDimensionCount );
+ m_bProvidesBarConnectors = ChartTypeHelper::isSupportingBarConnectors( xChartType, nDimensionCount );
+ m_bProvidesStartingAngle = ChartTypeHelper::isSupportingStartingAngle( xChartType );
+
+ m_bProvidesMissingValueTreatments = ChartTypeHelper::getSupportedMissingValueTreatments( xChartType )
+ .hasElements();
+ }
+ }
+
+ if( m_eObjectType == OBJECTTYPE_DATA_ERRORS_X ||
+ m_eObjectType == OBJECTTYPE_DATA_ERRORS_Y ||
+ m_eObjectType == OBJECTTYPE_DATA_ERRORS_Z)
+ m_bHasStatisticProperties = true;
+
+ if( m_eObjectType == OBJECTTYPE_AXIS )
+ {
+ //show scale properties only for a single axis not for multiselection
+ m_bHasScaleProperties = !m_bAffectsMultipleObjects;
+
+ if( m_bHasScaleProperties )
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( m_aObjectCID, xChartModel );
+ if( xAxis.is() )
+ {
+ //no scale page for series axis
+ ScaleData aData( xAxis->getScaleData() );
+ if( aData.AxisType == chart2::AxisType::SERIES )
+ m_bHasScaleProperties = false;
+ if( aData.AxisType != chart2::AxisType::SERIES )
+ m_bHasNumberProperties = true;
+
+ //is the crossing main axis a category axes?:
+ rtl::Reference< BaseCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( xAxis, xDiagram ) );
+ uno::Reference< XAxis > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, xCooSys ) );
+ if( xCrossingMainAxis.is() )
+ {
+ ScaleData aScale( xCrossingMainAxis->getScaleData() );
+ m_bIsCrossingAxisIsCategoryAxis = ( aScale.AxisType == chart2::AxisType::CATEGORY );
+ if( m_bIsCrossingAxisIsCategoryAxis )
+ {
+ if (xChartModel)
+ m_aCategories = DiagramHelper::getExplicitSimpleCategories( *xChartModel );
+ }
+ }
+
+ sal_Int32 nCooSysIndex=0;
+ sal_Int32 nDimensionIndex=0;
+ sal_Int32 nAxisIndex=0;
+ if( AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex ) )
+ {
+ xChartType = AxisHelper::getFirstChartTypeWithSeriesAttachedToAxisIndex( xDiagram, nAxisIndex );
+ //show positioning controls only if they make sense
+ m_bSupportingAxisPositioning = ChartTypeHelper::isSupportingAxisPositioning( xChartType, nDimensionCount, nDimensionIndex );
+
+ //show axis origin only for secondary y axis
+ if( nDimensionIndex==1 && nAxisIndex==1 && ChartTypeHelper::isSupportingBaseValue( xChartType ) )
+ m_bShowAxisOrigin = true;
+
+ if ( nDimensionIndex == 0 && ( aData.AxisType == chart2::AxisType::CATEGORY || aData.AxisType == chart2::AxisType::DATE ) )
+ {
+ if (xChartModel)
+ {
+ ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, *xChartModel );
+ m_bComplexCategoriesAxis = aExplicitCategoriesProvider.hasComplexCategories();
+ }
+
+ if (!m_bComplexCategoriesAxis)
+ m_bSupportingCategoryPositioning = ChartTypeHelper::isSupportingCategoryPositioning( xChartType, nDimensionCount );
+ }
+ }
+ }
+ }
+
+ //no staggering of labels for 3D axis
+ m_bCanAxisLabelsBeStaggered = nDimensionCount==2;
+ }
+
+ if( m_eObjectType == OBJECTTYPE_DATA_CURVE )
+ {
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aDataSeqs( xSeries->getDataSequences2());
+ Sequence< double > aXValues, aYValues;
+ bool bXValuesFound = false, bYValuesFound = false;
+ m_nNbPoints = 0;
+ for( std::size_t i=0;
+ ! (bXValuesFound && bYValuesFound) && i<aDataSeqs.size();
+ ++i )
+ {
+ try
+ {
+ Reference< data::XDataSequence > xSeq( aDataSeqs[i]->getValues());
+ Reference< XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
+ OUString aRole;
+ if( xProp->getPropertyValue( "Role" ) >>= aRole )
+ {
+ if( !bXValuesFound && aRole == "values-x" )
+ {
+ aXValues = DataSequenceToDoubleSequence( xSeq );
+ bXValuesFound = true;
+ }
+ else if( !bYValuesFound && aRole == "values-y" )
+ {
+ aYValues = DataSequenceToDoubleSequence( xSeq );
+ bYValuesFound = true;
+ }
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ if( !bXValuesFound && bYValuesFound )
+ {
+ // initialize with 1, 2, ...
+ //first category (index 0) matches with real number 1.0
+ aXValues.realloc( aYValues.getLength() );
+ auto pXValues = aXValues.getArray();
+ for( sal_Int32 i=0; i<aXValues.getLength(); ++i )
+ pXValues[i] = i+1;
+ bXValuesFound = true;
+ }
+
+ if( bXValuesFound && bYValuesFound &&
+ aXValues.hasElements() &&
+ aYValues.hasElements() )
+ {
+ RegressionCalculationHelper::tDoubleVectorPair aValues(
+ RegressionCalculationHelper::cleanup( aXValues, aYValues, RegressionCalculationHelper::isValid()));
+ m_nNbPoints = aValues.second.size();
+ }
+ }
+
+ //create gui name for this object
+ {
+ if( !m_bAffectsMultipleObjects && m_eObjectType == OBJECTTYPE_AXIS )
+ {
+ m_aLocalizedName = ObjectNameProvider::getAxisName( m_aObjectCID, xChartModel );
+ }
+ else if( !m_bAffectsMultipleObjects && ( m_eObjectType == OBJECTTYPE_GRID || m_eObjectType == OBJECTTYPE_SUBGRID ) )
+ {
+ m_aLocalizedName = ObjectNameProvider::getGridName( m_aObjectCID, xChartModel );
+ }
+ else if( !m_bAffectsMultipleObjects && m_eObjectType == OBJECTTYPE_TITLE )
+ {
+ m_aLocalizedName = ObjectNameProvider::getTitleName( m_aObjectCID, xChartModel );
+ }
+ else
+ {
+ switch( m_eObjectType )
+ {
+ case OBJECTTYPE_DATA_POINT:
+ case OBJECTTYPE_DATA_LABEL:
+ case OBJECTTYPE_DATA_LABELS:
+ case OBJECTTYPE_DATA_ERRORS_X:
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ case OBJECTTYPE_DATA_CURVE:
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ if( m_bAffectsMultipleObjects )
+ m_aLocalizedName = ObjectNameProvider::getName_ObjectForAllSeries( m_eObjectType );
+ else
+ m_aLocalizedName = ObjectNameProvider::getName_ObjectForSeries( m_eObjectType, m_aObjectCID, m_xChartDocument );
+ break;
+ default:
+ m_aLocalizedName = ObjectNameProvider::getName(m_eObjectType,m_bAffectsMultipleObjects);
+ break;
+ }
+ }
+ }
+}
+
+const sal_uInt16 nNoArrowNoShadowDlg = 1101;
+
+void SchAttribTabDlg::setSymbolInformation( SfxItemSet&& rSymbolShapeProperties,
+ std::optional<Graphic> oAutoSymbolGraphic )
+{
+ m_oSymbolShapeProperties.emplace(std::move(rSymbolShapeProperties));
+ m_oAutoSymbolGraphic = std::move(oAutoSymbolGraphic);
+}
+
+void SchAttribTabDlg::SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth )
+{
+ m_fAxisMinorStepWidthForErrorBarDecimals = fMinorStepWidth;
+}
+
+SchAttribTabDlg::SchAttribTabDlg(weld::Window* pParent,
+ const SfxItemSet* pAttr,
+ const ObjectPropertiesDialogParameter* pDialogParameter,
+ const ViewElementListProvider* pViewElementListProvider,
+ const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier)
+ : SfxTabDialogController(pParent, "modules/schart/ui/attributedialog.ui", "AttributeDialog", pAttr)
+ , m_pParameter( pDialogParameter )
+ , m_pViewElementListProvider( pViewElementListProvider )
+ , m_pNumberFormatter(nullptr)
+ , m_fAxisMinorStepWidthForErrorBarDecimals(0.1)
+ , m_bOKPressed(false)
+{
+ NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
+ m_pNumberFormatter = aNumberFormatterWrapper.getSvNumberFormatter();
+
+ m_xDialog->set_title(pDialogParameter->getLocalizedName());
+
+ switch (pDialogParameter->getObjectType())
+ {
+ case OBJECTTYPE_TITLE:
+ AddTabPage("border", SchResId(STR_PAGE_BORDER), RID_SVXPAGE_LINE);
+ AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA);
+ AddTabPage("transparent", SchResId(STR_PAGE_TRANSPARENCY), RID_SVXPAGE_TRANSPARENCE);
+ AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME);
+ AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS);
+ AddTabPage("alignment", SchResId(STR_PAGE_ALIGNMENT), SchAlignmentTabPage::Create);
+ if( SvtCJKOptions::IsAsianTypographyEnabled() )
+ AddTabPage("asian", SchResId(STR_PAGE_ASIAN), RID_SVXPAGE_PARA_ASIAN);
+ break;
+
+ case OBJECTTYPE_LEGEND:
+ AddTabPage("border", SchResId(STR_PAGE_BORDER), RID_SVXPAGE_LINE);
+ AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA);
+ AddTabPage("transparent", SchResId(STR_PAGE_TRANSPARENCY), RID_SVXPAGE_TRANSPARENCE);
+ AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME);
+ AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS);
+ AddTabPage("legendpos", SchResId(STR_PAGE_POSITION), SchLegendPosTabPage::Create);
+ if (SvtCJKOptions::IsAsianTypographyEnabled())
+ AddTabPage("asian", SchResId(STR_PAGE_ASIAN), RID_SVXPAGE_PARA_ASIAN);
+ break;
+
+ case OBJECTTYPE_DATA_SERIES:
+ case OBJECTTYPE_DATA_POINT:
+ if( m_pParameter->ProvidesSecondaryYAxis() || m_pParameter->ProvidesOverlapAndGapWidth() || m_pParameter->ProvidesMissingValueTreatments() )
+ AddTabPage("options", SchResId(STR_PAGE_OPTIONS),SchOptionTabPage::Create);
+ if( m_pParameter->ProvidesStartingAngle())
+ AddTabPage("polaroptions", SchResId(STR_PAGE_OPTIONS), PolarOptionsTabPage::Create);
+ if (m_pParameter->IsPieChartDataPoint())
+ AddTabPage("datapointoption", SchResId(STR_PAGE_OPTIONS), DataPointOptionTabPage::Create);
+
+ if( m_pParameter->HasGeometryProperties() )
+ AddTabPage("layout", SchResId(STR_PAGE_LAYOUT), SchLayoutTabPage::Create);
+
+ if(m_pParameter->HasAreaProperties())
+ {
+ AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA);
+ AddTabPage("transparent", SchResId(STR_PAGE_TRANSPARENCY), RID_SVXPAGE_TRANSPARENCE);
+ }
+ AddTabPage("border", SchResId( m_pParameter->HasAreaProperties() ? STR_PAGE_BORDER : STR_PAGE_LINE ), RID_SVXPAGE_LINE);
+ break;
+
+ case OBJECTTYPE_DATA_LABEL:
+ case OBJECTTYPE_DATA_LABELS:
+ AddTabPage("border", SchResId(STR_PAGE_BORDER), RID_SVXPAGE_LINE);
+ AddTabPage("datalabels", SchResId(STR_OBJECT_DATALABELS), DataLabelsTabPage::Create);
+ AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME);
+ AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS);
+ if( SvtCJKOptions::IsAsianTypographyEnabled() )
+ AddTabPage("asian", SchResId(STR_PAGE_ASIAN), RID_SVXPAGE_PARA_ASIAN);
+
+ break;
+
+ case OBJECTTYPE_AXIS:
+ {
+ if( m_pParameter->HasScaleProperties() )
+ {
+ AddTabPage("scale", SchResId(STR_PAGE_SCALE), ScaleTabPage::Create);
+ //no positioning page for z axes so far as the tickmarks are not shown so far
+ AddTabPage("axispos", SchResId(STR_PAGE_POSITIONING), AxisPositionsTabPage::Create);
+ }
+ AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE);
+ AddTabPage("axislabel", SchResId(STR_OBJECT_LABEL), SchAxisLabelTabPage::Create);
+ if( m_pParameter->HasNumberProperties() )
+ AddTabPage("numberformat", SchResId(STR_PAGE_NUMBERS), RID_SVXPAGE_NUMBERFORMAT);
+ AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME);
+ AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS);
+ if( SvtCJKOptions::IsAsianTypographyEnabled() )
+ AddTabPage("asian", SchResId(STR_PAGE_ASIAN), RID_SVXPAGE_PARA_ASIAN);
+ break;
+ }
+
+ case OBJECTTYPE_DATA_ERRORS_X:
+ AddTabPage("xerrorbar", SchResId(STR_PAGE_XERROR_BARS), ErrorBarsTabPage::Create);
+ AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE);
+ break;
+
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ AddTabPage("yerrorbar", SchResId(STR_PAGE_YERROR_BARS), ErrorBarsTabPage::Create);
+ AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE);
+ break;
+
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ break;
+
+ case OBJECTTYPE_GRID:
+ case OBJECTTYPE_SUBGRID:
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ case OBJECTTYPE_DATA_STOCK_RANGE:
+ AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE);
+ break;
+
+ case OBJECTTYPE_DATA_CURVE:
+ AddTabPage("trendline", SchResId(STR_PAGE_TRENDLINE_TYPE), TrendlineTabPage::Create);
+ AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE);
+ break;
+
+ case OBJECTTYPE_DATA_STOCK_LOSS:
+ case OBJECTTYPE_DATA_STOCK_GAIN:
+ case OBJECTTYPE_PAGE:
+ case OBJECTTYPE_DIAGRAM_FLOOR:
+ case OBJECTTYPE_DIAGRAM_WALL:
+ case OBJECTTYPE_DIAGRAM:
+ AddTabPage("border", SchResId(STR_PAGE_BORDER), RID_SVXPAGE_LINE);
+ AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA);
+ AddTabPage("transparent", SchResId(STR_PAGE_TRANSPARENCY), RID_SVXPAGE_TRANSPARENCE);
+ break;
+
+ case OBJECTTYPE_LEGEND_ENTRY:
+ case OBJECTTYPE_AXIS_UNITLABEL:
+ case OBJECTTYPE_UNKNOWN:
+ // nothing
+ break;
+ case OBJECTTYPE_DATA_TABLE:
+ AddTabPage("datatable", SchResId(STR_DATA_TABLE), DataTableTabPage::Create);
+ AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE);
+ AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA);
+ AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME);
+ AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS);
+ break;
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ AddTabPage("border", SchResId(STR_PAGE_BORDER), RID_SVXPAGE_LINE);
+ AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA);
+ AddTabPage("transparent", SchResId(STR_PAGE_TRANSPARENCY), RID_SVXPAGE_TRANSPARENCE);
+ AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME);
+ AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS);
+ AddTabPage("numberformat", SchResId(STR_PAGE_NUMBERS), RID_SVXPAGE_NUMBERFORMAT);
+ if (SvtCTLOptions::IsCTLFontEnabled())
+ {
+ /* When rotation is supported for equation text boxes, use
+ SchAlignmentTabPage::Create here. The special
+ SchAlignmentTabPage::CreateWithoutRotation can be deleted. */
+ AddTabPage("alignment", SchResId(STR_PAGE_ALIGNMENT), SchAlignmentTabPage::CreateWithoutRotation);
+ }
+ break;
+ default:
+ break;
+ }
+
+ // used to find out if user left the dialog with OK. When OK is pressed but
+ // no changes were done, Cancel is returned by the SfxTabDialog. See method
+ // DialogWasClosedWithOK.
+ GetOKButton().connect_clicked(LINK(this, SchAttribTabDlg, OKPressed));
+}
+
+SchAttribTabDlg::~SchAttribTabDlg()
+{
+}
+
+void SchAttribTabDlg::PageCreated(const OUString& rId, SfxTabPage &rPage)
+{
+ SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool()));
+ if (rId == "border")
+ {
+ aSet.Put (SvxColorListItem(m_pViewElementListProvider->GetColorTable(),SID_COLOR_TABLE));
+ aSet.Put (SvxDashListItem(m_pViewElementListProvider->GetDashList(),SID_DASH_LIST));
+ aSet.Put (SvxLineEndListItem(m_pViewElementListProvider->GetLineEndList(),SID_LINEEND_LIST));
+ aSet.Put (SfxUInt16Item(SID_PAGE_TYPE,0));
+ aSet.Put (SfxUInt16Item(SID_DLG_TYPE,nNoArrowNoShadowDlg));
+
+ if( m_pParameter->HasSymbolProperties() )
+ {
+ aSet.Put(OfaPtrItem(SID_OBJECT_LIST,m_pViewElementListProvider->GetSymbolList()));
+ if( m_oSymbolShapeProperties )
+ aSet.Put(SfxTabDialogItem(SID_ATTR_SET, *m_oSymbolShapeProperties));
+ if( m_oAutoSymbolGraphic )
+ aSet.Put(SvxGraphicItem(*m_oAutoSymbolGraphic));
+ }
+ rPage.PageCreated(aSet);
+ }
+ else if (rId == "area")
+ {
+ aSet.Put(SvxColorListItem(m_pViewElementListProvider->GetColorTable(),SID_COLOR_TABLE));
+ aSet.Put(SvxGradientListItem(m_pViewElementListProvider->GetGradientList(),SID_GRADIENT_LIST));
+ aSet.Put(SvxHatchListItem(m_pViewElementListProvider->GetHatchList(),SID_HATCH_LIST));
+ aSet.Put(SvxBitmapListItem(m_pViewElementListProvider->GetBitmapList(),SID_BITMAP_LIST));
+ aSet.Put(SvxPatternListItem(m_pViewElementListProvider->GetPatternList(),SID_PATTERN_LIST));
+ aSet.Put(SfxUInt16Item(SID_PAGE_TYPE,0));
+ aSet.Put(SfxUInt16Item(SID_DLG_TYPE,nNoArrowNoShadowDlg));
+ rPage.PageCreated(aSet);
+ }
+ else if (rId == "transparent")
+ {
+ aSet.Put (SfxUInt16Item(SID_PAGE_TYPE,0));
+ aSet.Put (SfxUInt16Item(SID_DLG_TYPE,nNoArrowNoShadowDlg));
+ rPage.PageCreated(aSet);
+ }
+ else if (rId == "fontname")
+ {
+ aSet.Put (SvxFontListItem(m_pViewElementListProvider->getFontList(), SID_ATTR_CHAR_FONTLIST));
+ rPage.PageCreated(aSet);
+ }
+ else if (rId == "effects")
+ {
+ aSet.Put (SfxUInt16Item(SID_DISABLE_CTL,DISABLE_CASEMAP));
+ rPage.PageCreated(aSet);
+ }
+ else if (rId == "axislabel")
+ {
+ bool bShowStaggeringControls = m_pParameter->CanAxisLabelsBeStaggered();
+ auto & rLabelPage = static_cast<SchAxisLabelTabPage&>(rPage);
+ rLabelPage.ShowStaggeringControls( bShowStaggeringControls );
+ rLabelPage.SetComplexCategories( m_pParameter->IsComplexCategoriesAxis() );
+ }
+ else if (rId == "axispos")
+ {
+ AxisPositionsTabPage* pPage = dynamic_cast< AxisPositionsTabPage* >( &rPage );
+ if(pPage)
+ {
+ pPage->SetNumFormatter( m_pNumberFormatter );
+ if( m_pParameter->IsCrossingAxisIsCategoryAxis() )
+ {
+ pPage->SetCrossingAxisIsCategoryAxis( m_pParameter->IsCrossingAxisIsCategoryAxis() );
+ pPage->SetCategories( m_pParameter->GetCategories() );
+ }
+ pPage->SupportAxisPositioning( m_pParameter->IsSupportingAxisPositioning() );
+ pPage->SupportCategoryPositioning( m_pParameter->IsSupportingCategoryPositioning() );
+ }
+ }
+ else if (rId == "scale")
+ {
+ ScaleTabPage* pScaleTabPage = dynamic_cast< ScaleTabPage* >( &rPage );
+ if(pScaleTabPage)
+ {
+ pScaleTabPage->SetNumFormatter( m_pNumberFormatter );
+ pScaleTabPage->ShowAxisOrigin( m_pParameter->ShowAxisOrigin() );
+ }
+ }
+ else if (rId == "datalabels")
+ {
+ DataLabelsTabPage* pLabelPage = dynamic_cast< DataLabelsTabPage* >( &rPage );
+ if( pLabelPage )
+ pLabelPage->SetNumberFormatter( m_pNumberFormatter );
+ }
+ else if (rId == "numberformat")
+ {
+ aSet.Put (SvxNumberInfoItem( m_pNumberFormatter, SID_ATTR_NUMBERFORMAT_INFO));
+ rPage.PageCreated(aSet);
+ }
+ else if (rId == "xerrorbar")
+ {
+ ErrorBarsTabPage * pTabPage = dynamic_cast< ErrorBarsTabPage * >( &rPage );
+ OSL_ASSERT( pTabPage );
+ if( pTabPage )
+ {
+ pTabPage->SetAxisMinorStepWidthForErrorBarDecimals( m_fAxisMinorStepWidthForErrorBarDecimals );
+ pTabPage->SetErrorBarType( ErrorBarResources::ERROR_BAR_X );
+ pTabPage->SetChartDocumentForRangeChoosing( m_pParameter->getDocument());
+ }
+ }
+ else if (rId == "yerrorbar")
+ {
+ ErrorBarsTabPage * pTabPage = dynamic_cast< ErrorBarsTabPage * >( &rPage );
+ OSL_ASSERT( pTabPage );
+ if( pTabPage )
+ {
+ pTabPage->SetAxisMinorStepWidthForErrorBarDecimals( m_fAxisMinorStepWidthForErrorBarDecimals );
+ pTabPage->SetErrorBarType( ErrorBarResources::ERROR_BAR_Y );
+ pTabPage->SetChartDocumentForRangeChoosing( m_pParameter->getDocument());
+ }
+ }
+ else if (rId == "options")
+ {
+ SchOptionTabPage* pTabPage = dynamic_cast< SchOptionTabPage* >( &rPage );
+ if( pTabPage && m_pParameter )
+ pTabPage->Init( m_pParameter->ProvidesSecondaryYAxis(), m_pParameter->ProvidesOverlapAndGapWidth(),
+ m_pParameter->ProvidesBarConnectors() );
+ }
+ else if (rId == "trendline")
+ {
+ TrendlineTabPage* pTrendlineTabPage = dynamic_cast< TrendlineTabPage* >( &rPage );
+ if(pTrendlineTabPage)
+ {
+ pTrendlineTabPage->SetNumFormatter( m_pNumberFormatter );
+ pTrendlineTabPage->SetNbPoints( m_pParameter->getNbPoints() );
+ }
+ }
+}
+
+IMPL_LINK(SchAttribTabDlg, OKPressed, weld::Button&, rButton, void)
+{
+ m_bOKPressed = true;
+ OkHdl(rButton);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_ShapeFont.cxx b/chart2/source/controller/dialogs/dlg_ShapeFont.cxx
new file mode 100644
index 0000000000..b742e8a22e
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_ShapeFont.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_ShapeFont.hxx>
+#include <ViewElementListProvider.hxx>
+
+#include <svl/intitem.hxx>
+#include <svx/dialogs.hrc>
+#include <svx/svxids.hrc>
+#include <svx/flagsdef.hxx>
+#include <editeng/flstitem.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+ShapeFontDialog::ShapeFontDialog(weld::Window* pParent, const SfxItemSet* pAttr,
+ const ViewElementListProvider* pViewElementListProvider)
+ : SfxTabDialogController(pParent, "modules/schart/ui/chardialog.ui", "CharDialog", pAttr)
+ , m_pViewElementListProvider(pViewElementListProvider)
+{
+ AddTabPage("font", RID_SVXPAGE_CHAR_NAME);
+ AddTabPage("fonteffects", RID_SVXPAGE_CHAR_EFFECTS);
+ AddTabPage("position", RID_SVXPAGE_CHAR_POSITION );
+}
+
+void ShapeFontDialog::PageCreated(const OUString& rId, SfxTabPage& rPage)
+{
+ SfxAllItemSet aSet( *( GetInputSetImpl()->GetPool() ) );
+ if (rId == "font")
+ {
+ aSet.Put( SvxFontListItem( m_pViewElementListProvider->getFontList(), SID_ATTR_CHAR_FONTLIST ) );
+ rPage.PageCreated( aSet );
+ }
+ else if (rId == "fonteffects")
+ {
+ aSet.Put( SfxUInt16Item( SID_DISABLE_CTL, DISABLE_CASEMAP ) );
+ rPage.PageCreated( aSet );
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_ShapeParagraph.cxx b/chart2/source/controller/dialogs/dlg_ShapeParagraph.cxx
new file mode 100644
index 0000000000..4c72d4d812
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_ShapeParagraph.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_ShapeParagraph.hxx>
+
+#include <svl/cjkoptions.hxx>
+#include <svl/intitem.hxx>
+#include <svx/dialogs.hrc>
+#include <svx/svxids.hrc>
+#include <svx/flagsdef.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+ShapeParagraphDialog::ShapeParagraphDialog(weld::Window* pParent,
+ const SfxItemSet* pAttr)
+ : SfxTabDialogController(pParent, "modules/schart/ui/paradialog.ui", "ParagraphDialog", pAttr)
+{
+ AddTabPage("labelTP_PARA_STD", RID_SVXPAGE_STD_PARAGRAPH);
+ AddTabPage("labelTP_PARA_ALIGN", RID_SVXPAGE_ALIGN_PARAGRAPH );
+ if (SvtCJKOptions::IsAsianTypographyEnabled())
+ {
+ AddTabPage("labelTP_PARA_ASIAN", RID_SVXPAGE_PARA_ASIAN);
+ }
+ else
+ {
+ RemoveTabPage("labelTP_PARA_ASIAN");
+ }
+ AddTabPage("labelTP_TABULATOR", RID_SVXPAGE_TABULATOR);
+}
+
+void ShapeParagraphDialog::PageCreated(const OUString& rId, SfxTabPage& rPage)
+{
+ if (rId == "labelTP_TABULATOR")
+ {
+ SfxAllItemSet aSet( *( GetInputSetImpl()->GetPool() ) );
+ TabulatorDisableFlags const nFlags(( TabulatorDisableFlags::TypeMask &~TabulatorDisableFlags::TypeLeft ) |
+ ( TabulatorDisableFlags::FillMask &~TabulatorDisableFlags::FillNone ));
+ aSet.Put( SfxUInt16Item( SID_SVXTABULATORTABPAGE_DISABLEFLAGS, static_cast<sal_uInt16>(nFlags)) );
+ rPage.PageCreated( aSet );
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/dlg_View3D.cxx b/chart2/source/controller/dialogs/dlg_View3D.cxx
new file mode 100644
index 0000000000..1891ffff67
--- /dev/null
+++ b/chart2/source/controller/dialogs/dlg_View3D.cxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <dlg_View3D.hxx>
+#include <strings.hrc>
+#include <ResId.hxx>
+#include "tp_3D_SceneGeometry.hxx"
+#include "tp_3D_SceneAppearance.hxx"
+#include "tp_3D_SceneIllumination.hxx"
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <Diagram.hxx>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+sal_uInt16 View3DDialog::m_nLastPageId = 0;
+
+View3DDialog::View3DDialog(weld::Window* pParent, const rtl::Reference<::chart::ChartModel> & xChartModel)
+ : GenericDialogController(pParent, "modules/schart/ui/3dviewdialog.ui", "3DViewDialog")
+ , m_aControllerLocker(xChartModel)
+ , m_xTabControl(m_xBuilder->weld_notebook("tabcontrol"))
+{
+ rtl::Reference< Diagram > xSceneProperties = xChartModel->getFirstChartDiagram();
+
+ m_xTabControl->append_page("geometry", SchResId(STR_PAGE_PERSPECTIVE));
+ m_xGeometry.reset(new ThreeD_SceneGeometry_TabPage(m_xTabControl->get_page("geometry"), xSceneProperties, m_aControllerLocker));
+
+ m_xTabControl->append_page("appearance", SchResId(STR_PAGE_APPEARANCE));
+ m_xAppearance.reset(new ThreeD_SceneAppearance_TabPage(m_xTabControl->get_page("appearance"), xChartModel, m_aControllerLocker));
+
+ m_xTabControl->append_page("illumination", SchResId(STR_PAGE_ILLUMINATION));
+ m_xIllumination.reset(new ThreeD_SceneIllumination_TabPage(m_xTabControl->get_page("illumination"), m_xDialog.get(),
+ xSceneProperties, xChartModel));
+
+ m_xTabControl->connect_enter_page(LINK(this, View3DDialog, ActivatePageHdl));
+
+ m_xTabControl->set_current_page(m_nLastPageId);
+}
+
+IMPL_LINK(View3DDialog, ActivatePageHdl, const OUString&, rPage, void)
+{
+ if (rPage == "appearance")
+ m_xAppearance->ActivatePage();
+}
+
+View3DDialog::~View3DDialog()
+{
+ m_nLastPageId = m_xTabControl->get_current_page();
+}
+
+short View3DDialog::run()
+{
+ short nResult = GenericDialogController::run();
+ if (nResult == RET_OK && m_xGeometry)
+ m_xGeometry->commitPendingChanges();
+ return nResult;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/res_BarGeometry.cxx b/chart2/source/controller/dialogs/res_BarGeometry.cxx
new file mode 100644
index 0000000000..81d933b208
--- /dev/null
+++ b/chart2/source/controller/dialogs/res_BarGeometry.cxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <res_BarGeometry.hxx>
+#include <ResId.hxx>
+#include <chart.hrc>
+
+namespace chart
+{
+BarGeometryResources::BarGeometryResources(weld::Builder* pBuilder)
+ : m_xFT_Geometry(pBuilder->weld_label("shapeft"))
+ , m_xLB_Geometry(pBuilder->weld_tree_view("shape"))
+{
+ for (size_t i = 0; i < std::size(CHART_TYPE); ++i)
+ m_xLB_Geometry->append_text(SchResId(CHART_TYPE[i]));
+ m_xLB_Geometry->set_size_request(-1, m_xLB_Geometry->get_height_rows(std::size(CHART_TYPE)));
+}
+
+void BarGeometryResources::connect_changed(const Link<weld::TreeView&, void>& rLink)
+{
+ m_xLB_Geometry->connect_changed(rLink);
+}
+
+void BarGeometryResources::set_visible(bool bShow)
+{
+ m_xFT_Geometry->set_visible(bShow);
+ m_xLB_Geometry->set_visible(bShow);
+}
+
+void BarGeometryResources::set_sensitive(bool bEnable)
+{
+ m_xFT_Geometry->set_sensitive(bEnable);
+ m_xLB_Geometry->set_sensitive(bEnable);
+}
+
+sal_Int32 BarGeometryResources::get_selected_index() const
+{
+ return m_xLB_Geometry->get_selected_index();
+}
+
+void BarGeometryResources::select(sal_Int32 nPos)
+{
+ if (nPos < m_xLB_Geometry->n_children())
+ m_xLB_Geometry->select(nPos);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/res_DataLabel.cxx b/chart2/source/controller/dialogs/res_DataLabel.cxx
new file mode 100644
index 0000000000..c3d755cf92
--- /dev/null
+++ b/chart2/source/controller/dialogs/res_DataLabel.cxx
@@ -0,0 +1,388 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include "res_DataLabel.hxx"
+
+#include <TextDirectionListBox.hxx>
+#include <chartview/ChartSfxItemIds.hxx>
+#include "dlg_NumberFormat.hxx"
+
+#include <svx/numinf.hxx>
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/ilstitem.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svx/sdangitm.hxx>
+#include <svx/svxids.hrc>
+#include <osl/diagnose.h>
+
+namespace chart
+{
+
+namespace
+{
+
+const std::u16string_view our_aLBEntryMap[] = {u" ", u", ", u"; ", u"\n", u". "};
+
+bool lcl_ReadNumberFormatFromItemSet( const SfxItemSet& rSet, TypedWhichId<SfxUInt32Item> nValueWhich, TypedWhichId<SfxBoolItem> nSourceFormatWhich, sal_uInt32& rnFormatKeyOut, bool& rbSourceFormatOut, bool& rbSourceFormatMixedStateOut )
+{
+ bool bSet = false;
+ if( const SfxUInt32Item* pNumItem = rSet.GetItemIfSet( nValueWhich ) )
+ {
+ rnFormatKeyOut = pNumItem->GetValue();
+ bSet = true;
+ }
+
+ rbSourceFormatMixedStateOut=true;
+ if( const SfxBoolItem * pBoolItem = rSet.GetItemIfSet( nSourceFormatWhich ) )
+ {
+ rbSourceFormatOut = pBoolItem->GetValue();
+ rbSourceFormatMixedStateOut=false;
+ }
+ return bSet;
+}
+
+void lcl_setBoolItemToCheckBox(const SfxItemSet& rInAttrs, TypedWhichId<SfxBoolItem> nWhichId, weld::CheckButton& rCheckbox, weld::TriStateEnabled& rTriState)
+{
+ if( const SfxBoolItem* pPoolItem = rInAttrs.GetItemIfSet(nWhichId) )
+ {
+ rCheckbox.set_active(pPoolItem->GetValue());
+ rTriState.bTriStateEnabled = false;
+ }
+ else
+ {
+ rCheckbox.set_state(TRISTATE_INDET);
+ rTriState.bTriStateEnabled = true;
+ }
+}
+
+}//end anonymous namespace
+
+DataLabelResources::DataLabelResources(weld::Builder* pBuilder, weld::Window* pParent, const SfxItemSet& rInAttrs)
+ : m_pNumberFormatter(nullptr)
+ , m_bNumberFormatMixedState(true)
+ , m_bPercentFormatMixedState(true)
+ , m_nNumberFormatForValue(0)
+ , m_nNumberFormatForPercent(11)
+ , m_bSourceFormatMixedState(true)
+ , m_bPercentSourceMixedState(true)
+ , m_bSourceFormatForValue(true)
+ , m_bSourceFormatForPercent(true)
+ , m_pWindow(pParent)
+ , m_pPool(rInAttrs.GetPool())
+ , m_xCBNumber(pBuilder->weld_check_button("CB_VALUE_AS_NUMBER"))
+ , m_xPB_NumberFormatForValue(pBuilder->weld_button("PB_NUMBERFORMAT"))
+ , m_xCBPercent(pBuilder->weld_check_button("CB_VALUE_AS_PERCENTAGE"))
+ , m_xPB_NumberFormatForPercent(pBuilder->weld_button("PB_PERCENT_NUMBERFORMAT"))
+ , m_xFT_NumberFormatForPercent(pBuilder->weld_label("STR_DLG_NUMBERFORMAT_FOR_PERCENTAGE_VALUE"))
+ , m_xCBCategory(pBuilder->weld_check_button("CB_CATEGORY"))
+ , m_xCBSymbol(pBuilder->weld_check_button("CB_SYMBOL"))
+ , m_xCBDataSeries(pBuilder->weld_check_button("CB_DATA_SERIES_NAME"))
+ , m_xCBWrapText(pBuilder->weld_check_button("CB_WRAP_TEXT"))
+ , m_xLB_Separator(pBuilder->weld_combo_box("LB_TEXT_SEPARATOR"))
+ , m_xLB_LabelPlacement(pBuilder->weld_combo_box("LB_LABEL_PLACEMENT"))
+ , m_xBxOrientation(pBuilder->weld_widget("boxORIENTATION"))
+ , m_xFT_Dial(pBuilder->weld_label("CT_LABEL_DIAL"))
+ , m_xNF_Degrees(pBuilder->weld_metric_spin_button("NF_LABEL_DEGREES", FieldUnit::DEGREE))
+ , m_xBxTextDirection(pBuilder->weld_widget("boxTXT_DIRECTION"))
+ , m_aLB_TextDirection(pBuilder->weld_combo_box("LB_LABEL_TEXTDIR"))
+ , m_xDC_Dial(new svx::DialControl)
+ , m_xDC_DialWin(new weld::CustomWeld(*pBuilder, "CT_DIAL", *m_xDC_Dial))
+ , m_xCBCustomLeaderLines(pBuilder->weld_check_button("CB_CUSTOM_LEADER_LINES"))
+{
+ m_xDC_Dial->SetText(m_xFT_Dial->get_label());
+
+ //fill label placement list
+ std::map< sal_Int32, OUString > aPlacementToStringMap;
+ for( sal_Int32 nEnum=0; nEnum<m_xLB_LabelPlacement->get_count(); ++nEnum )
+ aPlacementToStringMap[nEnum] = m_xLB_LabelPlacement->get_text(static_cast<sal_uInt16>(nEnum));
+
+
+ std::vector< sal_Int32 > aAvailablePlacementList;
+ if( const SfxIntegerListItem* pPlacementsItem = rInAttrs.GetItemIfSet(SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS) )
+ aAvailablePlacementList = pPlacementsItem->GetList();
+
+ m_xLB_LabelPlacement->clear();
+ for( size_t nN=0; nN<aAvailablePlacementList.size(); ++nN )
+ {
+ sal_uInt16 nListBoxPos = static_cast<sal_uInt16>( nN );
+ sal_Int32 nPlacement = aAvailablePlacementList[nN];
+ m_aPlacementToListBoxMap[nPlacement]=nListBoxPos;
+ m_aListBoxToPlacementMap[nListBoxPos]=nPlacement;
+ m_xLB_LabelPlacement->append_text( aPlacementToStringMap[nPlacement] );
+ }
+
+ //some click handler
+ m_xPB_NumberFormatForValue->connect_clicked( LINK( this, DataLabelResources, NumberFormatDialogHdl ) );
+ m_xPB_NumberFormatForPercent->connect_clicked( LINK( this, DataLabelResources, NumberFormatDialogHdl ) );
+ m_xCBNumber->connect_toggled( LINK( this, DataLabelResources, CheckHdl ));
+ m_xCBPercent->connect_toggled( LINK( this, DataLabelResources, CheckHdl ));
+ m_xCBCategory->connect_toggled( LINK( this, DataLabelResources, CheckHdl ));
+ m_xCBSymbol->connect_toggled( LINK( this, DataLabelResources, CheckHdl ));
+ m_xCBDataSeries->connect_toggled( LINK( this, DataLabelResources, CheckHdl ));
+ m_xCBWrapText->connect_toggled( LINK( this, DataLabelResources, CheckHdl ));
+ m_xCBCustomLeaderLines->connect_toggled( LINK( this, DataLabelResources, CheckHdl ));
+
+ m_bNumberFormatMixedState = !lcl_ReadNumberFormatFromItemSet( rInAttrs, SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_SOURCE, m_nNumberFormatForValue, m_bSourceFormatForValue, m_bSourceFormatMixedState );
+ m_bPercentFormatMixedState = !lcl_ReadNumberFormatFromItemSet( rInAttrs, SCHATTR_PERCENT_NUMBERFORMAT_VALUE, SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, m_nNumberFormatForPercent, m_bSourceFormatForPercent , m_bPercentSourceMixedState);
+
+ if( const SfxBoolItem* pNoPercentValueItem = rInAttrs.GetItemIfSet(SCHATTR_DATADESCR_NO_PERCENTVALUE) )
+ {
+ bool bForbidPercentValue = pNoPercentValueItem->GetValue();
+ if( bForbidPercentValue )
+ m_xCBPercent->set_sensitive(false);
+ }
+
+ m_xDC_Dial->SetLinkedField(m_xNF_Degrees.get());
+}
+
+DataLabelResources::~DataLabelResources()
+{
+}
+
+void DataLabelResources::SetNumberFormatter( SvNumberFormatter* pFormatter )
+{
+ m_pNumberFormatter = pFormatter;
+}
+
+IMPL_LINK(DataLabelResources, NumberFormatDialogHdl, weld::Button&, rButton, void)
+{
+ if( !m_pPool || !m_pNumberFormatter )
+ {
+ OSL_FAIL("Missing item pool or number formatter");
+ return;
+ }
+
+ if (&rButton == m_xPB_NumberFormatForValue.get() && !m_xCBNumber->get_active())
+ {
+ m_xCBNumber->set_active(true);
+ m_aNumberState.bTriStateEnabled = false;
+ }
+ else if (&rButton == m_xPB_NumberFormatForPercent.get() && !m_xCBPercent->get_active())
+ {
+ m_xCBPercent->set_active(true);
+ m_aPercentState.bTriStateEnabled = false;
+ }
+
+ SfxItemSet aNumberSet = NumberFormatDialog::CreateEmptyItemSetForNumberFormatDialog( *m_pPool );
+ aNumberSet.Put (SvxNumberInfoItem( m_pNumberFormatter, SID_ATTR_NUMBERFORMAT_INFO));
+
+ bool bPercent = (&rButton == m_xPB_NumberFormatForPercent.get());
+
+ sal_uInt32& rnFormatKey = bPercent ? m_nNumberFormatForPercent : m_nNumberFormatForValue;
+ bool& rUseSourceFormat = bPercent ? m_bSourceFormatForPercent : m_bSourceFormatForValue;
+ bool& rbMixedState = bPercent ? m_bPercentFormatMixedState : m_bNumberFormatMixedState;
+ bool& rbSourceMixedState = bPercent ? m_bPercentSourceMixedState : m_bSourceFormatMixedState;
+
+ if(!rbMixedState)
+ aNumberSet.Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, rnFormatKey ));
+ aNumberSet.Put( SfxBoolItem( SID_ATTR_NUMBERFORMAT_SOURCE, rUseSourceFormat ));
+
+ NumberFormatDialog aDlg(m_pWindow, aNumberSet);
+ if( bPercent )
+ aDlg.set_title(m_xFT_NumberFormatForPercent->get_label());
+ if (aDlg.run() != RET_OK)
+ return;
+
+ const SfxItemSet* pResult = aDlg.GetOutputItemSet();
+ if( pResult )
+ {
+ bool bOldSource = rUseSourceFormat;
+ sal_uInt32 nOldFormat = rnFormatKey;
+ bool bOldMixedState = rbMixedState || rbSourceMixedState;
+
+ rbMixedState = !lcl_ReadNumberFormatFromItemSet( *pResult, SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_SOURCE, rnFormatKey, rUseSourceFormat, rbSourceMixedState );
+
+ //todo this maybe can be removed when the numberformatter dialog does handle mixed state for source format correctly
+ if( bOldMixedState && bOldSource == rUseSourceFormat && nOldFormat == rnFormatKey )
+ rbMixedState = rbSourceMixedState = true;
+ }
+}
+
+IMPL_LINK(DataLabelResources, CheckHdl, weld::Toggleable&, rToggle, void)
+{
+ if (&rToggle == m_xCBNumber.get())
+ m_aNumberState.ButtonToggled(rToggle);
+ else if (&rToggle == m_xCBPercent.get())
+ m_aPercentState.ButtonToggled(rToggle);
+ else if (&rToggle == m_xCBCategory.get())
+ m_aCategoryState.ButtonToggled(rToggle);
+ else if (&rToggle == m_xCBSymbol.get())
+ m_aSymbolState.ButtonToggled(rToggle);
+ else if (&rToggle == m_xCBDataSeries.get())
+ m_aDataSeriesState.ButtonToggled(rToggle);
+ else if (&rToggle == m_xCBWrapText.get())
+ m_aWrapTextState.ButtonToggled(rToggle);
+ else if (&rToggle == m_xCBCustomLeaderLines.get())
+ m_aCustomLeaderLinesState.ButtonToggled(rToggle);
+ EnableControls();
+}
+
+void DataLabelResources::EnableControls()
+{
+ m_xCBSymbol->set_sensitive( m_xCBNumber->get_active() || (m_xCBPercent->get_active() && m_xCBPercent->get_sensitive())
+ || m_xCBCategory->get_active() || m_xCBDataSeries->get_active());
+
+ m_xCBWrapText->set_sensitive( m_xCBNumber->get_active() || (m_xCBPercent->get_active() && m_xCBPercent->get_sensitive())
+ || m_xCBCategory->get_active() || m_xCBDataSeries->get_active() );
+
+ // Enable or disable separator, placement and direction based on the check
+ // box states. Note that the check boxes are tri-state.
+ {
+ tools::Long nNumberOfCheckedLabelParts = 0;
+ if (m_xCBNumber->get_state() != TRISTATE_FALSE)
+ ++nNumberOfCheckedLabelParts;
+ if (m_xCBPercent->get_state() != TRISTATE_FALSE && m_xCBPercent->get_sensitive())
+ ++nNumberOfCheckedLabelParts;
+ if (m_xCBCategory->get_state() != TRISTATE_FALSE)
+ ++nNumberOfCheckedLabelParts;
+ if (m_xCBDataSeries->get_state() != TRISTATE_FALSE)
+ ++nNumberOfCheckedLabelParts;
+
+ m_xLB_Separator->set_sensitive( nNumberOfCheckedLabelParts > 1 );
+
+ bool bEnableTextDir = nNumberOfCheckedLabelParts > 0;
+ m_xBxTextDirection->set_sensitive( bEnableTextDir );
+ bool bEnablePlacement = nNumberOfCheckedLabelParts > 0 && m_xLB_LabelPlacement->get_count()>1;
+ m_xLB_LabelPlacement->set_sensitive( bEnablePlacement );
+ }
+
+ m_xPB_NumberFormatForValue->set_sensitive( m_pNumberFormatter && m_xCBNumber->get_active() );
+ m_xPB_NumberFormatForPercent->set_sensitive( m_pNumberFormatter && m_xCBPercent->get_active() && m_xCBPercent->get_sensitive() );
+
+ bool bEnableRotation = (m_xCBNumber->get_active() || m_xCBPercent->get_active()
+ || m_xCBCategory->get_active() || m_xCBDataSeries->get_active());
+ m_xBxOrientation->set_sensitive(bEnableRotation);
+}
+
+void DataLabelResources::FillItemSet( SfxItemSet* rOutAttrs ) const
+{
+ if( m_xCBNumber->get_active() )
+ {
+ if( !m_bNumberFormatMixedState )
+ rOutAttrs->Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, m_nNumberFormatForValue ));
+ if( !m_bSourceFormatMixedState )
+ rOutAttrs->Put( SfxBoolItem( SID_ATTR_NUMBERFORMAT_SOURCE, m_bSourceFormatForValue ));
+ }
+ if( m_xCBPercent->get_active() )
+ {
+ if( !m_bPercentFormatMixedState )
+ rOutAttrs->Put( SfxUInt32Item( SCHATTR_PERCENT_NUMBERFORMAT_VALUE, m_nNumberFormatForPercent ));
+ if( !m_bPercentSourceMixedState )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, m_bSourceFormatForPercent ));
+ }
+
+ if( m_xCBNumber->get_state()!= TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_NUMBER, m_xCBNumber->get_active() ) );
+ if( m_xCBPercent->get_state()!= TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_PERCENTAGE, m_xCBPercent->get_active() ) );
+ if( m_xCBCategory->get_state()!= TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_CATEGORY, m_xCBCategory->get_active() ) );
+ if( m_xCBSymbol->get_state()!= TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_SYMBOL, m_xCBSymbol->get_active()) );
+ if( m_xCBDataSeries->get_state()!= TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME, m_xCBDataSeries->get_active()) );
+ if( m_xCBWrapText->get_state()!= TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_WRAP_TEXT, m_xCBWrapText->get_active()) );
+ if( m_xCBCustomLeaderLines->get_state() != TRISTATE_INDET )
+ rOutAttrs->Put(SfxBoolItem( SCHATTR_DATADESCR_CUSTOM_LEADER_LINES, m_xCBCustomLeaderLines->get_active()) );
+
+ auto const aSep = our_aLBEntryMap[m_xLB_Separator->get_active()];
+ rOutAttrs->Put( SfxStringItem( SCHATTR_DATADESCR_SEPARATOR, OUString(aSep)) );
+
+ std::map< sal_uInt16, sal_Int32 >::const_iterator aIt( m_aListBoxToPlacementMap.find(m_xLB_LabelPlacement->get_active()) );
+ if(aIt!=m_aListBoxToPlacementMap.end())
+ {
+ sal_Int32 nValue = aIt->second;
+ rOutAttrs->Put( SfxInt32Item( SCHATTR_DATADESCR_PLACEMENT, nValue ) );
+ }
+
+ if (m_aLB_TextDirection.get_active() != -1)
+ rOutAttrs->Put( SvxFrameDirectionItem( m_aLB_TextDirection.get_active_id(), EE_PARA_WRITINGDIR ) );
+
+ if( m_xDC_Dial->IsVisible() )
+ {
+ Degree100 nDegrees = m_xDC_Dial->GetRotation();
+ rOutAttrs->Put(SdrAngleItem( SCHATTR_TEXT_DEGREES, nDegrees ) );
+ }
+}
+
+void DataLabelResources::Reset(const SfxItemSet& rInAttrs)
+{
+ // default state
+ m_xCBSymbol->set_sensitive( false );
+
+ lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_NUMBER, *m_xCBNumber, m_aNumberState );
+ lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_PERCENTAGE, *m_xCBPercent, m_aPercentState );
+ lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_CATEGORY, *m_xCBCategory, m_aCategoryState );
+ lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_SYMBOL, *m_xCBSymbol, m_aSymbolState );
+ lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME, *m_xCBDataSeries, m_aDataSeriesState );
+ lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_WRAP_TEXT, *m_xCBWrapText, m_aWrapTextState );
+ lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_CUSTOM_LEADER_LINES, *m_xCBCustomLeaderLines, m_aCustomLeaderLinesState );
+
+ m_bNumberFormatMixedState = !lcl_ReadNumberFormatFromItemSet( rInAttrs, SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_SOURCE, m_nNumberFormatForValue, m_bSourceFormatForValue, m_bSourceFormatMixedState );
+ m_bPercentFormatMixedState = !lcl_ReadNumberFormatFromItemSet( rInAttrs, SCHATTR_PERCENT_NUMBERFORMAT_VALUE, SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, m_nNumberFormatForPercent, m_bSourceFormatForPercent , m_bPercentSourceMixedState);
+
+ if( const SfxStringItem* pSeparatorItem = rInAttrs.GetItemIfSet(SCHATTR_DATADESCR_SEPARATOR) )
+ for(size_t i=0; i < std::size(our_aLBEntryMap); ++i )
+ {
+ if( our_aLBEntryMap[i] == pSeparatorItem->GetValue())
+ m_xLB_Separator->set_active( i );
+ }
+ else
+ m_xLB_Separator->set_active( 0 );
+
+ if( const SfxInt32Item* pPlacementItem = rInAttrs.GetItemIfSet(SCHATTR_DATADESCR_PLACEMENT) )
+ {
+ sal_Int32 nPlacement = pPlacementItem->GetValue();
+ std::map< sal_Int32, sal_uInt16 >::const_iterator aIt( m_aPlacementToListBoxMap.find(nPlacement) );
+ if(aIt!=m_aPlacementToListBoxMap.end())
+ {
+ sal_uInt16 nPos = aIt->second;
+ m_xLB_LabelPlacement->set_active( nPos );
+ }
+ else
+ m_xLB_LabelPlacement->set_active(-1);
+ }
+ else
+ m_xLB_LabelPlacement->set_active(-1);
+
+ if( const SvxFrameDirectionItem* pDirectionItem = rInAttrs.GetItemIfSet(EE_PARA_WRITINGDIR) )
+ m_aLB_TextDirection.set_active_id( pDirectionItem->GetValue() );
+
+ if( const SdrAngleItem* pAngleItem = rInAttrs.GetItemIfSet( SCHATTR_TEXT_DEGREES ) )
+ {
+ Degree100 nDegrees = pAngleItem->GetValue();
+ m_xDC_Dial->SetRotation( nDegrees );
+ }
+ else
+ m_xDC_Dial->SetRotation( 0_deg100 );
+
+ EnableControls();
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/res_DataLabel.hxx b/chart2/source/controller/dialogs/res_DataLabel.hxx
new file mode 100644
index 0000000000..66a062d2ca
--- /dev/null
+++ b/chart2/source/controller/dialogs/res_DataLabel.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svl/itemset.hxx>
+#include <svx/dialcontrol.hxx>
+#include <TextDirectionListBox.hxx>
+
+#include <map>
+
+class SvNumberFormatter;
+
+namespace chart
+{
+
+class DataLabelResources final
+{
+public:
+ DataLabelResources(weld::Builder* pBuilder, weld::Window* pParent, const SfxItemSet& rInAttrs);
+ ~DataLabelResources();
+
+ void FillItemSet(SfxItemSet* rOutAttrs) const;
+ void Reset(const SfxItemSet& rInAttrs);
+
+ void SetNumberFormatter( SvNumberFormatter* pFormatter );
+
+private:
+ std::map< sal_Int32, sal_uInt16 > m_aPlacementToListBoxMap;
+ std::map< sal_uInt16, sal_Int32 > m_aListBoxToPlacementMap;
+
+ SvNumberFormatter* m_pNumberFormatter;
+ bool m_bNumberFormatMixedState;
+ bool m_bPercentFormatMixedState;
+ sal_uInt32 m_nNumberFormatForValue;
+ sal_uInt32 m_nNumberFormatForPercent;
+
+ bool m_bSourceFormatMixedState;
+ bool m_bPercentSourceMixedState;
+ bool m_bSourceFormatForValue;
+ bool m_bSourceFormatForPercent;
+
+ weld::Window* m_pWindow;
+ SfxItemPool* m_pPool;
+
+ weld::TriStateEnabled m_aNumberState;
+ weld::TriStateEnabled m_aPercentState;
+ weld::TriStateEnabled m_aCategoryState;
+ weld::TriStateEnabled m_aSymbolState;
+ weld::TriStateEnabled m_aDataSeriesState;
+ weld::TriStateEnabled m_aWrapTextState;
+ weld::TriStateEnabled m_aCustomLeaderLinesState;
+
+ std::unique_ptr<weld::CheckButton> m_xCBNumber;
+ std::unique_ptr<weld::Button> m_xPB_NumberFormatForValue;
+ std::unique_ptr<weld::CheckButton> m_xCBPercent;
+ std::unique_ptr<weld::Button> m_xPB_NumberFormatForPercent;
+ std::unique_ptr<weld::Label> m_xFT_NumberFormatForPercent;
+ std::unique_ptr<weld::CheckButton> m_xCBCategory;
+ std::unique_ptr<weld::CheckButton> m_xCBSymbol;
+ std::unique_ptr<weld::CheckButton> m_xCBDataSeries;
+ std::unique_ptr<weld::CheckButton> m_xCBWrapText;
+
+ std::unique_ptr<weld::ComboBox> m_xLB_Separator;
+ std::unique_ptr<weld::ComboBox> m_xLB_LabelPlacement;
+
+ std::unique_ptr<weld::Widget> m_xBxOrientation;
+ std::unique_ptr<weld::Label> m_xFT_Dial;
+ std::unique_ptr<weld::MetricSpinButton> m_xNF_Degrees;
+
+ std::unique_ptr<weld::Widget> m_xBxTextDirection;
+
+ TextDirectionListBox m_aLB_TextDirection;
+ std::unique_ptr<svx::DialControl> m_xDC_Dial;
+ std::unique_ptr<weld::CustomWeld> m_xDC_DialWin;
+
+ std::unique_ptr<weld::CheckButton> m_xCBCustomLeaderLines;
+
+ DECL_LINK(NumberFormatDialogHdl, weld::Button&, void );
+ DECL_LINK(CheckHdl, weld::Toggleable&, void );
+ void EnableControls();
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/res_DataTableProperties.cxx b/chart2/source/controller/dialogs/res_DataTableProperties.cxx
new file mode 100644
index 0000000000..bf87b3e6b9
--- /dev/null
+++ b/chart2/source/controller/dialogs/res_DataTableProperties.cxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <res_DataTableProperties.hxx>
+
+#include <chartview/ChartSfxItemIds.hxx>
+#include <svl/eitem.hxx>
+
+using namespace css;
+
+namespace chart
+{
+DataTablePropertiesResources::DataTablePropertiesResources(weld::Builder& rBuilder)
+ : m_xCbHorizontalBorder(rBuilder.weld_check_button("horizontalBorderCB"))
+ , m_xCbVerticalBorder(rBuilder.weld_check_button("verticalBorderCB"))
+ , m_xCbOutilne(rBuilder.weld_check_button("outlineCB"))
+ , m_xCbKeys(rBuilder.weld_check_button("keysCB"))
+{
+}
+
+void DataTablePropertiesResources::setChecksSensitive(bool bSensitive)
+{
+ m_xCbHorizontalBorder->set_sensitive(bSensitive);
+ m_xCbVerticalBorder->set_sensitive(bSensitive);
+ m_xCbOutilne->set_sensitive(bSensitive);
+ m_xCbKeys->set_sensitive(bSensitive);
+}
+
+void DataTablePropertiesResources::initFromItemSet(const SfxItemSet& rInAttrs)
+{
+ const SfxPoolItem* pPoolItem = nullptr;
+ SfxItemState aState;
+
+ aState = rInAttrs.GetItemState(SCHATTR_DATA_TABLE_HORIZONTAL_BORDER, false, &pPoolItem);
+ if (aState == SfxItemState::DONTCARE)
+ {
+ m_xCbHorizontalBorder->set_state(TRISTATE_INDET);
+ }
+ else
+ {
+ if (aState == SfxItemState::SET)
+ m_xCbHorizontalBorder->set_active(
+ static_cast<const SfxBoolItem*>(pPoolItem)->GetValue());
+ }
+
+ aState = rInAttrs.GetItemState(SCHATTR_DATA_TABLE_VERTICAL_BORDER, false, &pPoolItem);
+ if (aState == SfxItemState::DONTCARE)
+ {
+ m_xCbVerticalBorder->set_state(TRISTATE_INDET);
+ }
+ else
+ {
+ if (aState == SfxItemState::SET)
+ m_xCbVerticalBorder->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue());
+ }
+
+ aState = rInAttrs.GetItemState(SCHATTR_DATA_TABLE_OUTLINE, false, &pPoolItem);
+ if (aState == SfxItemState::DONTCARE)
+ {
+ m_xCbOutilne->set_state(TRISTATE_INDET);
+ }
+ else
+ {
+ if (aState == SfxItemState::SET)
+ m_xCbOutilne->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue());
+ }
+
+ aState = rInAttrs.GetItemState(SCHATTR_DATA_TABLE_KEYS, false, &pPoolItem);
+ if (aState == SfxItemState::DONTCARE)
+ {
+ m_xCbKeys->set_state(TRISTATE_INDET);
+ }
+ else
+ {
+ if (aState == SfxItemState::SET)
+ m_xCbKeys->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue());
+ }
+}
+
+bool DataTablePropertiesResources::writeToItemSet(SfxItemSet& rOutAttrs) const
+{
+ if (m_xCbHorizontalBorder->get_state() != TRISTATE_INDET)
+ {
+ rOutAttrs.Put(
+ SfxBoolItem(SCHATTR_DATA_TABLE_HORIZONTAL_BORDER, m_xCbHorizontalBorder->get_active()));
+ }
+ if (m_xCbVerticalBorder->get_state() != TRISTATE_INDET)
+ {
+ rOutAttrs.Put(
+ SfxBoolItem(SCHATTR_DATA_TABLE_VERTICAL_BORDER, m_xCbVerticalBorder->get_active()));
+ }
+ if (m_xCbOutilne->get_state() != TRISTATE_INDET)
+ {
+ rOutAttrs.Put(SfxBoolItem(SCHATTR_DATA_TABLE_OUTLINE, m_xCbOutilne->get_active()));
+ }
+ if (m_xCbKeys->get_state() != TRISTATE_INDET)
+ {
+ rOutAttrs.Put(SfxBoolItem(SCHATTR_DATA_TABLE_KEYS, m_xCbKeys->get_active()));
+ }
+ return true;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/res_ErrorBar.cxx b/chart2/source/controller/dialogs/res_ErrorBar.cxx
new file mode 100644
index 0000000000..3eb875098b
--- /dev/null
+++ b/chart2/source/controller/dialogs/res_ErrorBar.cxx
@@ -0,0 +1,716 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <res_ErrorBar.hxx>
+#include <bitmaps.hlst>
+#include <RangeSelectionHelper.hxx>
+#include <helpids.h>
+#include <chartview/ChartSfxItemIds.hxx>
+#include <vcl/weld.hxx>
+#include <ChartModel.hxx>
+
+#include <rtl/math.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <osl/diagnose.h>
+#include <svl/stritem.hxx>
+
+#define CHART_LB_FUNCTION_STD_ERROR 0
+#define CHART_LB_FUNCTION_STD_DEV 1
+#define CHART_LB_FUNCTION_VARIANCE 2
+#define CHART_LB_FUNCTION_ERROR_MARGIN 3
+
+using namespace ::com::sun::star;
+
+namespace
+{
+void lcl_enableRangeChoosing(bool bEnable, weld::DialogController* pController)
+{
+ weld::Window* pWeldDialog = pController->getDialog();
+ pWeldDialog->set_modal(!bEnable);
+ pWeldDialog->set_visible(!bEnable);
+}
+
+sal_uInt16 lcl_getLbEntryPosByErrorKind( SvxChartKindError eErrorKind )
+{
+ sal_uInt16 nResult = 0;
+ switch( eErrorKind )
+ {
+ // for these cases select the default in the list box
+ case SvxChartKindError::NONE:
+ case SvxChartKindError::Percent:
+ case SvxChartKindError::Const:
+ case SvxChartKindError::Range:
+ nResult = CHART_LB_FUNCTION_STD_DEV;
+ break;
+ case SvxChartKindError::Variant:
+ nResult = CHART_LB_FUNCTION_VARIANCE;
+ break;
+ case SvxChartKindError::Sigma:
+ nResult = CHART_LB_FUNCTION_STD_DEV;
+ break;
+ case SvxChartKindError::BigError:
+ nResult = CHART_LB_FUNCTION_ERROR_MARGIN;
+ break;
+ case SvxChartKindError::StdError:
+ nResult = CHART_LB_FUNCTION_STD_ERROR;
+ break;
+ }
+ return nResult;
+}
+} // anonymous namespace
+
+namespace chart
+{
+
+ErrorBarResources::ErrorBarResources(weld::Builder* pParent, weld::DialogController* pController,
+ const SfxItemSet& rInAttrs, bool bNoneAvailable,
+ tErrorBarType eType /* = ERROR_BAR_Y */ )
+ : m_eErrorKind( SvxChartKindError::NONE )
+ , m_eIndicate( SvxChartIndicate::Both )
+ , m_bErrorKindUnique( true )
+ , m_bIndicatorUnique( true )
+ , m_bRangePosUnique( true )
+ , m_bRangeNegUnique( true )
+ , m_eErrorBarType( eType )
+ , m_nConstDecimalDigits( 1 )
+ , m_nConstSpinSize( 1 )
+ , m_fPlusValue(0.0)
+ , m_fMinusValue(0.0)
+ , m_pController(pController)
+ , m_pCurrentRangeChoosingField( nullptr )
+ , m_bHasInternalDataProvider( true )
+ , m_bEnableDataTableDialog( true )
+ , m_xRbNone(pParent->weld_radio_button("RB_NONE"))
+ , m_xRbConst(pParent->weld_radio_button("RB_CONST"))
+ , m_xRbPercent(pParent->weld_radio_button("RB_PERCENT"))
+ , m_xRbFunction(pParent->weld_radio_button("RB_FUNCTION"))
+ , m_xRbRange(pParent->weld_radio_button("RB_RANGE"))
+ , m_xLbFunction(pParent->weld_combo_box("LB_FUNCTION"))
+ , m_xFlParameters(pParent->weld_frame("framePARAMETERS"))
+ , m_xBxPositive(pParent->weld_widget("boxPOSITIVE"))
+ , m_xMfPositive(pParent->weld_metric_spin_button("MF_POSITIVE", FieldUnit::NONE))
+ , m_xEdRangePositive(pParent->weld_entry("ED_RANGE_POSITIVE"))
+ , m_xIbRangePositive(pParent->weld_button("IB_RANGE_POSITIVE"))
+ , m_xBxNegative(pParent->weld_widget("boxNEGATIVE"))
+ , m_xMfNegative(pParent->weld_metric_spin_button("MF_NEGATIVE", FieldUnit::NONE))
+ , m_xEdRangeNegative(pParent->weld_entry("ED_RANGE_NEGATIVE"))
+ , m_xIbRangeNegative(pParent->weld_button("IB_RANGE_NEGATIVE"))
+ , m_xCbSyncPosNeg(pParent->weld_check_button("CB_SYN_POS_NEG"))
+ , m_xRbBoth(pParent->weld_radio_button("RB_BOTH"))
+ , m_xRbPositive(pParent->weld_radio_button("RB_POSITIVE"))
+ , m_xRbNegative(pParent->weld_radio_button("RB_NEGATIVE"))
+ , m_xFiBoth(pParent->weld_image("FI_BOTH"))
+ , m_xFiPositive(pParent->weld_image("FI_POSITIVE"))
+ , m_xFiNegative(pParent->weld_image("FI_NEGATIVE"))
+ , m_xUIStringPos(pParent->weld_label("STR_DATA_SELECT_RANGE_FOR_POSITIVE_ERRORBARS"))
+ , m_xUIStringNeg(pParent->weld_label("STR_DATA_SELECT_RANGE_FOR_NEGATIVE_ERRORBARS"))
+ , m_xUIStringRbRange(pParent->weld_label("STR_CONTROLTEXT_ERROR_BARS_FROM_DATA"))
+{
+ if( bNoneAvailable )
+ m_xRbNone->connect_toggled(LINK(this, ErrorBarResources, CategoryChosen));
+ else
+ m_xRbNone->hide();
+
+ m_xRbConst->connect_toggled( LINK( this, ErrorBarResources, CategoryChosen ));
+ m_xRbPercent->connect_toggled( LINK( this, ErrorBarResources, CategoryChosen ));
+ m_xRbFunction->connect_toggled( LINK( this, ErrorBarResources, CategoryChosen ));
+ m_xRbRange->connect_toggled( LINK( this, ErrorBarResources, CategoryChosen ));
+ m_xLbFunction->connect_changed( LINK( this, ErrorBarResources, CategoryChosen2 ));
+
+ m_xCbSyncPosNeg->set_active( false );
+ m_xCbSyncPosNeg->connect_toggled( LINK( this, ErrorBarResources, SynchronizePosAndNeg ));
+
+ m_xMfPositive->connect_value_changed( LINK( this, ErrorBarResources, PosValueChanged ));
+ m_xEdRangePositive->connect_changed( LINK( this, ErrorBarResources, RangeChanged ));
+ m_xEdRangeNegative->connect_changed( LINK( this, ErrorBarResources, RangeChanged ));
+
+ m_xRbPositive->connect_toggled( LINK( this, ErrorBarResources, IndicatorChanged ));
+ m_xRbNegative->connect_toggled( LINK( this, ErrorBarResources, IndicatorChanged ));
+ m_xRbBoth->connect_toggled( LINK( this, ErrorBarResources, IndicatorChanged ));
+
+ m_xIbRangePositive->connect_clicked( LINK( this, ErrorBarResources, ChooseRange ));
+ m_xIbRangeNegative->connect_clicked( LINK( this, ErrorBarResources, ChooseRange ));
+
+ FillValueSets();
+ Reset( rInAttrs );
+}
+
+ErrorBarResources::~ErrorBarResources()
+{
+}
+
+void ErrorBarResources::SetErrorBarType( tErrorBarType eNewType )
+{
+ if( m_eErrorBarType != eNewType )
+ {
+ m_eErrorBarType = eNewType;
+ FillValueSets();
+ }
+}
+
+void ErrorBarResources::SetChartDocumentForRangeChoosing(
+ const rtl::Reference<::chart::ChartModel> & xChartDocument )
+{
+ if( xChartDocument.is())
+ {
+ m_bHasInternalDataProvider = xChartDocument->hasInternalDataProvider();
+ uno::Reference< beans::XPropertySet > xProps( static_cast<cppu::OWeakObject*>(xChartDocument.get()), uno::UNO_QUERY );
+ if ( xProps.is() )
+ {
+ try
+ {
+ xProps->getPropertyValue("EnableDataTableDialog") >>= m_bEnableDataTableDialog;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ }
+ m_apRangeSelectionHelper.reset( new RangeSelectionHelper( xChartDocument ));
+
+ // has internal data provider => rename "cell range" to "from data"
+ OSL_ASSERT(m_apRangeSelectionHelper);
+ if( m_bHasInternalDataProvider )
+ {
+ m_xRbRange->set_label(m_xUIStringRbRange->get_label());
+ m_xRbRange->set_help_id(HID_SCH_ERROR_BARS_FROM_DATA);
+ }
+
+ if( m_xRbRange->get_active())
+ {
+ isRangeFieldContentValid( *m_xEdRangePositive );
+ isRangeFieldContentValid( *m_xEdRangeNegative );
+ }
+}
+
+void ErrorBarResources::SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth )
+{
+ if( fMinorStepWidth < 0 )
+ fMinorStepWidth = -fMinorStepWidth;
+
+ sal_Int32 nExponent = static_cast< sal_Int32 >( ::rtl::math::approxFloor( log10( fMinorStepWidth )));
+ if( nExponent <= 0 )
+ {
+ // one digit precision more
+ m_nConstDecimalDigits = static_cast< sal_uInt16 >( (-nExponent) + 1 );
+ m_nConstSpinSize = 10;
+ }
+ else
+ {
+ m_nConstDecimalDigits = 0;
+ m_nConstSpinSize = static_cast< sal_Int64 >( pow( 10.0, static_cast<int>(nExponent) ));
+ }
+}
+
+void ErrorBarResources::UpdateControlStates()
+{
+ // function
+ bool bIsFunction = m_xRbFunction->get_active();
+ m_xLbFunction->set_sensitive( bIsFunction );
+
+ // range buttons
+ m_xRbRange->set_sensitive( !m_bHasInternalDataProvider || m_bEnableDataTableDialog );
+ bool bShowRange = m_xRbRange->get_active();
+ bool bCanChooseRange =
+ ( bShowRange &&
+ m_apRangeSelectionHelper &&
+ m_apRangeSelectionHelper->hasRangeSelection());
+
+ m_xMfPositive->set_visible( ! bShowRange );
+ m_xMfNegative->set_visible( ! bShowRange );
+
+ // use range but without range chooser => hide controls
+ m_xEdRangePositive->set_visible( bShowRange && ! m_bHasInternalDataProvider );
+ m_xIbRangePositive->set_visible( bCanChooseRange );
+ m_xEdRangeNegative->set_visible( bShowRange && ! m_bHasInternalDataProvider );
+ m_xIbRangeNegative->set_visible( bCanChooseRange );
+
+ bool bShowPosNegAndSync = ! (bShowRange && m_bHasInternalDataProvider);
+ m_xFlParameters->set_visible( bShowPosNegAndSync );
+
+ // unit for metric fields
+ bool bIsErrorMargin(
+ ( m_xRbFunction->get_active()) &&
+ ( m_xLbFunction->get_active() == CHART_LB_FUNCTION_ERROR_MARGIN ));
+ bool bIsPercentage( m_xRbPercent->get_active() || bIsErrorMargin );
+ FieldUnit eFieldUnit = FieldUnit::NONE;
+
+ if( bIsPercentage )
+ {
+ eFieldUnit = FieldUnit::PERCENT;
+ m_xMfPositive->set_digits( 1 );
+ m_xMfPositive->set_increments(10, 100, FieldUnit::NONE);
+ m_xMfNegative->set_digits( 1 );
+ m_xMfNegative->set_increments(10, 100, FieldUnit::NONE);
+ }
+ else
+ {
+ m_xMfPositive->set_digits( m_nConstDecimalDigits );
+ m_xMfPositive->set_increments(m_nConstSpinSize, m_nConstSpinSize * 10, FieldUnit::NONE);
+ m_xMfNegative->set_digits( m_nConstDecimalDigits );
+ m_xMfNegative->set_increments(m_nConstSpinSize, m_nConstSpinSize * 10, FieldUnit::NONE);
+ }
+
+ sal_Int32 nPlusValue = static_cast< sal_Int32 >( m_fPlusValue * pow(10.0,m_xMfPositive->get_digits()) );
+ sal_Int32 nMinusValue = static_cast< sal_Int32 >( m_fMinusValue * pow(10.0,m_xMfNegative->get_digits()) );
+
+ m_xMfPositive->set_value(nPlusValue, FieldUnit::NONE);
+ m_xMfNegative->set_value(nMinusValue, FieldUnit::NONE);
+
+ m_xMfPositive->set_unit(eFieldUnit);
+ m_xMfNegative->set_unit(eFieldUnit);
+
+ // positive and negative value fields
+ bool bPosEnabled = ( m_xRbPositive->get_active() || m_xRbBoth->get_active());
+ bool bNegEnabled = ( m_xRbNegative->get_active() || m_xRbBoth->get_active());
+ if( !( bPosEnabled || bNegEnabled ))
+ {
+ // all three controls are not checked -> ambiguous state
+ bPosEnabled = true;
+ bNegEnabled = true;
+ }
+
+ // functions with only one parameter
+ bool bOneParameterCategory =
+ bIsErrorMargin || m_xRbPercent->get_active();
+ if( bOneParameterCategory )
+ {
+ m_xCbSyncPosNeg->set_active(true);
+ }
+
+ if( m_xCbSyncPosNeg->get_active())
+ {
+ bPosEnabled = true;
+ bNegEnabled = false;
+ }
+
+ // all functions except error margin take no arguments
+ if( m_xRbFunction->get_active() && ( m_xLbFunction->get_active() != CHART_LB_FUNCTION_ERROR_MARGIN ))
+ {
+ bPosEnabled = false;
+ bNegEnabled = false;
+ }
+
+ // enable/disable pos/neg fields
+ m_xBxPositive->set_sensitive( bPosEnabled );
+ m_xBxNegative->set_sensitive( bNegEnabled );
+ if( bShowRange )
+ {
+ m_xEdRangePositive->set_sensitive( bPosEnabled );
+ m_xIbRangePositive->set_sensitive( bPosEnabled );
+ m_xEdRangeNegative->set_sensitive( bNegEnabled );
+ m_xIbRangeNegative->set_sensitive( bNegEnabled );
+ }
+ else
+ {
+ m_xMfPositive->set_sensitive( bPosEnabled );
+ m_xMfNegative->set_sensitive( bNegEnabled );
+ }
+
+ m_xCbSyncPosNeg->set_sensitive( !bOneParameterCategory && ( bPosEnabled || bNegEnabled ));
+
+ // mark invalid entries in the range fields
+ if( bShowRange && ! m_bHasInternalDataProvider )
+ {
+ isRangeFieldContentValid( *m_xEdRangePositive );
+ isRangeFieldContentValid( *m_xEdRangeNegative );
+ }
+}
+
+IMPL_LINK_NOARG( ErrorBarResources, CategoryChosen2, weld::ComboBox&, void )
+{
+ CategoryChosen(*m_xRbConst);
+}
+
+IMPL_LINK_NOARG( ErrorBarResources, CategoryChosen, weld::Toggleable&, void )
+{
+ m_bErrorKindUnique = true;
+ SvxChartKindError eOldError = m_eErrorKind;
+
+ if( m_xRbNone->get_active())
+ m_eErrorKind = SvxChartKindError::NONE;
+ else if( m_xRbConst->get_active())
+ m_eErrorKind = SvxChartKindError::Const;
+ else if( m_xRbPercent->get_active())
+ m_eErrorKind = SvxChartKindError::Percent;
+ else if( m_xRbRange->get_active())
+ m_eErrorKind = SvxChartKindError::Range;
+ else if( m_xRbFunction->get_active())
+ {
+ switch( m_xLbFunction->get_active())
+ {
+ case CHART_LB_FUNCTION_STD_ERROR:
+ m_eErrorKind = SvxChartKindError::StdError; break;
+ case CHART_LB_FUNCTION_STD_DEV:
+ m_eErrorKind = SvxChartKindError::Sigma; break;
+ case CHART_LB_FUNCTION_VARIANCE:
+ m_eErrorKind = SvxChartKindError::Variant; break;
+ case CHART_LB_FUNCTION_ERROR_MARGIN:
+ m_eErrorKind = SvxChartKindError::BigError; break;
+ default:
+ m_bErrorKindUnique = false;
+ }
+ }
+ else
+ {
+ OSL_FAIL( "Unknown category chosen" );
+ m_bErrorKindUnique = false;
+ }
+
+ // changed to range
+ if( m_eErrorKind == SvxChartKindError::Range &&
+ eOldError != SvxChartKindError::Range )
+ {
+ m_xCbSyncPosNeg->set_active(
+ (!m_xEdRangePositive->get_text().isEmpty()) &&
+ m_xEdRangePositive->get_text() == m_xEdRangeNegative->get_text());
+ }
+ // changed from range
+ else if( m_eErrorKind != SvxChartKindError::Range &&
+ eOldError == SvxChartKindError::Range )
+ {
+ m_xCbSyncPosNeg->set_active( m_xMfPositive->get_value(FieldUnit::NONE) == m_xMfNegative->get_value(FieldUnit::NONE));
+ }
+
+ UpdateControlStates();
+}
+
+IMPL_LINK_NOARG(ErrorBarResources, SynchronizePosAndNeg, weld::Toggleable&, void)
+{
+ UpdateControlStates();
+ PosValueChanged( *m_xMfPositive );
+}
+
+IMPL_LINK_NOARG(ErrorBarResources, PosValueChanged, weld::MetricSpinButton&, void)
+{
+ if( m_xCbSyncPosNeg->get_active())
+ {
+ if( m_xRbRange->get_active())
+ {
+ m_xEdRangeNegative->set_text( m_xEdRangePositive->get_text());
+ m_bRangeNegUnique = m_bRangePosUnique;
+ }
+ else
+ m_xMfNegative->set_value(m_xMfPositive->get_value(FieldUnit::NONE), FieldUnit::NONE);
+ }
+}
+
+IMPL_LINK_NOARG(ErrorBarResources, IndicatorChanged, weld::Toggleable&, void)
+{
+ m_bIndicatorUnique = true;
+ if( m_xRbBoth->get_active())
+ m_eIndicate = SvxChartIndicate::Both;
+ else if( m_xRbPositive->get_active())
+ m_eIndicate = SvxChartIndicate::Up;
+ else if( m_xRbNegative->get_active())
+ m_eIndicate = SvxChartIndicate::Down;
+ else
+ m_bIndicatorUnique = false;
+
+ UpdateControlStates();
+}
+
+IMPL_LINK(ErrorBarResources, ChooseRange, weld::Button&, rButton, void)
+{
+ OSL_ASSERT(m_apRangeSelectionHelper);
+ if (!m_apRangeSelectionHelper)
+ return;
+ OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
+
+ OUString aUIString;
+
+ if (&rButton == m_xIbRangePositive.get())
+ {
+ m_pCurrentRangeChoosingField = m_xEdRangePositive.get();
+ aUIString = m_xUIStringPos->get_label();
+ }
+ else
+ {
+ m_pCurrentRangeChoosingField = m_xEdRangeNegative.get();
+ aUIString = m_xUIStringNeg->get_label();
+ }
+
+ lcl_enableRangeChoosing(true, m_pController);
+ m_apRangeSelectionHelper->chooseRange(
+ m_pCurrentRangeChoosingField->get_text(),
+ aUIString, *this );
+}
+
+IMPL_LINK( ErrorBarResources, RangeChanged, weld::Entry&, rEdit, void )
+{
+ if( &rEdit == m_xEdRangePositive.get() )
+ {
+ m_bRangePosUnique = true;
+ PosValueChanged( *m_xMfPositive );
+ }
+ else
+ {
+ m_bRangeNegUnique = true;
+ }
+
+ isRangeFieldContentValid( rEdit );
+}
+
+void ErrorBarResources::Reset(const SfxItemSet& rInAttrs)
+{
+ const SfxPoolItem *pPoolItem = nullptr;
+
+ // category
+ m_eErrorKind = SvxChartKindError::NONE;
+ SfxItemState aState = rInAttrs.GetItemState( SCHATTR_STAT_KIND_ERROR, true, &pPoolItem );
+ m_bErrorKindUnique = ( aState != SfxItemState::DONTCARE );
+
+ if( aState == SfxItemState::SET )
+ m_eErrorKind = static_cast<const SvxChartKindErrorItem*>(pPoolItem)->GetValue();
+
+ m_xLbFunction->set_active( lcl_getLbEntryPosByErrorKind( m_eErrorKind ));
+
+ if( m_bErrorKindUnique )
+ {
+ switch( m_eErrorKind )
+ {
+ case SvxChartKindError::NONE:
+ m_xRbNone->set_active(true);
+ break;
+ case SvxChartKindError::Percent:
+ m_xRbPercent->set_active(true);
+ break;
+ case SvxChartKindError::Const:
+ m_xRbConst->set_active(true);
+ break;
+ case SvxChartKindError::StdError:
+ case SvxChartKindError::Variant:
+ case SvxChartKindError::Sigma:
+ case SvxChartKindError::BigError:
+ m_xRbFunction->set_active(true);
+ break;
+ case SvxChartKindError::Range:
+ m_xRbRange->set_active(true);
+ break;
+ }
+ }
+ else
+ {
+ m_xRbNone->set_active( false );
+ m_xRbConst->set_active( false );
+ m_xRbPercent->set_active( false );
+ m_xRbFunction->set_active( false );
+ }
+
+ // parameters
+ if( const SvxDoubleItem* pDoubleItem = rInAttrs.GetItemIfSet( SCHATTR_STAT_CONSTPLUS ) )
+ {
+ m_fPlusValue = pDoubleItem->GetValue();
+ }
+
+ if( const SvxDoubleItem* pStatItem = rInAttrs.GetItemIfSet( SCHATTR_STAT_CONSTMINUS ) )
+ {
+ m_fMinusValue = pStatItem->GetValue();
+
+ if( m_eErrorKind != SvxChartKindError::Range &&
+ m_fPlusValue == m_fMinusValue )
+ m_xCbSyncPosNeg->set_active(true);
+ }
+
+ // indicator
+ aState = rInAttrs.GetItemState( SCHATTR_STAT_INDICATE, true, &pPoolItem );
+ m_bIndicatorUnique = ( aState != SfxItemState::DONTCARE );
+ if( aState == SfxItemState::SET)
+ m_eIndicate = static_cast<const SvxChartIndicateItem *>(pPoolItem)->GetValue();
+
+ if( m_bIndicatorUnique )
+ {
+ switch( m_eIndicate )
+ {
+ case SvxChartIndicate::NONE :
+ // no longer used, use both as default
+ m_eIndicate = SvxChartIndicate::Both;
+ [[fallthrough]]; // to BOTH
+ case SvxChartIndicate::Both :
+ m_xRbBoth->set_active(true); break;
+ case SvxChartIndicate::Up :
+ m_xRbPositive->set_active(true); break;
+ case SvxChartIndicate::Down :
+ m_xRbNegative->set_active(true); break;
+ }
+ }
+ else
+ {
+ m_xRbBoth->set_active( false );
+ m_xRbPositive->set_active( false );
+ m_xRbNegative->set_active( false );
+ }
+
+ // ranges
+ aState = rInAttrs.GetItemState( SCHATTR_STAT_RANGE_POS, true, &pPoolItem );
+ m_bRangePosUnique = ( aState != SfxItemState::DONTCARE );
+ if( aState == SfxItemState::SET )
+ {
+ OUString sRangePositive = static_cast< const SfxStringItem * >( pPoolItem )->GetValue();
+ m_xEdRangePositive->set_text( sRangePositive );
+ }
+
+ aState = rInAttrs.GetItemState( SCHATTR_STAT_RANGE_NEG, true, &pPoolItem );
+ m_bRangeNegUnique = ( aState != SfxItemState::DONTCARE );
+ if( aState == SfxItemState::SET )
+ {
+ OUString sRangeNegative = static_cast< const SfxStringItem * >( pPoolItem )->GetValue();
+ m_xEdRangeNegative->set_text( sRangeNegative );
+ if( m_eErrorKind == SvxChartKindError::Range &&
+ !sRangeNegative.isEmpty() &&
+ sRangeNegative == m_xEdRangePositive->get_text() )
+ m_xCbSyncPosNeg->set_active(true);
+ }
+
+ UpdateControlStates();
+}
+
+void ErrorBarResources::FillItemSet(SfxItemSet& rOutAttrs) const
+{
+ if( m_bErrorKindUnique )
+ rOutAttrs.Put( SvxChartKindErrorItem( m_eErrorKind, SCHATTR_STAT_KIND_ERROR ));
+ if( m_bIndicatorUnique )
+ rOutAttrs.Put( SvxChartIndicateItem( m_eIndicate, SCHATTR_STAT_INDICATE ));
+
+ if( m_bErrorKindUnique )
+ {
+ if( m_eErrorKind == SvxChartKindError::Range )
+ {
+ OUString aPosRange;
+ OUString aNegRange;
+ if( m_bHasInternalDataProvider )
+ {
+ // the strings aPosRange/aNegRange have to be set to a non-empty
+ // arbitrary string to generate error-bar sequences
+ aPosRange = "x";
+ aNegRange = aPosRange;
+ }
+ else
+ {
+ aPosRange = m_xEdRangePositive->get_text();
+ if( m_xCbSyncPosNeg->get_active())
+ aNegRange = aPosRange;
+ else
+ aNegRange = m_xEdRangeNegative->get_text();
+ }
+
+ if( m_bRangePosUnique )
+ rOutAttrs.Put( SfxStringItem( SCHATTR_STAT_RANGE_POS, aPosRange ));
+ if( m_bRangeNegUnique )
+ rOutAttrs.Put( SfxStringItem( SCHATTR_STAT_RANGE_NEG, aNegRange ));
+ }
+ else if( m_eErrorKind == SvxChartKindError::Const ||
+ m_eErrorKind == SvxChartKindError::Percent ||
+ m_eErrorKind == SvxChartKindError::BigError )
+ {
+ double fPosValue = static_cast< double >( m_xMfPositive->get_value(FieldUnit::NONE)) /
+ pow( 10.0, m_xMfPositive->get_digits());
+ double fNegValue = 0.0;
+
+ if( m_xCbSyncPosNeg->get_active())
+ fNegValue = fPosValue;
+ else
+ fNegValue = static_cast< double >( m_xMfNegative->get_value(FieldUnit::NONE)) /
+ pow( 10.0, m_xMfNegative->get_digits());
+
+ rOutAttrs.Put( SvxDoubleItem( fPosValue, SCHATTR_STAT_CONSTPLUS ));
+ rOutAttrs.Put( SvxDoubleItem( fNegValue, SCHATTR_STAT_CONSTMINUS ));
+ }
+ }
+
+ rOutAttrs.Put( SfxBoolItem( SCHATTR_STAT_ERRORBAR_TYPE , m_eErrorBarType == ERROR_BAR_Y ));
+}
+
+void ErrorBarResources::FillValueSets()
+{
+ if( m_eErrorBarType == ERROR_BAR_Y )
+ {
+ m_xFiNegative->set_from_icon_name(BMP_INDICATE_DOWN);
+ m_xFiPositive->set_from_icon_name(BMP_INDICATE_UP);
+ m_xFiBoth->set_from_icon_name(BMP_INDICATE_BOTH_VERTI);
+ }
+ else if( m_eErrorBarType == ERROR_BAR_X )
+ {
+ m_xFiNegative->set_from_icon_name(BMP_INDICATE_LEFT);
+ m_xFiPositive->set_from_icon_name(BMP_INDICATE_RIGHT);
+ m_xFiBoth->set_from_icon_name(BMP_INDICATE_BOTH_HORI);
+ }
+}
+
+void ErrorBarResources::listeningFinished(
+ const OUString & rNewRange )
+{
+ OSL_ASSERT(m_apRangeSelectionHelper);
+ if (!m_apRangeSelectionHelper)
+ return;
+
+ // rNewRange becomes invalid after removing the listener
+ OUString aRange( rNewRange );
+
+ // stop listening
+ m_apRangeSelectionHelper->stopRangeListening();
+
+ // change edit field
+// if( m_pParentWindow )
+// {
+// m_pParentWindow->ToTop();
+// m_pParentWindow->grab_focus();
+// }
+
+ if( m_pCurrentRangeChoosingField )
+ {
+ m_pCurrentRangeChoosingField->set_text( aRange );
+ m_pCurrentRangeChoosingField->grab_focus();
+ PosValueChanged( *m_xMfPositive );
+ }
+
+ m_pCurrentRangeChoosingField = nullptr;
+
+ UpdateControlStates();
+ lcl_enableRangeChoosing(false, m_pController);
+}
+
+void ErrorBarResources::disposingRangeSelection()
+{
+ OSL_ASSERT(m_apRangeSelectionHelper);
+ if (m_apRangeSelectionHelper)
+ m_apRangeSelectionHelper->stopRangeListening( false );
+}
+
+void ErrorBarResources::isRangeFieldContentValid(weld::Entry& rEdit)
+{
+ OUString aRange( rEdit.get_text());
+ bool bIsValid = ( aRange.isEmpty() ) ||
+ ( m_apRangeSelectionHelper &&
+ m_apRangeSelectionHelper->verifyCellRange( aRange ));
+
+ if( bIsValid || !rEdit.get_sensitive())
+ {
+ rEdit.set_message_type(weld::EntryMessageType::Normal);
+ }
+ else
+ {
+ rEdit.set_message_type(weld::EntryMessageType::Error);
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/res_LegendPosition.cxx b/chart2/source/controller/dialogs/res_LegendPosition.cxx
new file mode 100644
index 0000000000..1562fcc719
--- /dev/null
+++ b/chart2/source/controller/dialogs/res_LegendPosition.cxx
@@ -0,0 +1,244 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <res_LegendPosition.hxx>
+#include <ChartModelHelper.hxx>
+#include <Legend.hxx>
+#include <LegendHelper.hxx>
+#include <ChartModel.hxx>
+#include <Diagram.hxx>
+
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart/ChartLegendExpansion.hpp>
+
+//itemset stuff
+#include <chartview/ChartSfxItemIds.hxx>
+#include <svl/intitem.hxx>
+#include <svl/eitem.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <utility>
+#include <vcl/weld.hxx>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+LegendPositionResources::LegendPositionResources(weld::Builder& rBuilder)
+ : m_xRbtLeft(rBuilder.weld_radio_button("left"))
+ , m_xRbtRight(rBuilder.weld_radio_button("right"))
+ , m_xRbtTop(rBuilder.weld_radio_button("top"))
+ , m_xRbtBottom(rBuilder.weld_radio_button("bottom"))
+{
+ impl_setRadioButtonToggleHdl();
+}
+
+LegendPositionResources::LegendPositionResources(weld::Builder& rBuilder,
+ uno::Reference< uno::XComponentContext > xCC)
+ : m_xCC(std::move(xCC))
+ , m_xCbxShow(rBuilder.weld_check_button("show"))
+ , m_xRbtLeft(rBuilder.weld_radio_button("left"))
+ , m_xRbtRight(rBuilder.weld_radio_button("right"))
+ , m_xRbtTop(rBuilder.weld_radio_button("top"))
+ , m_xRbtBottom(rBuilder.weld_radio_button("bottom"))
+{
+ m_xCbxShow->connect_toggled( LINK( this, LegendPositionResources, PositionEnableHdl ) );
+ impl_setRadioButtonToggleHdl();
+}
+
+void LegendPositionResources::impl_setRadioButtonToggleHdl()
+{
+ m_xRbtLeft->connect_toggled( LINK( this, LegendPositionResources, PositionChangeHdl ) );
+ m_xRbtTop->connect_toggled( LINK( this, LegendPositionResources, PositionChangeHdl ) );
+ m_xRbtRight->connect_toggled( LINK( this, LegendPositionResources, PositionChangeHdl ) );
+ m_xRbtBottom->connect_toggled( LINK( this, LegendPositionResources, PositionChangeHdl ) );
+}
+
+LegendPositionResources::~LegendPositionResources()
+{
+}
+
+void LegendPositionResources::writeToResources( const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ try
+ {
+ rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
+ rtl::Reference< Legend > xLegend = xDiagram->getLegend2();
+ if( xLegend.is() )
+ {
+ //show
+ bool bShowLegend = false;
+ xLegend->getPropertyValue( "Show" ) >>= bShowLegend;
+ if (m_xCbxShow)
+ m_xCbxShow->set_active( bShowLegend );
+ PositionEnable();
+
+ //position
+ chart2::LegendPosition ePos;
+ xLegend->getPropertyValue( "AnchorPosition" ) >>= ePos;
+ switch( ePos )
+ {
+ case chart2::LegendPosition_LINE_START:
+ m_xRbtLeft->set_active(true);
+ break;
+ case chart2::LegendPosition_PAGE_START:
+ m_xRbtTop->set_active(true);
+ break;
+ case chart2::LegendPosition_PAGE_END:
+ m_xRbtBottom->set_active(true);
+ break;
+ case chart2::LegendPosition_LINE_END:
+ default:
+ m_xRbtRight->set_active(true);
+ break;
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void LegendPositionResources::writeToModel( const rtl::Reference<::chart::ChartModel>& xChartModel ) const
+{
+ try
+ {
+ bool bShowLegend = m_xCbxShow && m_xCbxShow->get_active();
+ ChartModel& rModel = *xChartModel;
+ rtl::Reference< Legend > xProp = LegendHelper::getLegend(rModel, m_xCC, bShowLegend);
+ if( xProp.is() )
+ {
+ //show
+ xProp->setPropertyValue( "Show" , uno::Any( bShowLegend ));
+
+ //position
+ chart2::LegendPosition eNewPos;
+ css::chart::ChartLegendExpansion eExp = css::chart::ChartLegendExpansion_HIGH;
+
+ if( m_xRbtLeft->get_active() )
+ eNewPos = chart2::LegendPosition_LINE_START;
+ else if( m_xRbtRight->get_active() )
+ {
+ eNewPos = chart2::LegendPosition_LINE_END;
+ }
+ else if( m_xRbtTop->get_active() )
+ {
+ eNewPos = chart2::LegendPosition_PAGE_START;
+ eExp = css::chart::ChartLegendExpansion_WIDE;
+ }
+ else if( m_xRbtBottom->get_active() )
+ {
+ eNewPos = chart2::LegendPosition_PAGE_END;
+ eExp = css::chart::ChartLegendExpansion_WIDE;
+ }
+
+ xProp->setPropertyValue( "AnchorPosition" , uno::Any( eNewPos ));
+ xProp->setPropertyValue( "Expansion" , uno::Any( eExp ));
+ xProp->setPropertyValue( "RelativePosition" , uno::Any());
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+}
+
+IMPL_LINK_NOARG(LegendPositionResources, PositionEnableHdl, weld::Toggleable&, void)
+{
+ PositionEnable();
+}
+
+void LegendPositionResources::PositionEnable()
+{
+ bool bEnable = !m_xCbxShow || m_xCbxShow->get_active();
+
+ m_xRbtLeft->set_sensitive( bEnable );
+ m_xRbtTop->set_sensitive( bEnable );
+ m_xRbtRight->set_sensitive( bEnable );
+ m_xRbtBottom->set_sensitive( bEnable );
+
+ m_aChangeLink.Call(nullptr);
+}
+
+void LegendPositionResources::initFromItemSet( const SfxItemSet& rInAttrs )
+{
+ if( const SfxInt32Item* pPosItem = rInAttrs.GetItemIfSet( SCHATTR_LEGEND_POS ) )
+ {
+ chart2::LegendPosition nLegendPosition = static_cast<chart2::LegendPosition>(pPosItem->GetValue());
+ switch( nLegendPosition )
+ {
+ case chart2::LegendPosition_LINE_START:
+ m_xRbtLeft->set_active(true);
+ break;
+ case chart2::LegendPosition_PAGE_START:
+ m_xRbtTop->set_active(true);
+ break;
+ case chart2::LegendPosition_LINE_END:
+ m_xRbtRight->set_active(true);
+ break;
+ case chart2::LegendPosition_PAGE_END:
+ m_xRbtBottom->set_active(true);
+ break;
+ default:
+ break;
+ }
+ }
+
+ const SfxBoolItem* pShowItem;
+ if( m_xCbxShow && (pShowItem = rInAttrs.GetItemIfSet( SCHATTR_LEGEND_SHOW )) )
+ {
+ m_xCbxShow->set_active(pShowItem->GetValue());
+ }
+}
+
+void LegendPositionResources::writeToItemSet( SfxItemSet& rOutAttrs ) const
+{
+ chart2::LegendPosition nLegendPosition = chart2::LegendPosition_LINE_END;
+ if( m_xRbtLeft->get_active() )
+ nLegendPosition = chart2::LegendPosition_LINE_START;
+ else if( m_xRbtTop->get_active() )
+ nLegendPosition = chart2::LegendPosition_PAGE_START;
+ else if( m_xRbtRight->get_active() )
+ nLegendPosition = chart2::LegendPosition_LINE_END;
+ else if( m_xRbtBottom->get_active() )
+ nLegendPosition = chart2::LegendPosition_PAGE_END;
+ rOutAttrs.Put( SfxInt32Item(SCHATTR_LEGEND_POS, static_cast<sal_Int32>(nLegendPosition) ) );
+
+ rOutAttrs.Put( SfxBoolItem(SCHATTR_LEGEND_SHOW, !m_xCbxShow || m_xCbxShow->get_active()) );
+}
+
+IMPL_LINK (LegendPositionResources, PositionChangeHdl, weld::Toggleable&, rRadio, void)
+{
+ //for each radio click there are coming two change events
+ //first uncheck of previous button -> ignore that call
+ //the second call gives the check of the new button
+ if( rRadio.get_active() )
+ m_aChangeLink.Call(nullptr);
+}
+
+void LegendPositionResources::SetChangeHdl( const Link<LinkParamNone*,void>& rLink )
+{
+ m_aChangeLink = rLink;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/res_Titles.cxx b/chart2/source/controller/dialogs/res_Titles.cxx
new file mode 100644
index 0000000000..59b0f00b9b
--- /dev/null
+++ b/chart2/source/controller/dialogs/res_Titles.cxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <res_Titles.hxx>
+#include <TitleDialogData.hxx>
+#include <vcl/weld.hxx>
+
+namespace chart
+{
+TitleResources::TitleResources(weld::Builder& rBuilder, bool bShowSecondaryAxesTitle)
+ : m_xFT_Main(rBuilder.weld_label("labelMainTitle"))
+ , m_xFT_Sub(rBuilder.weld_label("labelSubTitle"))
+ , m_xEd_Main(rBuilder.weld_entry("maintitle"))
+ , m_xEd_Sub(rBuilder.weld_entry("subtitle"))
+ , m_xFT_XAxis(rBuilder.weld_label("labelPrimaryXaxis"))
+ , m_xFT_YAxis(rBuilder.weld_label("labelPrimaryYaxis"))
+ , m_xFT_ZAxis(rBuilder.weld_label("labelPrimaryZaxis"))
+ , m_xEd_XAxis(rBuilder.weld_entry("primaryXaxis"))
+ , m_xEd_YAxis(rBuilder.weld_entry("primaryYaxis"))
+ , m_xEd_ZAxis(rBuilder.weld_entry("primaryZaxis"))
+ , m_xFT_SecondaryXAxis(rBuilder.weld_label("labelSecondaryXAxis"))
+ , m_xFT_SecondaryYAxis(rBuilder.weld_label("labelSecondaryYAxis"))
+ , m_xEd_SecondaryXAxis(rBuilder.weld_entry("secondaryXaxis"))
+ , m_xEd_SecondaryYAxis(rBuilder.weld_entry("secondaryYaxis"))
+{
+ m_xFT_SecondaryXAxis->set_visible(bShowSecondaryAxesTitle);
+ m_xFT_SecondaryYAxis->set_visible(bShowSecondaryAxesTitle);
+ m_xEd_SecondaryXAxis->set_visible(bShowSecondaryAxesTitle);
+ m_xEd_SecondaryYAxis->set_visible(bShowSecondaryAxesTitle);
+}
+
+TitleResources::~TitleResources() {}
+
+void TitleResources::connect_changed(const Link<weld::Entry&, void>& rLink)
+{
+ m_xEd_Main->connect_changed(rLink);
+ m_xEd_Sub->connect_changed(rLink);
+ m_xEd_XAxis->connect_changed(rLink);
+ m_xEd_YAxis->connect_changed(rLink);
+ m_xEd_ZAxis->connect_changed(rLink);
+ m_xEd_SecondaryXAxis->connect_changed(rLink);
+ m_xEd_SecondaryYAxis->connect_changed(rLink);
+}
+
+bool TitleResources::get_value_changed_from_saved() const
+{
+ return m_xEd_Main->get_value_changed_from_saved() || m_xEd_Sub->get_value_changed_from_saved()
+ || m_xEd_XAxis->get_value_changed_from_saved()
+ || m_xEd_YAxis->get_value_changed_from_saved()
+ || m_xEd_ZAxis->get_value_changed_from_saved()
+ || m_xEd_SecondaryXAxis->get_value_changed_from_saved()
+ || m_xEd_SecondaryYAxis->get_value_changed_from_saved();
+}
+
+void TitleResources::save_value()
+{
+ m_xEd_Main->save_value();
+ m_xEd_Sub->save_value();
+ m_xEd_XAxis->save_value();
+ m_xEd_YAxis->save_value();
+ m_xEd_ZAxis->save_value();
+ m_xEd_SecondaryXAxis->save_value();
+ m_xEd_SecondaryYAxis->save_value();
+}
+
+void TitleResources::writeToResources(const TitleDialogData& rInput)
+{
+ m_xFT_Main->set_sensitive(rInput.aPossibilityList[0]);
+ m_xFT_Sub->set_sensitive(rInput.aPossibilityList[1]);
+ m_xFT_XAxis->set_sensitive(rInput.aPossibilityList[2]);
+ m_xFT_YAxis->set_sensitive(rInput.aPossibilityList[3]);
+ m_xFT_ZAxis->set_sensitive(rInput.aPossibilityList[4]);
+ m_xFT_SecondaryXAxis->set_sensitive(rInput.aPossibilityList[5]);
+ m_xFT_SecondaryYAxis->set_sensitive(rInput.aPossibilityList[6]);
+
+ m_xEd_Main->set_sensitive(rInput.aPossibilityList[0]);
+ m_xEd_Sub->set_sensitive(rInput.aPossibilityList[1]);
+ m_xEd_XAxis->set_sensitive(rInput.aPossibilityList[2]);
+ m_xEd_YAxis->set_sensitive(rInput.aPossibilityList[3]);
+ m_xEd_ZAxis->set_sensitive(rInput.aPossibilityList[4]);
+ m_xEd_SecondaryXAxis->set_sensitive(rInput.aPossibilityList[5]);
+ m_xEd_SecondaryYAxis->set_sensitive(rInput.aPossibilityList[6]);
+
+ m_xEd_Main->set_text(rInput.aTextList[0]);
+ m_xEd_Sub->set_text(rInput.aTextList[1]);
+ m_xEd_XAxis->set_text(rInput.aTextList[2]);
+ m_xEd_YAxis->set_text(rInput.aTextList[3]);
+ m_xEd_ZAxis->set_text(rInput.aTextList[4]);
+ m_xEd_SecondaryXAxis->set_text(rInput.aTextList[5]);
+ m_xEd_SecondaryYAxis->set_text(rInput.aTextList[6]);
+}
+
+void TitleResources::readFromResources(TitleDialogData& rOutput)
+{
+ sal_Bool* pExistenceList = rOutput.aExistenceList.getArray();
+ pExistenceList[0] = !m_xEd_Main->get_text().isEmpty();
+ pExistenceList[1] = !m_xEd_Sub->get_text().isEmpty();
+ pExistenceList[2] = !m_xEd_XAxis->get_text().isEmpty();
+ pExistenceList[3] = !m_xEd_YAxis->get_text().isEmpty();
+ pExistenceList[4] = !m_xEd_ZAxis->get_text().isEmpty();
+ pExistenceList[5] = !m_xEd_SecondaryXAxis->get_text().isEmpty();
+ pExistenceList[6] = !m_xEd_SecondaryYAxis->get_text().isEmpty();
+
+ auto pTextList = rOutput.aTextList.getArray();
+ pTextList[0] = m_xEd_Main->get_text();
+ pTextList[1] = m_xEd_Sub->get_text();
+ pTextList[2] = m_xEd_XAxis->get_text();
+ pTextList[3] = m_xEd_YAxis->get_text();
+ pTextList[4] = m_xEd_ZAxis->get_text();
+ pTextList[5] = m_xEd_SecondaryXAxis->get_text();
+ pTextList[6] = m_xEd_SecondaryYAxis->get_text();
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/res_Trendline.cxx b/chart2/source/controller/dialogs/res_Trendline.cxx
new file mode 100644
index 0000000000..58ef6497a5
--- /dev/null
+++ b/chart2/source/controller/dialogs/res_Trendline.cxx
@@ -0,0 +1,434 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "res_Trendline.hxx"
+#include <bitmaps.hlst>
+#include <chartview/ChartSfxItemIds.hxx>
+
+#include <com/sun/star/chart2/MovingAverageType.hpp>
+
+#include <svl/intitem.hxx>
+#include <svl/numformat.hxx>
+#include <svl/stritem.hxx>
+#include <vcl/formatter.hxx>
+#include <vcl/weld.hxx>
+
+using namespace css::chart2;
+
+namespace chart
+{
+
+static void lcl_setValue(weld::FormattedSpinButton& rFmtField, double fValue )
+{
+ Formatter& rFieldFormatter = rFmtField.GetFormatter();
+ rFieldFormatter.SetValue(fValue);
+ rFieldFormatter.SetDefaultValue( fValue );
+}
+
+TrendlineResources::TrendlineResources(weld::Builder& rBuilder, const SfxItemSet& rInAttrs)
+ : m_eTrendLineType(SvxChartRegress::Linear)
+ , m_bTrendLineUnique(true)
+ , m_pNumFormatter(nullptr)
+ , m_nNbPoints(0)
+ , m_xRB_Linear(rBuilder.weld_radio_button("linear"))
+ , m_xRB_Logarithmic(rBuilder.weld_radio_button("logarithmic"))
+ , m_xRB_Exponential(rBuilder.weld_radio_button("exponential"))
+ , m_xRB_Power(rBuilder.weld_radio_button("power"))
+ , m_xRB_Polynomial(rBuilder.weld_radio_button("polynomial"))
+ , m_xRB_MovingAverage(rBuilder.weld_radio_button("movingAverage"))
+ , m_xFI_Linear(rBuilder.weld_image("imageLinear"))
+ , m_xFI_Logarithmic(rBuilder.weld_image("imageLogarithmic"))
+ , m_xFI_Exponential(rBuilder.weld_image("imageExponential"))
+ , m_xFI_Power(rBuilder.weld_image("imagePower"))
+ , m_xFI_Polynomial(rBuilder.weld_image("imagePolynomial"))
+ , m_xFI_MovingAverage(rBuilder.weld_image("imageMovingAverage"))
+ , m_xNF_Degree(rBuilder.weld_spin_button("degree"))
+ , m_xNF_Period(rBuilder.weld_spin_button("period"))
+ , m_xEE_Name(rBuilder.weld_entry("entry_name"))
+ , m_xFmtFld_ExtrapolateForward(rBuilder.weld_formatted_spin_button("extrapolateForward"))
+ , m_xFmtFld_ExtrapolateBackward(rBuilder.weld_formatted_spin_button("extrapolateBackward"))
+ , m_xCB_SetIntercept(rBuilder.weld_check_button("setIntercept"))
+ , m_xFmtFld_InterceptValue(rBuilder.weld_formatted_spin_button("interceptValue"))
+ , m_xCB_ShowEquation(rBuilder.weld_check_button("showEquation"))
+ , m_xEE_XName(rBuilder.weld_entry("entry_Xname"))
+ , m_xEE_YName(rBuilder.weld_entry("entry_Yname"))
+ , m_xCB_ShowCorrelationCoeff(rBuilder.weld_check_button("showCorrelationCoefficient"))
+ , m_xCB_RegressionMovingType(rBuilder.weld_combo_box("combo_moving_type"))
+{
+ FillValueSets();
+
+ Formatter& rForwardFormatter = m_xFmtFld_ExtrapolateForward->GetFormatter();
+ rForwardFormatter.ClearMinValue();
+ rForwardFormatter.ClearMaxValue();
+ Formatter& rBackwardFormatter = m_xFmtFld_ExtrapolateBackward->GetFormatter();
+ rBackwardFormatter.ClearMinValue();
+ rBackwardFormatter.ClearMaxValue();
+ Formatter& rInterceptFormatter = m_xFmtFld_InterceptValue->GetFormatter();
+ rInterceptFormatter.ClearMinValue();
+ rInterceptFormatter.ClearMaxValue();
+
+ Link<weld::Toggleable&,void> aLink = LINK(this, TrendlineResources, SelectTrendLine);
+ m_xRB_Linear->connect_toggled( aLink );
+ m_xRB_Logarithmic->connect_toggled( aLink );
+ m_xRB_Exponential->connect_toggled( aLink );
+ m_xRB_Power->connect_toggled( aLink );
+ m_xRB_Polynomial->connect_toggled( aLink );
+ m_xRB_MovingAverage->connect_toggled( aLink );
+
+ Link<weld::SpinButton&,void> aLink2 = LINK(this, TrendlineResources, ChangeSpinValue);
+ m_xNF_Degree->connect_value_changed(aLink2);
+ m_xNF_Period->connect_value_changed(aLink2);
+ m_xFmtFld_InterceptValue->connect_value_changed(LINK(this, TrendlineResources, ChangeFormattedValue));
+
+ m_xCB_ShowEquation->connect_toggled(LINK(this, TrendlineResources, ShowEquation));
+
+ Reset( rInAttrs );
+ UpdateControlStates();
+}
+
+TrendlineResources::~TrendlineResources()
+{}
+
+IMPL_LINK_NOARG(TrendlineResources, SelectTrendLine, weld::Toggleable&, void)
+{
+ if (m_xRB_Linear->get_active())
+ m_eTrendLineType = SvxChartRegress::Linear;
+ else if (m_xRB_Logarithmic->get_active())
+ m_eTrendLineType = SvxChartRegress::Log;
+ else if (m_xRB_Exponential->get_active())
+ m_eTrendLineType = SvxChartRegress::Exp;
+ else if (m_xRB_Power->get_active())
+ m_eTrendLineType = SvxChartRegress::Power;
+ else if (m_xRB_Polynomial->get_active())
+ m_eTrendLineType = SvxChartRegress::Polynomial;
+ else if (m_xRB_MovingAverage->get_active())
+ m_eTrendLineType = SvxChartRegress::MovingAverage;
+ m_bTrendLineUnique = true;
+
+ UpdateControlStates();
+}
+
+void TrendlineResources::Reset( const SfxItemSet& rInAttrs )
+{
+ if( const SfxStringItem* pCurveNameItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_CURVE_NAME ) )
+ {
+ OUString aName = pCurveNameItem->GetValue();
+ m_xEE_Name->set_text(aName);
+ }
+ else
+ {
+ m_xEE_Name->set_text("");
+ }
+ if( const SfxStringItem* pRegressionXNameItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_XNAME ) )
+ {
+ OUString aName = pRegressionXNameItem->GetValue();
+ m_xEE_XName->set_text(aName);
+ }
+ else
+ {
+ m_xEE_XName->set_text("x");
+ }
+ if( const SfxStringItem* pRegressionYNameItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_YNAME ) )
+ {
+ OUString aName = pRegressionYNameItem->GetValue();
+ m_xEE_YName->set_text(aName);
+ }
+ else
+ {
+ m_xEE_YName->set_text("f(x)");
+ }
+
+ const SfxPoolItem* pPoolItem = nullptr;
+ SfxItemState aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_TYPE, true, &pPoolItem );
+ m_bTrendLineUnique = ( aState != SfxItemState::DONTCARE );
+ if( aState == SfxItemState::SET )
+ {
+ const SvxChartRegressItem * pItem = dynamic_cast< const SvxChartRegressItem * >( pPoolItem );
+ if( pItem )
+ {
+ m_eTrendLineType = pItem->GetValue();
+ }
+ }
+
+ if( const SfxInt32Item* pDegreeItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_DEGREE ) )
+ {
+ sal_Int32 nDegree = pDegreeItem->GetValue();
+ m_xNF_Degree->set_value( nDegree );
+ }
+ else
+ {
+ m_xNF_Degree->set_value( 2 );
+ }
+
+ m_xNF_Degree->save_value();
+
+ if( const SfxInt32Item* pPeriodItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_PERIOD ) )
+ {
+ sal_Int32 nPeriod = pPeriodItem->GetValue();
+ m_xNF_Period->set_value( nPeriod );
+ }
+ else
+ {
+ m_xNF_Period->set_value( 2 );
+ }
+
+ m_xNF_Period->save_value();
+
+ double nValue = 0.0;
+ if( const SvxDoubleItem* pForwardItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD ) )
+ {
+ nValue = pForwardItem->GetValue() ;
+ }
+ lcl_setValue(*m_xFmtFld_ExtrapolateForward, nValue);
+
+ nValue = 0.0;
+ if( const SvxDoubleItem* pBackwardItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD ) )
+ {
+ nValue = pBackwardItem->GetValue() ;
+ }
+ lcl_setValue(*m_xFmtFld_ExtrapolateBackward, nValue);
+
+ nValue = 0.0;
+ if( const SvxDoubleItem* pValueItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_INTERCEPT_VALUE ) )
+ {
+ nValue = pValueItem->GetValue() ;
+ }
+ lcl_setValue(*m_xFmtFld_InterceptValue, nValue);
+
+ aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SET_INTERCEPT, true, &pPoolItem );
+ if( aState == SfxItemState::DONTCARE )
+ {
+ m_xCB_SetIntercept->set_state(TRISTATE_INDET);
+ }
+ else
+ {
+ if( aState == SfxItemState::SET )
+ m_xCB_SetIntercept->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue());
+ }
+
+ aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SHOW_EQUATION, true, &pPoolItem );
+ if( aState == SfxItemState::DONTCARE )
+ {
+ m_xCB_ShowEquation->set_state(TRISTATE_INDET);
+ }
+ else
+ {
+ if( aState == SfxItemState::SET )
+ m_xCB_ShowEquation->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue());
+ }
+
+ aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SHOW_COEFF, true, &pPoolItem );
+ if( aState == SfxItemState::DONTCARE )
+ {
+ m_xCB_ShowCorrelationCoeff->set_state(TRISTATE_INDET);
+ }
+ else
+ {
+ if( aState == SfxItemState::SET )
+ m_xCB_ShowCorrelationCoeff->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue());
+ }
+
+ if( const SfxInt32Item* pMovingTypeItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_MOVING_TYPE ) )
+ {
+ sal_Int32 nMovingType = pMovingTypeItem->GetValue();
+ if (nMovingType == MovingAverageType::Prior)
+ m_xCB_RegressionMovingType->set_active(0);
+ else if (nMovingType == MovingAverageType::Central)
+ m_xCB_RegressionMovingType->set_active(1);
+ else if (nMovingType == MovingAverageType::AveragedAbscissa)
+ m_xCB_RegressionMovingType->set_active(2);
+ }
+ else
+ {
+ m_xCB_RegressionMovingType->set_active(0);
+ }
+
+ if( !m_bTrendLineUnique )
+ return;
+
+ switch( m_eTrendLineType )
+ {
+ case SvxChartRegress::Linear :
+ m_xRB_Linear->set_active(true);
+ break;
+ case SvxChartRegress::Log :
+ m_xRB_Logarithmic->set_active(true);
+ break;
+ case SvxChartRegress::Exp :
+ m_xRB_Exponential->set_active(true);
+ break;
+ case SvxChartRegress::Power :
+ m_xRB_Power->set_active(true);
+ break;
+ case SvxChartRegress::Polynomial :
+ m_xRB_Polynomial->set_active(true);
+ break;
+ case SvxChartRegress::MovingAverage :
+ m_xRB_MovingAverage->set_active(true);
+ break;
+ default:
+ break;
+ }
+}
+
+void TrendlineResources::FillItemSet(SfxItemSet* rOutAttrs) const
+{
+ if( m_bTrendLineUnique )
+ rOutAttrs->Put( SvxChartRegressItem( m_eTrendLineType, SCHATTR_REGRESSION_TYPE ));
+
+ if (m_eTrendLineType == SvxChartRegress::MovingAverage)
+ {
+ sal_Int32 nType = MovingAverageType::Prior;
+ if (m_xCB_RegressionMovingType->get_active() == 1)
+ nType = MovingAverageType::Central;
+ else if (m_xCB_RegressionMovingType->get_active() == 2)
+ nType = MovingAverageType::AveragedAbscissa;
+
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_REGRESSION_MOVING_TYPE, nType));
+ }
+
+ if( m_xCB_ShowEquation->get_state() != TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_REGRESSION_SHOW_EQUATION, m_xCB_ShowEquation->get_active() ));
+
+ if( m_xCB_ShowCorrelationCoeff->get_state() != TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_REGRESSION_SHOW_COEFF, m_xCB_ShowCorrelationCoeff->get_active() ));
+
+ OUString aName = m_xEE_Name->get_text();
+ rOutAttrs->Put(SfxStringItem(SCHATTR_REGRESSION_CURVE_NAME, aName));
+ aName = m_xEE_XName->get_text();
+ if ( aName.isEmpty() )
+ aName = "x";
+ rOutAttrs->Put(SfxStringItem(SCHATTR_REGRESSION_XNAME, aName));
+ aName = m_xEE_YName->get_text();
+ if ( aName.isEmpty() )
+ aName = "f(x)";
+ rOutAttrs->Put(SfxStringItem(SCHATTR_REGRESSION_YNAME, aName));
+
+ sal_Int32 aDegree = m_xNF_Degree->get_value();
+ rOutAttrs->Put(SfxInt32Item( SCHATTR_REGRESSION_DEGREE, aDegree ) );
+
+ sal_Int32 aPeriod = m_xNF_Period->get_value();
+ rOutAttrs->Put(SfxInt32Item( SCHATTR_REGRESSION_PERIOD, aPeriod ) );
+
+ sal_uInt32 nIndex = 0;
+ double aValue = 0.0;
+ (void)m_pNumFormatter->IsNumberFormat(m_xFmtFld_ExtrapolateForward->get_text(),nIndex,aValue);
+ rOutAttrs->Put(SvxDoubleItem( aValue, SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD ) );
+
+ aValue = 0.0;
+ (void)m_pNumFormatter->IsNumberFormat(m_xFmtFld_ExtrapolateBackward->get_text(),nIndex,aValue);
+ rOutAttrs->Put(SvxDoubleItem( aValue, SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD ) );
+
+ if( m_xCB_SetIntercept->get_state() != TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_REGRESSION_SET_INTERCEPT, m_xCB_SetIntercept->get_active() ));
+
+ aValue = 0.0;
+ (void)m_pNumFormatter->IsNumberFormat(m_xFmtFld_InterceptValue->get_text(),nIndex,aValue);
+ rOutAttrs->Put(SvxDoubleItem( aValue, SCHATTR_REGRESSION_INTERCEPT_VALUE ) );
+}
+
+void TrendlineResources::FillValueSets()
+{
+ m_xFI_Linear->set_from_icon_name(BMP_REGRESSION_LINEAR);
+ m_xFI_Logarithmic->set_from_icon_name(BMP_REGRESSION_LOG);
+ m_xFI_Exponential->set_from_icon_name(BMP_REGRESSION_EXP);
+ m_xFI_Power->set_from_icon_name(BMP_REGRESSION_POWER);
+ m_xFI_Polynomial->set_from_icon_name(BMP_REGRESSION_POLYNOMIAL);
+ m_xFI_MovingAverage->set_from_icon_name(BMP_REGRESSION_MOVING_AVERAGE);
+}
+
+void TrendlineResources::UpdateControlStates()
+{
+ if( m_nNbPoints > 0 )
+ {
+ sal_Int32 nMaxValue = m_nNbPoints - 1 + (m_xCB_SetIntercept->get_active() ? 1 : 0);
+ m_xNF_Degree->set_max(nMaxValue);
+ m_xNF_Period->set_max(m_nNbPoints - 1);
+ }
+ bool bMovingAverage = ( m_eTrendLineType == SvxChartRegress::MovingAverage );
+ bool bPolynomial = ( m_eTrendLineType == SvxChartRegress::Polynomial );
+ bool bInterceptAvailable = ( m_eTrendLineType == SvxChartRegress::Linear )
+ || ( m_eTrendLineType == SvxChartRegress::Polynomial )
+ || ( m_eTrendLineType == SvxChartRegress::Exp );
+ m_xFmtFld_ExtrapolateForward->set_sensitive( !bMovingAverage );
+ m_xFmtFld_ExtrapolateBackward->set_sensitive( !bMovingAverage );
+ m_xCB_SetIntercept->set_sensitive( bInterceptAvailable );
+ m_xFmtFld_InterceptValue->set_sensitive( bInterceptAvailable );
+ if( bMovingAverage )
+ {
+ m_xCB_ShowCorrelationCoeff->set_state(TRISTATE_FALSE);
+ }
+ m_xCB_ShowCorrelationCoeff->set_sensitive( !bMovingAverage );
+ m_xCB_RegressionMovingType->set_sensitive(bMovingAverage);
+ m_xNF_Period->set_sensitive(bMovingAverage);
+ m_xNF_Degree->set_sensitive(bPolynomial);
+ m_xEE_XName->set_sensitive( !bMovingAverage && m_xCB_ShowEquation->get_active() );
+ m_xEE_YName->set_sensitive( !bMovingAverage && m_xCB_ShowEquation->get_active() );
+}
+
+IMPL_LINK(TrendlineResources, ChangeSpinValue, weld::SpinButton&, rNumericField, void)
+{
+ if (&rNumericField == m_xNF_Degree.get())
+ {
+ if (!m_xRB_Polynomial->get_active() && m_xNF_Degree->get_value_changed_from_saved())
+ {
+ m_xRB_Polynomial->set_active(true);
+ SelectTrendLine(*m_xRB_Polynomial);
+ }
+ }
+ else if (&rNumericField == m_xNF_Period.get())
+ {
+ if (!m_xRB_MovingAverage->get_active() && m_xNF_Period->get_value_changed_from_saved())
+ {
+ m_xRB_MovingAverage->set_active(true);
+ SelectTrendLine(*m_xRB_MovingAverage);
+ }
+ }
+ UpdateControlStates();
+}
+
+IMPL_LINK_NOARG(TrendlineResources, ChangeFormattedValue, weld::FormattedSpinButton&, void)
+{
+ if (!m_xCB_SetIntercept->get_active())
+ m_xCB_SetIntercept->set_active(true);
+ UpdateControlStates();
+}
+
+void TrendlineResources::SetNumFormatter( SvNumberFormatter* pFormatter )
+{
+ m_pNumFormatter = pFormatter;
+ m_xFmtFld_ExtrapolateForward->GetFormatter().SetFormatter(m_pNumFormatter);
+ m_xFmtFld_ExtrapolateBackward->GetFormatter().SetFormatter(m_pNumFormatter);
+ m_xFmtFld_InterceptValue->GetFormatter().SetFormatter(m_pNumFormatter);
+}
+
+void TrendlineResources::SetNbPoints( sal_Int32 nNbPoints )
+{
+ m_nNbPoints = nNbPoints;
+ UpdateControlStates();
+}
+
+IMPL_LINK_NOARG(TrendlineResources, ShowEquation, weld::Toggleable&, void)
+{
+ UpdateControlStates();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/res_Trendline.hxx b/chart2/source/controller/dialogs/res_Trendline.hxx
new file mode 100644
index 0000000000..e520d6da3b
--- /dev/null
+++ b/chart2/source/controller/dialogs/res_Trendline.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <tools/link.hxx>
+#include <svl/itemset.hxx>
+#include <svx/chrtitem.hxx>
+
+namespace weld { class Builder; }
+namespace weld { class CheckButton; }
+namespace weld { class ComboBox; }
+namespace weld { class Entry; }
+namespace weld { class FormattedSpinButton; }
+namespace weld { class Image; }
+namespace weld { class RadioButton; }
+namespace weld { class SpinButton; }
+namespace weld { class Toggleable; }
+
+class SvNumberFormatter;
+
+namespace chart
+{
+
+class TrendlineResources final
+{
+public:
+ TrendlineResources(weld::Builder& rParent, const SfxItemSet& rInAttrs);
+ ~TrendlineResources();
+
+ void Reset(const SfxItemSet& rInAttrs);
+ void FillItemSet(SfxItemSet* rOutAttrs) const;
+
+ void FillValueSets();
+
+ void SetNumFormatter( SvNumberFormatter* pFormatter );
+ void SetNbPoints( sal_Int32 nNbPoints );
+
+private:
+ SvxChartRegress m_eTrendLineType;
+
+ bool m_bTrendLineUnique;
+
+ SvNumberFormatter* m_pNumFormatter;
+ sal_Int32 m_nNbPoints;
+
+ std::unique_ptr<weld::RadioButton> m_xRB_Linear;
+ std::unique_ptr<weld::RadioButton> m_xRB_Logarithmic;
+ std::unique_ptr<weld::RadioButton> m_xRB_Exponential;
+ std::unique_ptr<weld::RadioButton> m_xRB_Power;
+ std::unique_ptr<weld::RadioButton> m_xRB_Polynomial;
+ std::unique_ptr<weld::RadioButton> m_xRB_MovingAverage;
+
+ std::unique_ptr<weld::Image> m_xFI_Linear;
+ std::unique_ptr<weld::Image> m_xFI_Logarithmic;
+ std::unique_ptr<weld::Image> m_xFI_Exponential;
+ std::unique_ptr<weld::Image> m_xFI_Power;
+ std::unique_ptr<weld::Image> m_xFI_Polynomial;
+ std::unique_ptr<weld::Image> m_xFI_MovingAverage;
+
+ std::unique_ptr<weld::SpinButton> m_xNF_Degree;
+ std::unique_ptr<weld::SpinButton> m_xNF_Period;
+ std::unique_ptr<weld::Entry> m_xEE_Name;
+ std::unique_ptr<weld::FormattedSpinButton> m_xFmtFld_ExtrapolateForward;
+ std::unique_ptr<weld::FormattedSpinButton> m_xFmtFld_ExtrapolateBackward;
+ std::unique_ptr<weld::CheckButton> m_xCB_SetIntercept;
+ std::unique_ptr<weld::FormattedSpinButton> m_xFmtFld_InterceptValue;
+ std::unique_ptr<weld::CheckButton> m_xCB_ShowEquation;
+ std::unique_ptr<weld::Entry> m_xEE_XName;
+ std::unique_ptr<weld::Entry> m_xEE_YName;
+ std::unique_ptr<weld::CheckButton> m_xCB_ShowCorrelationCoeff;
+ std::unique_ptr<weld::ComboBox> m_xCB_RegressionMovingType;
+
+ void UpdateControlStates();
+ DECL_LINK(SelectTrendLine, weld::Toggleable&, void);
+ DECL_LINK(ChangeSpinValue, weld::SpinButton&, void);
+ DECL_LINK(ChangeFormattedValue, weld::FormattedSpinButton&, void);
+ DECL_LINK(ShowEquation, weld::Toggleable&, void);
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_3D_SceneAppearance.cxx b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.cxx
new file mode 100644
index 0000000000..e07969c957
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.cxx
@@ -0,0 +1,318 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_3D_SceneAppearance.hxx"
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <ThreeDHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <Diagram.hxx>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+
+struct lcl_ModelProperties
+{
+ drawing::ShadeMode m_aShadeMode;
+ sal_Int32 m_nRoundedEdges;
+ sal_Int32 m_nObjectLines;
+ ::chart::ThreeDLookScheme m_eScheme;
+
+ lcl_ModelProperties()
+ : m_aShadeMode(drawing::ShadeMode_FLAT)
+ , m_nRoundedEdges(-1)
+ , m_nObjectLines(-1)
+ , m_eScheme(::chart::ThreeDLookScheme::ThreeDLookScheme_Unknown)
+ {}
+};
+
+lcl_ModelProperties lcl_getPropertiesFromModel( rtl::Reference<::chart::ChartModel> const & xModel )
+{
+ lcl_ModelProperties aProps;
+ try
+ {
+ rtl::Reference< ::chart::Diagram > xDiagram( xModel->getFirstChartDiagram() );
+ xDiagram->getPropertyValue( "D3DSceneShadeMode" ) >>= aProps.m_aShadeMode;
+ ::chart::ThreeDHelper::getRoundedEdgesAndObjectLines( xDiagram, aProps.m_nRoundedEdges, aProps.m_nObjectLines );
+ aProps.m_eScheme = xDiagram->detectScheme();
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return aProps;
+}
+
+void lcl_setShadeModeAtModel( rtl::Reference<::chart::ChartModel> const & xModel, drawing::ShadeMode aShadeMode )
+{
+ try
+ {
+ rtl::Reference< ::chart::Diagram > xDiaProp = xModel->getFirstChartDiagram();
+ xDiaProp->setPropertyValue( "D3DSceneShadeMode" , uno::Any( aShadeMode ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+#define POS_3DSCHEME_SIMPLE 0
+#define POS_3DSCHEME_REALISTIC 1
+#define POS_3DSCHEME_CUSTOM 2
+
+ThreeD_SceneAppearance_TabPage::ThreeD_SceneAppearance_TabPage(weld::Container* pParent,
+ rtl::Reference<::chart::ChartModel> xChartModel,
+ ControllerLockHelper& rControllerLockHelper)
+ : m_xChartModel(std::move(xChartModel))
+ , m_bUpdateOtherControls(true)
+ , m_bCommitToModel(true)
+ , m_rControllerLockHelper(rControllerLockHelper)
+ , m_xBuilder(Application::CreateBuilder(pParent, "modules/schart/ui/tp_3D_SceneAppearance.ui"))
+ , m_xContainer(m_xBuilder->weld_container("tp_3D_SceneAppearance"))
+ , m_xLB_Scheme(m_xBuilder->weld_combo_box("LB_SCHEME"))
+ , m_xCB_Shading(m_xBuilder->weld_check_button("CB_SHADING"))
+ , m_xCB_ObjectLines(m_xBuilder->weld_check_button("CB_OBJECTLINES"))
+ , m_xCB_RoundedEdge(m_xBuilder->weld_check_button("CB_ROUNDEDEDGE"))
+{
+ m_aCustom = m_xLB_Scheme->get_text(POS_3DSCHEME_CUSTOM);
+ m_xLB_Scheme->remove(POS_3DSCHEME_CUSTOM);
+
+ m_xLB_Scheme->connect_changed( LINK( this, ThreeD_SceneAppearance_TabPage, SelectSchemeHdl ) );
+
+ m_xCB_RoundedEdge->connect_toggled( LINK( this, ThreeD_SceneAppearance_TabPage, SelectRoundedEdgeOrObjectLines ) );
+ m_xCB_Shading->connect_toggled( LINK( this, ThreeD_SceneAppearance_TabPage, SelectShading ) );
+ m_xCB_ObjectLines->connect_toggled( LINK( this, ThreeD_SceneAppearance_TabPage, SelectRoundedEdgeOrObjectLines ) );
+
+ initControlsFromModel();
+}
+
+ThreeD_SceneAppearance_TabPage::~ThreeD_SceneAppearance_TabPage()
+{
+}
+
+void ThreeD_SceneAppearance_TabPage::ActivatePage()
+{
+ updateScheme();
+}
+
+void ThreeD_SceneAppearance_TabPage::applyRoundedEdgeAndObjectLinesToModel()
+{
+ if(!m_bCommitToModel)
+ return;
+
+ sal_Int32 nObjectLines = -1;
+
+ switch( m_xCB_ObjectLines->get_state())
+ {
+ case TRISTATE_FALSE:
+ nObjectLines = 0;
+ break;
+ case TRISTATE_TRUE:
+ nObjectLines = 1;
+ break;
+ case TRISTATE_INDET:
+ nObjectLines = -1;
+ break;
+ }
+
+ sal_Int32 nCurrentRoundedEdges = -1;
+ switch( m_xCB_RoundedEdge->get_state() )
+ {
+ case TRISTATE_FALSE:
+ nCurrentRoundedEdges = 0;
+ break;
+ case TRISTATE_TRUE:
+ nCurrentRoundedEdges = 5;
+ break;
+ case TRISTATE_INDET:
+ nCurrentRoundedEdges = -1;
+ break;
+ }
+
+ // locked controllers
+ ControllerLockHelperGuard aGuard( m_rControllerLockHelper );
+ ThreeDHelper::setRoundedEdgesAndObjectLines(
+ m_xChartModel->getFirstChartDiagram(), nCurrentRoundedEdges, nObjectLines );
+}
+
+void ThreeD_SceneAppearance_TabPage::applyShadeModeToModel()
+{
+ if(!m_bCommitToModel)
+ return;
+
+ drawing::ShadeMode aShadeMode = drawing::ShadeMode_PHONG;
+
+ switch( m_xCB_Shading->get_state())
+ {
+ case TRISTATE_FALSE:
+ aShadeMode = drawing::ShadeMode_FLAT;
+ break;
+ case TRISTATE_TRUE:
+ aShadeMode = drawing::ShadeMode_SMOOTH;
+ break;
+ case TRISTATE_INDET:
+ // nothing
+ break;
+ }
+
+ lcl_setShadeModeAtModel( m_xChartModel, aShadeMode );
+}
+
+void ThreeD_SceneAppearance_TabPage::initControlsFromModel()
+{
+ m_bCommitToModel = false;
+ m_bUpdateOtherControls = false;
+
+ lcl_ModelProperties aProps( lcl_getPropertiesFromModel( m_xChartModel ));
+
+ if(aProps.m_aShadeMode == drawing::ShadeMode_FLAT)
+ {
+ m_xCB_Shading->set_active(false);
+ }
+ else if(aProps.m_aShadeMode == drawing::ShadeMode_SMOOTH)
+ {
+ m_xCB_Shading->set_active(true);
+ }
+ else
+ {
+ m_xCB_Shading->set_state(TRISTATE_INDET);
+ }
+
+ if(aProps.m_nObjectLines == 0)
+ {
+ m_xCB_ObjectLines->set_active(false);
+ }
+ else if(aProps.m_nObjectLines==1)
+ {
+ m_xCB_ObjectLines->set_active(true);
+ }
+ else
+ {
+ m_xCB_ObjectLines->set_state(TRISTATE_INDET);
+ }
+
+ if(aProps.m_nRoundedEdges >= 5)
+ {
+ m_xCB_RoundedEdge->set_active(true);
+ }
+ else if(aProps.m_nRoundedEdges<0)
+ {
+ m_xCB_RoundedEdge->set_state(TRISTATE_INDET);
+ }
+ else
+ {
+ m_xCB_RoundedEdge->set_active(false);
+ }
+ m_xCB_RoundedEdge->set_sensitive( !m_xCB_ObjectLines->get_active() );
+
+ updateScheme();
+
+ m_bCommitToModel = true;
+ m_bUpdateOtherControls = true;
+}
+
+void ThreeD_SceneAppearance_TabPage::updateScheme()
+{
+ lcl_ModelProperties aProps( lcl_getPropertiesFromModel( m_xChartModel ));
+
+ if (m_xLB_Scheme->get_count() == (POS_3DSCHEME_CUSTOM+1))
+ m_xLB_Scheme->remove(POS_3DSCHEME_CUSTOM);
+ switch( aProps.m_eScheme )
+ {
+ case ThreeDLookScheme::ThreeDLookScheme_Simple:
+ m_xLB_Scheme->set_active( POS_3DSCHEME_SIMPLE );
+ break;
+ case ThreeDLookScheme::ThreeDLookScheme_Realistic:
+ m_xLB_Scheme->set_active( POS_3DSCHEME_REALISTIC );
+ break;
+ case ThreeDLookScheme::ThreeDLookScheme_Unknown:
+ {
+ m_xLB_Scheme->insert_text(POS_3DSCHEME_CUSTOM, m_aCustom);
+ m_xLB_Scheme->set_active(POS_3DSCHEME_CUSTOM);
+ }
+ break;
+ }
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneAppearance_TabPage, SelectSchemeHdl, weld::ComboBox&, void)
+{
+ if( !m_bUpdateOtherControls )
+ return;
+
+ {
+ // locked controllers
+ ControllerLockHelperGuard aGuard( m_rControllerLockHelper );
+
+ rtl::Reference< Diagram > xDiagram = m_xChartModel->getFirstChartDiagram();
+
+ if( m_xLB_Scheme->get_active() == POS_3DSCHEME_REALISTIC )
+ xDiagram->setScheme( ThreeDLookScheme::ThreeDLookScheme_Realistic );
+ else if( m_xLB_Scheme->get_active() == POS_3DSCHEME_SIMPLE )
+ xDiagram->setScheme( ThreeDLookScheme::ThreeDLookScheme_Simple );
+ else
+ {
+ OSL_FAIL( "Invalid Entry selected" );
+ }
+ }
+
+ // update other controls
+ initControlsFromModel();
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneAppearance_TabPage, SelectShading, weld::Toggleable&, void)
+{
+ if( !m_bUpdateOtherControls )
+ return;
+
+ applyShadeModeToModel();
+ updateScheme();
+}
+
+IMPL_LINK(ThreeD_SceneAppearance_TabPage, SelectRoundedEdgeOrObjectLines, weld::Toggleable&, rCheckBox, void)
+{
+ if( !m_bUpdateOtherControls )
+ return;
+
+ if (&rCheckBox == m_xCB_ObjectLines.get())
+ {
+ m_bUpdateOtherControls = false;
+ m_xCB_RoundedEdge->set_sensitive( !m_xCB_ObjectLines->get_active() );
+ if(!m_xCB_RoundedEdge->get_sensitive())
+ m_xCB_RoundedEdge->set_active(false);
+ m_bUpdateOtherControls = true;
+ }
+
+ applyRoundedEdgeAndObjectLinesToModel();
+ updateScheme();
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx
new file mode 100644
index 0000000000..4136625172
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+
+namespace chart { class ControllerLockHelper; }
+namespace com::sun::star::frame { class XModel; }
+
+namespace chart
+{
+class ChartModel;
+
+class ThreeD_SceneAppearance_TabPage
+{
+public:
+ ThreeD_SceneAppearance_TabPage(
+ weld::Container* pParent,
+ rtl::Reference<::chart::ChartModel> xChartModel,
+ ControllerLockHelper & rControllerLockHelper );
+ void ActivatePage();
+ ~ThreeD_SceneAppearance_TabPage();
+
+private:
+ DECL_LINK( SelectSchemeHdl, weld::ComboBox&, void );
+ DECL_LINK( SelectShading, weld::Toggleable&, void );
+ DECL_LINK( SelectRoundedEdgeOrObjectLines, weld::Toggleable&, void );
+
+ void initControlsFromModel();
+ void applyShadeModeToModel();
+ void applyRoundedEdgeAndObjectLinesToModel();
+ void updateScheme();
+
+private:
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+
+ bool m_bUpdateOtherControls;
+ bool m_bCommitToModel;
+ OUString m_aCustom;
+
+ ControllerLockHelper& m_rControllerLockHelper;
+
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+ std::unique_ptr<weld::ComboBox> m_xLB_Scheme;
+ std::unique_ptr<weld::CheckButton> m_xCB_Shading;
+ std::unique_ptr<weld::CheckButton> m_xCB_ObjectLines;
+ std::unique_ptr<weld::CheckButton> m_xCB_RoundedEdge;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_3D_SceneGeometry.cxx b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.cxx
new file mode 100644
index 0000000000..138952775e
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.cxx
@@ -0,0 +1,258 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_3D_SceneGeometry.hxx"
+
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ThreeDHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <com/sun/star/drawing/ProjectionMode.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/helpers.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+
+namespace
+{
+
+void lcl_SetMetricFieldLimits(weld::MetricSpinButton& rField, sal_Int64 nLimit)
+{
+ rField.set_range(-1*nLimit, nLimit, FieldUnit::DEGREE);
+}
+
+}
+
+ThreeD_SceneGeometry_TabPage::ThreeD_SceneGeometry_TabPage(weld::Container* pParent,
+ rtl::Reference< ::chart::Diagram > xDiagram,
+ ControllerLockHelper & rControllerLockHelper)
+ : m_xDiagram(std::move( xDiagram ))
+ , m_aAngleTimer("chart2 ThreeD_SceneGeometry_TabPage m_aAngleTimer")
+ , m_aPerspectiveTimer("chart2 ThreeD_SceneGeometry_TabPage m_aPerspectiveTimer")
+ , m_nXRotation(0)
+ , m_nYRotation(0)
+ , m_nZRotation(0)
+ , m_bAngleChangePending( false )
+ , m_bPerspectiveChangePending( false )
+ , m_rControllerLockHelper( rControllerLockHelper )
+ , m_xBuilder(Application::CreateBuilder(pParent, "modules/schart/ui/tp_3D_SceneGeometry.ui"))
+ , m_xContainer(m_xBuilder->weld_container("tp_3DSceneGeometry"))
+ , m_xCbxRightAngledAxes(m_xBuilder->weld_check_button("CBX_RIGHT_ANGLED_AXES"))
+ , m_xMFXRotation(m_xBuilder->weld_metric_spin_button("MTR_FLD_X_ROTATION", FieldUnit::DEGREE))
+ , m_xMFYRotation(m_xBuilder->weld_metric_spin_button("MTR_FLD_Y_ROTATION", FieldUnit::DEGREE))
+ , m_xFtZRotation(m_xBuilder->weld_label("FT_Z_ROTATION"))
+ , m_xMFZRotation(m_xBuilder->weld_metric_spin_button("MTR_FLD_Z_ROTATION", FieldUnit::DEGREE))
+ , m_xCbxPerspective(m_xBuilder->weld_check_button("CBX_PERSPECTIVE"))
+ , m_xMFPerspective(m_xBuilder->weld_metric_spin_button("MTR_FLD_PERSPECTIVE", FieldUnit::PERCENT))
+{
+ double fXAngle, fYAngle, fZAngle;
+ m_xDiagram->getRotationAngle( fXAngle, fYAngle, fZAngle );
+
+ fXAngle = basegfx::rad2deg(fXAngle);
+ fYAngle = basegfx::rad2deg(fYAngle);
+ fZAngle = basegfx::rad2deg(fZAngle);
+
+ OSL_ENSURE( fZAngle>=-90 && fZAngle<=90, "z angle is out of valid range" );
+
+ lcl_SetMetricFieldLimits( *m_xMFZRotation, 90 );
+
+ m_nXRotation = NormAngle180(
+ ::basegfx::fround(fXAngle * pow(10.0, m_xMFXRotation->get_digits())));
+ m_nYRotation = NormAngle180(
+ ::basegfx::fround(-1.0 * fYAngle * pow(10.0, m_xMFYRotation->get_digits())));
+ m_nZRotation = NormAngle180(
+ ::basegfx::fround(-1.0 * fZAngle * pow(10.0, m_xMFZRotation->get_digits())));
+
+ m_xMFXRotation->set_value(m_nXRotation, FieldUnit::DEGREE);
+ m_xMFYRotation->set_value(m_nYRotation, FieldUnit::DEGREE);
+ m_xMFZRotation->set_value(m_nZRotation, FieldUnit::DEGREE);
+
+ const int nTimeout = 4*EDIT_UPDATEDATA_TIMEOUT;
+ m_aAngleTimer.SetTimeout(nTimeout);
+ m_aAngleTimer.SetInvokeHandler( LINK( this, ThreeD_SceneGeometry_TabPage, AngleChanged ) );
+
+ Link<weld::MetricSpinButton&,void> aAngleEditedLink( LINK( this, ThreeD_SceneGeometry_TabPage, AngleEdited ));
+ m_xMFXRotation->connect_value_changed( aAngleEditedLink );
+ m_xMFYRotation->connect_value_changed( aAngleEditedLink );
+ m_xMFZRotation->connect_value_changed( aAngleEditedLink );
+
+ drawing::ProjectionMode aProjectionMode = drawing::ProjectionMode_PERSPECTIVE;
+ m_xDiagram->getPropertyValue( "D3DScenePerspective" ) >>= aProjectionMode;
+ m_xCbxPerspective->set_active( aProjectionMode == drawing::ProjectionMode_PERSPECTIVE );
+ m_xCbxPerspective->connect_toggled( LINK( this, ThreeD_SceneGeometry_TabPage, PerspectiveToggled ));
+
+ sal_Int32 nPerspectivePercentage = 20;
+ m_xDiagram->getPropertyValue( "Perspective" ) >>= nPerspectivePercentage;
+ m_xMFPerspective->set_value(nPerspectivePercentage, FieldUnit::PERCENT);
+
+ m_aPerspectiveTimer.SetTimeout(nTimeout);
+ m_aPerspectiveTimer.SetInvokeHandler( LINK( this, ThreeD_SceneGeometry_TabPage, PerspectiveChanged ) );
+ m_xMFPerspective->connect_value_changed( LINK( this, ThreeD_SceneGeometry_TabPage, PerspectiveEdited ) );
+ m_xMFPerspective->set_sensitive( m_xCbxPerspective->get_active() );
+
+ //RightAngledAxes
+ if (ChartTypeHelper::isSupportingRightAngledAxes(m_xDiagram->getChartTypeByIndex(0)))
+ {
+ bool bRightAngledAxes = false;
+ m_xDiagram->getPropertyValue( "RightAngledAxes" ) >>= bRightAngledAxes;
+ m_xCbxRightAngledAxes->connect_toggled( LINK( this, ThreeD_SceneGeometry_TabPage, RightAngledAxesToggled ));
+ m_xCbxRightAngledAxes->set_active( bRightAngledAxes );
+ RightAngledAxesToggled(*m_xCbxRightAngledAxes);
+ }
+ else
+ {
+ m_xCbxRightAngledAxes->set_sensitive(false);
+ }
+}
+
+ThreeD_SceneGeometry_TabPage::~ThreeD_SceneGeometry_TabPage()
+{
+}
+
+void ThreeD_SceneGeometry_TabPage::commitPendingChanges()
+{
+ ControllerLockHelperGuard aGuard( m_rControllerLockHelper );
+
+ if( m_bAngleChangePending )
+ applyAnglesToModel();
+ if( m_bPerspectiveChangePending )
+ applyPerspectiveToModel();
+}
+
+void ThreeD_SceneGeometry_TabPage::applyAnglesToModel()
+{
+ ControllerLockHelperGuard aGuard( m_rControllerLockHelper );
+
+ double fXAngle = 0.0, fYAngle = 0.0, fZAngle = 0.0;
+
+ if (m_xMFZRotation->get_sensitive())
+ m_nZRotation = m_xMFZRotation->get_value(FieldUnit::DEGREE);
+
+ fXAngle = double(m_nXRotation)/pow(10.0,m_xMFXRotation->get_digits());
+ fYAngle = double(-1.0*m_nYRotation)/pow(10.0,m_xMFYRotation->get_digits());
+ fZAngle = double(-1.0*m_nZRotation)/pow(10.0,m_xMFZRotation->get_digits());
+
+ fXAngle = basegfx::deg2rad(fXAngle);
+ fYAngle = basegfx::deg2rad(fYAngle);
+ fZAngle = basegfx::deg2rad(fZAngle);
+
+ m_xDiagram->setRotationAngle( fXAngle, fYAngle, fZAngle );
+
+ m_bAngleChangePending = false;
+ m_aAngleTimer.Stop();
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, AngleEdited, weld::MetricSpinButton&, void)
+{
+ m_nXRotation = m_xMFXRotation->get_value(FieldUnit::DEGREE);
+ m_nYRotation = m_xMFYRotation->get_value(FieldUnit::DEGREE);
+
+ m_bAngleChangePending = true;
+
+ m_aAngleTimer.Start();
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, AngleChanged, Timer *, void)
+{
+ applyAnglesToModel();
+}
+
+void ThreeD_SceneGeometry_TabPage::applyPerspectiveToModel()
+{
+ ControllerLockHelperGuard aGuard( m_rControllerLockHelper );
+
+ drawing::ProjectionMode aMode = m_xCbxPerspective->get_active()
+ ? drawing::ProjectionMode_PERSPECTIVE
+ : drawing::ProjectionMode_PARALLEL;
+
+ try
+ {
+ m_xDiagram->setPropertyValue( "D3DScenePerspective" , uno::Any( aMode ));
+ m_xDiagram->setPropertyValue( "Perspective" , uno::Any( static_cast<sal_Int32>(m_xMFPerspective->get_value(FieldUnit::PERCENT)) ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ m_bPerspectiveChangePending = false;
+ m_aPerspectiveTimer.Stop();
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, PerspectiveEdited, weld::MetricSpinButton&, void)
+{
+ m_bPerspectiveChangePending = true;
+ m_aPerspectiveTimer.Start();
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, PerspectiveChanged, Timer *, void)
+{
+ applyPerspectiveToModel();
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, PerspectiveToggled, weld::Toggleable&, void)
+{
+ m_xMFPerspective->set_sensitive(m_xCbxPerspective->get_active());
+ applyPerspectiveToModel();
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, RightAngledAxesToggled, weld::Toggleable&, void)
+{
+ ControllerLockHelperGuard aGuard( m_rControllerLockHelper );
+
+ bool bEnableZ = !m_xCbxRightAngledAxes->get_active();
+ m_xFtZRotation->set_sensitive( bEnableZ );
+ m_xMFZRotation->set_sensitive( bEnableZ );
+ if (!bEnableZ)
+ {
+ m_nXRotation = m_xMFXRotation->get_value(FieldUnit::DEGREE);
+ m_nYRotation = m_xMFYRotation->get_value(FieldUnit::DEGREE);
+ m_nZRotation = m_xMFZRotation->get_value(FieldUnit::DEGREE);
+
+ m_xMFXRotation->set_value(static_cast<sal_Int64>(ThreeDHelper::getValueClippedToRange(static_cast<double>(m_nXRotation), ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes())), FieldUnit::DEGREE);
+ m_xMFYRotation->set_value(static_cast<sal_Int64>(ThreeDHelper::getValueClippedToRange(static_cast<double>(m_nYRotation), ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes())), FieldUnit::DEGREE);
+ m_xMFZRotation->set_text("");
+
+ lcl_SetMetricFieldLimits( *m_xMFXRotation, static_cast<sal_Int64>(ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes()));
+ lcl_SetMetricFieldLimits( *m_xMFYRotation, static_cast<sal_Int64>(ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes()));
+ }
+ else
+ {
+ lcl_SetMetricFieldLimits( *m_xMFXRotation, 180 );
+ lcl_SetMetricFieldLimits( *m_xMFYRotation, 180 );
+
+ m_xMFXRotation->set_value(m_nXRotation, FieldUnit::DEGREE);
+ m_xMFYRotation->set_value(m_nYRotation, FieldUnit::DEGREE);
+ m_xMFZRotation->set_value(m_nZRotation, FieldUnit::DEGREE);
+ }
+
+ if (m_xDiagram)
+ m_xDiagram->switchRightAngledAxes( m_xCbxRightAngledAxes->get_active() );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx
new file mode 100644
index 0000000000..d0fc8a69d6
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/timer.hxx>
+#include <vcl/weld.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace chart { class ControllerLockHelper; }
+
+namespace chart
+{
+class Diagram;
+
+class ThreeD_SceneGeometry_TabPage
+{
+public:
+ ThreeD_SceneGeometry_TabPage(weld::Container* pWindow,
+ rtl::Reference< ::chart::Diagram > xDiagram,
+ ControllerLockHelper & rControllerLockHelper);
+ ~ThreeD_SceneGeometry_TabPage();
+
+ // has to be called in case the dialog was closed with OK
+ void commitPendingChanges();
+
+ // is called by timer to apply changes to model
+ DECL_LINK( AngleChanged, Timer *, void);
+ // is called immediately when a field changes
+ DECL_LINK( AngleEdited, weld::MetricSpinButton&, void );
+
+ // is called by timer to apply changes to model
+ DECL_LINK( PerspectiveChanged, Timer *, void);
+ // is called immediately when a field changes
+ DECL_LINK( PerspectiveEdited, weld::MetricSpinButton&, void );
+ DECL_LINK( PerspectiveToggled, weld::Toggleable&, void );
+ DECL_LINK( RightAngledAxesToggled, weld::Toggleable&, void );
+
+private:
+ void applyAnglesToModel();
+ void applyPerspectiveToModel();
+
+ rtl::Reference< ::chart::Diagram > m_xDiagram;
+
+ Timer m_aAngleTimer;
+ Timer m_aPerspectiveTimer;
+
+ //to keep old values when switching to right angled axes
+ sal_Int64 m_nXRotation;
+ sal_Int64 m_nYRotation;
+ sal_Int64 m_nZRotation;
+
+ bool m_bAngleChangePending;
+ bool m_bPerspectiveChangePending;
+
+ ControllerLockHelper & m_rControllerLockHelper;
+
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+ std::unique_ptr<weld::CheckButton> m_xCbxRightAngledAxes;
+ std::unique_ptr<weld::MetricSpinButton> m_xMFXRotation;
+ std::unique_ptr<weld::MetricSpinButton> m_xMFYRotation;
+ std::unique_ptr<weld::Label> m_xFtZRotation;
+ std::unique_ptr<weld::MetricSpinButton> m_xMFZRotation;
+ std::unique_ptr<weld::CheckButton> m_xCbxPerspective;
+ std::unique_ptr<weld::MetricSpinButton> m_xMFPerspective;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_3D_SceneIllumination.cxx b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.cxx
new file mode 100644
index 0000000000..2020365fd1
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.cxx
@@ -0,0 +1,533 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_3D_SceneIllumination.hxx"
+#include <CommonConverters.hxx>
+#include <ControllerLockGuard.hxx>
+#include <ChartModel.hxx>
+
+#include <svx/colorbox.hxx>
+#include <svx/float3d.hxx>
+#include <svx/strings.hrc>
+#include <svx/dialmgr.hxx>
+#include <svtools/colrdlg.hxx>
+#include <svx/svx3ditems.hxx>
+#include <svx/svddef.hxx>
+#include <utility>
+#include <svx/obj3d.hxx>
+#include <vcl/svapp.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+namespace {
+
+struct LightSource
+{
+ Color nDiffuseColor;
+ css::drawing::Direction3D aDirection;
+ bool bIsEnabled;
+
+ LightSource() :
+ nDiffuseColor( 0xcccccc ),
+ aDirection( 1.0, 1.0, -1.0 ),
+ bIsEnabled( false )
+ {}
+};
+
+}
+
+struct LightSourceInfo
+{
+ LightButton* pButton;
+ LightSource aLightSource;
+
+ LightSourceInfo();
+ void initButtonFromSource();
+};
+
+LightSourceInfo::LightSourceInfo()
+ : pButton(nullptr)
+{
+ aLightSource.nDiffuseColor = Color(0xffffff); // white
+ aLightSource.aDirection = drawing::Direction3D(1,1,1);
+ aLightSource.bIsEnabled = false;
+}
+
+void LightSourceInfo::initButtonFromSource()
+{
+ if (!pButton)
+ return;
+ pButton->switchLightOn(aLightSource.bIsEnabled);
+}
+
+namespace
+{
+ OUString lcl_makeColorName(const Color& rColor)
+ {
+ OUString aStr = SvxResId(RID_SVXFLOAT3D_FIX_R) +
+ OUString::number(rColor.GetRed()) +
+ " " +
+ SvxResId(RID_SVXFLOAT3D_FIX_G) +
+ OUString::number(rColor.GetGreen()) +
+ " " +
+ SvxResId(RID_SVXFLOAT3D_FIX_B) +
+ OUString::number(rColor.GetBlue());
+ return aStr;
+ }
+
+ void lcl_selectColor(ColorListBox& rListBox, const Color& rColor)
+ {
+ rListBox.SetNoSelection();
+ rListBox.SelectEntry({rColor, lcl_makeColorName(rColor)});
+ }
+
+ ::chart::LightSource lcl_getLightSourceFromProperties(
+ const uno::Reference< beans::XPropertySet > & xSceneProperties,
+ sal_Int32 nIndex )
+ {
+ ::chart::LightSource aResult;
+ if( 0 <= nIndex && nIndex < 8 )
+ {
+ OUString aIndex( OUString::number( nIndex + 1 ));
+
+ try
+ {
+ xSceneProperties->getPropertyValue( "D3DSceneLightColor" + aIndex ) >>= aResult.nDiffuseColor;
+ xSceneProperties->getPropertyValue( "D3DSceneLightDirection" + aIndex ) >>= aResult.aDirection;
+ xSceneProperties->getPropertyValue( "D3DSceneLightOn" + aIndex ) >>= aResult.bIsEnabled;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ return aResult;
+ }
+
+ void lcl_setLightSource(
+ const uno::Reference< beans::XPropertySet > & xSceneProperties,
+ const ::chart::LightSource & rLightSource,
+ sal_Int32 nIndex )
+ {
+ if( 0 > nIndex || nIndex >= 8 )
+ return;
+
+ OUString aIndex( OUString::number( nIndex + 1 ));
+
+ try
+ {
+ xSceneProperties->setPropertyValue( "D3DSceneLightColor" + aIndex,
+ uno::Any( rLightSource.nDiffuseColor ));
+ xSceneProperties->setPropertyValue( "D3DSceneLightDirection" + aIndex,
+ uno::Any( rLightSource.aDirection ));
+ xSceneProperties->setPropertyValue( "D3DSceneLightOn" + aIndex,
+ uno::Any( rLightSource.bIsEnabled ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ Color lcl_getAmbientColor(
+ const uno::Reference< beans::XPropertySet > & xSceneProperties )
+ {
+ Color nResult;
+ try
+ {
+ xSceneProperties->getPropertyValue("D3DSceneAmbientColor") >>= nResult;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return nResult;
+ }
+
+ void lcl_setAmbientColor(
+ const uno::Reference< beans::XPropertySet > & xSceneProperties,
+ const Color & rColor )
+ {
+ try
+ {
+ xSceneProperties->setPropertyValue("D3DSceneAmbientColor",
+ uno::Any( rColor ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+}
+
+ThreeD_SceneIllumination_TabPage::ThreeD_SceneIllumination_TabPage(weld::Container* pParent,
+ weld::Window* pTopLevel,
+ uno::Reference< beans::XPropertySet > xSceneProperties,
+ const rtl::Reference<::chart::ChartModel>& xChartModel)
+ : m_xSceneProperties(std::move( xSceneProperties ))
+ , m_aTimerTriggeredControllerLock( xChartModel )
+ , m_bInCommitToModel( false )
+ , m_aModelChangeListener( LINK( this, ThreeD_SceneIllumination_TabPage, fillControlsFromModel ) )
+ , m_xChartModel( xChartModel )
+ , m_pTopLevel(pTopLevel)
+ , m_xBuilder(Application::CreateBuilder(pParent, "modules/schart/ui/tp_3D_SceneIllumination.ui"))
+ , m_xContainer(m_xBuilder->weld_container("tp_3D_SceneIllumination"))
+ , m_aBtn_Light1(m_xBuilder->weld_toggle_button("BTN_LIGHT_1"))
+ , m_aBtn_Light2(m_xBuilder->weld_toggle_button("BTN_LIGHT_2"))
+ , m_aBtn_Light3(m_xBuilder->weld_toggle_button("BTN_LIGHT_3"))
+ , m_aBtn_Light4(m_xBuilder->weld_toggle_button("BTN_LIGHT_4"))
+ , m_aBtn_Light5(m_xBuilder->weld_toggle_button("BTN_LIGHT_5"))
+ , m_aBtn_Light6(m_xBuilder->weld_toggle_button("BTN_LIGHT_6"))
+ , m_aBtn_Light7(m_xBuilder->weld_toggle_button("BTN_LIGHT_7"))
+ , m_aBtn_Light8(m_xBuilder->weld_toggle_button("BTN_LIGHT_8"))
+ , m_xLB_LightSource(new ColorListBox(m_xBuilder->weld_menu_button("LB_LIGHTSOURCE"), [this]{ return m_pTopLevel; }))
+ , m_xBtn_LightSource_Color(m_xBuilder->weld_button("BTN_LIGHTSOURCE_COLOR"))
+ , m_xLB_AmbientLight(new ColorListBox(m_xBuilder->weld_menu_button("LB_AMBIENTLIGHT"), [this]{ return m_pTopLevel; }))
+ , m_xBtn_AmbientLight_Color(m_xBuilder->weld_button("BTN_AMBIENT_COLOR"))
+ , m_xHoriScale(m_xBuilder->weld_scale("hori"))
+ , m_xVertScale(m_xBuilder->weld_scale("vert"))
+ , m_xBtn_Corner(m_xBuilder->weld_button("corner"))
+ , m_xPreview(new Svx3DLightControl)
+ , m_xPreviewWnd(new weld::CustomWeld(*m_xBuilder, "CTL_LIGHT_PREVIEW", *m_xPreview))
+ , m_xCtl_Preview(new SvxLightCtl3D(*m_xPreview, *m_xHoriScale, *m_xVertScale, *m_xBtn_Corner))
+{
+ m_pLightSourceInfoList.reset(new LightSourceInfo[8]);
+ m_pLightSourceInfoList[0].pButton = &m_aBtn_Light1;
+ m_pLightSourceInfoList[1].pButton = &m_aBtn_Light2;
+ m_pLightSourceInfoList[2].pButton = &m_aBtn_Light3;
+ m_pLightSourceInfoList[3].pButton = &m_aBtn_Light4;
+ m_pLightSourceInfoList[4].pButton = &m_aBtn_Light5;
+ m_pLightSourceInfoList[5].pButton = &m_aBtn_Light6;
+ m_pLightSourceInfoList[6].pButton = &m_aBtn_Light7;
+ m_pLightSourceInfoList[7].pButton = &m_aBtn_Light8;
+
+ fillControlsFromModel(nullptr);
+
+ m_aBtn_Light1.connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) );
+ m_aBtn_Light2.connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) );
+ m_aBtn_Light3.connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) );
+ m_aBtn_Light4.connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) );
+ m_aBtn_Light5.connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) );
+ m_aBtn_Light6.connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) );
+ m_aBtn_Light7.connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) );
+ m_aBtn_Light8.connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) );
+
+ m_xLB_AmbientLight->SetSelectHdl( LINK( this, ThreeD_SceneIllumination_TabPage, SelectColorHdl ) );
+ m_xLB_LightSource->SetSelectHdl( LINK( this, ThreeD_SceneIllumination_TabPage, SelectColorHdl ) );
+
+ m_xBtn_AmbientLight_Color->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ColorDialogHdl ) );
+ m_xBtn_LightSource_Color->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ColorDialogHdl ) );
+
+ m_xCtl_Preview->SetUserInteractiveChangeCallback( LINK( this, ThreeD_SceneIllumination_TabPage, PreviewChangeHdl ) );
+ m_xCtl_Preview->SetUserSelectionChangeCallback( LINK( this, ThreeD_SceneIllumination_TabPage, PreviewSelectHdl ) );
+
+ ClickLightSourceButtonHdl(*m_aBtn_Light2.get_widget());
+
+ m_aModelChangeListener.startListening( uno::Reference< util::XModifyBroadcaster >(m_xSceneProperties, uno::UNO_QUERY) );
+}
+
+ThreeD_SceneIllumination_TabPage::~ThreeD_SceneIllumination_TabPage()
+{
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneIllumination_TabPage, fillControlsFromModel, void*, void)
+{
+ if( m_bInCommitToModel )//don't read own changes
+ return;
+
+ sal_Int32 nL=0;
+ for( nL=0; nL<8; nL++)
+ m_pLightSourceInfoList[nL].aLightSource = lcl_getLightSourceFromProperties( m_xSceneProperties, nL );
+ for( nL=0; nL<8; nL++)
+ m_pLightSourceInfoList[nL].initButtonFromSource();
+
+ lcl_selectColor( *m_xLB_AmbientLight, lcl_getAmbientColor( m_xSceneProperties ));
+
+ updatePreview();
+}
+
+void ThreeD_SceneIllumination_TabPage::applyLightSourceToModel( sal_uInt32 nLightNumber )
+{
+ ControllerLockGuardUNO aGuard( m_xChartModel );
+ m_bInCommitToModel = true;
+ sal_Int32 nIndex( nLightNumber );
+ lcl_setLightSource( m_xSceneProperties, m_pLightSourceInfoList[nIndex].aLightSource, nIndex );
+ m_bInCommitToModel = false;
+}
+
+void ThreeD_SceneIllumination_TabPage::applyLightSourcesToModel()
+{
+ m_aTimerTriggeredControllerLock.startTimer();
+ ControllerLockGuardUNO aGuard( m_xChartModel );
+ for( sal_Int32 nL=0; nL<8; nL++)
+ applyLightSourceToModel( nL );
+ m_aTimerTriggeredControllerLock.startTimer();
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneIllumination_TabPage, PreviewChangeHdl, SvxLightCtl3D*, void)
+{
+ m_aTimerTriggeredControllerLock.startTimer();
+
+ //update m_pLightSourceInfoList from preview
+ const SfxItemSet a3DLightAttributes(m_xCtl_Preview->GetSvx3DLightControl().Get3DAttributes());
+ LightSourceInfo* pInfo = &m_pLightSourceInfoList[0];
+
+ pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1).GetValue();
+ pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_1).GetValue();
+ pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1).GetValue());
+
+ pInfo = &m_pLightSourceInfoList[1];
+ pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2).GetValue();
+ pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_2).GetValue();
+ pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2).GetValue());
+
+ pInfo = &m_pLightSourceInfoList[2];
+ pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3).GetValue();
+ pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_3).GetValue();
+ pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3).GetValue());
+
+ pInfo = &m_pLightSourceInfoList[3];
+ pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4).GetValue();
+ pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_4).GetValue();
+ pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4).GetValue());
+
+ pInfo = &m_pLightSourceInfoList[4];
+ pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5).GetValue();
+ pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_5).GetValue();
+ pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5).GetValue());
+
+ pInfo = &m_pLightSourceInfoList[5];
+ pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6).GetValue();
+ pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_6).GetValue();
+ pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6).GetValue());
+
+ pInfo = &m_pLightSourceInfoList[6];
+ pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7).GetValue();
+ pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_7).GetValue();
+ pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7).GetValue());
+
+ pInfo = &m_pLightSourceInfoList[7];
+ pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8).GetValue();
+ pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_8).GetValue();
+ pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8).GetValue());
+
+ applyLightSourcesToModel();
+}
+
+IMPL_LINK_NOARG(ThreeD_SceneIllumination_TabPage, PreviewSelectHdl, SvxLightCtl3D*, void)
+{
+ sal_uInt32 nLightNumber = m_xCtl_Preview->GetSvx3DLightControl().GetSelectedLight();
+ if(nLightNumber<8)
+ {
+ LightButton* pButton = m_pLightSourceInfoList[nLightNumber].pButton;
+ if(!pButton->get_active())
+ ClickLightSourceButtonHdl(*pButton->get_widget());
+
+ applyLightSourcesToModel();
+ }
+}
+
+IMPL_LINK( ThreeD_SceneIllumination_TabPage, ColorDialogHdl, weld::Button&, rButton, void )
+{
+ bool bIsAmbientLight = (&rButton == m_xBtn_AmbientLight_Color.get());
+ ColorListBox* pListBox = bIsAmbientLight ? m_xLB_AmbientLight.get() : m_xLB_LightSource.get();
+
+ SvColorDialog aColorDlg;
+ aColorDlg.SetColor( pListBox->GetSelectEntryColor() );
+ if( aColorDlg.Execute(m_pTopLevel) != RET_OK )
+ return;
+
+ Color aColor( aColorDlg.GetColor());
+ lcl_selectColor( *pListBox, aColor );
+ if( bIsAmbientLight )
+ {
+ m_bInCommitToModel = true;
+ lcl_setAmbientColor( m_xSceneProperties, aColor );
+ m_bInCommitToModel = false;
+ }
+ else
+ {
+ //get active lightsource:
+ LightSourceInfo* pInfo = nullptr;
+ sal_Int32 nL=0;
+ for( nL=0; nL<8; nL++)
+ {
+ pInfo = &m_pLightSourceInfoList[nL];
+ if(pInfo->pButton->get_active())
+ break;
+ pInfo = nullptr;
+ }
+ if(pInfo)
+ applyLightSourceToModel( nL );
+ }
+ SelectColorHdl( *pListBox );
+}
+
+IMPL_LINK( ThreeD_SceneIllumination_TabPage, SelectColorHdl, ColorListBox&, rBox, void )
+{
+ ColorListBox* pListBox = &rBox;
+ if (pListBox == m_xLB_AmbientLight.get())
+ {
+ m_bInCommitToModel = true;
+ lcl_setAmbientColor( m_xSceneProperties, pListBox->GetSelectEntryColor());
+ m_bInCommitToModel = false;
+ }
+ else if (pListBox == m_xLB_LightSource.get())
+ {
+ //get active lightsource:
+ LightSourceInfo* pInfo = nullptr;
+ sal_Int32 nL=0;
+ for( nL=0; nL<8; nL++)
+ {
+ pInfo = &m_pLightSourceInfoList[nL];
+ if (pInfo->pButton->get_active())
+ break;
+ pInfo = nullptr;
+ }
+ if(pInfo)
+ {
+ pInfo->aLightSource.nDiffuseColor = pListBox->GetSelectEntryColor();
+ applyLightSourceToModel( nL );
+ }
+ }
+ updatePreview();
+}
+
+IMPL_LINK(ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl, weld::Button&, rBtn, void)
+{
+ LightButton* pButton = nullptr;
+ LightSourceInfo* pInfo = nullptr;
+ sal_Int32 nL=0;
+ for( nL=0; nL<8; nL++)
+ {
+ if (m_pLightSourceInfoList[nL].pButton->get_widget() == &rBtn)
+ {
+ pButton = m_pLightSourceInfoList[nL].pButton;
+ pInfo = &m_pLightSourceInfoList[nL];
+ break;
+ }
+ }
+
+ assert(pInfo);
+
+ bool bIsChecked = pInfo->pButton->get_prev_active();
+
+ ControllerLockGuardUNO aGuard( m_xChartModel );
+ for (sal_Int32 i = 0; i < 8; ++i)
+ {
+ LightButton* pLightButton = m_pLightSourceInfoList[i].pButton;
+ if (pLightButton == pButton)
+ {
+ pLightButton->set_active(true);
+ if (!pLightButton->get_widget()->has_focus())
+ pLightButton->get_widget()->grab_focus();
+ m_pLightSourceInfoList[i].pButton->set_prev_active(true);
+ }
+ else
+ {
+ pLightButton->set_active(false);
+ m_pLightSourceInfoList[i].pButton->set_prev_active(false);
+ }
+ }
+
+ //update light button
+ if (bIsChecked)
+ {
+ pButton->switchLightOn(!pButton->isLightOn());
+ pInfo->aLightSource.bIsEnabled=pButton->isLightOn();
+ applyLightSourceToModel( nL );
+ }
+
+ //update color list box
+ lcl_selectColor( *m_xLB_LightSource, pInfo->aLightSource.nDiffuseColor );
+ updatePreview();
+}
+
+void ThreeD_SceneIllumination_TabPage::updatePreview()
+{
+ SfxItemSet aItemSet(m_xCtl_Preview->GetSvx3DLightControl().Get3DAttributes());
+ LightSourceInfo* pInfo = &m_pLightSourceInfoList[0];
+
+ // AmbientColor
+ aItemSet.Put(makeSvx3DAmbientcolorItem(m_xLB_AmbientLight->GetSelectEntryColor()));
+
+ aItemSet.Put(makeSvx3DLightcolor1Item(pInfo->aLightSource.nDiffuseColor));
+ aItemSet.Put(makeSvx3DLightOnOff1Item(pInfo->aLightSource.bIsEnabled));
+ aItemSet.Put(makeSvx3DLightDirection1Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection)));
+
+ pInfo = &m_pLightSourceInfoList[1];
+ aItemSet.Put(makeSvx3DLightcolor2Item(pInfo->aLightSource.nDiffuseColor));
+ aItemSet.Put(makeSvx3DLightOnOff2Item(pInfo->aLightSource.bIsEnabled));
+ aItemSet.Put(makeSvx3DLightDirection2Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection)));
+
+ pInfo = &m_pLightSourceInfoList[2];
+ aItemSet.Put(makeSvx3DLightcolor3Item(pInfo->aLightSource.nDiffuseColor));
+ aItemSet.Put(makeSvx3DLightOnOff3Item(pInfo->aLightSource.bIsEnabled));
+ aItemSet.Put(makeSvx3DLightDirection3Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection)));
+
+ pInfo = &m_pLightSourceInfoList[3];
+ aItemSet.Put(makeSvx3DLightcolor4Item(pInfo->aLightSource.nDiffuseColor));
+ aItemSet.Put(makeSvx3DLightOnOff4Item(pInfo->aLightSource.bIsEnabled));
+ aItemSet.Put(makeSvx3DLightDirection4Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection)));
+
+ pInfo = &m_pLightSourceInfoList[4];
+ aItemSet.Put(makeSvx3DLightcolor5Item(pInfo->aLightSource.nDiffuseColor));
+ aItemSet.Put(makeSvx3DLightOnOff5Item(pInfo->aLightSource.bIsEnabled));
+ aItemSet.Put(makeSvx3DLightDirection5Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection)));
+
+ pInfo = &m_pLightSourceInfoList[5];
+ aItemSet.Put(makeSvx3DLightcolor6Item(pInfo->aLightSource.nDiffuseColor));
+ aItemSet.Put(makeSvx3DLightOnOff6Item(pInfo->aLightSource.bIsEnabled));
+ aItemSet.Put(makeSvx3DLightDirection6Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection)));
+
+ pInfo = &m_pLightSourceInfoList[6];
+ aItemSet.Put(makeSvx3DLightcolor7Item(pInfo->aLightSource.nDiffuseColor));
+ aItemSet.Put(makeSvx3DLightOnOff7Item(pInfo->aLightSource.bIsEnabled));
+ aItemSet.Put(makeSvx3DLightDirection7Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection)));
+
+ pInfo = &m_pLightSourceInfoList[7];
+ aItemSet.Put(makeSvx3DLightcolor8Item(pInfo->aLightSource.nDiffuseColor));
+ aItemSet.Put(makeSvx3DLightOnOff8Item(pInfo->aLightSource.bIsEnabled));
+ aItemSet.Put(makeSvx3DLightDirection8Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection)));
+
+ // set lights and ambient light
+ m_xCtl_Preview->GetSvx3DLightControl().Set3DAttributes(aItemSet);
+
+ // select light
+ for(sal_uInt32 a(0); a < 8; a++)
+ {
+ if (m_pLightSourceInfoList[a].pButton->get_active())
+ {
+ m_xCtl_Preview->GetSvx3DLightControl().SelectLight(a);
+ m_xCtl_Preview->CheckSelection();
+ break;
+ }
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx
new file mode 100644
index 0000000000..98a1f32736
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ModifyListenerCallBack.hxx>
+#include <TimerTriggeredControllerLock.hxx>
+#include <vcl/weld.hxx>
+#include <svx/dlgctl3d.hxx>
+#include <svx/float3d.hxx>
+
+namespace com::sun::star::beans
+{
+class XPropertySet;
+}
+
+class ColorListBox;
+
+namespace chart
+{
+struct LightSourceInfo;
+class ChartModel;
+
+class ThreeD_SceneIllumination_TabPage
+{
+public:
+ ThreeD_SceneIllumination_TabPage(weld::Container* pParent, weld::Window* pTopLevel,
+ css::uno::Reference<css::beans::XPropertySet> xSceneProperties,
+ const rtl::Reference<::chart::ChartModel>& xChartModel);
+ ~ThreeD_SceneIllumination_TabPage();
+
+private:
+ DECL_LINK(ClickLightSourceButtonHdl, weld::Button&, void);
+ DECL_LINK(SelectColorHdl, ColorListBox&, void);
+ DECL_LINK(ColorDialogHdl, weld::Button&, void);
+ DECL_LINK(PreviewChangeHdl, SvxLightCtl3D*, void);
+ DECL_LINK(PreviewSelectHdl, SvxLightCtl3D*, void);
+
+ void updatePreview();
+
+private:
+ DECL_LINK(fillControlsFromModel, void*, void);
+
+ void applyLightSourceToModel(sal_uInt32 nLightNumber);
+ void applyLightSourcesToModel();
+
+ std::unique_ptr<LightSourceInfo[]> m_pLightSourceInfoList;
+
+ css::uno::Reference<css::beans::XPropertySet> m_xSceneProperties;
+
+ TimerTriggeredControllerLock m_aTimerTriggeredControllerLock;
+
+ bool m_bInCommitToModel;
+
+ ModifyListenerCallBack m_aModelChangeListener;
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+
+ weld::Window* m_pTopLevel;
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+ LightButton m_aBtn_Light1;
+ LightButton m_aBtn_Light2;
+ LightButton m_aBtn_Light3;
+ LightButton m_aBtn_Light4;
+ LightButton m_aBtn_Light5;
+ LightButton m_aBtn_Light6;
+ LightButton m_aBtn_Light7;
+ LightButton m_aBtn_Light8;
+ std::unique_ptr<ColorListBox> m_xLB_LightSource;
+ std::unique_ptr<weld::Button> m_xBtn_LightSource_Color;
+ std::unique_ptr<ColorListBox> m_xLB_AmbientLight;
+ std::unique_ptr<weld::Button> m_xBtn_AmbientLight_Color;
+ std::unique_ptr<weld::Scale> m_xHoriScale;
+ std::unique_ptr<weld::Scale> m_xVertScale;
+ std::unique_ptr<weld::Button> m_xBtn_Corner;
+ std::unique_ptr<Svx3DLightControl> m_xPreview;
+ std::unique_ptr<weld::CustomWeld> m_xPreviewWnd;
+ std::unique_ptr<SvxLightCtl3D> m_xCtl_Preview;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_AxisLabel.cxx b/chart2/source/controller/dialogs/tp_AxisLabel.cxx
new file mode 100644
index 0000000000..33faff6c53
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_AxisLabel.cxx
@@ -0,0 +1,300 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_AxisLabel.hxx"
+
+#include <chartview/ChartSfxItemIds.hxx>
+#include <TextDirectionListBox.hxx>
+
+#include <svx/chrtitem.hxx>
+#include <svx/sdangitm.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/frmdiritem.hxx>
+
+namespace chart
+{
+
+SchAxisLabelTabPage::SchAxisLabelTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_axisLabel.ui", "AxisLabelTabPage", &rInAttrs)
+ , m_bShowStaggeringControls( true )
+ , m_nInitialDegrees( 0 )
+ , m_bHasInitialDegrees( true )
+ , m_bInitialStacking( false )
+ , m_bHasInitialStacking( true )
+ , m_bComplexCategories( false )
+ , m_xCbShowDescription(m_xBuilder->weld_check_button("showlabelsCB"))
+ , m_xFlOrder(m_xBuilder->weld_label("orderL"))
+ , m_xRbSideBySide(m_xBuilder->weld_radio_button("tile"))
+ , m_xRbUpDown(m_xBuilder->weld_radio_button("odd"))
+ , m_xRbDownUp(m_xBuilder->weld_radio_button("even"))
+ , m_xRbAuto(m_xBuilder->weld_radio_button("auto"))
+ , m_xFlTextFlow(m_xBuilder->weld_label("textflowL"))
+ , m_xCbTextOverlap(m_xBuilder->weld_check_button("overlapCB"))
+ , m_xCbTextBreak(m_xBuilder->weld_check_button("breakCB"))
+ , m_xFtABCD(m_xBuilder->weld_label("labelABCD"))
+ , m_xFtRotate(m_xBuilder->weld_label("degreeL"))
+ , m_xNfRotate(m_xBuilder->weld_metric_spin_button("OrientDegree", FieldUnit::DEGREE))
+ , m_xCbStacked(m_xBuilder->weld_check_button("stackedCB"))
+ , m_xFtTextDirection(m_xBuilder->weld_label("textdirL"))
+ , m_aLbTextDirection(m_xBuilder->weld_combo_box("textdirLB"))
+ , m_xCtrlDial(new svx::DialControl)
+ , m_xCtrlDialWin(new weld::CustomWeld(*m_xBuilder, "dialCtrl", *m_xCtrlDial))
+{
+ m_xCtrlDial->SetText(m_xFtABCD->get_label());
+ m_xCtrlDial->SetLinkedField(m_xNfRotate.get());
+ m_xCtrlDialWin->set_sensitive(true);
+ m_xNfRotate->set_sensitive(true);
+ m_xCbStacked->set_sensitive(true);
+ m_xFtRotate->set_sensitive(true);
+
+ m_xCbStacked->connect_toggled(LINK(this, SchAxisLabelTabPage, StackedToggleHdl));
+ m_xCbShowDescription->connect_toggled(LINK(this, SchAxisLabelTabPage, ToggleShowLabel));
+}
+
+SchAxisLabelTabPage::~SchAxisLabelTabPage()
+{
+ m_xCtrlDialWin.reset();
+ m_xCtrlDial.reset();
+}
+
+std::unique_ptr<SfxTabPage> SchAxisLabelTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs)
+{
+ return std::make_unique<SchAxisLabelTabPage>(pPage, pController, *rAttrs);
+}
+
+bool SchAxisLabelTabPage::FillItemSet( SfxItemSet* rOutAttrs )
+{
+ bool bStacked = false;
+ if (m_xCbStacked->get_state() != TRISTATE_INDET )
+ {
+ bStacked = m_xCbStacked->get_state() == TRISTATE_TRUE;
+ if( !m_bHasInitialStacking || (bStacked != m_bInitialStacking) )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_TEXT_STACKED, bStacked ) );
+ }
+
+ if( m_xCtrlDial->HasRotation() )
+ {
+ Degree100 nDegrees = bStacked ? 0_deg100 : m_xCtrlDial->GetRotation();
+ if( !m_bHasInitialDegrees || (nDegrees != m_nInitialDegrees) )
+ rOutAttrs->Put( SdrAngleItem( SCHATTR_TEXT_DEGREES, nDegrees ) );
+ }
+
+ if( m_bShowStaggeringControls )
+ {
+ SvxChartTextOrder eOrder = SvxChartTextOrder::SideBySide;
+ bool bRadioButtonChecked = true;
+
+ if( m_xRbUpDown->get_active())
+ eOrder = SvxChartTextOrder::UpDown;
+ else if( m_xRbDownUp->get_active())
+ eOrder = SvxChartTextOrder::DownUp;
+ else if( m_xRbAuto->get_active())
+ eOrder = SvxChartTextOrder::Auto;
+ else if( m_xRbSideBySide->get_active())
+ eOrder = SvxChartTextOrder::SideBySide;
+ else
+ bRadioButtonChecked = false;
+
+ if( bRadioButtonChecked )
+ rOutAttrs->Put( SvxChartTextOrderItem( eOrder, SCHATTR_AXIS_LABEL_ORDER ));
+ }
+
+ if( m_xCbTextOverlap->get_state() != TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_AXIS_LABEL_OVERLAP, m_xCbTextOverlap->get_active() ) );
+ if( m_xCbTextBreak->get_state() != TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_AXIS_LABEL_BREAK, m_xCbTextBreak->get_active() ) );
+ if( m_xCbShowDescription->get_state() != TRISTATE_INDET )
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_AXIS_SHOWDESCR, m_xCbShowDescription->get_active() ) );
+
+ if (m_aLbTextDirection.get_active() != -1)
+ rOutAttrs->Put( SvxFrameDirectionItem( m_aLbTextDirection.get_active_id(), EE_PARA_WRITINGDIR ) );
+
+ return true;
+}
+
+void SchAxisLabelTabPage::Reset( const SfxItemSet* rInAttrs )
+{
+ const SfxPoolItem* pPoolItem = nullptr;
+
+ // show description
+ SfxItemState aState = rInAttrs->GetItemState( SCHATTR_AXIS_SHOWDESCR, false, &pPoolItem );
+ if( aState == SfxItemState::DONTCARE )
+ {
+ m_xCbShowDescription->set_state( TRISTATE_INDET );
+ }
+ else
+ {
+ bool bCheck = false;
+ if( aState == SfxItemState::SET )
+ bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue();
+ m_xCbShowDescription->set_active( bCheck );
+
+ if( aState != SfxItemState::DEFAULT && aState != SfxItemState::SET )
+ m_xCbShowDescription->hide();
+ }
+
+ // Rotation as orient item or in degrees ----------
+
+ // check new degree item
+ m_nInitialDegrees = 0_deg100;
+ aState = rInAttrs->GetItemState( SCHATTR_TEXT_DEGREES, false, &pPoolItem );
+ if( aState == SfxItemState::SET )
+ m_nInitialDegrees = static_cast< const SdrAngleItem * >( pPoolItem )->GetValue();
+
+ m_bHasInitialDegrees = aState != SfxItemState::DONTCARE;
+ if( m_bHasInitialDegrees )
+ m_xCtrlDial->SetRotation( m_nInitialDegrees );
+ else
+ m_xCtrlDial->SetNoRotation();
+
+ // check stacked item
+ m_bInitialStacking = false;
+ aState = rInAttrs->GetItemState( SCHATTR_TEXT_STACKED, false, &pPoolItem );
+ if( aState == SfxItemState::SET )
+ m_bInitialStacking = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue();
+
+ m_bHasInitialStacking = aState != SfxItemState::DONTCARE;
+ if( m_bHasInitialDegrees )
+ m_xCbStacked->set_state(m_bInitialStacking ? TRISTATE_TRUE : TRISTATE_FALSE);
+ else
+ m_xCbStacked->set_state(TRISTATE_INDET);
+ StackedToggleHdl(*m_xCbStacked);
+
+ if( const SvxFrameDirectionItem* pDirectionItem = rInAttrs->GetItemIfSet( EE_PARA_WRITINGDIR ) )
+ m_aLbTextDirection.set_active_id( pDirectionItem->GetValue() );
+
+ // Text overlap ----------
+ aState = rInAttrs->GetItemState( SCHATTR_AXIS_LABEL_OVERLAP, false, &pPoolItem );
+ if( aState == SfxItemState::DONTCARE )
+ {
+ m_xCbTextOverlap->set_state( TRISTATE_INDET );
+ }
+ else
+ {
+ bool bCheck = false;
+ if( aState == SfxItemState::SET )
+ bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue();
+ m_xCbTextOverlap->set_active( bCheck );
+
+ if( aState != SfxItemState::DEFAULT && aState != SfxItemState::SET )
+ m_xCbTextOverlap->hide();
+ }
+
+ // text break ----------
+ aState = rInAttrs->GetItemState( SCHATTR_AXIS_LABEL_BREAK, false, &pPoolItem );
+ if( aState == SfxItemState::DONTCARE )
+ {
+ m_xCbTextBreak->set_state( TRISTATE_INDET );
+ }
+ else
+ {
+ bool bCheck = false;
+ if( aState == SfxItemState::SET )
+ bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue();
+ m_xCbTextBreak->set_active( bCheck );
+
+ if( aState != SfxItemState::DEFAULT && aState != SfxItemState::SET )
+ {
+ m_xCbTextBreak->hide();
+ if( ! m_xCbTextOverlap->get_visible() )
+ m_xFlTextFlow->hide();
+ }
+ }
+
+ // text order ----------
+ if( m_bShowStaggeringControls )
+ {
+ if( const SvxChartTextOrderItem* pOrderItem = rInAttrs->GetItemIfSet( SCHATTR_AXIS_LABEL_ORDER, false ) )
+ {
+ SvxChartTextOrder eOrder = pOrderItem->GetValue();
+
+ switch( eOrder )
+ {
+ case SvxChartTextOrder::SideBySide:
+ m_xRbSideBySide->set_active(true);
+ break;
+ case SvxChartTextOrder::UpDown:
+ m_xRbUpDown->set_active(true);
+ break;
+ case SvxChartTextOrder::DownUp:
+ m_xRbDownUp->set_active(true);
+ break;
+ case SvxChartTextOrder::Auto:
+ m_xRbAuto->set_active(true);
+ break;
+ }
+ }
+ }
+
+ ToggleShowLabel(*m_xCbShowDescription);
+}
+
+void SchAxisLabelTabPage::ShowStaggeringControls( bool bShowStaggeringControls )
+{
+ m_bShowStaggeringControls = bShowStaggeringControls;
+
+ if( !m_bShowStaggeringControls )
+ {
+ m_xRbSideBySide->hide();
+ m_xRbUpDown->hide();
+ m_xRbDownUp->hide();
+ m_xRbAuto->hide();
+ m_xFlOrder->hide();
+ }
+}
+
+void SchAxisLabelTabPage::SetComplexCategories( bool bComplexCategories )
+{
+ m_bComplexCategories = bComplexCategories;
+}
+
+// event handling routines
+
+IMPL_LINK_NOARG(SchAxisLabelTabPage, StackedToggleHdl, weld::Toggleable&, void)
+{
+ bool bActive = m_xCbStacked->get_active() && m_xCbStacked->get_sensitive();
+ m_xNfRotate->set_sensitive(!bActive);
+ m_xCtrlDialWin->set_sensitive(!bActive);
+ m_xCtrlDial->StyleUpdated();
+ m_xFtRotate->set_sensitive(!bActive);
+}
+
+IMPL_LINK_NOARG(SchAxisLabelTabPage, ToggleShowLabel, weld::Toggleable&, void)
+{
+ bool bEnable = ( m_xCbShowDescription->get_state() != TRISTATE_FALSE );
+
+ m_xCbStacked->set_sensitive(bEnable);
+ StackedToggleHdl(*m_xCbStacked);
+
+ m_xFlOrder->set_sensitive( bEnable );
+ m_xRbSideBySide->set_sensitive( bEnable );
+ m_xRbUpDown->set_sensitive( bEnable );
+ m_xRbDownUp->set_sensitive( bEnable );
+ m_xRbAuto->set_sensitive( bEnable );
+
+ m_xFlTextFlow->set_sensitive( bEnable );
+ m_xCbTextOverlap->set_sensitive( bEnable && !m_bComplexCategories );
+ m_xCbTextBreak->set_sensitive( bEnable );
+
+ m_xFtTextDirection->set_sensitive( bEnable );
+ m_aLbTextDirection.set_sensitive( bEnable );
+}
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_AxisLabel.hxx b/chart2/source/controller/dialogs/tp_AxisLabel.hxx
new file mode 100644
index 0000000000..75704ec4e4
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_AxisLabel.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <svx/dialcontrol.hxx>
+#include <tools/degree.hxx>
+#include <TextDirectionListBox.hxx>
+
+namespace weld {
+ class CheckButton;
+ class CustomWeld;
+ class Label;
+ class RadioButton;
+ class SpinButton;
+ class ToggleButton;
+}
+
+namespace chart
+{
+
+class SchAxisLabelTabPage : public SfxTabPage
+{
+private:
+ bool m_bShowStaggeringControls;
+
+ Degree100 m_nInitialDegrees;
+ bool m_bHasInitialDegrees; /// false = DialControl in tristate
+ bool m_bInitialStacking;
+ bool m_bHasInitialStacking; /// false = checkbox in tristate
+ bool m_bComplexCategories;
+
+ std::unique_ptr<weld::CheckButton> m_xCbShowDescription;
+ std::unique_ptr<weld::Label> m_xFlOrder;
+ std::unique_ptr<weld::RadioButton> m_xRbSideBySide;
+ std::unique_ptr<weld::RadioButton> m_xRbUpDown;
+ std::unique_ptr<weld::RadioButton> m_xRbDownUp;
+ std::unique_ptr<weld::RadioButton> m_xRbAuto;
+ std::unique_ptr<weld::Label> m_xFlTextFlow;
+ std::unique_ptr<weld::CheckButton> m_xCbTextOverlap;
+ std::unique_ptr<weld::CheckButton> m_xCbTextBreak;
+ std::unique_ptr<weld::Label> m_xFtABCD;
+ std::unique_ptr<weld::Label> m_xFtRotate;
+ std::unique_ptr<weld::MetricSpinButton> m_xNfRotate;
+ std::unique_ptr<weld::CheckButton> m_xCbStacked;
+ std::unique_ptr<weld::Label> m_xFtTextDirection;
+ TextDirectionListBox m_aLbTextDirection;
+ std::unique_ptr<svx::DialControl> m_xCtrlDial;
+ std::unique_ptr<weld::CustomWeld> m_xCtrlDialWin;
+
+ DECL_LINK(StackedToggleHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleShowLabel, weld::Toggleable&, void);
+
+public:
+ SchAxisLabelTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs);
+ virtual ~SchAxisLabelTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs );
+ virtual bool FillItemSet( SfxItemSet* rOutAttrs ) override;
+ virtual void Reset( const SfxItemSet* rInAttrs ) override;
+
+ void ShowStaggeringControls( bool bShowStaggeringControls );
+ void SetComplexCategories( bool bComplexCategories );
+};
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_AxisPositions.cxx b/chart2/source/controller/dialogs/tp_AxisPositions.cxx
new file mode 100644
index 0000000000..4e3e4bb759
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_AxisPositions.cxx
@@ -0,0 +1,320 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_AxisPositions.hxx"
+
+#include <chartview/ChartSfxItemIds.hxx>
+#include <AxisHelper.hxx>
+
+#include <rtl/math.hxx>
+#include <svx/chrtitem.hxx>
+#include <svl/intitem.hxx>
+#include <vcl/formatter.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+AxisPositionsTabPage::AxisPositionsTabPage(weld::Container* pPage, weld::DialogController* pController,const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_AxisPositions.ui", "tp_AxisPositions", &rInAttrs)
+ , m_pNumFormatter(nullptr)
+ , m_bCrossingAxisIsCategoryAxis(false)
+ , m_bSupportAxisPositioning(false)
+ , m_bSupportCategoryPositioning(false)
+ , m_xFL_AxisLine(m_xBuilder->weld_frame("FL_AXIS_LINE"))
+ , m_xLB_CrossesAt(m_xBuilder->weld_combo_box("LB_CROSSES_OTHER_AXIS_AT"))
+ , m_xED_CrossesAt(m_xBuilder->weld_formatted_spin_button("EDT_CROSSES_OTHER_AXIS_AT"))
+ , m_xED_CrossesAtCategory(m_xBuilder->weld_combo_box( "EDT_CROSSES_OTHER_AXIS_AT_CATEGORY"))
+ , m_xFL_Position(m_xBuilder->weld_frame("FL_POSITION"))
+ , m_xRB_On(m_xBuilder->weld_radio_button("RB_ON"))
+ , m_xRB_Between(m_xBuilder->weld_radio_button("RB_BETWEEN"))
+ , m_xFL_Labels(m_xBuilder->weld_frame("FL_LABELS"))
+ , m_xLB_PlaceLabels(m_xBuilder->weld_combo_box("LB_PLACE_LABELS"))
+ , m_xCB_TicksInner(m_xBuilder->weld_check_button("CB_TICKS_INNER"))
+ , m_xCB_TicksOuter(m_xBuilder->weld_check_button("CB_TICKS_OUTER"))
+ , m_xCB_MinorInner(m_xBuilder->weld_check_button("CB_MINOR_INNER"))
+ , m_xCB_MinorOuter(m_xBuilder->weld_check_button("CB_MINOR_OUTER"))
+ , m_xBxPlaceTicks(m_xBuilder->weld_widget("boxPLACE_TICKS"))
+ , m_xLB_PlaceTicks(m_xBuilder->weld_combo_box("LB_PLACE_TICKS"))
+{
+ m_xLB_CrossesAt->connect_changed(LINK(this, AxisPositionsTabPage, CrossesAtSelectHdl));
+ m_xLB_PlaceLabels->connect_changed(LINK(this, AxisPositionsTabPage, PlaceLabelsSelectHdl));
+
+ Formatter& rCrossFormatter = m_xED_CrossesAt->GetFormatter();
+ rCrossFormatter.ClearMinValue();
+ rCrossFormatter.ClearMaxValue();
+ Formatter& rDistanceFormatter = m_xED_CrossesAt->GetFormatter();
+ rDistanceFormatter.ClearMinValue();
+ rDistanceFormatter.ClearMaxValue();
+}
+
+AxisPositionsTabPage::~AxisPositionsTabPage()
+{
+}
+
+std::unique_ptr<SfxTabPage> AxisPositionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs)
+{
+ return std::make_unique<AxisPositionsTabPage>(pPage, pController, *rOutAttrs);
+}
+
+bool AxisPositionsTabPage::FillItemSet(SfxItemSet* rOutAttrs)
+{
+ // axis line
+ sal_Int32 nPos = m_xLB_CrossesAt->get_active();
+ rOutAttrs->Put( SfxInt32Item( SCHATTR_AXIS_POSITION, nPos+1 ));
+ if( nPos==2 )
+ {
+ Formatter& rCrossFormatter = m_xED_CrossesAt->GetFormatter();
+ double fCrossover = rCrossFormatter.GetValue();
+ if( m_bCrossingAxisIsCategoryAxis )
+ fCrossover = m_xED_CrossesAtCategory->get_active()+1;
+ rOutAttrs->Put(SvxDoubleItem(fCrossover,SCHATTR_AXIS_POSITION_VALUE));
+ }
+
+ // shifted category position
+ if (m_xFL_Position->get_visible())
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION, m_xRB_Between->get_active()));
+
+ // labels
+ sal_Int32 nLabelPos = m_xLB_PlaceLabels->get_active();
+ if (nLabelPos != -1)
+ rOutAttrs->Put( SfxInt32Item( SCHATTR_AXIS_LABEL_POSITION, nLabelPos ));
+
+ // tick marks
+ sal_Int32 nTicks=0;
+ sal_Int32 nMinorTicks=0;
+
+ if(m_xCB_MinorInner->get_active())
+ nMinorTicks|=CHAXIS_MARK_INNER;
+ if(m_xCB_MinorOuter->get_active())
+ nMinorTicks|=CHAXIS_MARK_OUTER;
+ if(m_xCB_TicksInner->get_active())
+ nTicks|=CHAXIS_MARK_INNER;
+ if(m_xCB_TicksOuter->get_active())
+ nTicks|=CHAXIS_MARK_OUTER;
+
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_TICKS,nTicks));
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_HELPTICKS,nMinorTicks));
+
+ sal_Int32 nMarkPos = m_xLB_PlaceTicks->get_active();
+ if (nMarkPos != -1)
+ rOutAttrs->Put( SfxInt32Item( SCHATTR_AXIS_MARK_POSITION, nMarkPos ));
+
+ return true;
+}
+
+void AxisPositionsTabPage::Reset(const SfxItemSet* rInAttrs)
+{
+ //init and enable controls
+ m_xED_CrossesAt->set_visible( !m_bCrossingAxisIsCategoryAxis );
+ m_xED_CrossesAtCategory->set_visible( m_bCrossingAxisIsCategoryAxis );
+ if (m_bCrossingAxisIsCategoryAxis)
+ {
+ for( auto const & cat : std::as_const(m_aCategories) )
+ m_xED_CrossesAtCategory->append_text(cat);
+ }
+
+ if( m_xLB_CrossesAt->get_count() > 3 )
+ {
+ if( m_bCrossingAxisIsCategoryAxis )
+ m_xLB_CrossesAt->remove(2);
+ else
+ m_xLB_CrossesAt->remove(3);
+ }
+
+ //fill controls
+
+ //axis line
+ if(SfxInt32Item const * pPositionItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_POSITION))
+ {
+ bool bZero = false;
+ sal_Int32 nPos = pPositionItem->GetValue();
+ if(nPos==0)
+ {
+ //switch to value
+ bZero = true;
+ nPos = 2;
+ }
+ else
+ nPos--;
+
+ if( nPos < m_xLB_CrossesAt->get_count() )
+ m_xLB_CrossesAt->set_active( nPos );
+ CrossesAtSelectHdl( *m_xLB_CrossesAt );
+
+ const SvxDoubleItem* pPosValueItem;
+ if( (pPosValueItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_POSITION_VALUE)) || bZero )
+ {
+ double fCrossover = 0.0;
+ if( !bZero )
+ fCrossover = pPosValueItem->GetValue();
+ if( m_bCrossingAxisIsCategoryAxis )
+ m_xED_CrossesAtCategory->set_active( static_cast<sal_uInt16>(::rtl::math::round(fCrossover-1.0)) );
+ else
+ {
+ Formatter& rCrossFormatter = m_xED_CrossesAt->GetFormatter();
+ rCrossFormatter.SetValue(fCrossover);
+ }
+ }
+ else
+ {
+ m_xED_CrossesAtCategory->set_active(-1);
+ m_xED_CrossesAt->set_text("");
+ }
+ }
+ else
+ {
+ m_xLB_CrossesAt->set_active(-1);
+ m_xED_CrossesAt->set_sensitive( false );
+ }
+
+ // shifted category position
+ const SfxBoolItem* pCatPosItem;
+ if (m_bSupportCategoryPositioning && (pCatPosItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION)))
+ {
+ if (pCatPosItem->GetValue())
+ m_xRB_Between->set_active(true);
+ else
+ m_xRB_On->set_active(true);
+ }
+ else
+ m_xFL_Position->hide();
+
+ // Labels
+ if( const SfxInt32Item* pLabelPosItem = rInAttrs->GetItemIfSet( SCHATTR_AXIS_LABEL_POSITION, false) )
+ {
+ sal_Int32 nPos = pLabelPosItem->GetValue();
+ if( nPos < m_xLB_PlaceLabels->get_count() )
+ m_xLB_PlaceLabels->set_active( nPos );
+ }
+ else
+ m_xLB_PlaceLabels->set_active(-1);
+ PlaceLabelsSelectHdl( *m_xLB_PlaceLabels );
+
+ // Tick marks
+ tools::Long nTicks = 0, nMinorTicks = 0;
+ if (const SfxInt32Item* pTicksItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_TICKS))
+ nTicks = pTicksItem->GetValue();
+ if (const SfxInt32Item* pHelpTicksItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_HELPTICKS))
+ nMinorTicks = pHelpTicksItem->GetValue();
+
+ m_xCB_TicksInner->set_active(bool(nTicks&CHAXIS_MARK_INNER));
+ m_xCB_TicksOuter->set_active(bool(nTicks&CHAXIS_MARK_OUTER));
+ m_xCB_MinorInner->set_active(bool(nMinorTicks&CHAXIS_MARK_INNER));
+ m_xCB_MinorOuter->set_active(bool(nMinorTicks&CHAXIS_MARK_OUTER));
+
+ // Tick position
+ if( const SfxInt32Item* pMarkPosItem = rInAttrs->GetItemIfSet( SCHATTR_AXIS_MARK_POSITION, false) )
+ {
+ sal_Int32 nPos = pMarkPosItem->GetValue();
+ if( nPos < m_xLB_PlaceTicks->get_count() )
+ m_xLB_PlaceTicks->set_active( nPos );
+ }
+ else
+ m_xLB_PlaceTicks->set_active(-1);
+
+ if( !m_bSupportAxisPositioning )
+ {
+ m_xFL_AxisLine->hide();
+ m_xFL_Labels->hide();
+ m_xBxPlaceTicks->hide();
+ }
+ else if( !AxisHelper::isAxisPositioningEnabled() )
+ {
+ m_xFL_AxisLine->set_sensitive(false);
+ m_xFL_Labels->set_sensitive(false);
+ m_xBxPlaceTicks->set_sensitive(false);
+ //todo: maybe set a special help id to all those controls
+ }
+}
+
+DeactivateRC AxisPositionsTabPage::DeactivatePage(SfxItemSet* pItemSet)
+{
+ if( pItemSet )
+ FillItemSet( pItemSet );
+
+ return DeactivateRC::LeavePage;
+}
+
+void AxisPositionsTabPage::SetNumFormatter( SvNumberFormatter* pFormatter )
+{
+ m_pNumFormatter = pFormatter;
+ Formatter& rCrossFormatter = m_xED_CrossesAt->GetFormatter();
+ rCrossFormatter.SetFormatter(m_pNumFormatter);
+ rCrossFormatter.UseInputStringForFormatting();
+
+ if( const SfxUInt32Item* pNumFormatItem = GetItemSet().GetItemIfSet(SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT) )
+ {
+ sal_uInt32 nFmt = pNumFormatItem->GetValue();
+ rCrossFormatter.SetFormatKey(nFmt);
+ }
+}
+
+void AxisPositionsTabPage::SetCrossingAxisIsCategoryAxis( bool bCrossingAxisIsCategoryAxis )
+{
+ m_bCrossingAxisIsCategoryAxis = bCrossingAxisIsCategoryAxis;
+}
+
+void AxisPositionsTabPage::SetCategories( const css::uno::Sequence< OUString >& rCategories )
+{
+ m_aCategories = rCategories;
+}
+
+void AxisPositionsTabPage::SupportAxisPositioning( bool bSupportAxisPositioning )
+{
+ m_bSupportAxisPositioning = bSupportAxisPositioning;
+}
+
+void AxisPositionsTabPage::SupportCategoryPositioning( bool bSupportCategoryPositioning )
+{
+ m_bSupportCategoryPositioning = bSupportCategoryPositioning;
+}
+
+IMPL_LINK_NOARG(AxisPositionsTabPage, CrossesAtSelectHdl, weld::ComboBox&, void)
+{
+ sal_Int32 nPos = m_xLB_CrossesAt->get_active();
+ m_xED_CrossesAt->set_visible( (nPos==2) && !m_bCrossingAxisIsCategoryAxis );
+ m_xED_CrossesAtCategory->set_visible( (nPos==2) && m_bCrossingAxisIsCategoryAxis );
+
+ if (m_xED_CrossesAt->get_text().isEmpty())
+ m_xED_CrossesAt->GetFormatter().SetValue(0.0);
+ if (m_xED_CrossesAtCategory->get_active() == -1 && m_xED_CrossesAtCategory->get_count())
+ m_xED_CrossesAtCategory->set_active(0);
+
+ PlaceLabelsSelectHdl(*m_xLB_PlaceLabels);
+}
+
+IMPL_LINK_NOARG(AxisPositionsTabPage, PlaceLabelsSelectHdl, weld::ComboBox&, void)
+{
+ sal_Int32 nLabelPos = m_xLB_PlaceLabels->get_active();
+
+ bool bEnableTickmarkPlacement = (nLabelPos>1);
+ if( bEnableTickmarkPlacement )
+ {
+ sal_Int32 nAxisPos = m_xLB_CrossesAt->get_active();
+ if( nLabelPos-2 == nAxisPos )
+ bEnableTickmarkPlacement=false;
+ }
+ m_xBxPlaceTicks->set_sensitive(bEnableTickmarkPlacement);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_AxisPositions.hxx b/chart2/source/controller/dialogs/tp_AxisPositions.hxx
new file mode 100644
index 0000000000..86f749a268
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_AxisPositions.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+namespace chart
+{
+class AxisPositionsTabPage : public SfxTabPage
+{
+public:
+ AxisPositionsTabPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& rInAttrs);
+ virtual ~AxisPositionsTabPage() override;
+
+ static std::unique_ptr<SfxTabPage>
+ Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs);
+ virtual bool FillItemSet(SfxItemSet* rOutAttrs) override;
+ virtual void Reset(const SfxItemSet* rInAttrs) override;
+ virtual DeactivateRC DeactivatePage(SfxItemSet* pItemSet) override;
+
+ void SetNumFormatter(SvNumberFormatter* pFormatter);
+
+ void SetCrossingAxisIsCategoryAxis(bool bCrossingAxisIsCategoryAxis);
+ void SetCategories(const css::uno::Sequence<OUString>& rCategories);
+
+ void SupportAxisPositioning(bool bSupportAxisPositioning);
+ void SupportCategoryPositioning(bool bSupportCategoryPositioning);
+
+private: //methods:
+ DECL_LINK(CrossesAtSelectHdl, weld::ComboBox&, void);
+ DECL_LINK(PlaceLabelsSelectHdl, weld::ComboBox&, void);
+
+private: //member:
+ SvNumberFormatter* m_pNumFormatter;
+
+ bool m_bCrossingAxisIsCategoryAxis;
+ css::uno::Sequence<OUString> m_aCategories;
+
+ bool m_bSupportAxisPositioning;
+ bool m_bSupportCategoryPositioning;
+
+ std::unique_ptr<weld::Frame> m_xFL_AxisLine;
+ std::unique_ptr<weld::ComboBox> m_xLB_CrossesAt;
+ std::unique_ptr<weld::FormattedSpinButton> m_xED_CrossesAt;
+ std::unique_ptr<weld::ComboBox> m_xED_CrossesAtCategory;
+
+ std::unique_ptr<weld::Frame> m_xFL_Position;
+ std::unique_ptr<weld::RadioButton> m_xRB_On;
+ std::unique_ptr<weld::RadioButton> m_xRB_Between;
+
+ std::unique_ptr<weld::Frame> m_xFL_Labels;
+ std::unique_ptr<weld::ComboBox> m_xLB_PlaceLabels;
+
+ std::unique_ptr<weld::CheckButton> m_xCB_TicksInner;
+ std::unique_ptr<weld::CheckButton> m_xCB_TicksOuter;
+
+ std::unique_ptr<weld::CheckButton> m_xCB_MinorInner;
+ std::unique_ptr<weld::CheckButton> m_xCB_MinorOuter;
+
+ std::unique_ptr<weld::Widget> m_xBxPlaceTicks;
+ std::unique_ptr<weld::ComboBox> m_xLB_PlaceTicks;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_ChartType.cxx b/chart2/source/controller/dialogs/tp_ChartType.cxx
new file mode 100644
index 0000000000..e0ddd62cd6
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_ChartType.cxx
@@ -0,0 +1,385 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_ChartType.hxx"
+#include <ChartResourceGroups.hxx>
+#include <ChartTypeManager.hxx>
+#include <strings.hrc>
+#include <ResId.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <unonames.hxx>
+
+#include <svtools/valueset.hxx>
+
+#include <utility>
+#include <vcl/weld.hxx>
+#include <vcl/outdev.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+ChartTypeTabPage::ChartTypeTabPage(weld::Container* pPage, weld::DialogController* pController, rtl::Reference<::chart::ChartModel> xChartModel,
+ bool bShowDescription)
+ : OWizardPage(pPage, pController, "modules/schart/ui/tp_ChartType.ui", "tp_ChartType")
+ , m_pDim3DLookResourceGroup( new Dim3DLookResourceGroup(m_xBuilder.get()) )
+ , m_pStackingResourceGroup( new StackingResourceGroup(m_xBuilder.get()) )
+ , m_pSplineResourceGroup( new SplineResourceGroup(m_xBuilder.get(), pController->getDialog()) )
+ , m_pGeometryResourceGroup( new GeometryResourceGroup(m_xBuilder.get()) )
+ , m_pSortByXValuesResourceGroup( new SortByXValuesResourceGroup(m_xBuilder.get()) )
+ , m_xChartModel(std::move( xChartModel ))
+ , m_aChartTypeDialogControllerList(0)
+ , m_pCurrentMainType(nullptr)
+ , m_nChangingCalls(0)
+ , m_aTimerTriggeredControllerLock( m_xChartModel )
+ , m_xFT_ChooseType(m_xBuilder->weld_label("FT_CAPTION_FOR_WIZARD"))
+ , m_xMainTypeList(m_xBuilder->weld_tree_view("charttype"))
+ , m_xSubTypeList(new ValueSet(m_xBuilder->weld_scrolled_window("subtypewin", true)))
+ , m_xSubTypeListWin(new weld::CustomWeld(*m_xBuilder, "subtype", *m_xSubTypeList))
+{
+ Size aSize(m_xSubTypeList->GetDrawingArea()->get_ref_device().LogicToPixel(Size(150, 50), MapMode(MapUnit::MapAppFont)));
+ m_xSubTypeListWin->set_size_request(aSize.Width(), aSize.Height());
+
+ if (bShowDescription)
+ {
+ m_xFT_ChooseType->show();
+ }
+ else
+ {
+ m_xFT_ChooseType->hide();
+ }
+
+ SetPageTitle(SchResId(STR_PAGE_CHARTTYPE));
+
+ m_xMainTypeList->connect_changed(LINK(this, ChartTypeTabPage, SelectMainTypeHdl));
+ m_xSubTypeList->SetSelectHdl( LINK( this, ChartTypeTabPage, SelectSubTypeHdl ) );
+
+ m_xSubTypeList->SetStyle(m_xSubTypeList->GetStyle() |
+ WB_ITEMBORDER | WB_DOUBLEBORDER | WB_NAMEFIELD | WB_FLATVALUESET | WB_3DLOOK );
+ m_xSubTypeList->SetColCount(4);
+ m_xSubTypeList->SetLineCount(1);
+
+ bool bEnableComplexChartTypes = true;
+ uno::Reference< beans::XPropertySet > xProps( static_cast<cppu::OWeakObject*>(m_xChartModel.get()), uno::UNO_QUERY );
+ if ( xProps.is() )
+ {
+ try
+ {
+ xProps->getPropertyValue("EnableComplexChartTypes") >>= bEnableComplexChartTypes;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<ColumnChartDialogController>());
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<BarChartDialogController>());
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<PieChartDialogController>());
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<AreaChartDialogController>());
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<LineChartDialogController>());
+ if (bEnableComplexChartTypes)
+ {
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<XYChartDialogController>());
+ m_aChartTypeDialogControllerList.push_back(
+ std::make_unique<BubbleChartDialogController>());
+ }
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<NetChartDialogController>());
+ if (bEnableComplexChartTypes)
+ {
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<StockChartDialogController>());
+ }
+ m_aChartTypeDialogControllerList.push_back(
+ std::make_unique<CombiColumnLineChartDialogController>());
+
+ for (auto const& elem : m_aChartTypeDialogControllerList)
+ {
+ m_xMainTypeList->append("", elem->getName(), elem->getImage());
+ elem->setChangeListener( this );
+ }
+
+ m_xMainTypeList->set_size_request(m_xMainTypeList->get_preferred_size().Width(), -1);
+
+ m_pDim3DLookResourceGroup->setChangeListener( this );
+ m_pStackingResourceGroup->setChangeListener( this );
+ m_pSplineResourceGroup->setChangeListener( this );
+ m_pGeometryResourceGroup->setChangeListener( this );
+ m_pSortByXValuesResourceGroup->setChangeListener( this );
+}
+
+ChartTypeTabPage::~ChartTypeTabPage()
+{
+ //delete all dialog controller
+ m_aChartTypeDialogControllerList.clear();
+
+ //delete all resource helper
+ m_pDim3DLookResourceGroup.reset();
+ m_pStackingResourceGroup.reset();
+ m_pSplineResourceGroup.reset();
+ m_pGeometryResourceGroup.reset();
+ m_pSortByXValuesResourceGroup.reset();
+ m_xSubTypeListWin.reset();
+ m_xSubTypeList.reset();
+}
+
+ChartTypeParameter ChartTypeTabPage::getCurrentParamter() const
+{
+ ChartTypeParameter aParameter;
+ aParameter.nSubTypeIndex = static_cast<sal_Int32>(m_xSubTypeList->GetSelectedItemId());
+ m_pDim3DLookResourceGroup->fillParameter( aParameter );
+ m_pStackingResourceGroup->fillParameter( aParameter );
+ m_pSplineResourceGroup->fillParameter( aParameter );
+ m_pGeometryResourceGroup->fillParameter( aParameter );
+ m_pSortByXValuesResourceGroup->fillParameter( aParameter );
+ return aParameter;
+}
+
+void ChartTypeTabPage::commitToModel( const ChartTypeParameter& rParameter )
+{
+ if( !m_pCurrentMainType )
+ return;
+
+ m_aTimerTriggeredControllerLock.startTimer();
+ m_pCurrentMainType->commitToModel( rParameter, m_xChartModel );
+}
+
+void ChartTypeTabPage::stateChanged()
+{
+ if(m_nChangingCalls)
+ return;
+ m_nChangingCalls++;
+
+ ChartTypeParameter aParameter( getCurrentParamter() );
+ if( m_pCurrentMainType )
+ {
+ m_pCurrentMainType->adjustParameterToSubType( aParameter );
+ m_pCurrentMainType->adjustSubTypeAndEnableControls( aParameter );
+ }
+ commitToModel( aParameter );
+
+ //detect the new ThreeDLookScheme
+ rtl::Reference< Diagram > xDiagram = m_xChartModel->getFirstChartDiagram();
+ // tdf#124295 - select always a 3D scheme
+ if (ThreeDLookScheme aThreeDLookScheme = xDiagram->detectScheme();
+ aThreeDLookScheme != ThreeDLookScheme::ThreeDLookScheme_Unknown)
+ aParameter.eThreeDLookScheme = aThreeDLookScheme;
+
+ try
+ {
+ xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues;
+ }
+ catch ( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ //the controls have to be enabled/disabled accordingly
+ fillAllControls( aParameter );
+
+ m_nChangingCalls--;
+}
+
+ChartTypeDialogController* ChartTypeTabPage::getSelectedMainType()
+{
+ ChartTypeDialogController* pTypeController = nullptr;
+ auto nM = static_cast< std::vector< ChartTypeDialogController* >::size_type >(
+ m_xMainTypeList->get_selected_index() );
+ if( nM<m_aChartTypeDialogControllerList.size() )
+ pTypeController = m_aChartTypeDialogControllerList[nM].get();
+ return pTypeController;
+}
+
+IMPL_LINK_NOARG(ChartTypeTabPage, SelectSubTypeHdl, ValueSet*, void)
+{
+ if( m_pCurrentMainType )
+ {
+ ChartTypeParameter aParameter( getCurrentParamter() );
+ m_pCurrentMainType->adjustParameterToSubType( aParameter );
+ fillAllControls( aParameter, false );
+ commitToModel( aParameter );
+ }
+}
+
+IMPL_LINK_NOARG(ChartTypeTabPage, SelectMainTypeHdl, weld::TreeView&, void)
+{
+ selectMainType();
+}
+
+void ChartTypeTabPage::selectMainType()
+{
+ ChartTypeParameter aParameter( getCurrentParamter() );
+
+ if( m_pCurrentMainType )
+ {
+ m_pCurrentMainType->adjustParameterToSubType( aParameter );
+ m_pCurrentMainType->hideExtraControls();
+ }
+
+ m_pCurrentMainType = getSelectedMainType();
+ if( !m_pCurrentMainType )
+ return;
+
+ showAllControls(*m_pCurrentMainType);
+
+ m_pCurrentMainType->adjustParameterToMainType( aParameter );
+ commitToModel( aParameter );
+ //detect the new ThreeDLookScheme
+ aParameter.eThreeDLookScheme = ThreeDLookScheme::ThreeDLookScheme_Unknown;
+ rtl::Reference< Diagram > xDiagram = m_xChartModel->getFirstChartDiagram();
+ if (xDiagram)
+ aParameter.eThreeDLookScheme = m_xChartModel->getFirstChartDiagram()->detectScheme();
+ if (!aParameter.b3DLook
+ && aParameter.eThreeDLookScheme != ThreeDLookScheme::ThreeDLookScheme_Realistic)
+ aParameter.eThreeDLookScheme = ThreeDLookScheme::ThreeDLookScheme_Realistic;
+
+ try
+ {
+ if (xDiagram)
+ xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues;
+ }
+ catch ( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ fillAllControls( aParameter );
+ uno::Reference< beans::XPropertySet > xTemplateProps( static_cast<cppu::OWeakObject*>(getCurrentTemplate().get()), uno::UNO_QUERY );
+ m_pCurrentMainType->fillExtraControls(m_xChartModel,xTemplateProps);
+}
+
+void ChartTypeTabPage::showAllControls( ChartTypeDialogController& rTypeController )
+{
+ m_xMainTypeList->show();
+ m_xSubTypeList->Show();
+
+ bool bShow = rTypeController.shouldShow_3DLookControl();
+ m_pDim3DLookResourceGroup->showControls( bShow );
+ bShow = rTypeController.shouldShow_StackingControl();
+ m_pStackingResourceGroup->showControls( bShow );
+ bShow = rTypeController.shouldShow_SplineControl();
+ m_pSplineResourceGroup->showControls( bShow );
+ bShow = rTypeController.shouldShow_GeometryControl();
+ m_pGeometryResourceGroup->showControls( bShow );
+ bShow = rTypeController.shouldShow_SortByXValuesResourceGroup();
+ m_pSortByXValuesResourceGroup->showControls( bShow );
+ rTypeController.showExtraControls(m_xBuilder.get());
+}
+
+void ChartTypeTabPage::fillAllControls( const ChartTypeParameter& rParameter, bool bAlsoResetSubTypeList )
+{
+ m_nChangingCalls++;
+ if( m_pCurrentMainType && bAlsoResetSubTypeList )
+ {
+ m_pCurrentMainType->fillSubTypeList(*m_xSubTypeList, rParameter);
+ }
+ m_xSubTypeList->SelectItem( static_cast<sal_uInt16>( rParameter.nSubTypeIndex) );
+ m_pDim3DLookResourceGroup->fillControls( rParameter );
+ m_pStackingResourceGroup->fillControls( rParameter );
+ m_pSplineResourceGroup->fillControls( rParameter );
+ m_pGeometryResourceGroup->fillControls( rParameter );
+ m_pSortByXValuesResourceGroup->fillControls( rParameter );
+ m_nChangingCalls--;
+}
+
+void ChartTypeTabPage::initializePage()
+{
+ if( !m_xChartModel.is() )
+ return;
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = m_xChartModel->getTypeManager();
+ rtl::Reference< Diagram > xDiagram = m_xChartModel->getFirstChartDiagram();
+ Diagram::tTemplateWithServiceName aTemplate;
+ if (xDiagram)
+ aTemplate = xDiagram->getTemplate( xChartTypeManager );
+ OUString aServiceName( aTemplate.sServiceName );
+
+ bool bFound = false;
+
+ sal_uInt16 nM=0;
+ for (auto const& elem : m_aChartTypeDialogControllerList)
+ {
+ if( elem->isSubType(aServiceName) )
+ {
+ bFound = true;
+
+ m_xMainTypeList->select(nM);
+ showAllControls(*elem);
+ uno::Reference< beans::XPropertySet > xTemplateProps( static_cast<cppu::OWeakObject*>(aTemplate.xChartTypeTemplate.get()), uno::UNO_QUERY );
+ ChartTypeParameter aParameter = elem->getChartTypeParameterForService( aServiceName, xTemplateProps );
+ m_pCurrentMainType = getSelectedMainType();
+
+ //set ThreeDLookScheme
+ aParameter.eThreeDLookScheme = xDiagram->detectScheme();
+ if (!aParameter.b3DLook
+ && aParameter.eThreeDLookScheme != ThreeDLookScheme::ThreeDLookScheme_Realistic)
+ aParameter.eThreeDLookScheme = ThreeDLookScheme::ThreeDLookScheme_Realistic;
+
+ try
+ {
+ xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues;
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ fillAllControls( aParameter );
+ if( m_pCurrentMainType )
+ m_pCurrentMainType->fillExtraControls(m_xChartModel,xTemplateProps);
+ break;
+ }
+ ++nM;
+ }
+
+ if( !bFound )
+ {
+ m_xMainTypeList->show();
+ m_xSubTypeList->Show();
+ m_pDim3DLookResourceGroup->showControls( false );
+ m_pStackingResourceGroup->showControls( false );
+ m_pSplineResourceGroup->showControls( false );
+ m_pGeometryResourceGroup->showControls( false );
+ m_pSortByXValuesResourceGroup->showControls( false );
+ }
+}
+
+bool ChartTypeTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ )
+{
+ return true; // return false if this page should not be left
+}
+
+rtl::Reference< ChartTypeTemplate > ChartTypeTabPage::getCurrentTemplate() const
+{
+ if( m_pCurrentMainType && m_xChartModel.is() )
+ {
+ ChartTypeParameter aParameter( getCurrentParamter() );
+ m_pCurrentMainType->adjustParameterToSubType( aParameter );
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = m_xChartModel->getTypeManager();
+ return m_pCurrentMainType->getCurrentTemplate( aParameter, xChartTypeManager );
+ }
+ return nullptr;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_ChartType.hxx b/chart2/source/controller/dialogs/tp_ChartType.hxx
new file mode 100644
index 0000000000..c01b599f58
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_ChartType.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <ChartTypeDialogController.hxx>
+#include <ChartTypeTemplateProvider.hxx>
+#include <TimerTriggeredControllerLock.hxx>
+
+#include <vcl/wizardmachine.hxx>
+
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace weld { class CustomWeld; }
+
+class ValueSet;
+
+namespace chart
+{
+
+class Dim3DLookResourceGroup;
+class StackingResourceGroup;
+class SplineResourceGroup;
+class GeometryResourceGroup;
+class SortByXValuesResourceGroup;
+
+class ChartTypeTabPage final : public ResourceChangeListener, public vcl::OWizardPage, public ChartTypeTemplateProvider
+{
+public:
+ ChartTypeTabPage( weld::Container* pPage, weld::DialogController* pController
+ , rtl::Reference<::chart::ChartModel> xChartModel
+ , bool bShowDescription = true );
+ virtual ~ChartTypeTabPage() override;
+
+ virtual void initializePage() override;
+ virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason eReason ) override;
+
+ virtual rtl::Reference< ::chart::ChartTypeTemplate > getCurrentTemplate() const override;
+
+private:
+ ChartTypeDialogController* getSelectedMainType();
+ void showAllControls( ChartTypeDialogController& rTypeController );
+ void fillAllControls( const ChartTypeParameter& rParameter, bool bAlsoResetSubTypeList=true );
+ ChartTypeParameter getCurrentParamter() const;
+
+ virtual void stateChanged() override;
+
+ void commitToModel( const ChartTypeParameter& rParameter );
+ void selectMainType();
+
+ DECL_LINK(SelectMainTypeHdl, weld::TreeView&, void);
+ DECL_LINK(SelectSubTypeHdl, ValueSet*, void );
+
+ std::unique_ptr<Dim3DLookResourceGroup> m_pDim3DLookResourceGroup;
+ std::unique_ptr<StackingResourceGroup> m_pStackingResourceGroup;
+ std::unique_ptr<SplineResourceGroup> m_pSplineResourceGroup;
+ std::unique_ptr<GeometryResourceGroup> m_pGeometryResourceGroup;
+ std::unique_ptr<SortByXValuesResourceGroup> m_pSortByXValuesResourceGroup;
+
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+
+ std::vector< std::unique_ptr<ChartTypeDialogController> > m_aChartTypeDialogControllerList;
+ ChartTypeDialogController* m_pCurrentMainType;
+
+ sal_Int32 m_nChangingCalls;
+
+ TimerTriggeredControllerLock m_aTimerTriggeredControllerLock;
+
+ std::unique_ptr<weld::Label> m_xFT_ChooseType;
+ std::unique_ptr<weld::TreeView> m_xMainTypeList;
+ std::unique_ptr<ValueSet> m_xSubTypeList;
+ std::unique_ptr<weld::CustomWeld> m_xSubTypeListWin;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_DataLabel.cxx b/chart2/source/controller/dialogs/tp_DataLabel.cxx
new file mode 100644
index 0000000000..3594e3e8ff
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_DataLabel.cxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_DataLabel.hxx"
+
+namespace chart
+{
+
+DataLabelsTabPage::DataLabelsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_DataLabel.ui", "tp_DataLabel", &rInAttrs)
+ , m_aDataLabelResources(m_xBuilder.get(), pController->getDialog(), rInAttrs)
+{
+}
+
+std::unique_ptr<SfxTabPage> DataLabelsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs)
+{
+ return std::make_unique<DataLabelsTabPage>(pPage, pController, *rOutAttrs);
+}
+
+bool DataLabelsTabPage::FillItemSet(SfxItemSet* rOutAttrs)
+{
+ m_aDataLabelResources.FillItemSet(rOutAttrs);
+ return true;
+}
+
+void DataLabelsTabPage::Reset(const SfxItemSet* rInAttrs)
+{
+ m_aDataLabelResources.Reset(*rInAttrs);
+}
+
+void DataLabelsTabPage::SetNumberFormatter( SvNumberFormatter* pFormatter )
+{
+ m_aDataLabelResources.SetNumberFormatter( pFormatter );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_DataLabel.hxx b/chart2/source/controller/dialogs/tp_DataLabel.hxx
new file mode 100644
index 0000000000..200063af96
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_DataLabel.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "res_DataLabel.hxx"
+#include <sfx2/tabdlg.hxx>
+
+class SvNumberFormatter;
+
+namespace chart
+{
+class DataLabelsTabPage : public SfxTabPage
+{
+public:
+ DataLabelsTabPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& rInAttrs);
+
+ static std::unique_ptr<SfxTabPage>
+ Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs);
+
+ void SetNumberFormatter(SvNumberFormatter* pFormatter);
+
+ virtual void Reset(const SfxItemSet* rInAttrs) override;
+ virtual bool FillItemSet(SfxItemSet* rOutAttrs) override;
+
+private:
+ DataLabelResources m_aDataLabelResources;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_DataPointOption.cxx b/chart2/source/controller/dialogs/tp_DataPointOption.cxx
new file mode 100644
index 0000000000..4c82428720
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_DataPointOption.cxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_DataPointOption.hxx"
+
+#include <chartview/ChartSfxItemIds.hxx>
+#include <svl/eitem.hxx>
+
+namespace chart
+{
+DataPointOptionTabPage::DataPointOptionTabPage(weld::Container* pPage,
+ weld::DialogController* pController,
+ const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_DataPointOption.ui",
+ "tp_DataPointOption", &rInAttrs)
+ , m_xCBHideLegendEntry(m_xBuilder->weld_check_button("CB_LEGEND_ENTRY_HIDDEN"))
+{
+}
+
+DataPointOptionTabPage::~DataPointOptionTabPage() {}
+
+std::unique_ptr<SfxTabPage> DataPointOptionTabPage::Create(weld::Container* pPage,
+ weld::DialogController* pController,
+ const SfxItemSet* rOutAttrs)
+{
+ return std::make_unique<DataPointOptionTabPage>(pPage, pController, *rOutAttrs);
+}
+
+bool DataPointOptionTabPage::FillItemSet(SfxItemSet* rOutAttrs)
+{
+ if (m_xCBHideLegendEntry->get_visible())
+ rOutAttrs->Put(
+ SfxBoolItem(SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, m_xCBHideLegendEntry->get_active()));
+
+ return true;
+}
+
+void DataPointOptionTabPage::Reset(const SfxItemSet* rInAttrs)
+{
+ if (const SfxBoolItem* pEntryItem
+ = rInAttrs->GetItemIfSet(SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY))
+ {
+ bool bVal = pEntryItem->GetValue();
+ m_xCBHideLegendEntry->set_active(bVal);
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_DataPointOption.hxx b/chart2/source/controller/dialogs/tp_DataPointOption.hxx
new file mode 100644
index 0000000000..b73a8a609e
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_DataPointOption.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+namespace weld
+{
+class CheckButton;
+}
+
+namespace chart
+{
+class DataPointOptionTabPage : public SfxTabPage
+{
+public:
+ DataPointOptionTabPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& rInAttrs);
+ virtual ~DataPointOptionTabPage() override;
+
+ static std::unique_ptr<SfxTabPage>
+ Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs);
+ virtual bool FillItemSet(SfxItemSet* rOutAttrs) override;
+ virtual void Reset(const SfxItemSet* rInAttrs) override;
+
+private:
+ std::unique_ptr<weld::CheckButton> m_xCBHideLegendEntry;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_DataSource.cxx b/chart2/source/controller/dialogs/tp_DataSource.cxx
new file mode 100644
index 0000000000..c30ce8afae
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_DataSource.cxx
@@ -0,0 +1,924 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_DataSource.hxx"
+#include <strings.hrc>
+#include <ResId.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeTemplateProvider.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <ChartModel.hxx>
+#include <RangeSelectionHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <DataSourceHelper.hxx>
+#include <LabeledDataSequence.hxx>
+#include "DialogModel.hxx"
+#include <o3tl/safeint.hxx>
+#include <TabPageNotifiable.hxx>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/chart2/data/XDataProvider.hpp>
+
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+
+constexpr OUString lcl_aLabelRole( u"label"_ustr );
+
+void lcl_UpdateCurrentRange(weld::TreeView& rOutListBox, const OUString & rRole,
+ const OUString& rRange)
+{
+ int nEntry = rOutListBox.get_selected_index();
+ if (nEntry != -1)
+ {
+ rOutListBox.set_text(nEntry, ::chart::DialogModel::ConvertRoleFromInternalToUI(rRole), 0);
+ rOutListBox.set_text(nEntry, rRange, 1);
+ ::chart::SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry));
+ pEntry->m_sRole = rRole;
+ }
+}
+
+bool lcl_UpdateCurrentSeriesName(weld::TreeView& rOutListBox)
+{
+ int nEntry = rOutListBox.get_selected_index();
+ if (nEntry == -1)
+ return false;
+
+ bool bResult = false;
+ ::chart::SeriesEntry * pEntry = weld::fromId<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry));
+ if (pEntry->m_xDataSeries.is() && pEntry->m_xChartType.is())
+ {
+ OUString aLabel(pEntry->m_xDataSeries->getLabelForRole(
+ pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel()));
+ if (!aLabel.isEmpty())
+ {
+ rOutListBox.set_text(nEntry, aLabel);
+ bResult = true;
+ }
+ }
+ return bResult;
+}
+
+OUString lcl_GetSelectedRole(const weld::TreeView& rRoleListBox, bool bUITranslated = false)
+{
+ int nEntry = rRoleListBox.get_selected_index();
+ if (nEntry != -1)
+ {
+ if (bUITranslated)
+ return rRoleListBox.get_text(nEntry);
+ ::chart::SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(rRoleListBox.get_id(nEntry));
+ return pEntry->m_sRole;
+ }
+ return OUString();
+}
+
+OUString lcl_GetSelectedRolesRange( const weld::TreeView& rRoleListBox )
+{
+ OUString aResult;
+ int nEntry = rRoleListBox.get_selected_index();
+ if (nEntry != -1)
+ aResult = rRoleListBox.get_text(nEntry, 1);
+ return aResult;
+}
+
+OUString lcl_GetSequenceNameForLabel(const ::chart::SeriesEntry* pEntry)
+{
+ OUString aResult("values-y");
+ if (pEntry && pEntry->m_xChartType.is())
+ aResult = pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel();
+ return aResult;
+}
+
+void lcl_enableRangeChoosing(bool bEnable, weld::DialogController* pDialog)
+{
+ if (!pDialog)
+ return;
+ weld::Dialog* pDlg = pDialog->getDialog();
+ pDlg->set_modal(!bEnable);
+ pDlg->set_visible(!bEnable);
+}
+
+void lcl_addLSequenceToDataSource(
+ const uno::Reference< chart2::data::XLabeledDataSequence > & xLSequence,
+ const Reference< ::chart::DataSeries > & xSource )
+{
+ if( xSource.is())
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = xSource->getDataSequences2();
+ aData.push_back( xLSequence );
+ xSource->setData( aData );
+ }
+}
+
+uno::Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
+ const rtl::Reference< ::chart::DataSeries > & xDataSource )
+{
+ uno::Reference< chart2::data::XLabeledDataSequence > xResult;
+
+ for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : xDataSource->getDataSequences2() )
+ {
+ // no values are set but a label exists
+ if( ! labeledDataSeq->getValues().is() &&
+ labeledDataSeq->getLabel().is())
+ {
+ xResult = labeledDataSeq;
+ break;
+ }
+ }
+
+ return xResult;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+DataSourceTabPage::DataSourceTabPage(weld::Container* pPage, weld::DialogController* pController,
+ DialogModel & rDialogModel,
+ ChartTypeTemplateProvider* pTemplateProvider,
+ bool bHideDescription /* = false */)
+ : ::vcl::OWizardPage(pPage, pController, "modules/schart/ui/tp_DataSource.ui", "tp_DataSource")
+ , m_pTemplateProvider(pTemplateProvider)
+ , m_rDialogModel(rDialogModel)
+ , m_pCurrentRangeChoosingField( nullptr )
+ , m_bIsDirty( false )
+ , m_pTabPageNotifiable(dynamic_cast<TabPageNotifiable*>(pController))
+ , m_xFT_CAPTION(m_xBuilder->weld_label("FT_CAPTION_FOR_WIZARD"))
+ , m_xFT_SERIES(m_xBuilder->weld_label("FT_SERIES"))
+ , m_xLB_SERIES(m_xBuilder->weld_tree_view("LB_SERIES"))
+ , m_xBTN_ADD(m_xBuilder->weld_button("BTN_ADD"))
+ , m_xBTN_REMOVE(m_xBuilder->weld_button("BTN_REMOVE"))
+ , m_xBTN_UP(m_xBuilder->weld_button("BTN_UP"))
+ , m_xBTN_DOWN(m_xBuilder->weld_button("BTN_DOWN"))
+ , m_xFT_ROLE(m_xBuilder->weld_label("FT_ROLE"))
+ , m_xLB_ROLE(m_xBuilder->weld_tree_view("LB_ROLE"))
+ , m_xFT_RANGE(m_xBuilder->weld_label("FT_RANGE"))
+ , m_xEDT_RANGE(m_xBuilder->weld_entry("EDT_RANGE"))
+ , m_xIMB_RANGE_MAIN(m_xBuilder->weld_button("IMB_RANGE_MAIN"))
+ , m_xFT_CATEGORIES(m_xBuilder->weld_label("FT_CATEGORIES"))
+ , m_xFT_DATALABELS(m_xBuilder->weld_label("FT_DATALABELS"))
+ , m_xEDT_CATEGORIES(m_xBuilder->weld_entry("EDT_CATEGORIES"))
+ , m_xIMB_RANGE_CAT(m_xBuilder->weld_button("IMB_RANGE_CAT"))
+{
+ m_xLB_SERIES->set_size_request(m_xLB_SERIES->get_approximate_digit_width() * 25,
+ m_xLB_SERIES->get_height_rows(10));
+ m_xLB_ROLE->set_size_request(m_xLB_ROLE->get_approximate_digit_width() * 60,
+ m_xLB_ROLE->get_height_rows(5));
+ m_xFT_CAPTION->set_visible(!bHideDescription);
+
+ m_aFixedTextRange = m_xFT_RANGE->get_label();
+ SetPageTitle(SchResId(STR_OBJECT_DATASERIES_PLURAL));
+
+ // set handlers
+ m_xLB_SERIES->connect_changed(LINK(this, DataSourceTabPage, SeriesSelectionChangedHdl));
+ m_xLB_ROLE->connect_changed(LINK(this, DataSourceTabPage, RoleSelectionChangedHdl));
+
+ m_xIMB_RANGE_MAIN->connect_clicked(LINK(this, DataSourceTabPage, MainRangeButtonClickedHdl));
+ m_xIMB_RANGE_CAT->connect_clicked(LINK(this, DataSourceTabPage, CategoriesRangeButtonClickedHdl));
+
+ m_xBTN_ADD->connect_clicked(LINK(this, DataSourceTabPage, AddButtonClickedHdl));
+ m_xBTN_REMOVE->connect_clicked(LINK(this, DataSourceTabPage, RemoveButtonClickedHdl));
+
+ m_xBTN_UP->connect_clicked(LINK(this, DataSourceTabPage, UpButtonClickedHdl));
+ m_xBTN_DOWN->connect_clicked(LINK(this, DataSourceTabPage, DownButtonClickedHdl));
+
+ m_xEDT_RANGE->connect_changed(LINK(this, DataSourceTabPage, RangeModifiedHdl));
+ m_xEDT_CATEGORIES->connect_changed(LINK( this, DataSourceTabPage, RangeModifiedHdl));
+
+ // init controls
+ std::vector<int> aWidths { o3tl::narrowing<int>(m_xLB_ROLE->get_approximate_digit_width() * 20) };
+ m_xLB_ROLE->set_column_fixed_widths(aWidths);
+ m_xLB_ROLE->show();
+
+ updateControlsFromDialogModel();
+
+ // select first series
+ if (m_xLB_SERIES->n_children())
+ m_xLB_SERIES->select(0);
+}
+
+void DataSourceTabPage::InsertRoleLBEntry(const OUString& rRole, const OUString& rRange)
+{
+ m_aEntries.emplace_back(new SeriesEntry);
+ SeriesEntry* pEntry = m_aEntries.back().get();
+ pEntry->m_sRole = rRole;
+ m_xLB_ROLE->append(weld::toId(pEntry),
+ ::chart::DialogModel::ConvertRoleFromInternalToUI(rRole));
+ m_xLB_ROLE->set_text(m_xLB_ROLE->n_children() - 1, rRange, 1);
+}
+
+DataSourceTabPage::~DataSourceTabPage()
+{
+}
+
+void DataSourceTabPage::Activate()
+{
+ OWizardPage::Activate();
+ updateControlsFromDialogModel();
+ m_xLB_SERIES->grab_focus();
+}
+
+void DataSourceTabPage::initializePage()
+{
+}
+
+void DataSourceTabPage::Deactivate()
+{
+ commitPage();
+ vcl::OWizardPage::Deactivate();
+}
+
+void DataSourceTabPage::commitPage()
+{
+ commitPage(::vcl::WizardTypes::eFinish);
+}
+
+bool DataSourceTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ )
+{
+ //ranges may have been edited in the meanwhile (dirty is true in that case here)
+ if( isValid() )
+ {
+ updateModelFromControl();
+ return true; //return false if this page should not be left
+ }
+ else
+ return false;
+}
+
+bool DataSourceTabPage::isRangeFieldContentValid(weld::Entry& rEdit )
+{
+ OUString aRange(rEdit.get_text());
+ bool bIsValid = aRange.isEmpty() ||
+ m_rDialogModel.getRangeSelectionHelper()->verifyCellRange(aRange);
+ rEdit.set_message_type(bIsValid ? weld::EntryMessageType::Normal : weld::EntryMessageType::Error);
+ return bIsValid;
+}
+
+bool DataSourceTabPage::isValid()
+{
+ bool bRoleRangeValid = true;
+ bool bCategoriesRangeValid = true;
+ bool bHasSelectedEntry = (m_xLB_SERIES->get_selected_index() != -1);
+
+ if (bHasSelectedEntry)
+ bRoleRangeValid = isRangeFieldContentValid(*m_xEDT_RANGE);
+ if (m_xEDT_CATEGORIES->get_sensitive())
+ bCategoriesRangeValid = isRangeFieldContentValid( *m_xEDT_CATEGORIES );
+ bool bValid = ( bRoleRangeValid && bCategoriesRangeValid );
+
+ if( m_pTabPageNotifiable )
+ {
+ if( bValid )
+ m_pTabPageNotifiable->setValidPage( this );
+ else
+ m_pTabPageNotifiable->setInvalidPage( this );
+ }
+
+ return bValid;
+}
+
+void DataSourceTabPage::setDirty()
+{
+ m_bIsDirty = true;
+}
+
+void DataSourceTabPage::updateControlsFromDialogModel()
+{
+ // series
+ fillSeriesListBox();
+ SeriesSelectionChangedHdl(*m_xLB_SERIES);
+
+ // categories
+ m_xEDT_CATEGORIES->set_text(m_rDialogModel.getCategoriesRange());
+
+ updateControlState();
+}
+
+void DataSourceTabPage::fillSeriesListBox()
+{
+ rtl::Reference< DataSeries > xSelected;
+ SeriesEntry* pEntry = nullptr;
+ int nEntry = m_xLB_SERIES->get_selected_index();
+ if (nEntry != -1)
+ {
+ pEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
+ xSelected = pEntry->m_xDataSeries;
+ }
+
+ bool bHasSelectedEntry = (pEntry != nullptr);
+ int nSelectedEntry = -1;
+
+ m_xLB_SERIES->freeze();
+ m_xLB_SERIES->clear();
+
+ std::vector< DialogModel::tSeriesWithChartTypeByName > aSeries(
+ m_rDialogModel.getAllDataSeriesWithLabel() );
+
+ sal_Int32 nUnnamedSeriesIndex = 1;
+ nEntry = 0;
+ for (auto const& series : aSeries)
+ {
+ OUString aLabel(series.first);
+ if (aLabel.isEmpty())
+ {
+ if( nUnnamedSeriesIndex > 1 )
+ {
+ OUString aResString(::chart::SchResId( STR_DATA_UNNAMED_SERIES_WITH_INDEX ));
+
+ // replace index of unnamed series
+ static constexpr OUString aReplacementStr( u"%NUMBER"_ustr );
+ sal_Int32 nIndex = aResString.indexOf( aReplacementStr );
+ if( nIndex != -1 )
+ aLabel = aResString.replaceAt(
+ nIndex, aReplacementStr.getLength(),
+ OUString::number(nUnnamedSeriesIndex));
+ }
+ if( aLabel.isEmpty() )
+ aLabel = ::chart::SchResId( STR_DATA_UNNAMED_SERIES );
+
+ ++nUnnamedSeriesIndex;
+ }
+
+ m_aEntries.emplace_back(new SeriesEntry);
+ pEntry = m_aEntries.back().get();
+ pEntry->m_xDataSeries = series.second.first;
+ pEntry->m_xChartType = series.second.second;
+ m_xLB_SERIES->append(weld::toId(pEntry), aLabel);
+ if (bHasSelectedEntry && series.second.first == xSelected)
+ nSelectedEntry = nEntry;
+ ++nEntry;
+ }
+
+ m_xLB_SERIES->thaw();
+
+ if (bHasSelectedEntry && nSelectedEntry != -1)
+ m_xLB_SERIES->select(nSelectedEntry);
+}
+
+void DataSourceTabPage::fillRoleListBox()
+{
+ int nSeriesEntry = m_xLB_SERIES->get_selected_index();
+ SeriesEntry* pSeriesEntry = nullptr;
+ if (nSeriesEntry != -1)
+ pSeriesEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry));
+ bool bHasSelectedEntry = (pSeriesEntry != nullptr);
+
+ int nRoleIndex = m_xLB_ROLE->get_selected_index();
+ if (!bHasSelectedEntry)
+ return;
+
+ DialogModel::tRolesWithRanges aRoles(
+ DialogModel::getRolesWithRanges(
+ pSeriesEntry->m_xDataSeries,
+ lcl_GetSequenceNameForLabel( pSeriesEntry ),
+ pSeriesEntry->m_xChartType ));
+
+ // fill role list
+ m_xLB_ROLE->freeze();
+ m_xLB_ROLE->clear();
+
+ for (auto const& elemRole : aRoles)
+ {
+ InsertRoleLBEntry(elemRole.first, elemRole.second);
+ }
+
+ m_xLB_ROLE->thaw();
+
+ // series may contain no roles, check listbox size before selecting entries
+ if (m_xLB_ROLE->n_children() > 0)
+ {
+ if (nRoleIndex == -1 || nRoleIndex >= m_xLB_ROLE->n_children())
+ nRoleIndex = 0;
+ m_xLB_ROLE->select(nRoleIndex);
+ }
+}
+
+void DataSourceTabPage::updateControlState()
+{
+ int nSeriesEntry = m_xLB_SERIES->get_selected_index();
+ bool bHasSelectedSeries = nSeriesEntry != -1;
+ bool bHasValidRole = false;
+ bool bHasRangeChooser = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection();
+
+ if( bHasSelectedSeries )
+ {
+ int nRoleEntry = m_xLB_ROLE->get_selected_index();
+ bHasValidRole = nRoleEntry != -1;
+ }
+
+ m_xBTN_ADD->set_sensitive(true);
+ m_xBTN_REMOVE->set_sensitive(bHasSelectedSeries);
+
+ m_xBTN_UP->set_sensitive(bHasSelectedSeries && (nSeriesEntry != 0));
+ m_xBTN_DOWN->set_sensitive(bHasSelectedSeries && (nSeriesEntry != m_xLB_SERIES->n_children() - 1));
+
+ bool bHasCategories = m_rDialogModel.isCategoryDiagram();
+
+ m_xFT_DATALABELS->set_visible(!bHasCategories);
+ m_xFT_CATEGORIES->set_visible( bHasCategories);
+ bool bShowIB = bHasRangeChooser;
+
+ m_xIMB_RANGE_CAT->set_visible(bShowIB);
+
+ m_xFT_ROLE->set_sensitive(bHasSelectedSeries);
+ m_xLB_ROLE->set_sensitive(bHasSelectedSeries);
+
+ m_xFT_RANGE->set_sensitive(bHasValidRole);
+ m_xEDT_RANGE->set_sensitive(bHasValidRole);
+
+ m_xFT_SERIES->set_sensitive(true);
+ m_xLB_SERIES->set_sensitive(true);
+
+ m_xIMB_RANGE_MAIN->set_visible(bShowIB);
+
+ isValid();
+}
+
+IMPL_LINK_NOARG(DataSourceTabPage, SeriesSelectionChangedHdl, weld::TreeView&, void)
+{
+ m_rDialogModel.startControllerLockTimer();
+ if (m_xLB_SERIES->get_selected_index() != -1)
+ {
+ fillRoleListBox();
+ RoleSelectionChangedHdl(*m_xLB_ROLE);
+ }
+ updateControlState();
+}
+
+IMPL_LINK_NOARG(DataSourceTabPage, RoleSelectionChangedHdl, weld::TreeView&, void)
+{
+ m_rDialogModel.startControllerLockTimer();
+ int nEntry = m_xLB_ROLE->get_selected_index();
+ if (nEntry == -1)
+ return;
+
+ OUString aSelectedRoleUI = lcl_GetSelectedRole( *m_xLB_ROLE, true );
+ OUString aSelectedRange = lcl_GetSelectedRolesRange( *m_xLB_ROLE );
+
+ // replace role in fixed text label
+ static constexpr OUString aReplacementStr( u"%VALUETYPE"_ustr );
+ sal_Int32 nIndex = m_aFixedTextRange.indexOf( aReplacementStr );
+ if( nIndex != -1 )
+ {
+ m_xFT_RANGE->set_label(
+ m_aFixedTextRange.replaceAt(
+ nIndex, aReplacementStr.getLength(), aSelectedRoleUI ));
+ }
+
+ m_xEDT_RANGE->set_text(aSelectedRange);
+ isValid();
+}
+
+IMPL_LINK_NOARG(DataSourceTabPage, MainRangeButtonClickedHdl, weld::Button&, void)
+{
+ OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
+ m_pCurrentRangeChoosingField = m_xEDT_RANGE.get();
+ if (!m_xEDT_RANGE->get_text().isEmpty() &&
+ !updateModelFromControl( m_pCurrentRangeChoosingField))
+ return;
+
+ int nEntry = m_xLB_SERIES->get_selected_index();
+ bool bHasSelectedEntry = (nEntry != -1);
+
+ OUString aSelectedRolesRange = lcl_GetSelectedRolesRange(*m_xLB_ROLE);
+
+ if (bHasSelectedEntry && (m_xLB_ROLE->get_selected_index() != -1))
+ {
+ OUString aUIStr(SchResId(STR_DATA_SELECT_RANGE_FOR_SERIES));
+
+ // replace role
+ OUString aReplacement( "%VALUETYPE" );
+ sal_Int32 nIndex = aUIStr.indexOf( aReplacement );
+ if( nIndex != -1 )
+ {
+ aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(),
+ lcl_GetSelectedRole( *m_xLB_ROLE, true ));
+ }
+ // replace series name
+ aReplacement = "%SERIESNAME";
+ nIndex = aUIStr.indexOf( aReplacement );
+ if( nIndex != -1 )
+ {
+ aUIStr = aUIStr.replaceAt(nIndex, aReplacement.getLength(),
+ m_xLB_SERIES->get_text(nEntry));
+ }
+
+ lcl_enableRangeChoosing(true, m_pDialogController);
+ m_rDialogModel.getRangeSelectionHelper()->chooseRange( aSelectedRolesRange, aUIStr, *this );
+ }
+ else
+ m_pCurrentRangeChoosingField = nullptr;
+}
+
+IMPL_LINK_NOARG(DataSourceTabPage, CategoriesRangeButtonClickedHdl, weld::Button&, void)
+{
+ OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
+ m_pCurrentRangeChoosingField = m_xEDT_CATEGORIES.get();
+ if( !m_xEDT_CATEGORIES->get_text().isEmpty() &&
+ ! updateModelFromControl( m_pCurrentRangeChoosingField ))
+ return;
+
+ OUString aStr(SchResId(m_xFT_CATEGORIES->get_visible() ? STR_DATA_SELECT_RANGE_FOR_CATEGORIES : STR_DATA_SELECT_RANGE_FOR_DATALABELS));
+ lcl_enableRangeChoosing(true, m_pDialogController);
+ m_rDialogModel.getRangeSelectionHelper()->chooseRange(
+ m_rDialogModel.getCategoriesRange(), aStr, *this );
+}
+
+IMPL_LINK_NOARG(DataSourceTabPage, AddButtonClickedHdl, weld::Button&, void)
+{
+ m_rDialogModel.startControllerLockTimer();
+ int nEntry = m_xLB_SERIES->get_selected_index();
+ rtl::Reference< DataSeries > xSeriesToInsertAfter;
+ rtl::Reference< ChartType > xChartTypeForNewSeries;
+ if( m_pTemplateProvider )
+ m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate());
+
+ if (nEntry != -1)
+ {
+ ::chart::SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
+ xSeriesToInsertAfter = pEntry->m_xDataSeries;
+ xChartTypeForNewSeries = pEntry->m_xChartType;
+ }
+ else
+ {
+ std::vector< rtl::Reference< ChartType > > aCntVec(
+ m_rDialogModel.getAllDataSeriesContainers());
+ if( ! aCntVec.empty())
+ xChartTypeForNewSeries = aCntVec.front();
+ }
+ OSL_ENSURE( xChartTypeForNewSeries.is(), "Cannot insert new series" );
+
+ m_rDialogModel.insertSeriesAfter( xSeriesToInsertAfter, xChartTypeForNewSeries );
+ setDirty();
+
+ fillSeriesListBox();
+ // note the box was cleared and refilled, so nEntry is invalid now
+
+ int nSelEntry = m_xLB_SERIES->get_selected_index();
+ if (nSelEntry != -1)
+ {
+ ++nSelEntry;
+ if (nSelEntry < m_xLB_SERIES->n_children())
+ m_xLB_SERIES->select(nSelEntry);
+ }
+ SeriesSelectionChangedHdl(*m_xLB_SERIES);
+}
+
+IMPL_LINK_NOARG(DataSourceTabPage, RemoveButtonClickedHdl, weld::Button&, void)
+{
+ m_rDialogModel.startControllerLockTimer();
+ int nEntry = m_xLB_SERIES->get_selected_index();
+ if (nEntry == -1)
+ return;
+
+ SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
+ rtl::Reference< DataSeries > xNewSelSeries;
+ SeriesEntry * pNewSelEntry = nullptr;
+ if (nEntry + 1 < m_xLB_SERIES->n_children())
+ pNewSelEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry + 1));
+ else if (nEntry > 0)
+ pNewSelEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry - 1));
+ if (pNewSelEntry)
+ xNewSelSeries = pNewSelEntry->m_xDataSeries;
+
+ m_rDialogModel.deleteSeries( pEntry->m_xDataSeries, pEntry->m_xChartType );
+ setDirty();
+
+ m_xLB_SERIES->remove(nEntry);
+ fillSeriesListBox();
+
+ // select previous or next series
+ if (xNewSelSeries.is())
+ {
+ for (int i = 0; i < m_xLB_SERIES->n_children(); ++i)
+ {
+ pEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(i));
+ if (pEntry->m_xDataSeries == xNewSelSeries)
+ {
+ m_xLB_SERIES->select(i);
+ break;
+ }
+ }
+ }
+ SeriesSelectionChangedHdl(*m_xLB_SERIES);
+}
+
+IMPL_LINK_NOARG(DataSourceTabPage, UpButtonClickedHdl, weld::Button&, void)
+{
+ m_rDialogModel.startControllerLockTimer();
+
+ int nEntry = m_xLB_SERIES->get_selected_index();
+ SeriesEntry* pEntry = nullptr;
+ if (nEntry != -1)
+ pEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
+
+ bool bHasSelectedEntry = (pEntry != nullptr);
+
+ if (bHasSelectedEntry)
+ {
+ m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MoveDirection::Up );
+ setDirty();
+ fillSeriesListBox();
+ SeriesSelectionChangedHdl(*m_xLB_SERIES);
+ }
+}
+
+IMPL_LINK_NOARG(DataSourceTabPage, DownButtonClickedHdl, weld::Button&, void)
+{
+ m_rDialogModel.startControllerLockTimer();
+
+ int nEntry = m_xLB_SERIES->get_selected_index();
+ SeriesEntry* pEntry = nullptr;
+ if (nEntry != -1)
+ pEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
+
+ bool bHasSelectedEntry = (pEntry != nullptr);
+
+ if (bHasSelectedEntry)
+ {
+ m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MoveDirection::Down );
+ setDirty();
+ fillSeriesListBox();
+ SeriesSelectionChangedHdl(*m_xLB_SERIES);
+ }
+}
+
+IMPL_LINK(DataSourceTabPage, RangeModifiedHdl, weld::Entry&, rEdit, void)
+{
+ // note: isValid sets the color of the edit field
+ if( isRangeFieldContentValid( rEdit ))
+ {
+ setDirty();
+ updateModelFromControl( &rEdit );
+ if (&rEdit == m_xEDT_RANGE.get())
+ {
+ if( ! lcl_UpdateCurrentSeriesName( *m_xLB_SERIES ))
+ fillSeriesListBox();
+ }
+ }
+
+ // enable/disable OK button
+ isValid();
+}
+
+void DataSourceTabPage::listeningFinished(
+ const OUString & rNewRange )
+{
+ // rNewRange becomes invalid after removing the listener
+ OUString aRange( rNewRange );
+
+ m_rDialogModel.startControllerLockTimer();
+
+ // stop listening
+ m_rDialogModel.getRangeSelectionHelper()->stopRangeListening();
+
+ // change edit field
+ if( m_pCurrentRangeChoosingField )
+ {
+ m_pCurrentRangeChoosingField->set_text(aRange);
+ m_pCurrentRangeChoosingField->grab_focus();
+ }
+
+ if (m_pCurrentRangeChoosingField == m_xEDT_RANGE.get())
+ {
+ m_xEDT_RANGE->set_text(aRange);
+ setDirty();
+ }
+ else if (m_pCurrentRangeChoosingField == m_xEDT_CATEGORIES.get())
+ {
+ m_xEDT_CATEGORIES->set_text(aRange);
+ setDirty();
+ }
+
+ updateModelFromControl(m_pCurrentRangeChoosingField);
+ if (!lcl_UpdateCurrentSeriesName(*m_xLB_SERIES))
+ fillSeriesListBox();
+
+ m_pCurrentRangeChoosingField = nullptr;
+
+ updateControlState();
+ lcl_enableRangeChoosing(false, m_pDialogController);
+}
+
+void DataSourceTabPage::disposingRangeSelection()
+{
+ m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false );
+}
+
+bool DataSourceTabPage::updateModelFromControl(const weld::Entry* pField)
+{
+ if (!m_bIsDirty)
+ return true;
+
+ ControllerLockGuardUNO aLockedControllers( m_rDialogModel.getChartModel() );
+
+ // @todo: validity check of field content
+ bool bResult = true;
+ bool bAll = (pField == nullptr);
+ Reference< data::XDataProvider > xDataProvider( m_rDialogModel.getDataProvider());
+
+ if (bAll || (pField == m_xEDT_CATEGORIES.get()))
+ {
+ uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( m_rDialogModel.getCategories() );
+ if( xDataProvider.is())
+ {
+ OUString aRange(m_xEDT_CATEGORIES->get_text());
+ if (!aRange.isEmpty())
+ {
+ // create or change categories
+ if( !xLabeledSeq.is())
+ {
+ xLabeledSeq = DataSourceHelper::createLabeledDataSequence();
+ m_rDialogModel.setCategories( xLabeledSeq );
+ }
+ try
+ {
+ xLabeledSeq->setValues( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
+ }
+ catch( const uno::Exception & )
+ {
+ // should work as validation should have happened before
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ else if( xLabeledSeq.is())
+ {
+ // clear existing categories
+ xLabeledSeq.clear();
+ m_rDialogModel.setCategories( xLabeledSeq );
+ }
+ }
+ }
+
+ int nSeriesEntry = m_xLB_SERIES->get_selected_index();
+ SeriesEntry* pSeriesEntry = nullptr;
+ if (nSeriesEntry != -1)
+ pSeriesEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry));
+ bool bHasSelectedEntry = (pSeriesEntry != nullptr);
+
+ if( bHasSelectedEntry )
+ {
+ if( bAll || (pField == m_xEDT_RANGE.get()) )
+ {
+ try
+ {
+ OUString aSelectedRole = lcl_GetSelectedRole( *m_xLB_ROLE );
+ OUString aRange(m_xEDT_RANGE->get_text());
+ OUString aSequenceRole( aSelectedRole );
+ bool bIsLabel = (aSequenceRole == lcl_aLabelRole );
+ OUString aSequenceNameForLabel( lcl_GetSequenceNameForLabel( pSeriesEntry ));
+
+ if( bIsLabel )
+ aSequenceRole = aSequenceNameForLabel;
+
+ uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq =
+ DataSeriesHelper::getDataSequenceByRole( pSeriesEntry->m_xDataSeries, aSequenceRole );
+
+ if( xDataProvider.is())
+ {
+ if( bIsLabel )
+ {
+ if( ! xLabeledSeq.is())
+ {
+ // check if there is already an "orphan" label sequence
+ xLabeledSeq = lcl_findLSequenceWithOnlyLabel( pSeriesEntry->m_xDataSeries );
+ if( ! xLabeledSeq.is())
+ {
+ // no corresponding labeled data sequence for label found
+ xLabeledSeq = DataSourceHelper::createLabeledDataSequence();
+ lcl_addLSequenceToDataSource( xLabeledSeq, pSeriesEntry->m_xDataSeries );
+ }
+ }
+ if( xLabeledSeq.is())
+ {
+ if( !aRange.isEmpty())
+ {
+ Reference< data::XDataSequence > xNewSeq;
+ try
+ {
+ xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
+ }
+ catch( const uno::Exception & )
+ {
+ // should work as validation should have happened before
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ if( xNewSeq.is())
+ {
+ // update range name by the full string provided
+ // by the data provider. E.g. "a1" might become
+ // "$Sheet1.$A$1"
+ aRange = xNewSeq->getSourceRangeRepresentation();
+ Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
+ xProp->setPropertyValue( "Role" , uno::Any( lcl_aLabelRole ));
+
+ //Labels should always include hidden cells, regardless of the setting chosen
+ xProp->setPropertyValue( "IncludeHiddenCells", uno::Any(true));
+ xLabeledSeq->setLabel( xNewSeq );
+ }
+ }
+ else
+ {
+ xLabeledSeq->setLabel( Reference< data::XDataSequence >());
+ }
+ }
+ }
+ else
+ {
+ if( !aRange.isEmpty())
+ {
+ Reference< data::XDataSequence > xNewSeq;
+ try
+ {
+ xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
+ }
+ catch( const uno::Exception & )
+ {
+ // should work as validation should have happened before
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ if( xNewSeq.is())
+ {
+ // update range name by the full string provided
+ // by the data provider. E.g. "a1:e1" might become
+ // "$Sheet1.$A$1:$E$1"
+ aRange = xNewSeq->getSourceRangeRepresentation();
+
+ Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
+ xProp->setPropertyValue( "Role" , uno::Any( aSelectedRole ));
+ if( !xLabeledSeq.is())
+ {
+ if( aSelectedRole == aSequenceNameForLabel )
+ xLabeledSeq = lcl_findLSequenceWithOnlyLabel( pSeriesEntry->m_xDataSeries );
+ if( ! xLabeledSeq.is())
+ {
+ xLabeledSeq = DataSourceHelper::createLabeledDataSequence();
+ lcl_addLSequenceToDataSource( xLabeledSeq, pSeriesEntry->m_xDataSeries );
+ }
+ }
+ xLabeledSeq->setValues( xNewSeq );
+ }
+ }
+ }
+ }
+
+ lcl_UpdateCurrentRange( *m_xLB_ROLE, aSelectedRole, aRange );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ bResult = false;
+ }
+ }
+ }
+
+ // update View
+ // @todo remove this when automatic view updates from calc, writer and own data sequences are available
+ if( bResult )
+ {
+ try
+ {
+ if( m_rDialogModel.getChartModel() )
+ m_rDialogModel.getChartModel()->setModified( true );
+ const DialogModelTimeBasedInfo& rInfo = m_rDialogModel.getTimeBasedInfo();
+ if(rInfo.bTimeBased)
+ {
+ m_rDialogModel.setTimeBasedRange(rInfo.bTimeBased, rInfo.nStart, rInfo.nEnd);
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return bResult;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_DataSource.hxx b/chart2/source/controller/dialogs/tp_DataSource.hxx
new file mode 100644
index 0000000000..40219d917f
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_DataSource.hxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <DataSeries.hxx>
+#include <ChartType.hxx>
+
+#include <vcl/wizardmachine.hxx>
+
+#include <RangeSelectionListener.hxx>
+
+namespace com::sun::star::chart2 { class XChartType; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+
+namespace chart { class TabPageNotifiable; }
+
+namespace chart
+{
+class ChartType;
+class ChartTypeTemplateProvider;
+class DataSeries;
+class DialogModel;
+
+class SeriesEntry
+{
+public:
+ OUString m_sRole;
+
+ /// the corresponding data series
+ rtl::Reference< ::chart::DataSeries > m_xDataSeries;
+
+ /// the chart type that contains the series (via XDataSeriesContainer)
+ rtl::Reference< ::chart::ChartType > m_xChartType;
+};
+
+class DataSourceTabPage final :
+ public ::vcl::OWizardPage,
+ public RangeSelectionListenerParent
+{
+public:
+ explicit DataSourceTabPage(weld::Container* pPage, weld::DialogController* pController,
+ DialogModel & rDialogModel,
+ ChartTypeTemplateProvider* pTemplateProvider,
+ bool bHideDescription = false);
+ virtual ~DataSourceTabPage() override;
+
+ virtual void Activate() override;
+
+ void commitPage();
+
+private:
+ // OWizardPage
+ virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason eReason ) override;
+
+ //TabPage
+ virtual void Deactivate() override;
+
+ virtual void initializePage() override;
+
+ DECL_LINK( SeriesSelectionChangedHdl, weld::TreeView&, void );
+ DECL_LINK( RoleSelectionChangedHdl, weld::TreeView&, void );
+ DECL_LINK( MainRangeButtonClickedHdl, weld::Button&, void );
+ DECL_LINK( CategoriesRangeButtonClickedHdl, weld::Button&, void );
+ DECL_LINK( AddButtonClickedHdl, weld::Button&, void );
+ DECL_LINK( RemoveButtonClickedHdl, weld::Button&, void );
+ DECL_LINK( RangeModifiedHdl, weld::Entry&, void );
+ DECL_LINK( UpButtonClickedHdl, weld::Button&, void );
+ DECL_LINK( DownButtonClickedHdl, weld::Button&, void );
+
+ // ____ RangeSelectionListenerParent ____
+ virtual void listeningFinished( const OUString & rNewRange ) override;
+ virtual void disposingRangeSelection() override;
+
+ void InsertRoleLBEntry(const OUString& rRole, const OUString& rRange);
+
+ void updateControlState();
+
+ /** updates the internal data according to the content of the given edit
+ field. If pField is 0, all relevant fields are used
+
+ @return
+ <TRUE/> if the text from the field is a valid format to the internal
+ data was valid
+ */
+ bool updateModelFromControl(const weld::Entry* pField = nullptr);
+
+ /** @return </sal_True>, if the edit field contains a valid range entry. If no
+ XCellRangesAccess can be obtained, </sal_False> is returned.
+ */
+ bool isRangeFieldContentValid(weld::Entry& rEdit);
+
+ /** @return </sal_True>, if the tab-page is in a consistent (committable) state
+ */
+ bool isValid();
+ void setDirty();
+
+ void updateControlsFromDialogModel();
+
+ void fillSeriesListBox();
+ void fillRoleListBox();
+
+ std::vector<std::unique_ptr<SeriesEntry>> m_aEntries;
+
+ OUString m_aFixedTextRange;
+
+ ChartTypeTemplateProvider * m_pTemplateProvider;
+ DialogModel & m_rDialogModel;
+ weld::Entry* m_pCurrentRangeChoosingField;
+ bool m_bIsDirty;
+
+ TabPageNotifiable * m_pTabPageNotifiable;
+
+ std::unique_ptr<weld::Label> m_xFT_CAPTION;
+ std::unique_ptr<weld::Label> m_xFT_SERIES;
+ std::unique_ptr<weld::TreeView> m_xLB_SERIES;
+ std::unique_ptr<weld::Button> m_xBTN_ADD;
+ std::unique_ptr<weld::Button> m_xBTN_REMOVE;
+ std::unique_ptr<weld::Button> m_xBTN_UP;
+ std::unique_ptr<weld::Button> m_xBTN_DOWN;
+ std::unique_ptr<weld::Label> m_xFT_ROLE;
+ std::unique_ptr<weld::TreeView> m_xLB_ROLE;
+ std::unique_ptr<weld::Label> m_xFT_RANGE;
+ std::unique_ptr<weld::Entry> m_xEDT_RANGE;
+ std::unique_ptr<weld::Button> m_xIMB_RANGE_MAIN;
+ std::unique_ptr<weld::Label> m_xFT_CATEGORIES;
+ std::unique_ptr<weld::Label> m_xFT_DATALABELS;//used for xy charts
+ std::unique_ptr<weld::Entry> m_xEDT_CATEGORIES;
+ std::unique_ptr<weld::Button> m_xIMB_RANGE_CAT;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_DataTable.cxx b/chart2/source/controller/dialogs/tp_DataTable.cxx
new file mode 100644
index 0000000000..e6982b4a50
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_DataTable.cxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "tp_DataTable.hxx"
+
+namespace chart
+{
+DataTableTabPage::DataTableTabPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_DataTable.ui", "DataTableTabPage",
+ &rInAttrs)
+ , m_aDataTablePropertiesResources(*m_xBuilder)
+{
+}
+
+DataTableTabPage::~DataTableTabPage() = default;
+
+std::unique_ptr<SfxTabPage> DataTableTabPage::Create(weld::Container* pPage,
+ weld::DialogController* pController,
+ const SfxItemSet* rAttrs)
+{
+ return std::make_unique<DataTableTabPage>(pPage, pController, *rAttrs);
+}
+
+bool DataTableTabPage::FillItemSet(SfxItemSet* pOutAttrs)
+{
+ return m_aDataTablePropertiesResources.writeToItemSet(*pOutAttrs);
+}
+
+void DataTableTabPage::Reset(const SfxItemSet* pInAttrs)
+{
+ m_aDataTablePropertiesResources.initFromItemSet(*pInAttrs);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_DataTable.hxx b/chart2/source/controller/dialogs/tp_DataTable.hxx
new file mode 100644
index 0000000000..00ab64cf89
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_DataTable.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <res_DataTableProperties.hxx>
+
+namespace chart
+{
+/** Tab page for the data table properties */
+class DataTableTabPage : public SfxTabPage
+{
+private:
+ DataTablePropertiesResources m_aDataTablePropertiesResources;
+
+public:
+ DataTableTabPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& rInAttrs);
+ virtual ~DataTableTabPage() override;
+
+ static std::unique_ptr<SfxTabPage>
+ Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs);
+
+ virtual bool FillItemSet(SfxItemSet* rOutAttrs) override;
+ virtual void Reset(const SfxItemSet* rInAttrs) override;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_ErrorBars.cxx b/chart2/source/controller/dialogs/tp_ErrorBars.cxx
new file mode 100644
index 0000000000..927bf1130a
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_ErrorBars.cxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_ErrorBars.hxx"
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+ErrorBarsTabPage::ErrorBarsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_ErrorBars.ui", "tp_ErrorBars", &rInAttrs)
+ , m_aErrorBarResources(m_xBuilder.get(), pController, rInAttrs, /* bNoneAvailable = */ false)
+{
+}
+
+std::unique_ptr<SfxTabPage> ErrorBarsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs)
+{
+ return std::make_unique<ErrorBarsTabPage>(pPage, pController, *rOutAttrs);
+}
+
+bool ErrorBarsTabPage::FillItemSet( SfxItemSet* rOutAttrs )
+{
+ m_aErrorBarResources.FillItemSet( *rOutAttrs );
+ return true;
+}
+
+void ErrorBarsTabPage::Reset( const SfxItemSet* rInAttrs )
+{
+ m_aErrorBarResources.Reset( *rInAttrs );
+}
+
+void ErrorBarsTabPage::SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth )
+{
+ m_aErrorBarResources.SetAxisMinorStepWidthForErrorBarDecimals( fMinorStepWidth );
+}
+
+void ErrorBarsTabPage::SetErrorBarType( ErrorBarResources::tErrorBarType eNewType )
+{
+ m_aErrorBarResources.SetErrorBarType( eNewType );
+}
+
+void ErrorBarsTabPage::SetChartDocumentForRangeChoosing(
+ const rtl::Reference<::chart::ChartModel> & xChartDocument )
+{
+ m_aErrorBarResources.SetChartDocumentForRangeChoosing( xChartDocument );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_ErrorBars.hxx b/chart2/source/controller/dialogs/tp_ErrorBars.hxx
new file mode 100644
index 0000000000..159de22b0d
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_ErrorBars.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <res_ErrorBar.hxx>
+
+#include <sfx2/tabdlg.hxx>
+#include <rtl/ref.hxx>
+
+namespace chart
+{
+class ChartModel;
+
+class ErrorBarsTabPage : public SfxTabPage
+{
+public:
+ ErrorBarsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs);
+
+ void SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth );
+ void SetErrorBarType( ErrorBarResources::tErrorBarType eNewType );
+ void SetChartDocumentForRangeChoosing(
+ const rtl::Reference<::chart::ChartModel> & xChartDocument );
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs );
+ virtual bool FillItemSet( SfxItemSet* rOutAttrs ) override;
+ virtual void Reset( const SfxItemSet* rInAttrs ) override;
+
+private:
+ ErrorBarResources m_aErrorBarResources;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_LegendPosition.cxx b/chart2/source/controller/dialogs/tp_LegendPosition.cxx
new file mode 100644
index 0000000000..21a889bf85
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_LegendPosition.cxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_LegendPosition.hxx"
+#include <res_LegendPosition.hxx>
+#include <TextDirectionListBox.hxx>
+#include <chartview/ChartSfxItemIds.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/frmdiritem.hxx>
+
+namespace chart
+{
+
+SchLegendPosTabPage::SchLegendPosTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_LegendPosition.ui", "tp_LegendPosition", &rInAttrs)
+ , m_aLegendPositionResources(*m_xBuilder)
+ , m_aLbTextDirection(m_xBuilder->weld_combo_box("LB_LEGEND_TEXTDIR"))
+ , m_xCBLegendNoOverlay(m_xBuilder->weld_check_button("CB_NO_OVERLAY"))
+{
+}
+
+SchLegendPosTabPage::~SchLegendPosTabPage()
+{
+}
+
+std::unique_ptr<SfxTabPage> SchLegendPosTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs)
+{
+ return std::make_unique<SchLegendPosTabPage>(pPage, pController, *rOutAttrs);
+}
+
+bool SchLegendPosTabPage::FillItemSet(SfxItemSet* rOutAttrs)
+{
+ m_aLegendPositionResources.writeToItemSet(*rOutAttrs);
+
+ if (m_aLbTextDirection.get_active() != -1)
+ rOutAttrs->Put(SvxFrameDirectionItem(m_aLbTextDirection.get_active_id(), EE_PARA_WRITINGDIR));
+
+ if (m_xCBLegendNoOverlay->get_visible())
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_LEGEND_NO_OVERLAY, m_xCBLegendNoOverlay->get_active()));
+
+ return true;
+}
+
+void SchLegendPosTabPage::Reset(const SfxItemSet* rInAttrs)
+{
+ m_aLegendPositionResources.initFromItemSet(*rInAttrs);
+
+ if( const SvxFrameDirectionItem* pDirectionItem = rInAttrs->GetItemIfSet( EE_PARA_WRITINGDIR ) )
+ m_aLbTextDirection.set_active_id( pDirectionItem->GetValue() );
+
+ if (const SfxBoolItem* pNoOverlayItem = rInAttrs->GetItemIfSet(SCHATTR_LEGEND_NO_OVERLAY))
+ {
+ bool bVal = pNoOverlayItem->GetValue();
+ m_xCBLegendNoOverlay->set_active(bVal);
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_LegendPosition.hxx b/chart2/source/controller/dialogs/tp_LegendPosition.hxx
new file mode 100644
index 0000000000..7a444694c3
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_LegendPosition.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+#include <res_LegendPosition.hxx>
+#include <TextDirectionListBox.hxx>
+#include <optional>
+
+namespace chart
+{
+
+class SchLegendPosTabPage : public SfxTabPage
+{
+private:
+
+ LegendPositionResources m_aLegendPositionResources;
+ TextDirectionListBox m_aLbTextDirection;
+ std::unique_ptr<weld::CheckButton> m_xCBLegendNoOverlay;
+
+public:
+ SchLegendPosTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs);
+ virtual ~SchLegendPosTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs);
+ virtual bool FillItemSet(SfxItemSet* rOutAttrs) override;
+ virtual void Reset(const SfxItemSet* rInAttrs) override;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_PointGeometry.cxx b/chart2/source/controller/dialogs/tp_PointGeometry.cxx
new file mode 100644
index 0000000000..7c2c4d942e
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_PointGeometry.cxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_PointGeometry.hxx"
+#include <res_BarGeometry.hxx>
+
+#include <chartview/ChartSfxItemIds.hxx>
+
+#include <svl/intitem.hxx>
+#include <svx/svx3ditems.hxx>
+
+namespace chart
+{
+
+SchLayoutTabPage::SchLayoutTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_ChartType.ui", "tp_ChartType", &rInAttrs)
+{
+ m_pGeometryResources.reset(new BarGeometryResources(m_xBuilder.get()));
+}
+
+SchLayoutTabPage::~SchLayoutTabPage()
+{
+ m_pGeometryResources.reset();
+}
+
+std::unique_ptr<SfxTabPage> SchLayoutTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs)
+{
+ return std::make_unique<SchLayoutTabPage>(pPage, pController, *rOutAttrs);
+}
+
+bool SchLayoutTabPage::FillItemSet(SfxItemSet* rOutAttrs)
+{
+ int nShape = m_pGeometryResources ? m_pGeometryResources->get_selected_index() : -1;
+ if (nShape != -1)
+ {
+ tools::Long nSegs=32;
+
+ if (nShape==CHART_SHAPE3D_PYRAMID)
+ nSegs=4;
+
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_STYLE_SHAPE,nShape));
+ rOutAttrs->Put(makeSvx3DHorizontalSegmentsItem(nSegs));
+ }
+ return true;
+}
+
+void SchLayoutTabPage::Reset(const SfxItemSet* rInAttrs)
+{
+ if (const SfxInt32Item* pShapeItem = rInAttrs->GetItemIfSet(SCHATTR_STYLE_SHAPE))
+ {
+ tools::Long nVal = pShapeItem->GetValue();
+ if(m_pGeometryResources)
+ {
+ m_pGeometryResources->select(static_cast<sal_uInt16>(nVal));
+ m_pGeometryResources->set_visible(true);
+ }
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_PointGeometry.hxx b/chart2/source/controller/dialogs/tp_PointGeometry.hxx
new file mode 100644
index 0000000000..326cc90259
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_PointGeometry.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+namespace chart
+{
+class BarGeometryResources;
+class SchLayoutTabPage : public SfxTabPage
+{
+public:
+ SchLayoutTabPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& rInAttrs);
+ virtual ~SchLayoutTabPage() override;
+
+ static std::unique_ptr<SfxTabPage>
+ Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs);
+ virtual bool FillItemSet(SfxItemSet* rOutAttrs) override;
+ virtual void Reset(const SfxItemSet* rInAttrs) override;
+
+private:
+ std::unique_ptr<BarGeometryResources> m_pGeometryResources;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_PolarOptions.cxx b/chart2/source/controller/dialogs/tp_PolarOptions.cxx
new file mode 100644
index 0000000000..ad7b2b6f0f
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_PolarOptions.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_PolarOptions.hxx"
+#include <chartview/ChartSfxItemIds.hxx>
+
+#include <svl/eitem.hxx>
+#include <svx/sdangitm.hxx>
+#include <officecfg/Office/Compatibility.hxx>
+
+namespace chart
+{
+
+PolarOptionsTabPage::PolarOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_PolarOptions.ui", "tp_PolarOptions", &rInAttrs)
+ , m_xCB_Clockwise(m_xBuilder->weld_check_button("CB_CLOCKWISE"))
+ , m_xFL_StartingAngle(m_xBuilder->weld_frame("frameANGLE"))
+ , m_xNF_StartingAngle(m_xBuilder->weld_metric_spin_button("NF_STARTING_ANGLE", FieldUnit::DEGREE))
+ , m_xFL_PlotOptions(m_xBuilder->weld_frame("framePLOT_OPTIONS"))
+ , m_xCB_IncludeHiddenCells(m_xBuilder->weld_check_button("CB_INCLUDE_HIDDEN_CELLS_POLAR"))
+ , m_xAngleDial(new svx::DialControl)
+ , m_xAngleDialWin(new weld::CustomWeld(*m_xBuilder, "CT_ANGLE_DIAL", *m_xAngleDial))
+{
+ m_xAngleDial->SetLinkedField(m_xNF_StartingAngle.get());
+}
+
+PolarOptionsTabPage::~PolarOptionsTabPage()
+{
+ m_xAngleDialWin.reset();
+ m_xAngleDial.reset();
+}
+
+std::unique_ptr<SfxTabPage> PolarOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs)
+{
+ return std::make_unique<PolarOptionsTabPage>(pPage, pController, *rOutAttrs);
+}
+
+bool PolarOptionsTabPage::FillItemSet( SfxItemSet* rOutAttrs )
+{
+ if (m_xAngleDialWin->get_visible())
+ {
+ rOutAttrs->Put(SdrAngleItem(SCHATTR_STARTING_ANGLE, m_xAngleDial->GetRotation()));
+ }
+
+ if( m_xCB_Clockwise->get_visible() )
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_CLOCKWISE,m_xCB_Clockwise->get_active()));
+
+ if (m_xCB_IncludeHiddenCells->get_visible())
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_INCLUDE_HIDDEN_CELLS, m_xCB_IncludeHiddenCells->get_active()));
+
+ return true;
+}
+
+void PolarOptionsTabPage::Reset(const SfxItemSet* rInAttrs)
+{
+ if (const SdrAngleItem* pAngleItem = rInAttrs->GetItemIfSet(SCHATTR_STARTING_ANGLE))
+ {
+ Degree100 nTmp = pAngleItem->GetValue();
+ m_xAngleDial->SetRotation( nTmp );
+ }
+ else
+ {
+ m_xFL_StartingAngle->hide();
+ }
+ // tdf#108059 Hide clockwise orientation checkbox in OOXML-heavy environments it would be useless anyways
+ const SfxBoolItem* pClockWiseItem = nullptr;
+ if (!officecfg::Office::Compatibility::View::ClockwisePieChartDirection::get() &&
+ (pClockWiseItem = rInAttrs->GetItemIfSet(SCHATTR_CLOCKWISE)))
+ {
+ bool bCheck = pClockWiseItem->GetValue();
+ m_xCB_Clockwise->set_active(bCheck);
+ }
+ else
+ {
+ m_xCB_Clockwise->hide();
+ }
+ if (const SfxBoolItem* pHiddenCellsItem = rInAttrs->GetItemIfSet(SCHATTR_INCLUDE_HIDDEN_CELLS))
+ {
+ bool bVal = pHiddenCellsItem->GetValue();
+ m_xCB_IncludeHiddenCells->set_active(bVal);
+ }
+ else
+ {
+ m_xFL_PlotOptions->hide();
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_PolarOptions.hxx b/chart2/source/controller/dialogs/tp_PolarOptions.hxx
new file mode 100644
index 0000000000..eba4018052
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_PolarOptions.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <svx/dialcontrol.hxx>
+
+namespace weld {
+ class CheckButton;
+ class CustomWeld;
+ class Frame;
+ class SpinButton;
+}
+
+namespace chart
+{
+
+class PolarOptionsTabPage : public SfxTabPage
+{
+
+public:
+ PolarOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs);
+ virtual ~PolarOptionsTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs);
+ virtual bool FillItemSet(SfxItemSet* rOutAttrs) override;
+ virtual void Reset(const SfxItemSet* rInAttrs) override;
+
+private:
+ std::unique_ptr<weld::CheckButton> m_xCB_Clockwise;
+ std::unique_ptr<weld::Frame> m_xFL_StartingAngle;
+ std::unique_ptr<weld::MetricSpinButton> m_xNF_StartingAngle;
+ std::unique_ptr<weld::Frame> m_xFL_PlotOptions;
+ std::unique_ptr<weld::CheckButton> m_xCB_IncludeHiddenCells;
+ std::unique_ptr<svx::DialControl> m_xAngleDial;
+ std::unique_ptr<weld::CustomWeld> m_xAngleDialWin;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_RangeChooser.cxx b/chart2/source/controller/dialogs/tp_RangeChooser.cxx
new file mode 100644
index 0000000000..a88f6a826e
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_RangeChooser.cxx
@@ -0,0 +1,380 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_RangeChooser.hxx"
+#include <DataSourceHelper.hxx>
+#include <ChartTypeTemplateProvider.hxx>
+#include <ChartTypeTemplate.hxx>
+#include "DialogModel.hxx"
+#include <RangeSelectionHelper.hxx>
+#include <TabPageNotifiable.hxx>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <officecfg/Office/Common.hxx>
+#include <osl/diagnose.h>
+
+namespace
+{
+ void lcl_ShowChooserButton(
+ weld::Button& rChooserButton,
+ bool bShow)
+ {
+ if( rChooserButton.get_visible() != bShow )
+ {
+ rChooserButton.set_visible( bShow );
+ }
+ }
+
+ void lcl_enableRangeChoosing(bool bEnable, weld::DialogController* pDialog)
+ {
+ if (!pDialog)
+ return;
+ weld::Dialog* pDlg = pDialog->getDialog();
+ pDlg->set_modal(!bEnable);
+ pDlg->set_visible(!bEnable);
+ }
+
+} // anonymous namespace
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Sequence;
+
+RangeChooserTabPage::RangeChooserTabPage(weld::Container* pPage, weld::DialogController* pController, DialogModel & rDialogModel,
+ ChartTypeTemplateProvider* pTemplateProvider,
+ bool bHideDescription /* = false */)
+ : OWizardPage(pPage, pController, "modules/schart/ui/tp_RangeChooser.ui", "tp_RangeChooser")
+ , m_nChangingControlCalls(0)
+ , m_bIsDirty(false)
+ , m_pTemplateProvider(pTemplateProvider)
+ , m_rDialogModel( rDialogModel )
+ , m_pTabPageNotifiable(dynamic_cast<TabPageNotifiable*>(pController))
+ , m_xFT_Caption(m_xBuilder->weld_label("FT_CAPTION_FOR_WIZARD"))
+ , m_xED_Range(m_xBuilder->weld_entry("ED_RANGE"))
+ , m_xIB_Range(m_xBuilder->weld_button("IB_RANGE"))
+ , m_xRB_Rows(m_xBuilder->weld_radio_button("RB_DATAROWS"))
+ , m_xRB_Columns(m_xBuilder->weld_radio_button("RB_DATACOLS"))
+ , m_xCB_FirstRowAsLabel(m_xBuilder->weld_check_button("CB_FIRST_ROW_ASLABELS"))
+ , m_xCB_FirstColumnAsLabel(m_xBuilder->weld_check_button("CB_FIRST_COLUMN_ASLABELS"))
+ , m_xFTTitle(m_xBuilder->weld_label("STR_PAGE_DATA_RANGE"))
+ , m_xFL_TimeBased(m_xBuilder->weld_widget("separator1"))
+ , m_xCB_TimeBased(m_xBuilder->weld_check_button("CB_TIME_BASED"))
+ , m_xFT_TimeStart(m_xBuilder->weld_label("label1"))
+ , m_xEd_TimeStart(m_xBuilder->weld_entry("ED_TIME_BASED_START"))
+ , m_xFT_TimeEnd(m_xBuilder->weld_label("label2"))
+ , m_xEd_TimeEnd(m_xBuilder->weld_entry("ED_TIME_BASED_END"))
+{
+ m_xFT_Caption->set_visible(!bHideDescription);
+
+ SetPageTitle(m_xFTTitle->get_label());// OH:remove later with dialog
+
+ // set defaults as long as DetectArguments does not work
+ m_xRB_Columns->set_active(true);
+ m_xCB_FirstColumnAsLabel->set_active(true);
+ m_xCB_FirstRowAsLabel->set_active(true);
+
+ // BM: Note, that the range selection is not available, if there is no view.
+ // This happens for charts having their own embedded spreadsheet. If you
+ // force to get the range selection here, this would mean when entering this
+ // page the calc view would be created in this case. So, I enable the
+ // button here, and in the worst case nothing happens when it is pressed.
+ // Not nice, but I see no better solution for the moment.
+ m_xIB_Range->connect_clicked( LINK( this, RangeChooserTabPage, ChooseRangeHdl ));
+
+ m_xED_Range->connect_changed( LINK( this, RangeChooserTabPage, ControlEditedHdl ));
+ m_xRB_Rows->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedRadioHdl ) );
+ m_xCB_FirstRowAsLabel->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedCheckBoxHdl ) );
+ m_xCB_FirstColumnAsLabel->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedCheckBoxHdl ) );
+ m_xCB_TimeBased->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedCheckBoxHdl ) );
+ m_xEd_TimeStart->connect_changed( LINK( this, RangeChooserTabPage, ControlChangedHdl ) );
+ m_xEd_TimeEnd->connect_changed( LINK( this, RangeChooserTabPage, ControlChangedHdl ) );
+
+ if ( !officecfg::Office::Common::Misc::ExperimentalMode::get() )
+ {
+ m_xFL_TimeBased->hide();
+ m_xCB_TimeBased->hide();
+ m_xFT_TimeStart->hide();
+ m_xEd_TimeStart->hide();
+ m_xFT_TimeEnd->hide();
+ m_xEd_TimeEnd->hide();
+ }
+}
+
+RangeChooserTabPage::~RangeChooserTabPage()
+{
+}
+
+void RangeChooserTabPage::Activate()
+{
+ OWizardPage::Activate();
+ initControlsFromModel();
+ m_xED_Range->grab_focus();
+}
+
+void RangeChooserTabPage::initControlsFromModel()
+{
+ m_nChangingControlCalls++;
+
+ if(m_pTemplateProvider)
+ m_xCurrentChartTypeTemplate = m_pTemplateProvider->getCurrentTemplate();
+
+ bool bUseColumns = !m_xRB_Rows->get_active();
+ bool bFirstCellAsLabel = bUseColumns ? m_xCB_FirstRowAsLabel->get_active() : m_xCB_FirstColumnAsLabel->get_active();
+ bool bHasCategories = bUseColumns ? m_xCB_FirstColumnAsLabel->get_active() : m_xCB_FirstRowAsLabel->get_active();
+
+ bool bIsValid = m_rDialogModel.allArgumentsForRectRangeDetected();
+ if( bIsValid )
+ m_rDialogModel.detectArguments(m_aLastValidRangeString, bUseColumns, bFirstCellAsLabel, bHasCategories );
+ else
+ m_aLastValidRangeString.clear();
+
+ m_xED_Range->set_text( m_aLastValidRangeString );
+
+ m_xRB_Rows->set_active( !bUseColumns );
+ m_xRB_Columns->set_active( bUseColumns );
+
+ m_xCB_FirstRowAsLabel->set_active( m_xRB_Rows->get_active()?bHasCategories:bFirstCellAsLabel );
+ m_xCB_FirstColumnAsLabel->set_active( m_xRB_Columns->get_active()?bHasCategories:bFirstCellAsLabel );
+
+ isValid();
+
+ m_nChangingControlCalls--;
+}
+
+void RangeChooserTabPage::Deactivate()
+{
+ commitPage();
+ vcl::OWizardPage::Deactivate();
+}
+
+void RangeChooserTabPage::commitPage()
+{
+ commitPage(::vcl::WizardTypes::eFinish);
+}
+
+bool RangeChooserTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ )
+{
+ //ranges may have been edited in the meanwhile (dirty is true in that case here)
+ if( isValid() )
+ {
+ changeDialogModelAccordingToControls();
+ return true; // return false if this page should not be left
+ }
+ else
+ return false;
+}
+
+void RangeChooserTabPage::changeDialogModelAccordingToControls()
+{
+ if(m_nChangingControlCalls>0)
+ return;
+
+ if( !m_xCurrentChartTypeTemplate.is() )
+ {
+ if(m_pTemplateProvider)
+ m_xCurrentChartTypeTemplate = m_pTemplateProvider->getCurrentTemplate();
+ if( !m_xCurrentChartTypeTemplate.is())
+ {
+ OSL_FAIL( "Need a template to change data source" );
+ return;
+ }
+ }
+
+ if( !m_bIsDirty )
+ return;
+
+ bool bFirstCellAsLabel = ( m_xCB_FirstColumnAsLabel->get_active() && !m_xRB_Columns->get_active() )
+ || ( m_xCB_FirstRowAsLabel->get_active() && !m_xRB_Rows->get_active() );
+ bool bHasCategories = ( m_xCB_FirstColumnAsLabel->get_active() && m_xRB_Columns->get_active() )
+ || ( m_xCB_FirstRowAsLabel->get_active() && m_xRB_Rows->get_active() );
+ bool bTimeBased = m_xCB_TimeBased->get_active();
+
+ Sequence< beans::PropertyValue > aArguments(
+ DataSourceHelper::createArguments(
+ m_xRB_Columns->get_active(), bFirstCellAsLabel, bHasCategories ) );
+
+ if(bTimeBased)
+ {
+ aArguments.realloc( aArguments.getLength() + 1 );
+ aArguments.getArray()[aArguments.getLength() - 1] =
+ beans::PropertyValue( "TimeBased", -1, uno::Any(bTimeBased),
+ beans::PropertyState_DIRECT_VALUE );
+ }
+
+ // only if range is valid
+ if( m_aLastValidRangeString != m_xED_Range->get_text())
+ return;
+
+ m_rDialogModel.setTemplate( m_xCurrentChartTypeTemplate );
+ aArguments.realloc( aArguments.getLength() + 1 );
+ aArguments.getArray()[aArguments.getLength() - 1] =
+ beans::PropertyValue( "CellRangeRepresentation" , -1,
+ uno::Any( m_aLastValidRangeString ),
+ beans::PropertyState_DIRECT_VALUE );
+ m_rDialogModel.setData( aArguments );
+ m_bIsDirty = false;
+
+ if(bTimeBased)
+ {
+ sal_Int32 nStart = m_xEd_TimeStart->get_text().toInt32();
+ sal_Int32 nEnd = m_xEd_TimeEnd->get_text().toInt32();
+ m_rDialogModel.setTimeBasedRange(true, nStart, nEnd);
+ }
+
+ //@todo warn user that the selected range is not valid
+ //@todo better: disable OK-Button if range is invalid
+}
+
+bool RangeChooserTabPage::isValid()
+{
+ OUString aRange( m_xED_Range->get_text());
+ bool bFirstCellAsLabel = ( m_xCB_FirstColumnAsLabel->get_active() && !m_xRB_Columns->get_active() )
+ || ( m_xCB_FirstRowAsLabel->get_active() && !m_xRB_Rows->get_active() );
+ bool bHasCategories = ( m_xCB_FirstColumnAsLabel->get_active() && m_xRB_Columns->get_active() )
+ || ( m_xCB_FirstRowAsLabel->get_active() && m_xRB_Rows->get_active() );
+ bool bIsValid = ( aRange.isEmpty() ) ||
+ m_rDialogModel.getRangeSelectionHelper()->verifyArguments(
+ DataSourceHelper::createArguments(
+ aRange, Sequence< sal_Int32 >(), m_xRB_Columns->get_active(), bFirstCellAsLabel, bHasCategories ));
+
+ if( bIsValid )
+ {
+ m_xED_Range->set_message_type(weld::EntryMessageType::Normal);
+ if( m_pTabPageNotifiable )
+ m_pTabPageNotifiable->setValidPage( this );
+ m_aLastValidRangeString = aRange;
+ }
+ else
+ {
+ m_xED_Range->set_message_type(weld::EntryMessageType::Error);
+ if( m_pTabPageNotifiable )
+ m_pTabPageNotifiable->setInvalidPage( this );
+ }
+
+ // enable/disable controls
+ // #i79531# if the range is valid but an action of one of these buttons
+ // would render it invalid, the button should be disabled
+ if( bIsValid )
+ {
+ bool bDataInColumns = m_xRB_Columns->get_active();
+ bool bIsSwappedRangeValid = m_rDialogModel.getRangeSelectionHelper()->verifyArguments(
+ DataSourceHelper::createArguments(
+ aRange, Sequence< sal_Int32 >(), ! bDataInColumns, bHasCategories, bFirstCellAsLabel ));
+ m_xRB_Rows->set_sensitive( bIsSwappedRangeValid );
+ m_xRB_Columns->set_sensitive( bIsSwappedRangeValid );
+
+ m_xCB_FirstRowAsLabel->set_sensitive(
+ m_rDialogModel.getRangeSelectionHelper()->verifyArguments(
+ DataSourceHelper::createArguments(
+ aRange, Sequence< sal_Int32 >(), m_xRB_Columns->get_active(),
+ bDataInColumns ? ! bFirstCellAsLabel : bFirstCellAsLabel,
+ bDataInColumns ? bHasCategories : ! bHasCategories )));
+ m_xCB_FirstColumnAsLabel->set_sensitive(
+ m_rDialogModel.getRangeSelectionHelper()->verifyArguments(
+ DataSourceHelper::createArguments(
+ aRange, Sequence< sal_Int32 >(), m_xRB_Columns->get_active(),
+ bDataInColumns ? bFirstCellAsLabel : ! bFirstCellAsLabel,
+ bDataInColumns ? ! bHasCategories : bHasCategories )));
+ }
+ else
+ {
+ m_xRB_Rows->set_sensitive( bIsValid );
+ m_xRB_Columns->set_sensitive( bIsValid );
+ m_xCB_FirstRowAsLabel->set_sensitive( bIsValid );
+ m_xCB_FirstColumnAsLabel->set_sensitive( bIsValid );
+ }
+
+ bool bShowIB = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection();
+ lcl_ShowChooserButton( *m_xIB_Range, bShowIB );
+
+ return bIsValid;
+}
+
+IMPL_LINK_NOARG(RangeChooserTabPage, ControlEditedHdl, weld::Entry&, void)
+{
+ setDirty();
+ isValid();
+}
+
+IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedRadioHdl, weld::Toggleable&, void)
+{
+ ControlChangedHdl(*m_xED_Range);
+}
+
+IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedCheckBoxHdl, weld::Toggleable&, void)
+{
+ ControlChangedHdl(*m_xED_Range);
+}
+
+IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedHdl, weld::Entry&, void)
+{
+ setDirty();
+ if( isValid())
+ changeDialogModelAccordingToControls();
+}
+
+IMPL_LINK_NOARG(RangeChooserTabPage, ChooseRangeHdl, weld::Button&, void)
+{
+ OUString aRange = m_xED_Range->get_text();
+ OUString aTitle = m_xFTTitle->get_label();
+
+ lcl_enableRangeChoosing(true, m_pDialogController);
+ m_rDialogModel.getRangeSelectionHelper()->chooseRange( aRange, aTitle, *this );
+}
+
+void RangeChooserTabPage::listeningFinished( const OUString & rNewRange )
+{
+ //user has selected a new range
+
+ // rNewRange becomes invalid after removing the listener
+ OUString aRange( rNewRange );
+
+ m_rDialogModel.startControllerLockTimer();
+
+ // stop listening
+ m_rDialogModel.getRangeSelectionHelper()->stopRangeListening();
+
+ //update dialog state
+ m_xED_Range->set_text(aRange);
+ m_xED_Range->grab_focus();
+
+ setDirty();
+ if( isValid())
+ changeDialogModelAccordingToControls();
+
+ lcl_enableRangeChoosing(false, m_pDialogController);
+}
+
+void RangeChooserTabPage::disposingRangeSelection()
+{
+ m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false );
+}
+
+void RangeChooserTabPage::setDirty()
+{
+ if( m_nChangingControlCalls == 0 )
+ m_bIsDirty = true;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_RangeChooser.hxx b/chart2/source/controller/dialogs/tp_RangeChooser.hxx
new file mode 100644
index 0000000000..428e8a127d
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_RangeChooser.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <RangeSelectionListener.hxx>
+
+#include <vcl/wizardmachine.hxx>
+
+namespace chart { class TabPageNotifiable; }
+
+namespace chart
+{
+class ChartTypeTemplate;
+class ChartTypeTemplateProvider;
+class DialogModel;
+
+class RangeChooserTabPage final : public vcl::OWizardPage, public RangeSelectionListenerParent
+{
+public:
+
+ RangeChooserTabPage(weld::Container* pPage, weld::DialogController* pController, DialogModel & rDialogModel,
+ ChartTypeTemplateProvider* pTemplateProvider,
+ bool bHideDescription = false);
+ virtual ~RangeChooserTabPage() override;
+
+ //RangeSelectionListenerParent
+ virtual void listeningFinished( const OUString & rNewRange ) override;
+ virtual void disposingRangeSelection() override;
+
+ virtual void Activate() override;
+
+ void commitPage();
+
+private:
+
+ //OWizardPage
+ virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason eReason ) override;
+
+ //TabPage
+ virtual void Deactivate() override;
+
+ void initControlsFromModel();
+ void changeDialogModelAccordingToControls();
+ bool isValid();
+ void setDirty();
+
+ DECL_LINK( ChooseRangeHdl, weld::Button&, void );
+ DECL_LINK( ControlChangedHdl, weld::Entry&, void );
+ DECL_LINK( ControlChangedCheckBoxHdl, weld::Toggleable&, void );
+ DECL_LINK( ControlChangedRadioHdl, weld::Toggleable&, void );
+ DECL_LINK( ControlEditedHdl, weld::Entry&, void );
+
+ sal_Int32 m_nChangingControlCalls;
+ bool m_bIsDirty;
+
+ OUString m_aLastValidRangeString;
+ rtl::Reference< ::chart::ChartTypeTemplate > m_xCurrentChartTypeTemplate;
+ ChartTypeTemplateProvider* m_pTemplateProvider;
+
+ DialogModel & m_rDialogModel;
+ TabPageNotifiable * m_pTabPageNotifiable;
+
+ std::unique_ptr<weld::Label> m_xFT_Caption;
+ std::unique_ptr<weld::Entry> m_xED_Range;
+ std::unique_ptr<weld::Button> m_xIB_Range;
+ std::unique_ptr<weld::RadioButton> m_xRB_Rows;
+ std::unique_ptr<weld::RadioButton> m_xRB_Columns;
+ std::unique_ptr<weld::CheckButton> m_xCB_FirstRowAsLabel;
+ std::unique_ptr<weld::CheckButton> m_xCB_FirstColumnAsLabel;
+ std::unique_ptr<weld::Label> m_xFTTitle;
+ std::unique_ptr<weld::Widget> m_xFL_TimeBased;
+ std::unique_ptr<weld::CheckButton> m_xCB_TimeBased;
+ std::unique_ptr<weld::Label> m_xFT_TimeStart;
+ std::unique_ptr<weld::Entry> m_xEd_TimeStart;
+ std::unique_ptr<weld::Label> m_xFT_TimeEnd;
+ std::unique_ptr<weld::Entry> m_xEd_TimeEnd;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_Scale.cxx b/chart2/source/controller/dialogs/tp_Scale.cxx
new file mode 100644
index 0000000000..b8c9f05983
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_Scale.cxx
@@ -0,0 +1,637 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_Scale.hxx"
+
+#include <ResId.hxx>
+#include <strings.hrc>
+#include <chartview/ChartSfxItemIds.hxx>
+#include <AxisHelper.hxx>
+
+#include <svx/svxids.hrc>
+#include <osl/diagnose.h>
+#include <sfx2/dialoghelper.hxx>
+#include <svx/chrtitem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/numformat.hxx>
+#include <vcl/formatter.hxx>
+#include <vcl/weld.hxx>
+#include <svl/zformat.hxx>
+#include <vcl/svapp.hxx>
+
+#include <com/sun/star/chart2/AxisType.hpp>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+namespace
+{
+
+void lcl_setValue(weld::FormattedSpinButton& rFmtField, double fValue)
+{
+ rFmtField.GetFormatter().SetValue(fValue);
+}
+
+}
+
+ScaleTabPage::ScaleTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_Scale.ui", "tp_Scale", &rInAttrs)
+ , fMin(0.0)
+ , fMax(0.0)
+ , fStepMain(0.0)
+ , nStepHelp(0)
+ , fOrigin(0.0)
+ , m_nTimeResolution(1)
+ , m_nMainTimeUnit(1)
+ , m_nHelpTimeUnit(1)
+ , m_nAxisType(chart2::AxisType::REALNUMBER)
+ , m_bAllowDateAxis(false)
+ , pNumFormatter(nullptr)
+ , m_bShowAxisOrigin(false)
+ , m_xCbxReverse(m_xBuilder->weld_check_button("CBX_REVERSE"))
+ , m_xCbxLogarithm(m_xBuilder->weld_check_button("CBX_LOGARITHM"))
+ , m_xBxType(m_xBuilder->weld_widget("boxTYPE"))
+ , m_xLB_AxisType(m_xBuilder->weld_combo_box("LB_AXIS_TYPE"))
+ , m_xBxMinMax(m_xBuilder->weld_widget("gridMINMAX"))
+ , m_xFmtFldMin(m_xBuilder->weld_formatted_spin_button("EDT_MIN"))
+ , m_xCbxAutoMin(m_xBuilder->weld_check_button("CBX_AUTO_MIN"))
+ , m_xFmtFldMax(m_xBuilder->weld_formatted_spin_button("EDT_MAX"))
+ , m_xCbxAutoMax(m_xBuilder->weld_check_button("CBX_AUTO_MAX"))
+ , m_xBxResolution(m_xBuilder->weld_widget("boxRESOLUTION"))
+ , m_xLB_TimeResolution(m_xBuilder->weld_combo_box("LB_TIME_RESOLUTION"))
+ , m_xCbx_AutoTimeResolution(m_xBuilder->weld_check_button("CBX_AUTO_TIME_RESOLUTION"))
+ , m_xTxtMain(m_xBuilder->weld_label("TXT_STEP_MAIN"))
+ , m_xFmtFldStepMain(m_xBuilder->weld_formatted_spin_button("EDT_STEP_MAIN"))
+ , m_xMt_MainDateStep(m_xBuilder->weld_spin_button("MT_MAIN_DATE_STEP"))
+ , m_xLB_MainTimeUnit(m_xBuilder->weld_combo_box("LB_MAIN_TIME_UNIT"))
+ , m_xCbxAutoStepMain(m_xBuilder->weld_check_button("CBX_AUTO_STEP_MAIN"))
+ , m_xTxtHelpCount(m_xBuilder->weld_label("TXT_STEP_HELP_COUNT"))
+ , m_xTxtHelp(m_xBuilder->weld_label("TXT_STEP_HELP"))
+ , m_xMtStepHelp(m_xBuilder->weld_spin_button("MT_STEPHELP"))
+ , m_xLB_HelpTimeUnit(m_xBuilder->weld_combo_box("LB_HELP_TIME_UNIT"))
+ , m_xCbxAutoStepHelp(m_xBuilder->weld_check_button("CBX_AUTO_STEP_HELP"))
+ , m_xFmtFldOrigin(m_xBuilder->weld_formatted_spin_button("EDT_ORIGIN"))
+ , m_xCbxAutoOrigin(m_xBuilder->weld_check_button("CBX_AUTO_ORIGIN"))
+ , m_xBxOrigin(m_xBuilder->weld_widget("boxORIGIN"))
+{
+ m_xCbxAutoMin->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl));
+ m_xCbxAutoMax->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl));
+ m_xCbxAutoStepMain->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl));
+ m_xCbxAutoStepHelp->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl));
+ m_xCbxAutoOrigin->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl));
+ m_xCbx_AutoTimeResolution->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl));
+
+ Formatter& rFmtFldMax = m_xFmtFldMax->GetFormatter();
+ rFmtFldMax.ClearMinValue();
+ rFmtFldMax.ClearMaxValue();
+ Formatter& rFmtFldMin = m_xFmtFldMin->GetFormatter();
+ rFmtFldMin.ClearMinValue();
+ rFmtFldMin.ClearMaxValue();
+ Formatter& rFmtFldStepMain = m_xFmtFldStepMain->GetFormatter();
+ rFmtFldStepMain.ClearMinValue();
+ rFmtFldStepMain.ClearMaxValue();
+ Formatter& rFmtFldOrigin = m_xFmtFldOrigin->GetFormatter();
+ rFmtFldOrigin.ClearMinValue();
+ rFmtFldOrigin.ClearMaxValue();
+
+ m_xLB_AxisType->connect_changed(LINK(this, ScaleTabPage, SelectAxisTypeHdl));
+
+ HideAllControls();
+}
+
+ScaleTabPage::~ScaleTabPage()
+{
+}
+
+void ScaleTabPage::EnableControls()
+{
+ bool bValueAxis = m_nAxisType == chart2::AxisType::REALNUMBER
+ || m_nAxisType == chart2::AxisType::PERCENT
+ || m_nAxisType == chart2::AxisType::DATE;
+ bool bDateAxis = m_nAxisType == chart2::AxisType::DATE;
+
+ m_xBxType->set_visible(m_bAllowDateAxis);
+
+ m_xCbxLogarithm->set_visible( bValueAxis && !bDateAxis );
+
+ m_xBxMinMax->set_visible(bValueAxis);
+
+ m_xTxtMain->set_visible( bValueAxis );
+ m_xCbxAutoStepMain->set_visible( bValueAxis );
+
+ m_xTxtHelpCount->set_visible( bValueAxis && !bDateAxis );
+ m_xTxtHelp->set_visible( bDateAxis );
+ m_xMtStepHelp->set_visible( bValueAxis );
+ m_xCbxAutoStepHelp->set_visible( bValueAxis );
+
+ m_xBxOrigin->set_visible( m_bShowAxisOrigin && bValueAxis );
+ m_xBxResolution->set_visible( bDateAxis );
+
+ bool bWasDateAxis = m_xMt_MainDateStep->get_visible();
+ if( bWasDateAxis != bDateAxis )
+ {
+ //transport value from one to other control
+ if( bWasDateAxis )
+ lcl_setValue( *m_xFmtFldStepMain, m_xMt_MainDateStep->get_value() );
+ else
+ m_xMt_MainDateStep->set_value(m_xFmtFldStepMain->GetFormatter().GetValue());
+ }
+
+ m_xFmtFldStepMain->set_visible( bValueAxis && !bDateAxis );
+ m_xMt_MainDateStep->set_visible( bDateAxis );
+
+ m_xLB_MainTimeUnit->set_visible( bDateAxis );
+ m_xLB_HelpTimeUnit->set_visible( bDateAxis );
+
+ EnableValueHdl(*m_xCbxAutoMin);
+ EnableValueHdl(*m_xCbxAutoMax);
+ EnableValueHdl(*m_xCbxAutoStepMain);
+ EnableValueHdl(*m_xCbxAutoStepHelp);
+ EnableValueHdl(*m_xCbxAutoOrigin);
+ EnableValueHdl(*m_xCbx_AutoTimeResolution);
+}
+
+IMPL_LINK( ScaleTabPage, EnableValueHdl, weld::Toggleable&, rCbx, void )
+{
+ bool bEnable = !rCbx.get_active() && rCbx.get_sensitive();
+ if (&rCbx == m_xCbxAutoMin.get())
+ {
+ m_xFmtFldMin->set_sensitive( bEnable );
+ }
+ else if (&rCbx == m_xCbxAutoMax.get())
+ {
+ m_xFmtFldMax->set_sensitive( bEnable );
+ }
+ else if (&rCbx == m_xCbxAutoStepMain.get())
+ {
+ m_xFmtFldStepMain->set_sensitive( bEnable );
+ m_xMt_MainDateStep->set_sensitive( bEnable );
+ m_xLB_MainTimeUnit->set_sensitive( bEnable );
+ }
+ else if (&rCbx == m_xCbxAutoStepHelp.get())
+ {
+ m_xMtStepHelp->set_sensitive( bEnable );
+ m_xLB_HelpTimeUnit->set_sensitive( bEnable );
+ }
+ else if (&rCbx == m_xCbx_AutoTimeResolution.get())
+ {
+ m_xLB_TimeResolution->set_sensitive( bEnable );
+ }
+ else if (&rCbx == m_xCbxAutoOrigin.get())
+ {
+ m_xFmtFldOrigin->set_sensitive( bEnable );
+ }
+}
+
+namespace {
+
+enum AxisTypeListBoxEntry
+{
+ TYPE_AUTO=0,
+ TYPE_TEXT=1,
+ TYPE_DATE=2
+};
+
+}
+
+IMPL_LINK_NOARG(ScaleTabPage, SelectAxisTypeHdl, weld::ComboBox&, void)
+{
+ const sal_Int32 nPos = m_xLB_AxisType->get_active();
+ if( nPos==TYPE_DATE )
+ m_nAxisType = chart2::AxisType::DATE;
+ else
+ m_nAxisType = chart2::AxisType::CATEGORY;
+ if( m_nAxisType == chart2::AxisType::DATE )
+ m_xCbxLogarithm->set_active(false);
+ EnableControls();
+ SetNumFormat();
+}
+
+std::unique_ptr<SfxTabPage> ScaleTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs)
+{
+ return std::make_unique<ScaleTabPage>(pPage, pController, *rOutAttrs);
+}
+
+bool ScaleTabPage::FillItemSet(SfxItemSet* rOutAttrs)
+{
+ OSL_PRECOND( pNumFormatter, "No NumberFormatter available" );
+
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_AXISTYPE, m_nAxisType));
+ if(m_bAllowDateAxis)
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_DATEAXIS, m_xLB_AxisType->get_active()==TYPE_AUTO));
+
+ bool bAutoScale = false;
+ if( m_nAxisType==chart2::AxisType::CATEGORY )
+ bAutoScale = true;//reset scaling for category charts
+
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_MIN ,bAutoScale || m_xCbxAutoMin->get_active()));
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_MAX ,bAutoScale || m_xCbxAutoMax->get_active()));
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_HELP,bAutoScale || m_xCbxAutoStepHelp->get_active()));
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_ORIGIN ,bAutoScale || m_xCbxAutoOrigin->get_active()));
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_LOGARITHM ,m_xCbxLogarithm->get_active()));
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_REVERSE ,m_xCbxReverse->get_active()));
+ rOutAttrs->Put(SvxDoubleItem(fMax , SCHATTR_AXIS_MAX));
+ rOutAttrs->Put(SvxDoubleItem(fMin , SCHATTR_AXIS_MIN));
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_STEP_HELP, nStepHelp));
+ rOutAttrs->Put(SvxDoubleItem(fOrigin , SCHATTR_AXIS_ORIGIN));
+
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_MAIN,bAutoScale || m_xCbxAutoStepMain->get_active()));
+ rOutAttrs->Put(SvxDoubleItem(fStepMain,SCHATTR_AXIS_STEP_MAIN));
+
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_TIME_RESOLUTION,bAutoScale || m_xCbx_AutoTimeResolution->get_active()));
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_TIME_RESOLUTION,m_nTimeResolution));
+
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_MAIN_TIME_UNIT,m_nMainTimeUnit));
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_HELP_TIME_UNIT,m_nHelpTimeUnit));
+
+ return true;
+}
+
+void ScaleTabPage::Reset(const SfxItemSet* rInAttrs)
+{
+ OSL_PRECOND( pNumFormatter, "No NumberFormatter available" );
+ if(!pNumFormatter)
+ return;
+
+ if (const SfxBoolItem* pDateAxisItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_ALLOW_DATEAXIS))
+ m_bAllowDateAxis = pDateAxisItem->GetValue();
+ m_nAxisType=chart2::AxisType::REALNUMBER;
+ if (const SfxInt32Item* pAxisTypeItem = rInAttrs->GetItemIfSet(SCHATTR_AXISTYPE))
+ m_nAxisType = static_cast<int>(pAxisTypeItem->GetValue());
+ if( m_nAxisType==chart2::AxisType::DATE && !m_bAllowDateAxis )
+ m_nAxisType=chart2::AxisType::CATEGORY;
+ if( m_bAllowDateAxis )
+ {
+ bool bAutoDateAxis = false;
+ if (const SfxBoolItem* pDateAxisItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_AUTO_DATEAXIS))
+ bAutoDateAxis = pDateAxisItem->GetValue();
+
+ sal_uInt16 nPos = 0;
+ if( m_nAxisType==chart2::AxisType::DATE )
+ nPos=TYPE_DATE;
+ else if( bAutoDateAxis )
+ nPos=TYPE_AUTO;
+ else
+ nPos=TYPE_TEXT;
+ m_xLB_AxisType->set_active( nPos );
+ }
+
+ m_xCbxAutoMin->set_active(true);
+ m_xCbxAutoMax->set_active(true);
+ m_xCbxAutoStepMain->set_active(true);
+ m_xCbxAutoStepHelp->set_active(true);
+ m_xCbxAutoOrigin->set_active(true);
+ m_xCbx_AutoTimeResolution->set_active(true);
+
+ if (const SfxBoolItem* pAutoMinItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_AUTO_MIN))
+ m_xCbxAutoMin->set_active(pAutoMinItem->GetValue());
+
+ if (const SvxDoubleItem* pAxisMinItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_MIN))
+ {
+ fMin = pAxisMinItem->GetValue();
+ lcl_setValue( *m_xFmtFldMin, fMin );
+ m_xFmtFldMin->save_value();
+ }
+
+ if (const SfxBoolItem* pAutoMaxItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_AUTO_MAX))
+ m_xCbxAutoMax->set_active(pAutoMaxItem->GetValue());
+
+ if (const SvxDoubleItem* pAxisMaxItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_MAX))
+ {
+ fMax = pAxisMaxItem->GetValue();
+ lcl_setValue( *m_xFmtFldMax, fMax );
+ m_xFmtFldMax->save_value();
+ }
+
+ if (const SfxBoolItem* pAutoStepMainItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_AUTO_STEP_MAIN))
+ m_xCbxAutoStepMain->set_active(pAutoStepMainItem->GetValue());
+
+ if (const SvxDoubleItem* pStepMainItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_STEP_MAIN))
+ {
+ fStepMain = pStepMainItem->GetValue();
+ lcl_setValue( *m_xFmtFldStepMain, fStepMain );
+ m_xFmtFldStepMain->save_value();
+ m_xMt_MainDateStep->set_value( static_cast<sal_Int32>(fStepMain) );
+ m_xMt_MainDateStep->save_value();
+ }
+ if (const SfxBoolItem* pAutoStepHelpItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_AUTO_STEP_HELP))
+ m_xCbxAutoStepHelp->set_active(pAutoStepHelpItem->GetValue());
+ if (const SfxBoolItem* pLogItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_LOGARITHM))
+ m_xCbxLogarithm->set_active(pLogItem->GetValue());
+ if (const SfxBoolItem* pReverseItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_REVERSE))
+ m_xCbxReverse->set_active(pReverseItem->GetValue());
+ if (const SfxInt32Item* pStepHelpItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_STEP_HELP))
+ {
+ nStepHelp = pStepHelpItem->GetValue();
+ m_xMtStepHelp->set_value( nStepHelp );
+ m_xMtStepHelp->save_value();
+ }
+ if (const SfxBoolItem* pOriginItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_AUTO_ORIGIN))
+ m_xCbxAutoOrigin->set_active(pOriginItem->GetValue());
+ if (const SvxDoubleItem* pOriginItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_ORIGIN))
+ {
+ fOrigin = pOriginItem->GetValue();
+ lcl_setValue( *m_xFmtFldOrigin, fOrigin );
+ m_xFmtFldOrigin->save_value();
+ }
+
+ if (const SfxBoolItem* pAutoTimeResItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_AUTO_TIME_RESOLUTION))
+ m_xCbx_AutoTimeResolution->set_active(pAutoTimeResItem->GetValue());
+ if (const SfxInt32Item* pTimeResItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_TIME_RESOLUTION))
+ {
+ m_nTimeResolution = pTimeResItem->GetValue();
+ m_xLB_TimeResolution->set_active( m_nTimeResolution );
+ }
+
+ if (const SfxInt32Item* pMainTimeUnitItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_MAIN_TIME_UNIT))
+ {
+ m_nMainTimeUnit = pMainTimeUnitItem->GetValue();
+ m_xLB_MainTimeUnit->set_active( m_nMainTimeUnit );
+ }
+ if (const SfxInt32Item* pHelpTimeUnitItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_HELP_TIME_UNIT))
+ {
+ m_nHelpTimeUnit = pHelpTimeUnitItem->GetValue();
+ m_xLB_HelpTimeUnit->set_active( m_nHelpTimeUnit );
+ }
+
+ EnableControls();
+ SetNumFormat();
+}
+
+DeactivateRC ScaleTabPage::DeactivatePage(SfxItemSet* pItemSet)
+{
+ if( !pNumFormatter )
+ {
+ OSL_FAIL( "No NumberFormatter available" );
+ return DeactivateRC::LeavePage;
+ }
+
+ bool bDateAxis = m_nAxisType == chart2::AxisType::DATE;
+
+ sal_uInt32 nMinMaxOriginFmt = m_xFmtFldMax->GetFormatter().GetFormatKey();
+ if (pNumFormatter->GetType(nMinMaxOriginFmt) == SvNumFormatType::TEXT)
+ nMinMaxOriginFmt = 0;
+ // numberformat_text cause numbers to fail being numbers... Shouldn't happen, but can.
+ sal_uInt32 nStepFmt = m_xFmtFldStepMain->GetFormatter().GetFormatKey();
+ if (pNumFormatter->GetType(nStepFmt) == SvNumFormatType::TEXT)
+ nStepFmt = 0;
+
+ weld::Widget* pControl = nullptr;
+ TranslateId pErrStrId;
+ double fDummy;
+
+ fMax = m_xFmtFldMax->GetFormatter().GetValue();
+ fMin = m_xFmtFldMin->GetFormatter().GetValue();
+ fOrigin = m_xFmtFldOrigin->GetFormatter().GetValue();
+ fStepMain = bDateAxis ? m_xMt_MainDateStep->get_value() : m_xFmtFldStepMain->GetFormatter().GetValue();
+ nStepHelp = m_xMtStepHelp->get_value();
+ m_nTimeResolution = m_xLB_TimeResolution->get_active();
+ m_nMainTimeUnit = m_xLB_MainTimeUnit->get_active();
+ m_nHelpTimeUnit = m_xLB_HelpTimeUnit->get_active();
+
+ if( m_nAxisType != chart2::AxisType::REALNUMBER )
+ m_xCbxLogarithm->hide();
+
+ //check which entries need user action
+
+ if ( m_xCbxLogarithm->get_active() &&
+ ( ( !m_xCbxAutoMin->get_active() && fMin <= 0.0 )
+ || ( !m_xCbxAutoMax->get_active() && fMax <= 0.0 ) ) )
+ {
+ pControl = m_xFmtFldMin.get();
+ pErrStrId = STR_BAD_LOGARITHM;
+ }
+ // check for entries that cannot be parsed for the current number format
+ else if ( m_xFmtFldMin->get_value_changed_from_saved()
+ && !m_xCbxAutoMin->get_active()
+ && !pNumFormatter->IsNumberFormat( m_xFmtFldMin->get_text(), nMinMaxOriginFmt, fDummy))
+ {
+ pControl = m_xFmtFldMin.get();
+ pErrStrId = STR_INVALID_NUMBER;
+ }
+ else if ( m_xFmtFldMax->get_value_changed_from_saved()
+ && !m_xCbxAutoMax->get_active()
+ && !pNumFormatter->IsNumberFormat( m_xFmtFldMax->get_text(), nMinMaxOriginFmt, fDummy))
+ {
+ pControl = m_xFmtFldMax.get();
+ pErrStrId = STR_INVALID_NUMBER;
+ }
+ else if ( !bDateAxis && m_xFmtFldStepMain->get_value_changed_from_saved()
+ && !m_xCbxAutoStepMain->get_active()
+ && !pNumFormatter->IsNumberFormat( m_xFmtFldStepMain->get_text(), nStepFmt, fDummy))
+ {
+ pControl = m_xFmtFldStepMain.get();
+ pErrStrId = STR_INVALID_NUMBER;
+ }
+ else if (m_xFmtFldOrigin->get_value_changed_from_saved() && !m_xCbxAutoOrigin->get_active() &&
+ !pNumFormatter->IsNumberFormat( m_xFmtFldOrigin->get_text(), nMinMaxOriginFmt, fDummy))
+ {
+ pControl = m_xFmtFldOrigin.get();
+ pErrStrId = STR_INVALID_NUMBER;
+ }
+ else if (!m_xCbxAutoStepMain->get_active() && fStepMain <= 0.0)
+ {
+ pControl = m_xFmtFldStepMain.get();
+ pErrStrId = STR_STEP_GT_ZERO;
+ }
+ else if (!m_xCbxAutoMax->get_active() && !m_xCbxAutoMin->get_active() &&
+ fMin >= fMax)
+ {
+ pControl = m_xFmtFldMin.get();
+ pErrStrId = STR_MIN_GREATER_MAX;
+ }
+ else if( bDateAxis )
+ {
+ if( !m_xCbxAutoStepMain->get_active() && !m_xCbxAutoStepHelp->get_active() )
+ {
+ if( m_nHelpTimeUnit > m_nMainTimeUnit )
+ {
+ pControl = m_xLB_MainTimeUnit.get();
+ pErrStrId = STR_INVALID_INTERVALS;
+ }
+ else if( m_nHelpTimeUnit == m_nMainTimeUnit && nStepHelp > fStepMain )
+ {
+ pControl = m_xLB_MainTimeUnit.get();
+ pErrStrId = STR_INVALID_INTERVALS;
+ }
+ }
+ if( !pErrStrId && !m_xCbx_AutoTimeResolution->get_active() )
+ {
+ if( (!m_xCbxAutoStepMain->get_active() && m_nTimeResolution > m_nMainTimeUnit )
+ ||
+ (!m_xCbxAutoStepHelp->get_active() && m_nTimeResolution > m_nHelpTimeUnit )
+ )
+ {
+ pControl = m_xLB_TimeResolution.get();
+ pErrStrId = STR_INVALID_TIME_UNIT;
+ }
+ }
+ }
+
+ if( ShowWarning( pErrStrId, pControl ) )
+ return DeactivateRC::KeepPage;
+
+ if( pItemSet )
+ FillItemSet( pItemSet );
+
+ return DeactivateRC::LeavePage;
+}
+
+void ScaleTabPage::SetNumFormatter( SvNumberFormatter* pFormatter )
+{
+ pNumFormatter = pFormatter;
+
+ Formatter& rFmtFldMax = m_xFmtFldMax->GetFormatter();
+ Formatter& rFmtFldMin = m_xFmtFldMin->GetFormatter();
+ Formatter& rFmtFldStepMain = m_xFmtFldStepMain->GetFormatter();
+ Formatter& rFmtFldOrigin = m_xFmtFldOrigin->GetFormatter();
+
+ rFmtFldMax.SetFormatter( pNumFormatter );
+ rFmtFldMin.SetFormatter( pNumFormatter );
+ rFmtFldStepMain.SetFormatter( pNumFormatter );
+ rFmtFldOrigin.SetFormatter( pNumFormatter );
+
+ // #i6278# allow more decimal places than the output format. As
+ // the numbers shown in the edit fields are used for input, it makes more
+ // sense to display the values in the input format rather than the output
+ // format.
+ rFmtFldMax.UseInputStringForFormatting();
+ rFmtFldMin.UseInputStringForFormatting();
+ rFmtFldStepMain.UseInputStringForFormatting();
+ rFmtFldOrigin.UseInputStringForFormatting();
+
+ SetNumFormat();
+}
+
+void ScaleTabPage::SetNumFormat()
+{
+ const SfxUInt32Item *pNumFormatItem = GetItemSet().GetItemIfSet( SID_ATTR_NUMBERFORMAT_VALUE );
+
+ if( !pNumFormatItem )
+ return;
+
+ sal_uInt32 nFmt = pNumFormatItem->GetValue();
+
+ Formatter& rFmtFldMax = m_xFmtFldMax->GetFormatter();
+ rFmtFldMax.SetFormatKey(nFmt);
+ Formatter& rFmtFldMin = m_xFmtFldMin->GetFormatter();
+ rFmtFldMin.SetFormatKey(nFmt);
+ Formatter& rFmtFldOrigin = m_xFmtFldOrigin->GetFormatter();
+ rFmtFldOrigin.SetFormatKey(nFmt);
+
+ if( pNumFormatter )
+ {
+ SvNumFormatType eType = pNumFormatter->GetType( nFmt );
+ if( eType == SvNumFormatType::DATE )
+ {
+ // for intervals use standard format for dates (so you can enter a number of days)
+ const SvNumberformat* pFormat = pNumFormatter->GetEntry( nFmt );
+ if( pFormat )
+ nFmt = pNumFormatter->GetStandardIndex( pFormat->GetLanguage());
+ else
+ nFmt = pNumFormatter->GetStandardIndex();
+ }
+ else if( eType == SvNumFormatType::DATETIME )
+ {
+ // for intervals use time format for date times
+ const SvNumberformat* pFormat = pNumFormatter->GetEntry( nFmt );
+ if( pFormat )
+ nFmt = pNumFormatter->GetStandardFormat( SvNumFormatType::TIME, pFormat->GetLanguage() );
+ else
+ nFmt = pNumFormatter->GetStandardFormat( SvNumFormatType::TIME );
+
+ // tdf#141625 give enough space to see full date+time
+ int nWidestTime(m_xFmtFldMin->get_pixel_size(getWidestDateTime(Application::GetSettings().GetLocaleDataWrapper(), true)).Width());
+ int nWidthChars = std::ceil(nWidestTime / m_xFmtFldMin->get_approximate_digit_width()) + 1;
+ m_xFmtFldMin->set_width_chars(nWidthChars);
+ m_xFmtFldMax->set_width_chars(nWidthChars);
+ }
+
+ if( m_nAxisType == chart2::AxisType::DATE && ( eType != SvNumFormatType::DATE && eType != SvNumFormatType::DATETIME) )
+ {
+ const SvNumberformat* pFormat = pNumFormatter->GetEntry( nFmt );
+ if( pFormat )
+ nFmt = pNumFormatter->GetStandardFormat( SvNumFormatType::DATE, pFormat->GetLanguage() );
+ else
+ nFmt = pNumFormatter->GetStandardFormat( SvNumFormatType::DATE );
+
+ rFmtFldMax.SetFormatKey(nFmt);
+ rFmtFldMin.SetFormatKey(nFmt);
+ rFmtFldOrigin.SetFormatKey(nFmt);
+ }
+ }
+
+ m_xFmtFldStepMain->GetFormatter().SetFormatKey(nFmt);
+}
+
+void ScaleTabPage::ShowAxisOrigin( bool bShowOrigin )
+{
+ m_bShowAxisOrigin = bShowOrigin;
+ if( !AxisHelper::isAxisPositioningEnabled() )
+ m_bShowAxisOrigin = true;
+}
+
+bool ScaleTabPage::ShowWarning(TranslateId pResIdMessage, weld::Widget* pControl /* = nullptr */)
+{
+ if (!pResIdMessage)
+ return false;
+
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ SchResId(pResIdMessage)));
+ xWarn->run();
+ if (pControl)
+ {
+ pControl->grab_focus();
+ weld::Entry* pEdit = dynamic_cast<weld::Entry*>(pControl);
+ if (pEdit)
+ pEdit->select_region(0, -1);
+ }
+ return true;
+}
+
+void ScaleTabPage::HideAllControls()
+{
+ // We need to set these controls invisible when the class is instantiated
+ // since some code in EnableControls() depends on that logic. The real
+ // visibility of these controls depend on axis data type, and are
+ // set in EnableControls().
+
+ m_xBxType->hide();
+ m_xCbxLogarithm->hide();
+ m_xBxMinMax->hide();
+ m_xTxtMain->hide();
+ m_xFmtFldStepMain->hide();
+ m_xMt_MainDateStep->hide();
+ m_xLB_MainTimeUnit->hide();
+ m_xCbxAutoStepMain->hide();
+ m_xTxtHelpCount->hide();
+ m_xTxtHelp->hide();
+ m_xMtStepHelp->hide();
+ m_xCbxAutoStepHelp->hide();
+ m_xBxOrigin->hide();
+ m_xBxResolution->hide();
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_Scale.hxx b/chart2/source/controller/dialogs/tp_Scale.hxx
new file mode 100644
index 0000000000..b90d3ef202
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_Scale.hxx
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <unotools/resmgr.hxx>
+
+namespace chart
+{
+
+class ScaleTabPage : public SfxTabPage
+{
+public:
+ ScaleTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs);
+ virtual ~ScaleTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs );
+ virtual bool FillItemSet( SfxItemSet* rOutAttrs ) override;
+ virtual void Reset( const SfxItemSet* rInAttrs ) override;
+ virtual DeactivateRC DeactivatePage( SfxItemSet* pItemSet ) override;
+
+ void SetNumFormatter( SvNumberFormatter* pFormatter );
+ void SetNumFormat();
+
+ void ShowAxisOrigin( bool bShowOrigin );
+
+private:
+ double fMin;
+ double fMax;
+ double fStepMain;
+ sal_Int32 nStepHelp;
+ double fOrigin;
+ sal_Int32 m_nTimeResolution;
+ sal_Int32 m_nMainTimeUnit;
+ sal_Int32 m_nHelpTimeUnit;
+ int m_nAxisType;
+ bool m_bAllowDateAxis;
+ SvNumberFormatter* pNumFormatter;
+
+ bool m_bShowAxisOrigin;
+
+ std::unique_ptr<weld::CheckButton> m_xCbxReverse;
+ std::unique_ptr<weld::CheckButton> m_xCbxLogarithm;
+ std::unique_ptr<weld::Widget> m_xBxType;
+ std::unique_ptr<weld::ComboBox> m_xLB_AxisType;
+ std::unique_ptr<weld::Widget> m_xBxMinMax;
+ std::unique_ptr<weld::FormattedSpinButton> m_xFmtFldMin;
+ std::unique_ptr<weld::CheckButton> m_xCbxAutoMin;
+ std::unique_ptr<weld::FormattedSpinButton> m_xFmtFldMax;
+ std::unique_ptr<weld::CheckButton> m_xCbxAutoMax;
+ std::unique_ptr<weld::Widget> m_xBxResolution;
+ std::unique_ptr<weld::ComboBox> m_xLB_TimeResolution;
+ std::unique_ptr<weld::CheckButton> m_xCbx_AutoTimeResolution;
+ std::unique_ptr<weld::Label> m_xTxtMain;
+ std::unique_ptr<weld::FormattedSpinButton> m_xFmtFldStepMain;
+ std::unique_ptr<weld::SpinButton> m_xMt_MainDateStep;
+ std::unique_ptr<weld::ComboBox> m_xLB_MainTimeUnit;
+ std::unique_ptr<weld::CheckButton> m_xCbxAutoStepMain;
+ std::unique_ptr<weld::Label> m_xTxtHelpCount;
+ std::unique_ptr<weld::Label> m_xTxtHelp;
+ std::unique_ptr<weld::SpinButton> m_xMtStepHelp;
+ std::unique_ptr<weld::ComboBox> m_xLB_HelpTimeUnit;
+ std::unique_ptr<weld::CheckButton> m_xCbxAutoStepHelp;
+ std::unique_ptr<weld::FormattedSpinButton> m_xFmtFldOrigin;
+ std::unique_ptr<weld::CheckButton> m_xCbxAutoOrigin;
+ std::unique_ptr<weld::Widget> m_xBxOrigin;
+
+ void EnableControls();
+
+ DECL_LINK(SelectAxisTypeHdl, weld::ComboBox&, void);
+ DECL_LINK(EnableValueHdl, weld::Toggleable&, void);
+
+ /** shows a warning window due to an invalid input.
+
+ @param pResIdMessage
+ The resource identifier that represents the localized warning text.
+ If this is nullptr, no warning is shown and false is returned.
+
+ @param pControl
+ If non-NULL, contains a pointer to the control in which the
+ erroneous value was in. This method gives this control the focus
+ and selects its content.
+
+ @return false, if nResIdMessage was 0, true otherwise
+ */
+ bool ShowWarning(TranslateId pResIdMessage, weld::Widget* pControl);
+
+ void HideAllControls();
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_SeriesToAxis.cxx b/chart2/source/controller/dialogs/tp_SeriesToAxis.cxx
new file mode 100644
index 0000000000..3ffbc3642e
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_SeriesToAxis.cxx
@@ -0,0 +1,248 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_SeriesToAxis.hxx"
+
+#include <chartview/ChartSfxItemIds.hxx>
+
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/ilstitem.hxx>
+
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+
+namespace chart
+{
+
+SchOptionTabPage::SchOptionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_SeriesToAxis.ui", "TP_OPTIONS", &rInAttrs)
+ , m_nAllSeriesAxisIndex(0)
+ , m_bProvidesSecondaryYAxis(true)
+ , m_bProvidesOverlapAndGapWidth(false)
+ , m_bProvidesBarConnectors(false)
+ , m_xGrpAxis(m_xBuilder->weld_widget("frameGrpAxis"))
+ , m_xRbtAxis1(m_xBuilder->weld_radio_button("RBT_OPT_AXIS_1"))
+ , m_xRbtAxis2(m_xBuilder->weld_radio_button("RBT_OPT_AXIS_2"))
+ , m_xGrpBar(m_xBuilder->weld_widget("frameSettings"))
+ , m_xMTGap(m_xBuilder->weld_metric_spin_button("MT_GAP", FieldUnit::PERCENT))
+ , m_xMTOverlap(m_xBuilder->weld_metric_spin_button("MT_OVERLAP", FieldUnit::PERCENT))
+ , m_xCBConnect(m_xBuilder->weld_check_button("CB_CONNECTOR"))
+ , m_xCBAxisSideBySide(m_xBuilder->weld_check_button("CB_BARS_SIDE_BY_SIDE"))
+ , m_xGrpPlotOptions(m_xBuilder->weld_widget("frameFL_PLOT_OPTIONS"))
+ , m_xGridPlotOptions(m_xBuilder->weld_widget("gridPLOT_OPTIONS"))
+ , m_xRB_DontPaint(m_xBuilder->weld_radio_button("RB_DONT_PAINT"))
+ , m_xRB_AssumeZero(m_xBuilder->weld_radio_button("RB_ASSUME_ZERO"))
+ , m_xRB_ContinueLine(m_xBuilder->weld_radio_button("RB_CONTINUE_LINE"))
+ , m_xCBIncludeHiddenCells(m_xBuilder->weld_check_button("CB_INCLUDE_HIDDEN_CELLS"))
+ , m_xCBHideLegendEntry(m_xBuilder->weld_check_button("CB_LEGEND_ENTRY_HIDDEN"))
+{
+ m_xRbtAxis1->connect_toggled(LINK(this, SchOptionTabPage, EnableHdl));
+ m_xRbtAxis2->connect_toggled(LINK(this, SchOptionTabPage, EnableHdl));
+}
+
+SchOptionTabPage::~SchOptionTabPage()
+{
+}
+
+IMPL_LINK_NOARG(SchOptionTabPage, EnableHdl, weld::Toggleable&, void)
+{
+ if( m_nAllSeriesAxisIndex == 0 )
+ m_xCBAxisSideBySide->set_sensitive( m_xRbtAxis2->get_active());
+ else if( m_nAllSeriesAxisIndex == 1 )
+ m_xCBAxisSideBySide->set_sensitive( m_xRbtAxis1->get_active());
+}
+
+std::unique_ptr<SfxTabPage> SchOptionTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rOutAttrs)
+{
+ return std::make_unique<SchOptionTabPage>(pPage, pController, *rOutAttrs);
+}
+
+bool SchOptionTabPage::FillItemSet(SfxItemSet* rOutAttrs)
+{
+ if(m_xRbtAxis2->get_active())
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS,CHART_AXIS_SECONDARY_Y));
+ else
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS,CHART_AXIS_PRIMARY_Y));
+
+ if(m_xMTGap->get_visible())
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_BAR_GAPWIDTH,static_cast< sal_Int32 >( m_xMTGap->get_value(FieldUnit::PERCENT))));
+
+ if(m_xMTOverlap->get_visible())
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_BAR_OVERLAP,static_cast< sal_Int32 >( m_xMTOverlap->get_value(FieldUnit::PERCENT))));
+
+ if(m_xCBConnect->get_visible())
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_BAR_CONNECT,m_xCBConnect->get_active()));
+
+ // model property is "group bars per axis", UI feature is the other way
+ // round: "show bars side by side"
+ if(m_xCBAxisSideBySide->get_visible())
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_GROUP_BARS_PER_AXIS, ! m_xCBAxisSideBySide->get_active()));
+
+ if(m_xRB_DontPaint->get_active())
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT,css::chart::MissingValueTreatment::LEAVE_GAP));
+ else if(m_xRB_AssumeZero->get_active())
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT,css::chart::MissingValueTreatment::USE_ZERO));
+ else if(m_xRB_ContinueLine->get_active())
+ rOutAttrs->Put(SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT,css::chart::MissingValueTreatment::CONTINUE));
+
+ if (m_xCBIncludeHiddenCells->get_visible())
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_INCLUDE_HIDDEN_CELLS, m_xCBIncludeHiddenCells->get_active()));
+
+ if(m_xCBHideLegendEntry->get_visible())
+ rOutAttrs->Put(SfxBoolItem(SCHATTR_HIDE_LEGEND_ENTRY, m_xCBHideLegendEntry->get_active()));
+
+ return true;
+}
+
+void SchOptionTabPage::Reset(const SfxItemSet* rInAttrs)
+{
+ m_xRbtAxis1->set_active(true);
+ m_xRbtAxis2->set_active(false);
+ if (const SfxInt32Item* pAxisItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS))
+ {
+ tools::Long nVal = pAxisItem->GetValue();
+ if(nVal==CHART_AXIS_SECONDARY_Y)
+ {
+ m_xRbtAxis2->set_active(true);
+ m_xRbtAxis1->set_active(false);
+ }
+ }
+
+ tools::Long nTmp;
+ if (const SfxInt32Item* pGapWidthItem = rInAttrs->GetItemIfSet(SCHATTR_BAR_GAPWIDTH))
+ {
+ nTmp = static_cast<tools::Long>(pGapWidthItem->GetValue());
+ m_xMTGap->set_value(nTmp, FieldUnit::PERCENT);
+ }
+
+ if (const SfxInt32Item* pOverlapItem = rInAttrs->GetItemIfSet(SCHATTR_BAR_OVERLAP))
+ {
+ nTmp = static_cast<tools::Long>(pOverlapItem->GetValue());
+ m_xMTOverlap->set_value(nTmp, FieldUnit::PERCENT);
+ }
+
+ if (const SfxBoolItem* pConnectItem = rInAttrs->GetItemIfSet(SCHATTR_BAR_CONNECT))
+ {
+ bool bCheck = pConnectItem->GetValue();
+ m_xCBConnect->set_active(bCheck);
+ }
+
+ if (const SfxInt32Item* pAllSeriesItem = rInAttrs->GetItemIfSet(SCHATTR_AXIS_FOR_ALL_SERIES))
+ {
+ m_nAllSeriesAxisIndex = pAllSeriesItem->GetValue();
+ m_xCBAxisSideBySide->set_sensitive(false);
+ }
+ if (const SfxBoolItem* pPerAxisItem = rInAttrs->GetItemIfSet(SCHATTR_GROUP_BARS_PER_AXIS))
+ {
+ // model property is "group bars per axis", UI feature is the other way
+ // round: "show bars side by side"
+ bool bCheck = ! pPerAxisItem->GetValue();
+ m_xCBAxisSideBySide->set_active( bCheck );
+ }
+ else
+ {
+ m_xCBAxisSideBySide->hide();
+ }
+
+ //missing value treatment
+ {
+ std::vector< sal_Int32 > aMissingValueTreatments;
+ if (const SfxIntegerListItem* pValueTreatmentsItem = rInAttrs->GetItemIfSet(SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS))
+ aMissingValueTreatments = pValueTreatmentsItem->GetList();
+
+ const SfxInt32Item* pMissingValueTreatmentItem;
+ if ( aMissingValueTreatments.size()>1 &&
+ (pMissingValueTreatmentItem = rInAttrs->GetItemIfSet(SCHATTR_MISSING_VALUE_TREATMENT)) )
+ {
+ m_xRB_DontPaint->set_sensitive(false);
+ m_xRB_AssumeZero->set_sensitive(false);
+ m_xRB_ContinueLine->set_sensitive(false);
+
+ for(int nVal : aMissingValueTreatments)
+ {
+ if(nVal==css::chart::MissingValueTreatment::LEAVE_GAP)
+ m_xRB_DontPaint->set_sensitive(true);
+ else if(nVal==css::chart::MissingValueTreatment::USE_ZERO)
+ m_xRB_AssumeZero->set_sensitive(true);
+ else if(nVal==css::chart::MissingValueTreatment::CONTINUE)
+ m_xRB_ContinueLine->set_sensitive(true);
+ }
+
+ tools::Long nVal=pMissingValueTreatmentItem->GetValue();
+ if(nVal==css::chart::MissingValueTreatment::LEAVE_GAP)
+ m_xRB_DontPaint->set_active(true);
+ else if(nVal==css::chart::MissingValueTreatment::USE_ZERO)
+ m_xRB_AssumeZero->set_active(true);
+ else if(nVal==css::chart::MissingValueTreatment::CONTINUE)
+ m_xRB_ContinueLine->set_active(true);
+ }
+ else
+ {
+ m_xGridPlotOptions->hide();
+ }
+ }
+
+ // Include hidden cells
+ if (const SfxBoolItem* pHiddenCellsItem = rInAttrs->GetItemIfSet(SCHATTR_INCLUDE_HIDDEN_CELLS))
+ {
+ bool bVal = pHiddenCellsItem->GetValue();
+ m_xCBIncludeHiddenCells->set_active(bVal);
+ }
+ else
+ {
+ m_xCBIncludeHiddenCells->hide();
+ // check if the radiobutton guys above
+ // are visible. If they aren't, we can
+ // as well hide the whole frame
+ if(!m_xGridPlotOptions->get_visible())
+ m_xGrpPlotOptions->hide();
+ }
+
+ if (const SfxBoolItem* pEntryItem = rInAttrs->GetItemIfSet(SCHATTR_HIDE_LEGEND_ENTRY))
+ {
+ bool bVal = pEntryItem->GetValue();
+ m_xCBHideLegendEntry->set_active(bVal);
+ }
+
+ AdaptControlPositionsAndVisibility();
+}
+
+void SchOptionTabPage::Init( bool bProvidesSecondaryYAxis, bool bProvidesOverlapAndGapWidth, bool bProvidesBarConnectors )
+{
+ m_bProvidesSecondaryYAxis = bProvidesSecondaryYAxis;
+ m_bProvidesOverlapAndGapWidth = bProvidesOverlapAndGapWidth;
+ m_bProvidesBarConnectors = bProvidesBarConnectors;
+
+ AdaptControlPositionsAndVisibility();
+}
+
+void SchOptionTabPage::AdaptControlPositionsAndVisibility()
+{
+ m_xGrpAxis->set_visible(m_bProvidesSecondaryYAxis);
+ m_xGrpBar->set_visible(m_bProvidesOverlapAndGapWidth);
+ m_xCBConnect->set_visible(m_bProvidesBarConnectors);
+
+ if (!m_xMTGap->get_visible() && !m_xMTOverlap->get_visible())
+ m_xGrpBar->hide();
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_SeriesToAxis.hxx b/chart2/source/controller/dialogs/tp_SeriesToAxis.hxx
new file mode 100644
index 0000000000..6b163f3c88
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_SeriesToAxis.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+namespace weld {
+ class CheckButton;
+ class MetricSpinButton;
+ class RadioButton;
+ class ToggleButton;
+ class Widget;
+}
+
+namespace chart
+{
+
+class SchOptionTabPage : public SfxTabPage
+{
+public:
+ SchOptionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs);
+ virtual ~SchOptionTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs);
+ virtual bool FillItemSet(SfxItemSet* rOutAttrs) override;
+ virtual void Reset(const SfxItemSet* rInAttrs) override;
+
+ void Init( bool bProvidesSecondaryYAxis, bool bProvidesOverlapAndGapWidth, bool bProvidesBarConnectors );
+
+private: //methods
+ void AdaptControlPositionsAndVisibility();
+
+private: //member
+ DECL_LINK(EnableHdl, weld::Toggleable&, void );
+
+ sal_Int32 m_nAllSeriesAxisIndex;
+
+ bool m_bProvidesSecondaryYAxis;
+ bool m_bProvidesOverlapAndGapWidth;
+ bool m_bProvidesBarConnectors;
+
+ std::unique_ptr<weld::Widget> m_xGrpAxis;
+ std::unique_ptr<weld::RadioButton> m_xRbtAxis1;
+ std::unique_ptr<weld::RadioButton> m_xRbtAxis2;
+ std::unique_ptr<weld::Widget> m_xGrpBar;
+ std::unique_ptr<weld::MetricSpinButton> m_xMTGap;
+ std::unique_ptr<weld::MetricSpinButton> m_xMTOverlap;
+ std::unique_ptr<weld::CheckButton> m_xCBConnect;
+ std::unique_ptr<weld::CheckButton> m_xCBAxisSideBySide;
+ std::unique_ptr<weld::Widget> m_xGrpPlotOptions;
+ std::unique_ptr<weld::Widget> m_xGridPlotOptions;
+ std::unique_ptr<weld::RadioButton> m_xRB_DontPaint;
+ std::unique_ptr<weld::RadioButton> m_xRB_AssumeZero;
+ std::unique_ptr<weld::RadioButton> m_xRB_ContinueLine;
+ std::unique_ptr<weld::CheckButton> m_xCBIncludeHiddenCells;
+ std::unique_ptr<weld::CheckButton> m_xCBHideLegendEntry;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_TitleRotation.cxx b/chart2/source/controller/dialogs/tp_TitleRotation.cxx
new file mode 100644
index 0000000000..f3380042eb
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_TitleRotation.cxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_TitleRotation.hxx"
+
+#include <chartview/ChartSfxItemIds.hxx>
+#include <TextDirectionListBox.hxx>
+
+#include <editeng/eeitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svx/sdangitm.hxx>
+
+namespace chart
+{
+
+SchAlignmentTabPage::SchAlignmentTabPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& rInAttrs, bool bWithRotation)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/titlerotationtabpage.ui", "TitleRotationTabPage", &rInAttrs)
+ , m_xFtRotate(m_xBuilder->weld_label("degreeL"))
+ , m_xNfRotate(m_xBuilder->weld_metric_spin_button("OrientDegree", FieldUnit::DEGREE))
+ , m_xCbStacked(m_xBuilder->weld_check_button("stackedCB"))
+ , m_xFtABCD(m_xBuilder->weld_label("labelABCD"))
+ , m_aLbTextDirection(m_xBuilder->weld_combo_box("textdirLB"))
+ , m_xCtrlDial(new svx::DialControl)
+ , m_xCtrlDialWin(new weld::CustomWeld(*m_xBuilder, "dialCtrl", *m_xCtrlDial))
+{
+ m_xCtrlDial->SetLinkedField(m_xNfRotate.get());
+ m_xCtrlDial->SetText(m_xFtABCD->get_label());
+ m_xCbStacked->connect_toggled(LINK(this, SchAlignmentTabPage, StackedToggleHdl));
+
+ m_xCtrlDialWin->set_sensitive(true);
+ m_xNfRotate->set_sensitive(true);
+ m_xCbStacked->set_sensitive(true);
+ m_xFtRotate->set_sensitive(true);
+
+ if( !bWithRotation )
+ {
+ m_xCtrlDialWin->hide();
+ m_xNfRotate->hide();
+ m_xCbStacked->hide();
+ m_xFtRotate->hide();
+ }
+}
+
+IMPL_LINK_NOARG(SchAlignmentTabPage, StackedToggleHdl, weld::Toggleable&, void)
+{
+ bool bActive = m_xCbStacked->get_active();
+ m_xNfRotate->set_sensitive(!bActive);
+ m_xCtrlDialWin->set_sensitive(!bActive);
+ m_xCtrlDial->StyleUpdated();
+ m_xFtRotate->set_sensitive(!bActive);
+}
+
+SchAlignmentTabPage::~SchAlignmentTabPage()
+{
+ m_xCtrlDialWin.reset();
+ m_xCtrlDial.reset();
+}
+
+std::unique_ptr<SfxTabPage> SchAlignmentTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rInAttrs)
+{
+ return std::make_unique<SchAlignmentTabPage>(pPage, pController, *rInAttrs);
+}
+
+std::unique_ptr<SfxTabPage> SchAlignmentTabPage::CreateWithoutRotation(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rInAttrs)
+{
+ return std::make_unique<SchAlignmentTabPage>(pPage, pController, *rInAttrs, false);
+}
+
+bool SchAlignmentTabPage::FillItemSet(SfxItemSet* rOutAttrs)
+{
+ //Since 04/1998 text can be rotated by an arbitrary angle: SCHATTR_TEXT_DEGREES
+ bool bStacked = m_xCbStacked->get_active();
+ rOutAttrs->Put( SfxBoolItem( SCHATTR_TEXT_STACKED, bStacked ) );
+
+ Degree100 nDegrees = bStacked ? 0_deg100 : m_xCtrlDial->GetRotation();
+ rOutAttrs->Put( SdrAngleItem( SCHATTR_TEXT_DEGREES, nDegrees ) );
+
+ SvxFrameDirection aDirection( m_aLbTextDirection.get_active_id() );
+ rOutAttrs->Put( SvxFrameDirectionItem( aDirection, EE_PARA_WRITINGDIR ) );
+
+ return true;
+}
+
+void SchAlignmentTabPage::Reset(const SfxItemSet* rInAttrs)
+{
+ const SfxPoolItem* pItem = GetItem( *rInAttrs, SCHATTR_TEXT_DEGREES );
+
+ Degree100 nDegrees = pItem ? static_cast<const SdrAngleItem*>(pItem)->GetValue() : 0_deg100;
+ m_xCtrlDial->SetRotation( nDegrees );
+
+ pItem = GetItem( *rInAttrs, SCHATTR_TEXT_STACKED );
+ bool bStacked = pItem && static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ m_xCbStacked->set_active(bStacked);
+ StackedToggleHdl(*m_xCbStacked);
+
+ if( const SvxFrameDirectionItem* pDirectionItem = rInAttrs->GetItemIfSet(EE_PARA_WRITINGDIR) )
+ m_aLbTextDirection.set_active_id(pDirectionItem->GetValue());
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_TitleRotation.hxx b/chart2/source/controller/dialogs/tp_TitleRotation.hxx
new file mode 100644
index 0000000000..9d59b693f9
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_TitleRotation.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <svx/dialcontrol.hxx>
+#include <TextDirectionListBox.hxx>
+
+namespace weld {
+ class CheckButton;
+ class CustomWeld;
+ class Label;
+ class SpinButton;
+ class ToggleButton;
+}
+
+namespace chart
+{
+
+class SchAlignmentTabPage : public SfxTabPage
+{
+private:
+ std::unique_ptr<weld::Label> m_xFtRotate;
+ std::unique_ptr<weld::MetricSpinButton> m_xNfRotate;
+ std::unique_ptr<weld::CheckButton> m_xCbStacked;
+ std::unique_ptr<weld::Label> m_xFtABCD;
+ TextDirectionListBox m_aLbTextDirection;
+ std::unique_ptr<svx::DialControl> m_xCtrlDial;
+ std::unique_ptr<weld::CustomWeld> m_xCtrlDialWin;
+
+ DECL_LINK(StackedToggleHdl, weld::Toggleable&, void);
+
+public:
+ SchAlignmentTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs, bool bWithRotation = true);
+ virtual ~SchAlignmentTabPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs);
+ static std::unique_ptr<SfxTabPage> CreateWithoutRotation(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs);
+ virtual bool FillItemSet(SfxItemSet* rOutAttrs) override;
+ virtual void Reset(const SfxItemSet* rInAttrs) override;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_Trendline.cxx b/chart2/source/controller/dialogs/tp_Trendline.cxx
new file mode 100644
index 0000000000..fe25959bdd
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_Trendline.cxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_Trendline.hxx"
+
+namespace chart
+{
+
+TrendlineTabPage::TrendlineTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs)
+ : SfxTabPage(pPage, pController, "modules/schart/ui/tp_Trendline.ui", "TP_TRENDLINE", &rInAttrs)
+ , m_aTrendlineResources(*m_xBuilder, rInAttrs)
+{
+}
+
+std::unique_ptr<SfxTabPage> TrendlineTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs)
+{
+ return std::make_unique<TrendlineTabPage>(pPage, pController, *rOutAttrs);
+}
+
+bool TrendlineTabPage::FillItemSet( SfxItemSet* rOutAttrs )
+{
+ m_aTrendlineResources.FillItemSet( rOutAttrs );
+ return true;
+}
+
+void TrendlineTabPage::Reset( const SfxItemSet* rInAttrs )
+{
+ m_aTrendlineResources.Reset( *rInAttrs );
+}
+
+void TrendlineTabPage::SetNumFormatter( SvNumberFormatter* pNumFormatter )
+{
+ m_aTrendlineResources.SetNumFormatter( pNumFormatter );
+}
+
+void TrendlineTabPage::SetNbPoints( sal_Int32 nNbPoints )
+{
+ m_aTrendlineResources.SetNbPoints( nNbPoints );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_Trendline.hxx b/chart2/source/controller/dialogs/tp_Trendline.hxx
new file mode 100644
index 0000000000..3a240af387
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_Trendline.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "res_Trendline.hxx"
+
+#include <sfx2/tabdlg.hxx>
+
+namespace chart
+{
+
+class TrendlineTabPage : public SfxTabPage
+{
+public:
+ TrendlineTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs);
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs );
+ virtual bool FillItemSet( SfxItemSet* rOutAttrs ) override;
+ virtual void Reset( const SfxItemSet* rInAttrs ) override;
+
+ void SetNumFormatter( SvNumberFormatter* pFormatter );
+ void SetNbPoints( sal_Int32 nNbPoints );
+
+private:
+ TrendlineResources m_aTrendlineResources;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx
new file mode 100644
index 0000000000..e0fd6a51f8
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "tp_Wizard_TitlesAndObjects.hxx"
+#include <res_Titles.hxx>
+#include <res_LegendPosition.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <Diagram.hxx>
+#include <AxisHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <utility>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+TitlesAndObjectsTabPage::TitlesAndObjectsTabPage(weld::Container* pPage, weld::DialogController* pController,
+ rtl::Reference<::chart::ChartModel> xChartModel,
+ const uno::Reference< uno::XComponentContext >& xContext )
+ : OWizardPage(pPage, pController, "modules/schart/ui/wizelementspage.ui", "WizElementsPage")
+ , m_xTitleResources(new TitleResources(*m_xBuilder, false))
+ , m_xLegendPositionResources(new LegendPositionResources(*m_xBuilder, xContext))
+ , m_xChartModel(std::move(xChartModel))
+ , m_xCC(xContext)
+ , m_bCommitToModel(true)
+ , m_aTimerTriggeredControllerLock( m_xChartModel )
+ , m_xCB_Grid_X(m_xBuilder->weld_check_button("x"))
+ , m_xCB_Grid_Y(m_xBuilder->weld_check_button("y"))
+ , m_xCB_Grid_Z(m_xBuilder->weld_check_button("z"))
+{
+ m_xTitleResources->connect_changed( LINK( this, TitlesAndObjectsTabPage, ChangeEditHdl ));
+ m_xLegendPositionResources->SetChangeHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));
+
+ m_xCB_Grid_X->connect_toggled( LINK( this, TitlesAndObjectsTabPage, ChangeCheckBoxHdl ));
+ m_xCB_Grid_Y->connect_toggled( LINK( this, TitlesAndObjectsTabPage, ChangeCheckBoxHdl ));
+ m_xCB_Grid_Z->connect_toggled( LINK( this, TitlesAndObjectsTabPage, ChangeCheckBoxHdl ));
+}
+
+TitlesAndObjectsTabPage::~TitlesAndObjectsTabPage()
+{
+}
+
+void TitlesAndObjectsTabPage::initializePage()
+{
+ m_bCommitToModel = false;
+
+ //init titles
+ {
+ TitleDialogData aTitleInput;
+ aTitleInput.readFromModel( m_xChartModel );
+ m_xTitleResources->writeToResources( aTitleInput );
+ }
+
+ //init legend
+ {
+ m_xLegendPositionResources->writeToResources( m_xChartModel );
+ }
+
+ //init grid checkboxes
+ {
+ rtl::Reference< Diagram > xDiagram = m_xChartModel->getFirstChartDiagram();
+ uno::Sequence< sal_Bool > aPossibilityList;
+ uno::Sequence< sal_Bool > aExistenceList;
+ AxisHelper::getAxisOrGridPossibilities( aPossibilityList, xDiagram, false );
+ AxisHelper::getAxisOrGridExistence( aExistenceList, xDiagram, false );
+ m_xCB_Grid_X->set_sensitive( aPossibilityList[0] );
+ m_xCB_Grid_Y->set_sensitive( aPossibilityList[1] );
+ m_xCB_Grid_Z->set_sensitive( aPossibilityList[2] );
+ m_xCB_Grid_X->set_active( aExistenceList[0] );
+ m_xCB_Grid_Y->set_active( aExistenceList[1] );
+ m_xCB_Grid_Z->set_active( aExistenceList[2] );
+ }
+
+ m_bCommitToModel = true;
+}
+
+bool TitlesAndObjectsTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ )
+{
+ if( m_xTitleResources->get_value_changed_from_saved() ) //titles may have changed in the meanwhile
+ commitToModel();
+ return true;//return false if this page should not be left
+}
+
+void TitlesAndObjectsTabPage::commitToModel()
+{
+ m_aTimerTriggeredControllerLock.startTimer();
+ rtl::Reference<::chart::ChartModel> xModel = m_xChartModel;
+
+ ControllerLockGuardUNO aLockedControllers( xModel );
+
+ //commit title changes to model
+ {
+ TitleDialogData aTitleOutput;
+ m_xTitleResources->readFromResources( aTitleOutput );
+ aTitleOutput.writeDifferenceToModel( xModel, m_xCC );
+ m_xTitleResources->save_value();
+ }
+
+ //commit legend changes to model
+ {
+ m_xLegendPositionResources->writeToModel( xModel );
+ }
+
+ //commit grid changes to model
+ {
+ rtl::Reference< Diagram > xDiagram = xModel->getFirstChartDiagram();
+ uno::Sequence< sal_Bool > aOldExistenceList;
+ AxisHelper::getAxisOrGridExistence( aOldExistenceList, xDiagram, false );
+ uno::Sequence< sal_Bool > aNewExistenceList(aOldExistenceList);
+ sal_Bool* pNewExistenceList = aNewExistenceList.getArray();
+ pNewExistenceList[0] = m_xCB_Grid_X->get_active();
+ pNewExistenceList[1] = m_xCB_Grid_Y->get_active();
+ pNewExistenceList[2] = m_xCB_Grid_Z->get_active();
+ AxisHelper::changeVisibilityOfGrids( xDiagram
+ , aOldExistenceList, aNewExistenceList );
+ }
+}
+
+IMPL_LINK_NOARG(TitlesAndObjectsTabPage, ChangeCheckBoxHdl, weld::Toggleable&, void)
+{
+ ChangeHdl(nullptr);
+}
+
+IMPL_LINK_NOARG(TitlesAndObjectsTabPage, ChangeEditHdl, weld::Entry&, void)
+{
+ ChangeHdl(nullptr);
+}
+
+IMPL_LINK_NOARG(TitlesAndObjectsTabPage, ChangeHdl, LinkParamNone*, void)
+{
+ if( m_bCommitToModel )
+ commitToModel();
+}
+
+bool TitlesAndObjectsTabPage::canAdvance() const
+{
+ return false;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx
new file mode 100644
index 0000000000..d2c30d8b43
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <TimerTriggeredControllerLock.hxx>
+
+#include <vcl/wizardmachine.hxx>
+#include <rtl/ref.hxx>
+
+#include <memory>
+
+namespace chart { class LegendPositionResources; }
+namespace chart { class TitleResources; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+class ChartModel;
+
+class TitlesAndObjectsTabPage final : public vcl::OWizardPage
+{
+public:
+ TitlesAndObjectsTabPage(weld::Container* pPage, weld::DialogController* pController,
+ rtl::Reference<::chart::ChartModel> xChartModel,
+ const css::uno::Reference< css::uno::XComponentContext >& xContext);
+ virtual ~TitlesAndObjectsTabPage() override;
+
+ virtual void initializePage() override;
+ virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason eReason ) override;
+ virtual bool canAdvance() const override;
+
+private:
+ void commitToModel();
+ DECL_LINK( ChangeHdl, LinkParamNone*, void );
+ DECL_LINK( ChangeEditHdl, weld::Entry&, void );
+ DECL_LINK( ChangeCheckBoxHdl, weld::Toggleable&, void );
+
+ std::unique_ptr< TitleResources > m_xTitleResources;
+ std::unique_ptr< LegendPositionResources > m_xLegendPositionResources;
+
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+ css::uno::Reference< css::uno::XComponentContext> m_xCC;
+
+ bool m_bCommitToModel;
+ TimerTriggeredControllerLock m_aTimerTriggeredControllerLock;
+
+ std::unique_ptr<weld::CheckButton> m_xCB_Grid_X;
+ std::unique_ptr<weld::CheckButton> m_xCB_Grid_Y;
+ std::unique_ptr<weld::CheckButton> m_xCB_Grid_Z;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/drawinglayer/DrawViewWrapper.cxx b/chart2/source/controller/drawinglayer/DrawViewWrapper.cxx
new file mode 100644
index 0000000000..1cd90c06b7
--- /dev/null
+++ b/chart2/source/controller/drawinglayer/DrawViewWrapper.cxx
@@ -0,0 +1,366 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DrawViewWrapper.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+
+#include <unotools/lingucfg.hxx>
+#include <unotools/syslocale.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/langitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/itempool.hxx>
+#include <svx/obj3d.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdetc.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/svxids.hrc>
+#include <editeng/fhgtitem.hxx>
+#include <osl/diagnose.h>
+
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+
+#include <sfx2/objsh.hxx>
+#include <svx/helperhittest3d.hxx>
+#include <officecfg/Office/Calc.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+namespace
+{
+ short lcl_getHitTolerance( OutputDevice const * pOutDev )
+ {
+ const short HITPIX=2; //hit-tolerance in pixel
+ short nHitTolerance = 50;
+ if(pOutDev)
+ nHitTolerance = static_cast<short>(pOutDev->PixelToLogic(Size(HITPIX,0)).Width());
+ return nHitTolerance;
+ }
+
+// this code is copied from sfx2/source/doc/objembed.cxx. It is a workaround to
+// get the reference device (e.g. printer) from the parent document
+OutputDevice * lcl_GetParentRefDevice( const uno::Reference< frame::XModel > & xModel )
+{
+ SfxObjectShell* pParent = SfxObjectShell::GetParentShell(xModel);
+ if ( pParent )
+ return pParent->GetDocumentRefDev();
+ return nullptr;
+}
+
+}
+
+DrawViewWrapper::DrawViewWrapper(
+ SdrModel& rSdrModel,
+ OutputDevice* pOut)
+: E3dView(rSdrModel, pOut)
+ ,m_pMarkHandleProvider(nullptr)
+ ,m_apOutliner(SdrMakeOutliner(OutlinerMode::TextObject, rSdrModel))
+ ,m_bRestoreMapMode( false )
+{
+ SetBufferedOutputAllowed(true);
+ SetBufferedOverlayAllowed(true);
+
+ // #i12587# support for shapes in chart
+ SdrOutliner* pOutliner = getOutliner();
+ SfxItemPool* pOutlinerPool = ( pOutliner ? pOutliner->GetEditTextObjectPool() : nullptr );
+ if ( pOutlinerPool )
+ {
+ SvtLinguConfig aLinguConfig;
+ SvtLinguOptions aLinguOptions;
+ aLinguConfig.GetOptions( aLinguOptions );
+ pOutlinerPool->SetPoolDefaultItem( SvxLanguageItem( aLinguOptions.nDefaultLanguage, EE_CHAR_LANGUAGE ) );
+ pOutlinerPool->SetPoolDefaultItem( SvxLanguageItem( aLinguOptions.nDefaultLanguage_CJK, EE_CHAR_LANGUAGE_CJK ) );
+ pOutlinerPool->SetPoolDefaultItem( SvxLanguageItem( aLinguOptions.nDefaultLanguage_CTL, EE_CHAR_LANGUAGE_CTL ) );
+
+ // set font height without changing SdrEngineDefaults
+ pOutlinerPool->SetPoolDefaultItem( SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT ) ); // 12pt
+ }
+
+ // #i121463# Use big handles by default
+ SetMarkHdlSizePixel(9);
+
+ ReInit();
+}
+
+void DrawViewWrapper::ReInit()
+{
+ OutputDevice* pOutDev = GetFirstOutputDevice();
+ Size aOutputSize(100,100);
+ if(pOutDev)
+ aOutputSize = pOutDev->GetOutputSize();
+
+ mbPageVisible = false;
+ mbPageBorderVisible = false;
+ mbBordVisible = false;
+ mbGridVisible = false;
+ mbHlplVisible = false;
+
+ SetNoDragXorPolys(true);//for interactive 3D resize-dragging: paint only a single rectangle (not a simulated 3D object)
+
+ //a correct work area is at least necessary for correct values in the position and size dialog
+ tools::Rectangle aRect(Point(0,0), aOutputSize);
+ SetWorkArea(aRect);
+
+ ShowSdrPage(GetModel().GetPage(0));
+}
+
+DrawViewWrapper::~DrawViewWrapper()
+{
+ maComeBackIdle.Stop();//@todo this should be done in destructor of base class
+ UnmarkAllObj();//necessary to avoid a paint call during the destructor hierarchy
+}
+
+SdrPageView* DrawViewWrapper::GetPageView() const
+{
+ SdrPageView* pSdrPageView = GetSdrPageView();
+ return pSdrPageView;
+};
+
+void DrawViewWrapper::SetMarkHandles(SfxViewShell* pOtherShell)
+{
+ if( m_pMarkHandleProvider && m_pMarkHandleProvider->getMarkHandles( maHdlList ) )
+ return;
+ else
+ SdrView::SetMarkHandles(pOtherShell);
+}
+
+SdrObject* DrawViewWrapper::getHitObject( const Point& rPnt ) const
+{
+ SdrPageView* pSdrPageView = GetPageView();
+ SdrObject* pRet = SdrView::PickObj(rPnt, lcl_getHitTolerance( GetFirstOutputDevice() ), pSdrPageView,
+ SdrSearchOptions::DEEP | SdrSearchOptions::TESTMARKABLE);
+
+ if( pRet )
+ {
+ // ignore some special shapes
+ OUString aShapeName = pRet->GetName();
+
+ // return right away if it is a field button
+ if (aShapeName.startsWith("FieldButton"))
+ return pRet;
+
+ if( aShapeName.match("PlotAreaIncludingAxes") || aShapeName.match("PlotAreaExcludingAxes") )
+ {
+ pRet->SetMarkProtect( true );
+ return getHitObject( rPnt );
+ }
+
+ //3d objects need a special treatment
+ //because the simple PickObj method is not accurate in this case for performance reasons
+ E3dObject* pE3d = DynCastE3dObject(pRet);
+ if( pE3d )
+ {
+ E3dScene* pScene(pE3d->getRootE3dSceneFromE3dObject());
+
+ if(nullptr != pScene)
+ {
+ // prepare result vector and call helper
+ std::vector< const E3dCompoundObject* > aHitList;
+ const basegfx::B2DPoint aHitPoint(rPnt.X(), rPnt.Y());
+ getAllHit3DObjectsSortedFrontToBack(aHitPoint, *pScene, aHitList);
+
+ if(!aHitList.empty())
+ {
+ // choose the frontmost hit 3D object of the scene
+ pRet = const_cast< E3dCompoundObject* >(aHitList[0]);
+ }
+ }
+ }
+ }
+ return pRet;
+}
+
+void DrawViewWrapper::MarkObject( SdrObject* pObj )
+{
+ bool bFrameDragSingles = true;//true == green == surrounding handles
+ if(pObj)
+ pObj->SetMarkProtect(false);
+ if( m_pMarkHandleProvider )
+ bFrameDragSingles = m_pMarkHandleProvider->getFrameDragSingles();
+
+ SetFrameDragSingles(bFrameDragSingles);//decide whether each single object should get handles
+ SdrView::MarkObj( pObj, GetPageView() );
+ showMarkHandles();
+}
+
+void DrawViewWrapper::setMarkHandleProvider( MarkHandleProvider* pMarkHandleProvider )
+{
+ m_pMarkHandleProvider = pMarkHandleProvider;
+}
+
+void DrawViewWrapper::CompleteRedraw(OutputDevice* pOut, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* /* pRedirector */)
+{
+ svtools::ColorConfig aColorConfig;
+ Color aFillColor( aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor );
+ SetApplicationBackgroundColor(aFillColor);
+ E3dView::CompleteRedraw( pOut, rReg );
+}
+
+SdrObject* DrawViewWrapper::getSelectedObject() const
+{
+ SdrObject* pObj(nullptr);
+ const SdrMarkList& rMarkList = GetMarkedObjectList();
+ if(rMarkList.GetMarkCount() == 1)
+ {
+ SdrMark* pMark = rMarkList.GetMark(0);
+ pObj = pMark->GetMarkedSdrObj();
+ }
+ return pObj;
+}
+
+SdrObject* DrawViewWrapper::getTextEditObject() const
+{
+ SdrObject* pObj = getSelectedObject();
+ SdrObject* pTextObj = nullptr;
+ if( pObj && pObj->HasTextEdit())
+ pTextObj = pObj;
+ return pTextObj;
+}
+
+void DrawViewWrapper::attachParentReferenceDevice( const uno::Reference< frame::XModel > & xChartModel )
+{
+ OutputDevice * pParentRefDev( lcl_GetParentRefDevice( xChartModel ));
+ SdrOutliner * pOutliner( getOutliner());
+ if( pParentRefDev && pOutliner )
+ {
+ pOutliner->SetRefDevice( pParentRefDev );
+ }
+}
+
+SdrOutliner* DrawViewWrapper::getOutliner() const
+{
+ return m_apOutliner.get();
+}
+
+SfxItemSet DrawViewWrapper::getPositionAndSizeItemSetFromMarkedObject() const
+{
+ SvtSysLocale aSysLocale;
+ MeasurementSystem eSys = aSysLocale.GetLocaleData().getMeasurementSystemEnum();
+ sal_uInt16 nAttrMetric;
+ if( eSys == MeasurementSystem::Metric )
+ nAttrMetric = officecfg::Office::Calc::Layout::Other::MeasureUnit::Metric::get();
+ else
+ nAttrMetric = officecfg::Office::Calc::Layout::Other::MeasureUnit::NonMetric::get();
+
+ SfxItemSet aFullSet(
+ GetModel().GetItemPool(),
+ svl::Items<
+ SDRATTR_CORNER_RADIUS, SDRATTR_CORNER_RADIUS,
+ SID_ATTR_TRANSFORM_POS_X, SID_ATTR_TRANSFORM_ANGLE,
+ SID_ATTR_TRANSFORM_PROTECT_POS, SID_ATTR_TRANSFORM_AUTOHEIGHT,
+ SID_ATTR_METRIC, SID_ATTR_METRIC>);
+ SfxItemSet aGeoSet( E3dView::GetGeoAttrFromMarked() );
+ aFullSet.Put( aGeoSet );
+ aFullSet.Put( SfxUInt16Item(SID_ATTR_METRIC, nAttrMetric) );
+ return aFullSet;
+}
+
+SdrObject* DrawViewWrapper::getNamedSdrObject( const OUString& rName ) const
+{
+ if(rName.isEmpty())
+ return nullptr;
+ SdrPageView* pSdrPageView = GetPageView();
+ if( pSdrPageView )
+ {
+ return DrawModelWrapper::getNamedSdrObject( rName, pSdrPageView->GetObjList() );
+ }
+ return nullptr;
+}
+
+bool DrawViewWrapper::IsObjectHit( SdrObject const * pObj, const Point& rPnt )
+{
+ if(pObj)
+ {
+ tools::Rectangle aRect(pObj->GetCurrentBoundRect());
+ return aRect.Contains(rPnt);
+ }
+ return false;
+}
+
+void DrawViewWrapper::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
+{
+ //prevent wrong reselection of objects
+ SdrModel& rSdrModel = GetModel();
+ if (rSdrModel.isLocked())
+ return;
+
+ const SdrHint* pSdrHint = ( rHint.GetId() == SfxHintId::ThisIsAnSdrHint ? static_cast<const SdrHint*>(&rHint) : nullptr );
+
+ //#i76053# do nothing when only changes on the hidden draw page were made ( e.g. when the symbols for the dialogs are created )
+ SdrPageView* pSdrPageView = GetPageView();
+ if( pSdrHint && pSdrPageView )
+ {
+ if( pSdrPageView->GetPage() != pSdrHint->GetPage() )
+ return;
+ }
+
+ E3dView::Notify(rBC, rHint);
+
+ if( pSdrHint == nullptr )
+ return;
+
+ SdrHintKind eKind = pSdrHint->GetKind();
+ if( eKind == SdrHintKind::BeginEdit )
+ {
+ // #i79965# remember map mode
+ OSL_ASSERT( ! m_bRestoreMapMode );
+ OutputDevice* pOutDev = GetFirstOutputDevice();
+ if( pOutDev )
+ {
+ m_aMapModeToRestore = pOutDev->GetMapMode();
+ m_bRestoreMapMode = true;
+ }
+ }
+ else if( eKind == SdrHintKind::EndEdit )
+ {
+ // #i79965# scroll back view when ending text edit
+ OSL_ASSERT( m_bRestoreMapMode );
+ if( m_bRestoreMapMode )
+ {
+ OutputDevice* pOutDev = GetFirstOutputDevice();
+ if( pOutDev )
+ {
+ pOutDev->SetMapMode( m_aMapModeToRestore );
+ m_bRestoreMapMode = false;
+ }
+ }
+ }
+}
+
+SdrObject* DrawViewWrapper::getSdrObject( const uno::Reference<
+ drawing::XShape >& xShape )
+{
+ SdrObject* pRet = nullptr;
+ uno::Reference< lang::XTypeProvider > xTypeProvider( xShape, uno::UNO_QUERY );
+ if(xTypeProvider.is())
+ {
+ pRet = SdrObject::getSdrObjectFromXShape(xShape);
+ }
+ return pRet;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/drawinglayer/ViewElementListProvider.cxx b/chart2/source/controller/drawinglayer/ViewElementListProvider.cxx
new file mode 100644
index 0000000000..0b3df1aa22
--- /dev/null
+++ b/chart2/source/controller/drawinglayer/ViewElementListProvider.cxx
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <ViewElementListProvider.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <chartview/DataPointSymbolSupplier.hxx>
+#include <DrawViewWrapper.hxx>
+
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <o3tl/safeint.hxx>
+#include <svx/xtable.hxx>
+#include <svl/itempool.hxx>
+#include <svtools/ctrltool.hxx>
+#include <vcl/svapp.hxx>
+#include <svx/svdobj.hxx>
+#include <vcl/virdev.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svdpage.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+ViewElementListProvider::ViewElementListProvider( DrawModelWrapper* pDrawModelWrapper )
+ : m_pDrawModelWrapper( pDrawModelWrapper )
+{
+}
+
+ViewElementListProvider::ViewElementListProvider(ViewElementListProvider&& rOther) noexcept
+{
+ m_pDrawModelWrapper = rOther.m_pDrawModelWrapper;
+ m_pFontList = std::move(rOther.m_pFontList);
+}
+
+ViewElementListProvider::~ViewElementListProvider()
+{
+}
+
+XColorListRef ViewElementListProvider::GetColorTable() const
+{
+ if(m_pDrawModelWrapper)
+ return m_pDrawModelWrapper->GetColorList();
+ return XColorListRef();
+}
+
+XDashListRef ViewElementListProvider::GetDashList() const
+{
+ if(m_pDrawModelWrapper)
+ return m_pDrawModelWrapper->GetDashList();
+ return XDashListRef();
+}
+
+XLineEndListRef ViewElementListProvider::GetLineEndList() const
+{
+ if(m_pDrawModelWrapper)
+ return m_pDrawModelWrapper->GetLineEndList();
+ return XLineEndListRef();
+}
+
+XGradientListRef ViewElementListProvider::GetGradientList() const
+{
+ if(m_pDrawModelWrapper)
+ return m_pDrawModelWrapper->GetGradientList();
+ return XGradientListRef();
+}
+XHatchListRef ViewElementListProvider::GetHatchList() const
+{
+ if(m_pDrawModelWrapper)
+ return m_pDrawModelWrapper->GetHatchList();
+ return nullptr;
+}
+
+XBitmapListRef ViewElementListProvider::GetBitmapList() const
+{
+ if(m_pDrawModelWrapper)
+ return m_pDrawModelWrapper->GetBitmapList();
+ return XBitmapListRef();
+}
+
+XPatternListRef ViewElementListProvider::GetPatternList() const
+{
+ if(m_pDrawModelWrapper)
+ return m_pDrawModelWrapper->GetPatternList();
+ return XPatternListRef();
+}
+
+//create chartspecific symbols for linecharts
+SdrObjList* ViewElementListProvider::GetSymbolList() const
+{
+ SdrObjList* pSymbolList = nullptr;
+ try
+ {
+ //@todo use mutex
+
+ //get hidden draw page (target):
+ rtl::Reference<SvxDrawPage> xTarget = m_pDrawModelWrapper->getHiddenDrawPage();
+
+ //create symbols via uno and convert to native sdr objects
+ drawing::Direction3D aSymbolSize(220, 220, 0); // should be 250, but 250 -> 280 ??
+ rtl::Reference< SvxShapeGroup > xSymbols
+ = DataPointSymbolSupplier::create2DSymbolList(xTarget, aSymbolSize);
+
+ SdrObject* pSdrObject = DrawViewWrapper::getSdrObject(
+ uno::Reference<drawing::XShape>(static_cast<cppu::OWeakObject*>(xSymbols.get()), uno::UNO_QUERY));
+ if (pSdrObject)
+ pSymbolList = pSdrObject->GetSubList();
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return pSymbolList;
+}
+
+Graphic ViewElementListProvider::GetSymbolGraphic( sal_Int32 nStandardSymbol, const SfxItemSet* pSymbolShapeProperties ) const
+{
+ SdrObjList* pSymbolList = GetSymbolList();
+ if( !pSymbolList->GetObjCount() )
+ return Graphic();
+ if(nStandardSymbol<0)
+ nStandardSymbol*=-1;
+ if( o3tl::make_unsigned(nStandardSymbol) >= pSymbolList->GetObjCount() )
+ nStandardSymbol %= pSymbolList->GetObjCount();
+ rtl::Reference<SdrObject> pObj = pSymbolList->GetObj(nStandardSymbol);
+
+ ScopedVclPtrInstance< VirtualDevice > pVDev;
+ pVDev->SetMapMode(MapMode(MapUnit::Map100thMM));
+
+ std::unique_ptr<SdrModel> pModel(
+ new SdrModel());
+
+ pModel->GetItemPool().FreezeIdRanges();
+ rtl::Reference<SdrPage> pPage = new SdrPage( *pModel, false );
+ pPage->SetSize(Size(1000,1000));
+ pModel->InsertPage( pPage.get(), 0 );
+ SdrView aView(*pModel, pVDev);
+ aView.hideMarkHandles();
+ SdrPageView* pPageView = aView.ShowSdrPage(pPage.get());
+
+ // directly clone to target SdrModel
+ pObj = pObj->CloneSdrObject(*pModel);
+
+ pPage->NbcInsertObject(pObj.get());
+ aView.MarkObj(pObj.get(),pPageView);
+ if( pSymbolShapeProperties )
+ pObj->SetMergedItemSet(*pSymbolShapeProperties);
+
+ GDIMetaFile aMeta(aView.GetMarkedObjMetaFile());
+
+ Graphic aGraph(aMeta);
+ Size aSize = pObj->GetSnapRect().GetSize();
+ aGraph.SetPrefSize(aSize);
+ aGraph.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+
+ aView.UnmarkAll();
+ pObj=pPage->RemoveObject(0);
+ // these need to die before the associated SdrModel
+ pObj.clear();
+ pPage.clear();
+
+ return aGraph;
+}
+
+FontList* ViewElementListProvider::getFontList() const
+{
+ //was old chart:
+ //SvxFontListItem* SfxObjectShell::.GetItem(SID_ATTR_CHAR_FONTLIST)
+
+ if(!m_pFontList)
+ {
+ OutputDevice* pRefDev = m_pDrawModelWrapper ? m_pDrawModelWrapper->getReferenceDevice() : nullptr;
+ OutputDevice* pDefaultOut = Application::GetDefaultDevice();
+ m_pFontList.reset( new FontList( pRefDev ? pRefDev : pDefaultOut
+ , pRefDev ? pDefaultOut : nullptr) );
+ }
+ return m_pFontList.get();
+}
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/AccessibleBase.hxx b/chart2/source/controller/inc/AccessibleBase.hxx
new file mode 100644
index 0000000000..a6076a0cc1
--- /dev/null
+++ b/chart2/source/controller/inc/AccessibleBase.hxx
@@ -0,0 +1,322 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ObjectIdentifier.hxx>
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <comphelper/accessibleeventnotifier.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <rtl/ref.hxx>
+#include <tools/color.hxx>
+#include <unotools/weakref.hxx>
+
+#include <map>
+#include <vector>
+#include <memory>
+
+namespace com::sun::star::awt { class XWindow; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::view { class XSelectionSupplier; }
+
+
+class SdrView;
+
+namespace accessibility
+{
+class IAccessibleViewForwarder;
+}
+
+namespace chart
+{
+
+class AccessibleBase;
+class ChartView;
+class ObjectHierarchy;
+class ChartController;
+
+typedef ObjectIdentifier AccessibleUniqueId;
+
+struct AccessibleElementInfo
+{
+ AccessibleUniqueId m_aOID;
+
+ unotools::WeakReference< ::chart::ChartModel > m_xChartDocument;
+ unotools::WeakReference< ::chart::ChartController > m_xChartController;
+ unotools::WeakReference< ::chart::ChartView > m_xView;
+ css::uno::WeakReference< css::awt::XWindow > m_xWindow;
+
+ std::shared_ptr< ObjectHierarchy > m_spObjectHierarchy;
+
+ AccessibleBase * m_pParent;
+ SdrView* m_pSdrView;
+ ::accessibility::IAccessibleViewForwarder* m_pViewForwarder;
+};
+
+namespace impl
+{
+typedef ::cppu::WeakComponentImplHelper<
+ css::accessibility::XAccessible,
+ css::accessibility::XAccessibleContext,
+ css::accessibility::XAccessibleComponent,
+ css::accessibility::XAccessibleEventBroadcaster,
+ css::lang::XServiceInfo,
+ css::lang::XEventListener
+ > AccessibleBase_Base;
+}
+
+/** Base class for all Chart Accessibility objects
+ */
+class AccessibleBase :
+ public cppu::BaseMutex,
+ public impl::AccessibleBase_Base
+{
+public:
+ enum class EventType
+ {
+ GOT_SELECTION,
+ LOST_SELECTION
+ };
+
+ AccessibleBase( AccessibleElementInfo aAccInfo,
+ bool bMayHaveChildren,
+ bool bAlwaysTransparent );
+ virtual ~AccessibleBase() override;
+
+protected:
+ // for all calls to protected methods it is assumed that the mutex is locked
+ // unless calls outside via UNO, e.g. event notification, are done
+
+ /** @param bThrowException if true, a DisposedException is thrown if the
+ object is already disposed
+ @return true, if the component is already disposed and bThrowException is false,
+ false otherwise
+ @throws css::lang::DisposedException
+ */
+ bool CheckDisposeState( bool bThrowException = true ) const;
+
+ /** Events coming from the core have to be processed in this methods. The
+ default implementation returns false, which indicates that the object is
+ not interested in the event. To react on events you have to implement
+ this method in derived classes.
+
+ The default implementation iterates over all children and forwards the
+ event until the first child returns true.
+
+ @param nObjId contains the object id of chart objects. If the object is
+ no chart object, the event is not broadcast.
+ @return If an object is the addressee of the event it should return
+ true, false otherwise.
+ */
+ bool NotifyEvent( EventType eType, const AccessibleUniqueId & rId );
+
+ /** Adds a state to the set.
+
+ @throws css::uno::RuntimeException
+ */
+ void AddState( sal_Int64 aState );
+
+ /** Removes a state from the set if the set contains the state, otherwise
+ nothing is done.
+
+ @throws css::uno::RuntimeException
+ */
+ void RemoveState( sal_Int64 aState );
+
+ /** has to be overridden by derived classes that support child elements.
+ With this method a rescan is initiated that should result in a correct
+ list of children.
+
+ This method is called when access to any methods concerning children is
+ invoked for the first time.
+ */
+ bool UpdateChildren();
+
+ /** Is called by UpdateChildren. This method is only called if an update is
+ really necessary.
+ */
+ virtual bool ImplUpdateChildren();
+
+ /** adds a child to the end of the internal vector of children. As a
+ result, the child-count increases by one, but all existing children keep
+ their indices.
+
+ Important: as the implementation is needed, this should remain the only
+ method for adding children (i.e. there mustn't be an AddChild( Reference<
+ XAccessible > ) or the like).
+ */
+ void AddChild( AccessibleBase* pChild );
+
+ /** removes a child from the internal vector. All children with index
+ greater than the index of the removed element get an index one less than
+ before.
+ */
+ void RemoveChildByOId( const ObjectIdentifier& rOId );
+
+ /** Retrieve the pixel coordinates of logical coordinates (0,0) of the
+ current logic coordinate system. This can be used for
+ getLocationOnScreen, if the coordinates of an object are not relative to
+ its direct parent, but a parent higher up in hierarchy.
+
+ @return the (x,y) pixel coordinates of the upper left corner
+ */
+ virtual css::awt::Point GetUpperLeftOnScreen() const;
+
+ /** This method creates an AccessibleEventObject and sends it to all
+ listeners that are currently listening to this object
+ */
+ void BroadcastAccEvent( sal_Int16 nId,
+ const css::uno::Any & rNew,
+ const css::uno::Any & rOld ) const;
+
+ /** Removes all children from the internal lists and broadcasts child remove
+ events.
+
+ This method cares about mutex locking, and thus should be called without
+ the mutex locked.
+ */
+ void KillAllChildren();
+
+ /** Is called from getAccessibleChild(). Before this method is called, an
+ update of children is done if necessary.
+
+ @throws css::lang::IndexOutOfBoundsException
+ @throws css::uno::RuntimeException
+ */
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ ImplGetAccessibleChildById( sal_Int64 i ) const;
+
+ /** Is called from getAccessibleChildCount(). Before this method is called,
+ an update of children is done if necessary.
+
+ @throws css::uno::RuntimeException
+ */
+ virtual sal_Int64 ImplGetAccessibleChildCount() const;
+
+ const AccessibleElementInfo& GetInfo() const { return m_aAccInfo;}
+ void SetInfo( const AccessibleElementInfo & rNewInfo );
+ const AccessibleUniqueId& GetId() const { return m_aAccInfo.m_aOID;}
+
+ // ________ WeakComponentImplHelper (XComponent::dispose) ________
+ virtual void SAL_CALL disposing() override;
+
+ // ________ XAccessible ________
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override;
+
+ // ________ XAccessibleContext ________
+ virtual sal_Int64 SAL_CALL getAccessibleChildCount() override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+ getAccessibleChild( sal_Int64 i ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+ getAccessibleParent() override;
+ virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override;
+ /// @return AccessibleRole.SHAPE
+ virtual sal_Int16 SAL_CALL getAccessibleRole() override;
+ // has to be implemented by derived classes
+// virtual OUString SAL_CALL getAccessibleName()
+// throw (css::uno::RuntimeException);
+ virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL
+ getAccessibleRelationSet() override;
+ virtual sal_Int64 SAL_CALL getAccessibleStateSet() override;
+ virtual css::lang::Locale SAL_CALL getLocale() override;
+ // has to be implemented by derived classes
+// virtual OUString SAL_CALL getAccessibleDescription()
+// throw (css::uno::RuntimeException);
+
+ // ________ XAccessibleComponent ________
+ virtual sal_Bool SAL_CALL containsPoint(
+ const css::awt::Point& aPoint ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
+ getAccessibleAtPoint( const css::awt::Point& aPoint ) override;
+ // has to be defined in derived classes
+ virtual css::awt::Rectangle SAL_CALL getBounds() override;
+ virtual css::awt::Point SAL_CALL getLocation() override;
+ virtual css::awt::Point SAL_CALL getLocationOnScreen() override;
+ virtual css::awt::Size SAL_CALL getSize() override;
+ virtual void SAL_CALL grabFocus() override;
+ virtual sal_Int32 SAL_CALL getForeground() override;
+ virtual sal_Int32 SAL_CALL getBackground() override;
+
+ // ________ XServiceInfo ________
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(
+ const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ________ XEventListener ________
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ________ XAccessibleEventBroadcaster ________
+ virtual void SAL_CALL addAccessibleEventListener(
+ const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override;
+ virtual void SAL_CALL removeAccessibleEventListener(
+ const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override;
+
+private:
+ enum eColorType
+ {
+ ACC_BASE_FOREGROUND,
+ ACC_BASE_BACKGROUND
+ };
+ Color getColor( eColorType eColType );
+
+private:
+ /** type of the vector containing the accessible children
+ */
+ typedef std::vector< css::uno::Reference< css::accessibility::XAccessible > > ChildListVectorType;
+ /** type of the hash containing a vector index for every AccessibleUniqueId
+ of the object in the child list
+ */
+ typedef std::map< ObjectIdentifier, css::uno::Reference< css::accessibility::XAccessible > > ChildOIDMap;
+
+ bool m_bIsDisposed;
+ const bool m_bMayHaveChildren;
+ bool m_bChildrenInitialized;
+ ChildListVectorType m_aChildList;
+
+ ChildOIDMap m_aChildOIDMap;
+
+ ::comphelper::AccessibleEventNotifier::TClientId m_nEventNotifierId;
+
+ /** for getAccessibleStateSet()
+ */
+ sal_Int64 m_nStateSet;
+
+ AccessibleElementInfo m_aAccInfo;
+ const bool m_bAlwaysTransparent;
+ /** denotes if the state-set is initialized. On initialization the selected
+ state is checked.
+
+ This variable is monitored by the solar mutex!
+
+ Note: declared volatile to enable double-check-locking
+ */
+ volatile bool m_bStateSetInitialized;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/AccessibleChartView.hxx b/chart2/source/controller/inc/AccessibleChartView.hxx
new file mode 100644
index 0000000000..793cdd69ab
--- /dev/null
+++ b/chart2/source/controller/inc/AccessibleChartView.hxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "AccessibleBase.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+
+#include <memory>
+
+namespace com::sun::star::accessibility { class XAccessible; }
+namespace com::sun::star::awt { class XWindow; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::view { class XSelectionSupplier; }
+
+namespace accessibility
+{
+class IAccessibleViewForwarder;
+}
+
+namespace chart
+{
+class ChartView;
+
+namespace impl
+{
+typedef ::cppu::ImplInheritanceHelper<
+ ::chart::AccessibleBase,
+ css::view::XSelectionChangeListener >
+ AccessibleChartView_Base;
+}
+
+class AccessibleChartView final :
+ public impl::AccessibleChartView_Base
+{
+public:
+ AccessibleChartView( SdrView* pView );
+ virtual ~AccessibleChartView() override;
+
+ AccessibleChartView() = delete;
+
+ // ____ WeakComponentHelper (called from XComponent::dispose()) ____
+ using AccessibleBase::disposing;
+
+ // 0: view::XSelectionSupplier offers notifications for selection changes and access to the selection itself
+ // 1: frame::XModel representing the chart model - offers access to object data
+ // 2: lang::XInterface representing the normal chart view - offers access to some extra object data
+ // 3: accessibility::XAccessible representing the parent accessible
+ // 4: awt::XWindow representing the view's window (is a vcl Window)
+ // all arguments are only valid until next initialization - don't keep them longer
+ void initialize( ChartController& rChartController,
+ const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const rtl::Reference<::chart::ChartView>& xChartView,
+ const css::uno::Reference< css::accessibility::XAccessible >& xParent,
+ const css::uno::Reference<css::awt::XWindow>& xViewWindow );
+ // used to disconnect from view
+ void initialize();
+
+ // ____ view::XSelectionChangeListener ____
+ virtual void SAL_CALL selectionChanged( const css::lang::EventObject& aEvent ) override;
+
+ // ________ XEventListener ________
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // ________ XAccessibleContext ________
+ virtual OUString SAL_CALL getAccessibleDescription() override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override;
+ virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override;
+ virtual OUString SAL_CALL getAccessibleName() override;
+ virtual sal_Int16 SAL_CALL getAccessibleRole() override;
+
+ // ________ XAccessibleComponent ________
+ virtual css::awt::Rectangle SAL_CALL getBounds() override;
+ virtual css::awt::Point SAL_CALL getLocationOnScreen() override;
+
+protected:
+ // ________ AccessibleChartElement ________
+ virtual css::awt::Point GetUpperLeftOnScreen() const override;
+
+private: // methods
+ /** @return the result that m_xWindow->getPosSize() _should_ return. It
+ returns (0,0) as upper left corner. When calling
+ getAccessibleParent, you get the parent's parent, which contains
+ a decoration. Thus you have an offset of (currently) (2,2)
+ which isn't taken into account.
+ */
+ css::awt::Rectangle GetWindowPosSize() const;
+
+private: // members
+ unotools::WeakReference< ::chart::ChartController > m_xChartController;
+ unotools::WeakReference< ::chart::ChartModel > m_xChartModel;
+ unotools::WeakReference< ChartView > m_xChartView;
+ css::uno::WeakReference< css::awt::XWindow > m_xWindow;
+ css::uno::WeakReference< css::accessibility::XAccessible > m_xParent;
+
+ std::shared_ptr< ObjectHierarchy > m_spObjectHierarchy;
+ AccessibleUniqueId m_aCurrentSelectionOID;
+ SdrView* m_pSdrView;
+ std::unique_ptr<::accessibility::IAccessibleViewForwarder> m_pViewForwarder;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/AccessibleTextHelper.hxx b/chart2/source/controller/inc/AccessibleTextHelper.hxx
new file mode 100644
index 0000000000..937af7da05
--- /dev/null
+++ b/chart2/source/controller/inc/AccessibleTextHelper.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include <comphelper/compbase.hxx>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+
+// forward declaration of helper class from svx
+namespace accessibility
+{
+class AccessibleTextHelper;
+}
+
+namespace chart
+{
+
+class DrawViewWrapper;
+
+namespace impl
+{
+typedef comphelper::WeakComponentImplHelper<
+ css::accessibility::XAccessibleContext >
+ AccessibleTextHelper_Base;
+}
+
+class AccessibleTextHelper final :
+ public impl::AccessibleTextHelper_Base
+{
+public:
+ explicit AccessibleTextHelper( DrawViewWrapper * pDrawViewWrapper );
+ virtual ~AccessibleTextHelper() override;
+
+ /** Must be called at least once for this helper class to work.
+
+ mandatory parameter 0: type string. This is the CID that is used to find
+ the corresponding drawing object that contains the text that should
+ be handled by this helper class.
+1
+ mandatory parameter 1: type XAccessible. Is used as EventSource for the
+ ::accessibility::AccessibleTextHelper (svx)
+
+ mandatory parameter 2: type awt::XWindow. The Window that shows the
+ text currently.
+ */
+ void initialize(const OUString& aCID,
+ const css::uno::Reference< css::accessibility::XAccessible >& xEventSource,
+ const css::uno::Reference< css::awt::XWindow >& xWindow );
+
+ // ____ XAccessibleContext ____
+ virtual sal_Int64 SAL_CALL getAccessibleChildCount() override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(
+ sal_Int64 i ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override;
+ virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override;
+ virtual ::sal_Int16 SAL_CALL getAccessibleRole() override;
+ virtual OUString SAL_CALL getAccessibleDescription() override;
+ virtual OUString SAL_CALL getAccessibleName() override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override;
+ virtual sal_Int64 SAL_CALL getAccessibleStateSet() override;
+ virtual css::lang::Locale SAL_CALL getLocale() override;
+
+private:
+ std::unique_ptr<::accessibility::AccessibleTextHelper> m_pTextHelper;
+ DrawViewWrapper * m_pDrawViewWrapper;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/AxisItemConverter.hxx b/chart2/source/controller/inc/AxisItemConverter.hxx
new file mode 100644
index 0000000000..c9f3049356
--- /dev/null
+++ b/chart2/source/controller/inc/AxisItemConverter.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+#include <rtl/ref.hxx>
+
+#include <vector>
+
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XAxis; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace chart { class Axis; }
+namespace chart { struct ExplicitIncrementData; }
+namespace chart { struct ExplicitScaleData; }
+namespace chart { class ChartModel; }
+
+class SdrModel;
+
+namespace chart::wrapper {
+
+class AxisItemConverter final : public ItemConverter
+{
+public:
+ AxisItemConverter(
+ const css::uno::Reference<css::beans::XPropertySet>& rPropertySet,
+ SfxItemPool& rItemPool, SdrModel& rDrawModel,
+ const rtl::Reference<::chart::ChartModel> & xChartDoc,
+ ExplicitScaleData const * pScale,
+ ExplicitIncrementData const * pIncrement,
+ const css::awt::Size* pRefSize );
+
+ virtual ~AxisItemConverter() override;
+
+ virtual void FillItemSet( SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplyItemSet( const SfxItemSet & rItemSet ) override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ std::vector< std::unique_ptr<ItemConverter> > m_aConverters;
+ rtl::Reference<::chart::Axis> m_xAxis;
+
+ rtl::Reference<::chart::ChartModel>m_xChartDoc;
+
+ std::unique_ptr<ExplicitScaleData> m_pExplicitScale;
+ std::unique_ptr<ExplicitIncrementData> m_pExplicitIncrement;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/CharacterPropertyItemConverter.hxx b/chart2/source/controller/inc/CharacterPropertyItemConverter.hxx
new file mode 100644
index 0000000000..a3d6ed6b26
--- /dev/null
+++ b/chart2/source/controller/inc/CharacterPropertyItemConverter.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+#include <com/sun/star/awt/Size.hpp>
+
+#include <optional>
+
+namespace chart::wrapper {
+
+class CharacterPropertyItemConverter final : public ItemConverter
+{
+public:
+ CharacterPropertyItemConverter(
+ const css::uno::Reference<css::beans::XPropertySet>& rPropertySet,
+ SfxItemPool& rItemPool );
+
+ CharacterPropertyItemConverter(
+ const css::uno::Reference<css::beans::XPropertySet>& rPropertySet,
+ SfxItemPool& rItemPool,
+ const css::awt::Size* pRefSize,
+ OUString aRefSizePropertyName,
+ const css::uno::Reference<css::beans::XPropertySet>& rRefSizePropSet = css::uno::Reference<css::beans::XPropertySet>() );
+
+ virtual ~CharacterPropertyItemConverter() override;
+
+private:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+ const css::uno::Reference<css::beans::XPropertySet>& GetRefSizePropertySet() const;
+
+ OUString m_aRefSizePropertyName;
+ css::uno::Reference<css::beans::XPropertySet> m_xRefSizePropSet;
+ std::optional<css::awt::Size> m_pRefSize;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/ChartController.hxx b/chart2/source/controller/inc/ChartController.hxx
new file mode 100644
index 0000000000..9e72e09ddb
--- /dev/null
+++ b/chart2/source/controller/inc/ChartController.hxx
@@ -0,0 +1,555 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <LifeTime.hxx>
+#include "CommandDispatchContainer.hxx"
+#include "SelectionHelper.hxx"
+
+#include <svx/svdtypes.hxx>
+#include <vcl/timer.hxx>
+
+#include <cppuhelper/implbase.hxx>
+#include <o3tl/sorted_vector.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/ui/XContextMenuInterception.hpp>
+#include <com/sun/star/util/XModeChangeListener.hpp>
+#include <com/sun/star/util/XCloseListener.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/frame/XController2.hpp>
+#include <com/sun/star/frame/XLayoutManagerListener.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <memory>
+#include <string_view>
+
+namespace com::sun::star::accessibility { class XAccessible; }
+namespace com::sun::star::accessibility { class XAccessibleContext; }
+namespace com::sun::star::awt { class XFocusListener; }
+namespace com::sun::star::awt { class XKeyListener; }
+namespace com::sun::star::awt { class XMouseListener; }
+namespace com::sun::star::awt { class XMouseMotionListener; }
+namespace com::sun::star::awt { class XPaintListener; }
+namespace com::sun::star::awt { class XWindow; }
+namespace com::sun::star::awt { class XWindowListener; }
+namespace com::sun::star::awt { struct Point; }
+namespace com::sun::star::document { class XUndoManager; }
+namespace com::sun::star::frame { class XDispatch; }
+namespace com::sun::star::frame { class XLayoutManagerEventBroadcaster; }
+namespace com::sun::star::graphic { class XGraphic; }
+namespace com::sun::star::lang { class XInitialization; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::util { class XCloseable; }
+namespace com::sun::star::view { class XSelectionSupplier; }
+
+class SdrModel;
+
+namespace svt
+{
+ class AcceleratorExecute;
+}
+
+namespace svx::sidebar {
+ class SelectionChangeHandler;
+}
+
+namespace weld {
+ class Window;
+}
+
+class DropTargetHelper;
+
+namespace chart
+{
+
+class UndoGuard;
+class ChartView;
+class ChartWindow;
+class DrawModelWrapper;
+class DrawViewWrapper;
+class ReferenceSizeProvider;
+class ViewElementListProvider;
+class Diagram;
+class AccessibleChartView;
+class AccessibleTextHelper;
+
+enum ChartDrawMode { CHARTDRAW_INSERT, CHARTDRAW_SELECT };
+
+
+class ChartController final : public ::cppu::WeakImplHelper <
+ css::frame::XController2 //comprehends XComponent (css::frame::XController is required interface)
+ ,css::frame::XDispatchProvider //(required interface)
+ ,css::view::XSelectionSupplier //(optional interface)
+ ,css::ui::XContextMenuInterception //(optional interface)
+ ,css::util::XCloseListener //(needed for communication with XModel)
+ ,css::frame::XDispatch
+ ,css::awt::XWindow //this is the Window Controller part of this Controller, that will be given to a Frame via setComponent
+ ,css::util::XModifyListener
+ ,css::util::XModeChangeListener
+ ,css::frame::XLayoutManagerListener
+ >
+{
+public:
+ ChartController() = delete;
+ explicit ChartController(css::uno::Reference< css::uno::XComponentContext > xContext);
+ virtual ~ChartController() override;
+
+ OUString GetContextName();
+
+ // css::frame::XController (required interface)
+ virtual void SAL_CALL
+ attachFrame( const css::uno::Reference< css::frame::XFrame > & xFrame ) override;
+
+ virtual sal_Bool SAL_CALL
+ attachModel( const css::uno::Reference< css::frame::XModel > & xModel ) override;
+
+ virtual css::uno::Reference< css::frame::XFrame > SAL_CALL
+ getFrame() override;
+
+ virtual css::uno::Reference< css::frame::XModel > SAL_CALL
+ getModel() override;
+
+ virtual css::uno::Any SAL_CALL
+ getViewData() override;
+
+ virtual void SAL_CALL
+ restoreViewData( const css::uno::Any& rValue ) override;
+
+ virtual sal_Bool SAL_CALL
+ suspend( sal_Bool bSuspend ) override;
+
+ // css::frame::XController2
+ virtual css::uno::Reference<css::awt::XWindow> SAL_CALL getComponentWindow() override;
+ virtual OUString SAL_CALL getViewControllerName() override;
+ virtual css::uno::Sequence<css::beans::PropertyValue> SAL_CALL getCreationArguments() override;
+ virtual css::uno::Reference<css::ui::XSidebarProvider> SAL_CALL getSidebar() override;
+
+ // css::lang::XComponent (base of XController)
+ virtual void SAL_CALL
+ dispose() override;
+
+ virtual void SAL_CALL
+ addEventListener( const css::uno::Reference< css::lang::XEventListener > & xListener ) override;
+
+ virtual void SAL_CALL
+ removeEventListener( const css::uno::Reference< css::lang::XEventListener > & xListener ) override;
+
+ // css::frame::XDispatchProvider (required interface)
+ virtual css::uno::Reference< css::frame::XDispatch> SAL_CALL
+ queryDispatch( const css::util::URL& rURL
+ , const OUString& rTargetFrameName
+ , sal_Int32 nSearchFlags) override;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL
+ queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor > & xDescripts) override;
+
+ // css::view::XSelectionSupplier (optional interface)
+ virtual sal_Bool SAL_CALL
+ select( const css::uno::Any& rSelection ) override;
+
+ virtual css::uno::Any SAL_CALL
+ getSelection() override;
+
+ virtual void SAL_CALL
+ addSelectionChangeListener( const css::uno::Reference< css::view::XSelectionChangeListener > & xListener ) override;
+
+ virtual void SAL_CALL
+ removeSelectionChangeListener( const css::uno::Reference< css::view::XSelectionChangeListener > & xListener ) override;
+
+ // css::ui::XContextMenuInterception (optional interface)
+ virtual void SAL_CALL
+ registerContextMenuInterceptor( const css::uno::Reference< css::ui::XContextMenuInterceptor > & xInterceptor) override;
+
+ virtual void SAL_CALL
+ releaseContextMenuInterceptor( const css::uno::Reference< css::ui::XContextMenuInterceptor > & xInterceptor) override;
+
+ //additional interfaces
+
+ // css::util::XCloseListener
+ virtual void SAL_CALL
+ queryClosing( const css::lang::EventObject& Source
+ , sal_Bool GetsOwnership ) override;
+
+ virtual void SAL_CALL
+ notifyClosing( const css::lang::EventObject& Source ) override;
+
+ // css::util::XEventListener (base of XCloseListener and XModifyListener)
+ virtual void SAL_CALL
+ disposing( const css::lang::EventObject& Source ) override;
+
+ // css::frame::XDispatch
+
+ virtual void SAL_CALL
+ dispatch( const css::util::URL& aURL
+ , const css::uno::Sequence< css::beans::PropertyValue >& aArgs ) override;
+
+ virtual void SAL_CALL
+ addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xControl
+ , const css::util::URL& aURL ) override;
+
+ virtual void SAL_CALL
+ removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xControl
+ , const css::util::URL& aURL ) override;
+
+ // css::awt::XWindow
+ virtual void SAL_CALL
+ setPosSize( sal_Int32 X, sal_Int32 Y
+ , sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags ) override;
+
+ virtual css::awt::Rectangle SAL_CALL
+ getPosSize() override;
+
+ virtual void SAL_CALL
+ setVisible( sal_Bool Visible ) override;
+
+ virtual void SAL_CALL
+ setEnable( sal_Bool Enable ) override;
+
+ virtual void SAL_CALL
+ setFocus() override;
+
+ virtual void SAL_CALL
+ addWindowListener( const css::uno::Reference< css::awt::XWindowListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ removeWindowListener( const css::uno::Reference< css::awt::XWindowListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ addFocusListener( const css::uno::Reference< css::awt::XFocusListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ removeFocusListener( const css::uno::Reference< css::awt::XFocusListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ addKeyListener( const css::uno::Reference< css::awt::XKeyListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ removeKeyListener( const css::uno::Reference< css::awt::XKeyListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ addMouseListener( const css::uno::Reference< css::awt::XMouseListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ removeMouseListener( const css::uno::Reference< css::awt::XMouseListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ addMouseMotionListener( const css::uno::Reference< css::awt::XMouseMotionListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ removeMouseMotionListener( const css::uno::Reference< css::awt::XMouseMotionListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ addPaintListener( const css::uno::Reference< css::awt::XPaintListener >& xListener ) override;
+
+ virtual void SAL_CALL
+ removePaintListener( const css::uno::Reference< css::awt::XPaintListener >& xListener ) override;
+
+ // css::util::XModifyListener
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // css::util::XModeChangeListener
+ virtual void SAL_CALL modeChanged(
+ const css::util::ModeChangeEvent& _rSource ) override;
+
+ // css::frame::XLayoutManagerListener
+ virtual void SAL_CALL layoutEvent(
+ const css::lang::EventObject& aSource,
+ ::sal_Int16 eLayoutEvent,
+ const css::uno::Any& aInfo ) override;
+
+ // WindowController stuff
+ void PrePaint();
+ void execute_Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect);
+ void execute_MouseButtonDown( const MouseEvent& rMEvt );
+ void execute_MouseMove( const MouseEvent& rMEvt );
+ void execute_MouseButtonUp( const MouseEvent& rMEvt );
+ void execute_Resize();
+ void execute_Command( const CommandEvent& rCEvt );
+ bool execute_KeyInput( const KeyEvent& rKEvt );
+
+ /** get help text to be shown in a quick help
+
+ @param aAtLogicPosition the position in logic coordinates (of the
+ window) of the mouse cursor to determine for
+ which object help is requested.
+
+ @param bIsBalloonHelp determines whether to return the long text version
+ (balloon help) or the shorter one (quick help).
+
+ @param rOutQuickHelpText is filled with the quick help text
+
+ @param rOutEqualRect is filled with a rectangle that denotes the region
+ in which the quick help does not change.
+
+ @return </sal_True>, if a quick help should be shown.
+ */
+ bool requestQuickHelp(
+ ::Point aAtLogicPosition, bool bIsBalloonHelp,
+ OUString & rOutQuickHelpText, css::awt::Rectangle & rOutEqualRect );
+
+ css::uno::Reference< css::accessibility::XAccessible > CreateAccessible();
+
+ /** Creates a helper accessibility class that must be initialized via initialize(). For
+ parameters see
+
+ The returned object should not be used directly. Instead a proxy object
+ should use this helper to retrieve its children and add them to its own
+ children.
+ */
+ rtl::Reference< ::chart::AccessibleTextHelper > createAccessibleTextContext();
+
+ static bool isObjectDeleteable( const css::uno::Any& rSelection );
+
+ void setDrawMode( ChartDrawMode eMode ) { m_eDrawMode = eMode; }
+
+ bool isShapeContext() const;
+
+ ViewElementListProvider getViewElementListProvider();
+ DrawModelWrapper* GetDrawModelWrapper();
+ DrawViewWrapper* GetDrawViewWrapper();
+ ChartWindow* GetChartWindow() const;
+ weld::Window* GetChartFrame();
+ bool isAdditionalShapeSelected() const;
+ void SetAndApplySelection(const css::uno::Reference<css::drawing::XShape>& rxShape);
+ void StartTextEdit( const Point* pMousePixel = nullptr );
+
+ void NotifyUndoActionHdl( std::unique_ptr<SdrUndoAction> );
+
+ rtl::Reference<::chart::ChartView> const & getChartView() const { return m_xChartView; }
+
+ rtl::Reference<::chart::ChartModel> getChartModel();
+ rtl::Reference<::chart::Diagram> getFirstDiagram();
+
+private:
+ class TheModel : public salhelper::SimpleReferenceObject
+ {
+ public:
+ explicit TheModel( rtl::Reference<::chart::ChartModel> xModel );
+
+ virtual ~TheModel() override;
+
+ void addListener( ChartController* pController );
+ void removeListener( ChartController* pController );
+ void tryTermination();
+ const rtl::Reference<::chart::ChartModel>&
+ getModel() const { return m_xModel;}
+
+ private:
+ rtl::Reference<::chart::ChartModel> m_xModel;
+
+ //the ownership between model and controller is not clear at first
+ //each controller might consider himself as owner of the model first
+ bool m_bOwnership;
+ };
+ class TheModelRef final
+ {
+ public:
+ TheModelRef( TheModel* pTheModel, ::osl::Mutex& rMutex );
+ TheModelRef( const TheModelRef& rTheModel, ::osl::Mutex& rMutex );
+ TheModelRef& operator=(ChartController::TheModel* pTheModel);
+ TheModelRef& operator=(const TheModelRef& rTheModel);
+ ~TheModelRef();
+ bool is() const;
+ TheModel* operator->() const { return m_xTheModel.get(); }
+ private:
+ rtl::Reference<TheModel> m_xTheModel;
+ ::osl::Mutex& m_rModelMutex;
+ };
+
+ mutable ::apphelper::LifeTimeManager m_aLifeTimeManager;
+
+ bool m_bSuspended;
+
+ css::uno::Reference< css::uno::XComponentContext> m_xCC;
+
+ //model
+ css::uno::Reference< css::frame::XFrame > m_xFrame;
+ mutable ::osl::Mutex m_aModelMutex;
+ TheModelRef m_aModel;
+
+ //view
+ css::uno::Reference<css::awt::XWindow> m_xViewWindow;
+ rtl::Reference<::chart::ChartView> m_xChartView;
+ std::shared_ptr< DrawModelWrapper > m_pDrawModelWrapper;
+ std::unique_ptr<DrawViewWrapper> m_pDrawViewWrapper;
+
+ Selection m_aSelection;
+ SdrDragMode m_eDragMode;
+
+ Timer m_aDoubleClickTimer;
+ bool m_bWaitingForDoubleClick;
+ bool m_bWaitingForMouseUp;
+ bool m_bFieldButtonDown;
+
+ bool m_bConnectingToView;
+ bool m_bDisposed;
+
+ css::uno::Reference< css::document::XUndoManager > m_xUndoManager;
+ std::unique_ptr< UndoGuard > m_pTextActionUndoGuard;
+
+ std::unique_ptr< ::svt::AcceleratorExecute > m_apAccelExecute;
+
+ CommandDispatchContainer m_aDispatchContainer;
+
+ std::unique_ptr< DropTargetHelper > m_apDropTargetHelper;
+ css::uno::Reference<
+ css::frame::XLayoutManagerEventBroadcaster > m_xLayoutManagerEventBroadcaster;
+
+ ChartDrawMode m_eDrawMode;
+
+ rtl::Reference<svx::sidebar::SelectionChangeHandler> mpSelectionChangeHandler;
+
+ bool impl_isDisposedOrSuspended() const;
+ std::unique_ptr<ReferenceSizeProvider> impl_createReferenceSizeProvider();
+ void impl_adaptDataSeriesAutoResize();
+
+ void impl_createDrawViewController();
+ void impl_deleteDrawViewController();
+
+ //executeDispatch methods
+ void executeDispatch_ObjectProperties();
+ void executeDispatch_FormatObject( std::u16string_view rDispatchCommand );
+ void executeDlg_ObjectProperties( const OUString& rObjectCID );
+ bool executeDlg_ObjectProperties_withoutUndoGuard( const OUString& rObjectCID, bool bSuccessOnUnchanged );
+
+ void executeDispatch_ChartType();
+
+ void executeDispatch_InsertTitles();
+ void executeDispatch_InsertLegend();
+ void executeDispatch_DeleteLegend();
+ void executeDispatch_OpenLegendDialog();
+ void executeDispatch_InsertAxes();
+ void executeDispatch_InsertGrid();
+
+ void executeDispatch_InsertDataTable();
+ void executeDispatch_DeleteDataTable();
+ void executeDispatch_OpenInsertDataTableDialog();
+
+ void executeDispatch_InsertMenu_DataLabels();
+ void executeDispatch_InsertMenu_Trendlines();
+ void executeDispatch_InsertMenu_MeanValues();
+
+ void executeDispatch_InsertMeanValue();
+ void executeDispatch_InsertTrendline();
+ void executeDispatch_InsertTrendlineEquation( bool bInsertR2=false );
+ void executeDispatch_InsertErrorBars( bool bYError );
+
+ void executeDispatch_InsertR2Value();
+ void executeDispatch_DeleteR2Value();
+
+ void executeDispatch_DeleteMeanValue();
+ void executeDispatch_DeleteTrendline();
+ void executeDispatch_DeleteTrendlineEquation();
+ void executeDispatch_DeleteErrorBars( bool bYError );
+
+ void executeDispatch_InsertDataLabels();
+ void executeDispatch_InsertDataLabel();
+ void executeDispatch_DeleteDataLabels();
+ void executeDispatch_DeleteDataLabel();
+
+ void executeDispatch_ResetAllDataPoints();
+ void executeDispatch_ResetDataPoint();
+
+ void executeDispatch_InsertAxis();
+ void executeDispatch_InsertAxisTitle();
+ void executeDispatch_InsertMajorGrid();
+ void executeDispatch_InsertMinorGrid();
+ void executeDispatch_DeleteAxis();
+ void executeDispatch_DeleteMajorGrid();
+ void executeDispatch_DeleteMinorGrid();
+
+ void executeDispatch_InsertSpecialCharacter();
+ void executeDispatch_EditText( const Point* pMousePixel = nullptr );
+ void executeDispatch_SourceData();
+ void executeDispatch_MoveSeries( bool bForward );
+
+ bool EndTextEdit();
+
+ void executeDispatch_View3D();
+ void executeDispatch_PositionAndSize( const ::css::uno::Sequence< ::css::beans::PropertyValue >* pArgs = nullptr );
+
+ void executeDispatch_EditData();
+
+ void executeDispatch_NewArrangement();
+ void executeDispatch_ScaleText();
+
+ void executeDispatch_Paste();
+ void executeDispatch_Copy();
+ void executeDispatch_Cut();
+ bool executeDispatch_Delete();
+ void executeDispatch_ToggleLegend();
+ void executeDispatch_ToggleGridHorizontal();
+ void executeDispatch_ToggleGridVertical();
+
+ void executeDispatch_LOKSetTextSelection(int nType, int nX, int nY);
+ void executeDispatch_LOKPieSegmentDragging(int nOffset);
+ void executeDispatch_FillColor(sal_uInt32 nColor);
+ void executeDispatch_FillGradient(std::u16string_view sJSONGradient);
+ void executeDispatch_LineColor(sal_uInt32 nColor);
+ void executeDispatch_LineWidth(sal_uInt32 nWidth);
+
+ void sendPopupRequest(std::u16string_view rCID, tools::Rectangle aRectangle);
+
+ void impl_ShapeControllerDispatch( const css::util::URL& rURL,
+ const css::uno::Sequence< css::beans::PropertyValue >& rArgs );
+
+ DECL_LINK( DoubleClickWaitingHdl, Timer*, void );
+ void execute_DoubleClick( const Point* pMousePixel );
+ void startDoubleClickWaiting();
+ void stopDoubleClickWaiting();
+
+ void impl_selectObjectAndNotiy();
+ void impl_notifySelectionChangeListeners();
+ void impl_invalidateAccessible();
+ void impl_initializeAccessible();
+ void impl_initializeAccessible( AccessibleChartView& xInit );
+
+ //sets the model member to null if it equals the parameter
+ //returns true if successful
+ bool impl_releaseThisModel( const css::uno::Reference< css::uno::XInterface > & xModel );
+
+ enum eMoveOrResizeType
+ {
+ MOVE_OBJECT,
+ CENTERED_RESIZE_OBJECT
+ };
+ /// @return </sal_True>, if resize/move was successful
+ bool impl_moveOrResizeObject(
+ const OUString & rCID, eMoveOrResizeType eType, double fAmountLogicX, double fAmountLogicY );
+ bool impl_DragDataPoint( std::u16string_view rCID, double fOffset );
+
+ static const o3tl::sorted_vector< OUString >& impl_getAvailableCommands();
+
+ void impl_PasteGraphic( css::uno::Reference< css::graphic::XGraphic > const & xGraphic,
+ const ::Point & aPosition );
+ void impl_PasteShapes( SdrModel* pModel );
+ void impl_PasteStringAsTextShape( const OUString& rString, const css::awt::Point& rPosition );
+ void impl_SetMousePointer( const MouseEvent & rEvent );
+
+ void impl_ClearSelection();
+
+ void impl_switchDiagramPositioningToExcludingPositioning();
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/ChartDocumentWrapper.hxx b/chart2/source/controller/inc/ChartDocumentWrapper.hxx
new file mode 100644
index 0000000000..a5bded3c8f
--- /dev/null
+++ b/chart2/source/controller/inc/ChartDocumentWrapper.hxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <WrappedPropertySet.hxx>
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uno/XAggregation.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <unotools/eventlisteneradapter.hxx>
+#include <rtl/ref.hxx>
+#include <svx/unopage.hxx>
+#include <memory>
+
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::util { class XRefreshable; }
+namespace chart { class ChartView; }
+
+namespace chart::wrapper
+{
+
+class Chart2ModelContact;
+
+class ChartDocumentWrapper_Base : public ::cppu::ImplInheritanceHelper
+ < WrappedPropertySet
+ , css::chart::XChartDocument
+ , css::drawing::XDrawPageSupplier
+ , css::lang::XMultiServiceFactory
+ , css::lang::XServiceInfo
+ , css::uno::XAggregation
+ >
+{
+};
+
+class ChartDocumentWrapper final : public ChartDocumentWrapper_Base
+ , public ::utl::OEventListenerAdapter
+{
+public:
+ explicit ChartDocumentWrapper( const css::uno::Reference< css::uno::XComponentContext > & xContext );
+ virtual ~ChartDocumentWrapper() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ void setAddIn( const css::uno::Reference< css::util::XRefreshable >& xAddIn );
+ const css::uno::Reference< css::util::XRefreshable >& getAddIn() const { return m_xAddIn;}
+
+ void setUpdateAddIn( bool bUpdateAddIn );
+ bool getUpdateAddIn() const { return m_bUpdateAddIn;}
+
+ void setBaseDiagram( const OUString& rBaseDiagram );
+ const OUString& getBaseDiagram() const { return m_aBaseDiagram;}
+
+ css::uno::Reference< css::drawing::XShapes > getAdditionalShapes() const;
+
+ /// @throws css::uno::RuntimeException
+ rtl::Reference<SvxDrawPage> impl_getDrawPage() const;
+
+protected:
+
+ // ____ chart::XChartDocument ____
+ virtual css::uno::Reference< css::drawing::XShape > SAL_CALL getTitle() override;
+ virtual css::uno::Reference< css::drawing::XShape > SAL_CALL getSubTitle() override;
+ virtual css::uno::Reference< css::drawing::XShape > SAL_CALL getLegend() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getArea() override;
+ virtual css::uno::Reference< css::chart::XDiagram > SAL_CALL getDiagram() override;
+ virtual void SAL_CALL setDiagram( const css::uno::Reference<
+ css::chart::XDiagram >& xDiagram ) override;
+ virtual css::uno::Reference< css::chart::XChartData > SAL_CALL getData() override;
+ virtual void SAL_CALL attachData( const css::uno::Reference<
+ css::chart::XChartData >& xData ) override;
+
+ // ____ XModel ____
+ virtual sal_Bool SAL_CALL attachResource( const OUString& URL,
+ const css::uno::Sequence< css::beans::PropertyValue >& Arguments ) override;
+ virtual OUString SAL_CALL getURL() override;
+ virtual css::uno::Sequence<
+ css::beans::PropertyValue > SAL_CALL getArgs() override;
+ virtual void SAL_CALL connectController( const css::uno::Reference<
+ css::frame::XController >& Controller ) override;
+ virtual void SAL_CALL disconnectController( const css::uno::Reference<
+ css::frame::XController >& Controller ) override;
+ virtual void SAL_CALL lockControllers() override;
+ virtual void SAL_CALL unlockControllers() override;
+ virtual sal_Bool SAL_CALL hasControllersLocked() override;
+ virtual css::uno::Reference<
+ css::frame::XController > SAL_CALL getCurrentController() override;
+ virtual void SAL_CALL setCurrentController( const css::uno::Reference< css::frame::XController >& Controller ) override;
+ virtual css::uno::Reference<css::uno::XInterface > SAL_CALL getCurrentSelection() override;
+
+ // ____ XComponent ____
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+
+ // ____ XInterface (for new interfaces) ____
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+
+ // ____ ::utl::OEventListenerAdapter ____
+ virtual void _disposing( const css::lang::EventObject& rSource ) override;
+
+ // ____ XDrawPageSupplier ____
+ virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL getDrawPage() override;
+
+ // ____ XMultiServiceFactory ____
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( const OUString& aServiceSpecifier ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(
+ const OUString& ServiceSpecifier,
+ const css::uno::Sequence< css::uno::Any >& Arguments ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
+
+ // ____ XAggregation ____
+ virtual void SAL_CALL setDelegator(
+ const css::uno::Reference< css::uno::XInterface >& rDelegator ) override;
+ virtual css::uno::Any SAL_CALL queryAggregation( const css::uno::Type& aType ) override;
+
+ // ____ WrappedPropertySet ____
+ virtual const css::uno::Sequence< css::beans::Property >& getPropertySequence() override;
+ virtual std::vector< std::unique_ptr<WrappedProperty> > createWrappedProperties() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() override;
+
+ // ____ XPropertySet ____
+ virtual void SAL_CALL setPropertyValue(const OUString& rPropertyName,
+ const css::uno::Any& rValue) override;
+
+private: //methods
+ void impl_resetAddIn();
+
+private: //member
+ std::shared_ptr< Chart2ModelContact > m_spChart2ModelContact;
+
+ css::uno::Reference< css::uno::XInterface > m_xDelegator;
+
+ css::uno::Reference< css::drawing::XShape > m_xTitle;
+ css::uno::Reference< css::drawing::XShape > m_xSubTitle;
+ css::uno::Reference< css::drawing::XShape > m_xLegend;
+ css::uno::Reference< css::chart::XChartData > m_xChartData;
+ css::uno::Reference< css::chart::XDiagram > m_xDiagram;
+ css::uno::Reference< css::beans::XPropertySet > m_xArea;
+
+ css::uno::Reference< css::util::XRefreshable > m_xAddIn;
+ OUString m_aBaseDiagram;
+ bool m_bUpdateAddIn;
+
+ rtl::Reference< ChartView > m_xChartView;
+ css::uno::Reference< css::lang::XMultiServiceFactory>
+ m_xShapeFactory;
+
+ bool m_bIsDisposed;
+};
+
+} // namespace chart::wrapper
+
+// CHART_CHARTDOCUMENT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/ChartToolbarController.hxx b/chart2/source/controller/inc/ChartToolbarController.hxx
new file mode 100644
index 0000000000..ce493bba67
--- /dev/null
+++ b/chart2/source/controller/inc/ChartToolbarController.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <comphelper/compbase.hxx>
+
+#include <com/sun/star/frame/XToolbarController.hpp>
+#include <com/sun/star/frame/XStatusListener.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+namespace com::sun::star::awt { class XWindow; }
+namespace com::sun::star::frame { class XFramesSupplier; }
+
+namespace chart {
+
+typedef comphelper::WeakComponentImplHelper<
+ css::frame::XToolbarController, css::frame::XStatusListener,
+ css::util::XUpdatable, css::lang::XInitialization,
+ css::lang::XServiceInfo> ChartToolbarControllerBase;
+
+class ChartToolbarController final : public ChartToolbarControllerBase
+{
+public:
+ ChartToolbarController(const css::uno::Sequence<css::uno::Any>& rProperties);
+ virtual ~ChartToolbarController() override;
+
+ ChartToolbarController(const ChartToolbarController&) = delete;
+ const ChartToolbarController& operator=(const ChartToolbarController&) = delete;
+
+ // XToolbarController
+ virtual void SAL_CALL execute(sal_Int16 nKeyModifier) override;
+
+ virtual void SAL_CALL click() override;
+
+ virtual void SAL_CALL doubleClick() override;
+
+ virtual css::uno::Reference<css::awt::XWindow> SAL_CALL createPopupWindow() override;
+
+ virtual css::uno::Reference<css::awt::XWindow> SAL_CALL
+ createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XStatusListener
+ virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& rEvent) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing(const css::lang::EventObject& rSource) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rAny) override;
+
+ // XUpdatable
+ virtual void SAL_CALL update() override;
+
+ using comphelper::WeakComponentImplHelperBase::disposing;
+
+private:
+
+ css::uno::Reference<css::frame::XFramesSupplier> mxFramesSupplier;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/ChartWindow.hxx b/chart2/source/controller/inc/ChartWindow.hxx
new file mode 100644
index 0000000000..918805cb3a
--- /dev/null
+++ b/chart2/source/controller/inc/ChartWindow.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/window.hxx>
+
+namespace chart
+{
+
+class ChartController;
+
+/** The ChartWindow collects events from the window and forwards them the to the controller
+thus the controller can perform appropriate actions
+*/
+
+class ChartWindow final : public vcl::Window
+{
+public:
+ ChartWindow( ChartController* pController, vcl::Window* pParent, WinBits nStyle );
+ virtual ~ChartWindow() override;
+ virtual void dispose() override;
+
+ //from base class Window:
+ virtual void PrePaint(vcl::RenderContext& rRenderContext) override;
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+ virtual void MouseButtonDown( const MouseEvent& rMEvt ) override;
+ virtual void MouseMove( const MouseEvent& rMEvt ) override;
+ virtual void Tracking( const TrackingEvent& rTEvt ) override;
+ virtual void MouseButtonUp( const MouseEvent& rMEvt ) override;
+ virtual void Resize() override;
+ virtual void Activate() override;
+ virtual void Deactivate() override;
+ virtual void GetFocus() override;
+ virtual void LoseFocus() override;
+ virtual void Command( const CommandEvent& rCEvt ) override;
+ virtual void KeyInput( const KeyEvent& rKEvt ) override;
+ virtual void DataChanged( const DataChangedEvent& rDCEvt ) override;
+ virtual void RequestHelp( const HelpEvent& rHEvt ) override;
+
+ void ForceInvalidate();
+ virtual void ImplInvalidate( const vcl::Region* rRegion, InvalidateFlags nFlags ) override;
+ /// Notify the LOK client about an invalidated area.
+ virtual void LogicInvalidate( const tools::Rectangle* pRectangle ) override;
+
+ virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override;
+
+ virtual FactoryFunction GetUITestFactory() const override;
+
+ ChartController* GetController();
+
+ virtual bool IsChart() const override { return true; }
+ vcl::Window* GetParentEditWin();
+
+private:
+ // returns the chart bounding box in twips
+ tools::Rectangle GetBoundingBox();
+
+private:
+ ChartController* m_pWindowController;
+ bool m_bInPaint;
+ VclPtr<vcl::Window> m_pViewShellWindow;
+
+ void adjustHighContrastMode();
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/CommandDispatchContainer.hxx b/chart2/source/controller/inc/CommandDispatchContainer.hxx
new file mode 100644
index 0000000000..ae95313c0f
--- /dev/null
+++ b/chart2/source/controller/inc/CommandDispatchContainer.hxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <unotools/weakref.hxx>
+#include <o3tl/sorted_vector.hxx>
+
+#include <map>
+#include <vector>
+
+namespace com::sun::star::frame { class XController; }
+namespace com::sun::star::frame { class XDispatch; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::frame { struct DispatchDescriptor; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::util { struct URL; }
+
+namespace chart
+{
+class ChartModel;
+class DrawCommandDispatch;
+class ShapeController;
+
+/** @HTML
+
+ Helper class for implementing the <code>XDispatchProvider</code> interface
+ of the ChartController. This class handles all commands to queryDispatch and
+ queryDispatches in the following way:
+
+ <ul>
+ <li>Check if there is a cached <code>XDispatch</code> for a given command.
+ If so, use it.</li>
+ <li>Check if the command is handled by this class, e.g. Undo. If so,
+ return a corresponding <code>XDispatch</code> implementation, and cache
+ this implementation for later use</li>
+ <li>Otherwise send the command to the chart dispatch provider, if it
+ can handle this dispatch (determined by the list of commands given in
+ <code>setChartDispatch()</code>).</li>
+ </ul>
+
+ <p>The <code>XDispatch</code>Provider is designed to return different
+ <code>XDispatch</code> implementations for each command. This class here
+ decides which implementation to use for which command.</p>
+
+ <p>As most commands need much information of the controller and are
+ implemented there, the controller handles most of the commands itself (it
+ also implements <code>XDispatch</code>). Therefore it is set here as
+ chart dispatch.</p>
+ */
+class CommandDispatchContainer
+{
+public:
+ // note: the chart dispatcher should be removed when all commands are
+ // handled by other dispatchers. (Chart is currently the controller
+ // itself)
+ explicit CommandDispatchContainer(
+ const css::uno::Reference< css::uno::XComponentContext > & xContext );
+
+ void setModel(
+ const rtl::Reference<::chart::ChartModel> & xModel );
+
+ /** Set a chart dispatcher that is used for all commands contained in
+ rChartCommands
+ */
+ void setChartDispatch(
+ const css::uno::Reference< css::frame::XDispatch >& rChartDispatch,
+ o3tl::sorted_vector< OUString > && rChartCommands );
+
+ /** Returns the dispatch that is able to do the command given in rURL, if
+ implemented here. If the URL is not implemented here, it should be
+ checked whether the command is one of the commands given via
+ the setChartDispatch() method. If so, call the chart dispatch.
+
+ <p>If all this fails, return an empty dispatch.</p>
+ */
+ css::uno::Reference< css::frame::XDispatch > getDispatchForURL(
+ const css::util::URL & rURL );
+
+ css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > getDispatchesForURLs(
+ const css::uno::Sequence< css::frame::DispatchDescriptor > & aDescriptors );
+
+ void DisposeAndClear();
+
+ static css::uno::Reference< css::frame::XDispatch >
+ getContainerDispatchForURL(
+ const css::uno::Reference< css::frame::XController > & xChartController,
+ const css::util::URL & rURL );
+
+ const css::uno::Reference< css::frame::XDispatch > & getChartDispatcher() const { return m_xChartDispatcher; }
+
+ void setDrawCommandDispatch( DrawCommandDispatch* pDispatch );
+ DrawCommandDispatch* getDrawCommandDispatch() { return m_pDrawCommandDispatch; }
+ void setShapeController( ShapeController* pController );
+ ShapeController* getShapeController() { return m_pShapeController; }
+
+private:
+ typedef
+ std::map< OUString,
+ css::uno::Reference< css::frame::XDispatch > >
+ tDispatchMap;
+
+ typedef
+ std::vector< css::uno::Reference< css::frame::XDispatch > > tDisposeVector;
+
+ mutable tDispatchMap m_aCachedDispatches;
+ mutable tDisposeVector m_aToBeDisposedDispatches;
+
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ unotools::WeakReference< ::chart::ChartModel > m_xModel;
+
+ css::uno::Reference< css::frame::XDispatch > m_xChartDispatcher;
+ o3tl::sorted_vector< OUString > m_aChartCommands;
+
+ DrawCommandDispatch* m_pDrawCommandDispatch;
+ ShapeController* m_pShapeController;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/DataPointItemConverter.hxx b/chart2/source/controller/inc/DataPointItemConverter.hxx
new file mode 100644
index 0000000000..3c6e276ff7
--- /dev/null
+++ b/chart2/source/controller/inc/DataPointItemConverter.hxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+#include "GraphicPropertyItemConverter.hxx"
+#include <com/sun/star/uno/Sequence.h>
+
+#include <tools/color.hxx>
+#include <rtl/ref.hxx>
+
+#include <vector>
+
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace chart { class ChartModel; }
+namespace chart { class DataSeries; }
+class SdrModel;
+
+namespace chart::wrapper {
+
+class DataPointItemConverter final : public ItemConverter
+{
+public:
+ DataPointItemConverter(
+ const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const css::uno::Reference<css::uno::XComponentContext>& xContext,
+ const css::uno::Reference<css::beans::XPropertySet>& rPropertySet,
+ const rtl::Reference<::chart::DataSeries>& xSeries,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const css::uno::Reference<css::lang::XMultiServiceFactory>& xNamedPropertyContainerFactory,
+ GraphicObjectType eMapTo,
+ const css::awt::Size* pRefSize = nullptr,
+ bool bDataSeries = false,
+ bool bUseSpecialFillColor = false,
+ sal_Int32 nSpecialFillColor = 0,
+ bool bOverwriteLabelsForAttributedDataPointsAlso = false,
+ sal_Int32 nNumberFormat = 0,
+ sal_Int32 nPercentNumberFormat = 0,
+ sal_Int32 nPointIndex = -1 );
+
+ virtual ~DataPointItemConverter() override;
+
+ virtual void FillItemSet( SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplyItemSet( const SfxItemSet & rItemSet ) override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ std::vector< std::unique_ptr<ItemConverter> > m_aConverters;
+ bool m_bDataSeries;
+ bool m_bOverwriteLabelsForAttributedDataPointsAlso;
+ bool m_bUseSpecialFillColor;
+ Color m_nSpecialFillColor;
+ sal_Int32 m_nNumberFormat;
+ sal_Int32 m_nPercentNumberFormat;
+ css::uno::Sequence<sal_Int32> m_aAvailableLabelPlacements;
+ bool m_bForbidPercentValue;
+ bool m_bHideLegendEntry;
+ sal_Int32 m_nPointIndex;
+ rtl::Reference<::chart::DataSeries> m_xSeries;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/DataTableItemConverter.hxx b/chart2/source/controller/inc/DataTableItemConverter.hxx
new file mode 100644
index 0000000000..f3809632f8
--- /dev/null
+++ b/chart2/source/controller/inc/DataTableItemConverter.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "ItemConverter.hxx"
+#include <rtl/ref.hxx>
+#include <vector>
+
+namespace com::sun::star::awt
+{
+struct Size;
+}
+namespace com::sun::star::beans
+{
+class XPropertySet;
+}
+namespace chart
+{
+class ChartModel;
+}
+
+class SdrModel;
+
+namespace chart::wrapper
+{
+/** Convert data table properties to and from ItemSet and UNO PropertySet */
+class DataTableItemConverter final : public ItemConverter
+{
+public:
+ DataTableItemConverter(const css::uno::Reference<css::beans::XPropertySet>& rPropertySet,
+ SfxItemPool& rItemPool, SdrModel& rDrawModel,
+ const rtl::Reference<::chart::ChartModel>& xChartDoc);
+
+ virtual ~DataTableItemConverter() override;
+
+ virtual void FillItemSet(SfxItemSet& rOutItemSet) const override;
+ virtual bool ApplyItemSet(const SfxItemSet& rItemSet) override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty(tWhichIdType nWhichId,
+ tPropertyNameWithMemberId& rOutProperty) const override;
+
+private:
+ std::vector<std::unique_ptr<ItemConverter>> m_aConverters;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/DrawViewWrapper.hxx b/chart2/source/controller/inc/DrawViewWrapper.hxx
new file mode 100644
index 0000000000..28c2a927ec
--- /dev/null
+++ b/chart2/source/controller/inc/DrawViewWrapper.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include <svx/view3d.hxx>
+
+namespace com::sun::star::drawing { class XShape; }
+namespace com::sun::star::frame { class XModel; }
+
+class SdrModel;
+
+namespace chart
+{
+
+/** The DrawViewWrapper should help us to reduce effort if the underlying DrawingLayer changes.
+Another task is to hide functionality we do not need, for example more than one page.
+*/
+
+class MarkHandleProvider
+{
+public:
+ virtual bool getMarkHandles( SdrHdlList& rHdlList ) =0;
+ virtual bool getFrameDragSingles() =0;
+
+protected:
+ ~MarkHandleProvider() {}
+};
+
+class DrawViewWrapper final : public E3dView
+{
+public:
+ DrawViewWrapper(
+ SdrModel& rSdrModel,
+ OutputDevice* pOut);
+
+ virtual ~DrawViewWrapper() override;
+
+ //triggers the use of an updated first page
+ void ReInit();
+
+ /// tries to get an OutputDevice from the XParent of the model to use as reference device
+ void attachParentReferenceDevice(
+ const css::uno::Reference< css::frame::XModel > & xChartModel );
+
+ //fill list of selection handles 'aHdl'
+ virtual void SetMarkHandles(SfxViewShell* pOtherShell) override;
+
+ SdrPageView* GetPageView() const;
+
+ SdrObject* getHitObject( const Point& rPnt ) const;
+
+ void MarkObject( SdrObject* pObj );
+
+ //pMarkHandleProvider can be NULL; ownership is not taken
+ void setMarkHandleProvider( MarkHandleProvider* pMarkHandleProvider );
+ void CompleteRedraw(OutputDevice* pOut, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector = nullptr) override;
+
+ SdrObject* getSelectedObject() const;
+ SdrObject* getTextEditObject() const;
+ SdrOutliner* getOutliner() const;
+
+ SfxItemSet getPositionAndSizeItemSetFromMarkedObject() const;
+
+ SdrObject* getNamedSdrObject( const OUString& rName ) const;
+ static bool IsObjectHit( SdrObject const * pObj, const Point& rPnt );
+
+ virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
+
+ static SdrObject* getSdrObject( const css::uno::Reference< css::drawing::XShape >& xShape );
+
+private:
+ mutable MarkHandleProvider* m_pMarkHandleProvider;
+
+ std::unique_ptr< SdrOutliner > m_apOutliner;
+
+ // #i79965# scroll back view when ending text edit
+ bool m_bRestoreMapMode;
+ MapMode m_aMapModeToRestore;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/ErrorBarItemConverter.hxx b/chart2/source/controller/inc/ErrorBarItemConverter.hxx
new file mode 100644
index 0000000000..a53fbe18ef
--- /dev/null
+++ b/chart2/source/controller/inc/ErrorBarItemConverter.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "ItemConverter.hxx"
+
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+
+class SdrModel;
+
+namespace chart::wrapper
+{
+
+class ErrorBarItemConverter final : public ItemConverter
+{
+public:
+ ErrorBarItemConverter(
+ css::uno::Reference< css::frame::XModel > xChartModel,
+ const css::uno::Reference< css::beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & xNamedPropertyContainerFactory );
+ virtual ~ErrorBarItemConverter() override;
+
+ virtual void FillItemSet( SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplyItemSet( const SfxItemSet & rItemSet ) override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ std::shared_ptr< ItemConverter > m_spGraphicConverter;
+ css::uno::Reference< css::frame::XModel > m_xModel;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/GraphicPropertyItemConverter.hxx b/chart2/source/controller/inc/GraphicPropertyItemConverter.hxx
new file mode 100644
index 0000000000..9d119d53ca
--- /dev/null
+++ b/chart2/source/controller/inc/GraphicPropertyItemConverter.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+
+class SdrModel;
+
+namespace chart::wrapper
+{
+
+enum class GraphicObjectType
+{
+ FilledDataPoint,
+ LineDataPoint,
+ LineProperties,
+ LineAndFillProperties
+};
+
+class GraphicPropertyItemConverter final : public ItemConverter
+{
+public:
+ GraphicPropertyItemConverter(
+ const css::uno::Reference< css::beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ css::uno::Reference< css::lang::XMultiServiceFactory > xNamedPropertyContainerFactory,
+ GraphicObjectType eObjectType );
+ virtual ~GraphicPropertyItemConverter() override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ GraphicObjectType m_GraphicObjectType;
+ SdrModel & m_rDrawModel;
+ css::uno::Reference< css::lang::XMultiServiceFactory > m_xNamedPropertyTableFactory;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/ItemConverter.hxx b/chart2/source/controller/inc/ItemConverter.hxx
new file mode 100644
index 0000000000..031a633c22
--- /dev/null
+++ b/chart2/source/controller/inc/ItemConverter.hxx
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <unotools/eventlisteneradapter.hxx>
+#include <svl/itemset.hxx>
+
+#include <utility>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::beans { class XPropertySetInfo; }
+
+namespace chart::wrapper {
+
+
+/** This class serves for conversion between properties of an XPropertySet and
+ SfxItems in SfxItemSets.
+
+ With this helper classes, you can feed dialogs with XPropertySets and let
+ those modify by the dialogs.
+
+ You must implement GetWhichPairs() such that an SfxItemSet created with
+ CreateEmptyItemSet() is able to hold all items that may be mapped.
+
+ You also have to implement GetItemProperty(), in order to return the
+ property name for a given which-id together with the corresponding member-id
+ that has to be used for conversion in QueryValue/PutValue.
+
+ FillSpecialItem and ApplySpecialItem may be used for special handling of
+ individual item, e.g. if you need member-ids in QueryValue/PutValue
+
+ A typical use could be the following:
+
+ ::comphelper::ChartTypeItemConverter aItemConverter( xPropertySet, GetItemPool() );
+ SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet();
+ aItemConverter.FillItemSet( aItemSet );
+ bool bChanged = false;
+
+ MyDialog aDlg( aItemSet );
+ if( aDlg.Execute() == RET_OK )
+ {
+ const SfxItemSet* pOutItemSet = aDlg.GetOutputItemSet();
+ if( pOutItemSet )
+ bChanged = aItemConverter.ApplyItemSet( *pOutItemSet );
+ }
+
+ if( bChanged )
+ {
+ [ apply model changes to view ]
+ }
+ */
+class ItemConverter :
+ public ::utl::OEventListenerAdapter
+{
+public:
+ /** Construct an item converter that uses the given property set for
+ reading/writing converted items
+ */
+ ItemConverter(
+ css::uno::Reference< css::beans::XPropertySet > xPropertySet ,
+ SfxItemPool& rItemPool );
+ virtual ~ItemConverter() override;
+
+ typedef sal_uInt16 tWhichIdType;
+ typedef OUString tPropertyNameType;
+ typedef sal_uInt8 tMemberIdType;
+
+ typedef std::pair< tPropertyNameType, tMemberIdType > tPropertyNameWithMemberId;
+
+ /** applies all properties that can be mapped to items into the given item
+ set.
+
+ Call this method before opening a dialog.
+
+ @param rOutItemSet
+ the SfxItemSet is filled with all items that are a result of a
+ conversion from a property of the internal XPropertySet.
+ */
+ virtual void FillItemSet( SfxItemSet & rOutItemSet ) const;
+
+ /** applies all properties that are results of a conversion from all items
+ in rItemSet to the internal XPropertySet.
+
+ Call this method after a dialog was closed with OK
+
+ @return true, if any properties have been changed, false otherwise.
+ */
+ virtual bool ApplyItemSet( const SfxItemSet & rItemSet );
+
+ /** creates an empty item set using the given pool or a common pool if empty
+ (see GetItemPool) and allowing all items given in the ranges returned by
+ GetWhichPairs.
+ */
+ SfxItemSet CreateEmptyItemSet() const;
+
+ /** Invalidates all items in rDestSet, that are set (state SfxItemState::SET) in
+ both item sets (rDestSet and rSourceSet) and have differing content.
+ */
+ static void InvalidateUnequalItems( SfxItemSet &rDestSet, const SfxItemSet &rSourceSet );
+
+protected:
+
+ /** implement this method to provide an array of which-ranges
+ */
+ virtual const WhichRangesContainer& GetWhichPairs() const = 0;
+
+ /** implement this method to return a Property object for a given which id.
+
+ @param rOutProperty
+ If true is returned, this contains the property name and the
+ corresponding Member-Id.
+
+ @return true, if the item can be mapped to a property.
+ */
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const = 0;
+
+ /** for items that can not be mapped directly to a property.
+
+ This method is called from FillItemSet(), if GetItemProperty() returns
+ false.
+
+ The default implementation does nothing except showing an assertion
+
+ @throws css::uno::Exception
+ */
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const;
+
+ /** for items that can not be mapped directly to a property.
+
+ This method is called from ApplyItemSet(), if GetItemProperty() returns
+ false.
+
+ The default implementation returns just false and shows an assertion
+
+ @return true if the item changed a property, false otherwise.
+
+ @throws css::uno::Exception
+ */
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet );
+
+ /// Returns the pool
+ SfxItemPool & GetItemPool() const { return m_rItemPool;}
+
+ /** Returns the XPropertySet that was given in the CTOR and is used to apply
+ items in ApplyItemSet().
+ */
+ const css::uno::Reference< css::beans::XPropertySet >& GetPropertySet() const { return m_xPropertySet;}
+
+ // ____ ::utl::OEventListenerAdapter ____
+ virtual void _disposing( const css::lang::EventObject& rSource ) override;
+
+protected:
+ /** sets a new property set, that you get with GetPropertySet(). It should
+ not be necessary to use this method. It is introduced to allow changing
+ the regression type of a regression curve which changes the object
+ identity.
+ */
+ void resetPropertySet( const css::uno::Reference< css::beans::XPropertySet > & xPropSet );
+
+private:
+ css::uno::Reference< css::beans::XPropertySet > m_xPropertySet;
+ css::uno::Reference< css::beans::XPropertySetInfo > m_xPropertySetInfo;
+
+ SfxItemPool& m_rItemPool;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/ItemPropertyMap.hxx b/chart2/source/controller/inc/ItemPropertyMap.hxx
new file mode 100644
index 0000000000..7bee6ae814
--- /dev/null
+++ b/chart2/source/controller/inc/ItemPropertyMap.hxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include "ItemConverter.hxx"
+
+#include <map>
+
+namespace chart::wrapper
+{
+typedef std::map<ItemConverter::tWhichIdType,
+ std::pair<ItemConverter::tPropertyNameType, ItemConverter::tMemberIdType>>
+ ItemPropertyMapType;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/LegendItemConverter.hxx b/chart2/source/controller/inc/LegendItemConverter.hxx
new file mode 100644
index 0000000000..3e9315acc2
--- /dev/null
+++ b/chart2/source/controller/inc/LegendItemConverter.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+
+#include <vector>
+
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+
+class SdrModel;
+
+namespace chart::wrapper
+{
+
+class LegendItemConverter final : public ItemConverter
+{
+public:
+ LegendItemConverter(
+ const css::uno::Reference< css::beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & xNamedPropertyContainerFactory,
+ const css::awt::Size* pRefSize );
+
+ virtual ~LegendItemConverter() override;
+
+ virtual void FillItemSet( SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplyItemSet( const SfxItemSet & rItemSet ) override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ std::vector< std::unique_ptr<ItemConverter> > m_aConverters;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/MultipleChartConverters.hxx b/chart2/source/controller/inc/MultipleChartConverters.hxx
new file mode 100644
index 0000000000..4fe1bb1de0
--- /dev/null
+++ b/chart2/source/controller/inc/MultipleChartConverters.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "MultipleItemConverter.hxx"
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace chart { class ChartModel; }
+class SdrModel;
+
+namespace chart::wrapper {
+
+class AllAxisItemConverter final : public MultipleItemConverter
+{
+public:
+ AllAxisItemConverter(
+ const rtl::Reference<::chart::ChartModel> & xChartModel,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const css::awt::Size* pRefSize );
+
+ virtual ~AllAxisItemConverter() override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+};
+
+class AllGridItemConverter final : public MultipleItemConverter
+{
+public:
+ AllGridItemConverter(
+ const rtl::Reference<::chart::ChartModel>& xChartModel,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const css::uno::Reference<css::lang::XMultiServiceFactory> & xNamedPropertyContainerFactory );
+ virtual ~AllGridItemConverter() override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+};
+
+class AllDataLabelItemConverter final : public MultipleItemConverter
+{
+public:
+ AllDataLabelItemConverter(
+ const rtl::Reference<::chart::ChartModel>& xChartModel,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const css::uno::Reference<css::lang::XMultiServiceFactory>& xNamedPropertyContainerFactory );
+
+ virtual ~AllDataLabelItemConverter() override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+};
+
+class AllTitleItemConverter final : public MultipleItemConverter
+{
+public:
+ AllTitleItemConverter(
+ const rtl::Reference<::chart::ChartModel>& xChartModel,
+ SfxItemPool& rItemPool, SdrModel& rDrawModel,
+ const css::uno::Reference<css::lang::XMultiServiceFactory>& xNamedPropertyContainerFactory );
+
+ virtual ~AllTitleItemConverter() override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+};
+
+class AllSeriesStatisticsConverter final : public MultipleItemConverter
+{
+public:
+ AllSeriesStatisticsConverter(
+ const rtl::Reference<::chart::ChartModel>& xChartModel, SfxItemPool& rItemPool );
+ virtual ~AllSeriesStatisticsConverter() override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/MultipleItemConverter.hxx b/chart2/source/controller/inc/MultipleItemConverter.hxx
new file mode 100644
index 0000000000..e2e8f07756
--- /dev/null
+++ b/chart2/source/controller/inc/MultipleItemConverter.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "ItemConverter.hxx"
+
+#include <vector>
+
+namespace chart::wrapper {
+
+/** Note: virtual const sal_uInt16 * GetWhichPairs() const; is still pure virtual
+ */
+class MultipleItemConverter : public ItemConverter
+{
+public:
+ virtual ~MultipleItemConverter() override;
+
+ virtual void FillItemSet( SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplyItemSet( const SfxItemSet & rItemSet ) override;
+
+ /// implemented empty (returns always false)
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+protected:
+ MultipleItemConverter( SfxItemPool& rItemPool );
+
+ std::vector< std::unique_ptr<ItemConverter> > m_aConverters;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/ObjectHierarchy.hxx b/chart2/source/controller/inc/ObjectHierarchy.hxx
new file mode 100644
index 0000000000..1531866aaf
--- /dev/null
+++ b/chart2/source/controller/inc/ObjectHierarchy.hxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartModel.hxx>
+#include <ObjectIdentifier.hxx>
+#include <map>
+#include <vector>
+
+namespace com::sun::star::awt { struct KeyEvent; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+
+namespace chart
+{
+
+class ExplicitValueProvider;
+
+class ObjectHierarchy
+{
+public:
+ typedef std::vector< ObjectIdentifier > tChildContainer;
+
+ /** @param bFlattenDiagram
+ If <TRUE/>, the content of the diagram (data series, wall, floor,
+ etc.) is treated as being at the same level as the diagram. (This is
+ used for keyboard navigation).
+ */
+ explicit ObjectHierarchy(
+ const rtl::Reference<::chart::ChartModel> & xChartDocument,
+ ExplicitValueProvider * pExplicitValueProvider,
+ bool bFlattenDiagram = false,
+ bool bOrderingForElementSelector = false );
+ ~ObjectHierarchy();
+
+ static ObjectIdentifier getRootNodeOID();
+ static bool isRootNode( const ObjectIdentifier& rOID );
+
+ /// equal to getChildren( getRootNodeOID())
+ const tChildContainer& getTopLevelChildren() const;
+ bool hasChildren(const ObjectIdentifier& rParent) const;
+ const tChildContainer& getChildren(const ObjectIdentifier& rParent) const;
+ const tChildContainer& getSiblings(const ObjectIdentifier& rNode) const;
+
+ /// The result is empty, if the node cannot be found in the tree
+ ObjectIdentifier getParent( const ObjectIdentifier& rNode ) const;
+ /// @returns -1, if no parent can be determined
+ sal_Int32 getIndexInParent( const ObjectIdentifier& rNode ) const;
+
+private:
+ void createTree( const rtl::Reference<::chart::ChartModel> & xChartDocument );
+ void createAxesTree(
+ tChildContainer & rContainer,
+ const rtl::Reference<::chart::ChartModel> & xChartDoc,
+ const rtl::Reference< ::chart::Diagram > & xDiagram );
+ void createDiagramTree(
+ tChildContainer& rContainer,
+ const rtl::Reference<::chart::ChartModel>& xChartDoc,
+ const rtl::Reference< ::chart::Diagram >& xDiagram );
+ void createDataSeriesTree(
+ tChildContainer & rOutDiagramSubContainer,
+ const rtl::Reference< ::chart::Diagram > & xDiagram );
+ static void createWallAndFloor(
+ tChildContainer & rContainer,
+ const rtl::Reference< ::chart::Diagram > & xDiagram );
+ void createLegendTree(
+ tChildContainer & rContainer,
+ const rtl::Reference<::chart::ChartModel> & xChartDoc,
+ const rtl::Reference< ::chart::Diagram > & xDiagram );
+ void createAdditionalShapesTree(tChildContainer& rContainer);
+ ObjectIdentifier getParentImpl(
+ const ObjectIdentifier& rParentOID,
+ const ObjectIdentifier& rOID ) const;
+
+ typedef std::map<ObjectIdentifier, tChildContainer> tChildMap;
+ tChildMap m_aChildMap;
+ ExplicitValueProvider* m_pExplicitValueProvider;
+ bool m_bFlattenDiagram;
+ bool m_bOrderingForElementSelector;
+};
+
+class ObjectKeyNavigation
+{
+public:
+ explicit ObjectKeyNavigation( ObjectIdentifier aCurrentOID,
+ rtl::Reference<::chart::ChartModel> xChartDocument,
+ ExplicitValueProvider * pExplicitValueProvider );
+
+ bool handleKeyEvent( const css::awt::KeyEvent & rEvent );
+ const ObjectIdentifier& getCurrentSelection() const { return m_aCurrentOID;}
+
+private:
+ void setCurrentSelection( const ObjectIdentifier& rOID );
+ bool first();
+ bool last();
+ bool next();
+ bool previous();
+ bool up();
+ bool down();
+ bool veryFirst();
+ bool veryLast();
+
+ ObjectIdentifier m_aCurrentOID;
+ rtl::Reference<::chart::ChartModel> m_xChartDocument;
+ ExplicitValueProvider * m_pExplicitValueProvider;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/ObjectNameProvider.hxx b/chart2/source/controller/inc/ObjectNameProvider.hxx
new file mode 100644
index 0000000000..c613dd5ce8
--- /dev/null
+++ b/chart2/source/controller/inc/ObjectNameProvider.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <ObjectIdentifier.hxx>
+#include <TitleHelper.hxx>
+
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::frame { class XModel; }
+
+namespace chart
+{
+
+/** Provides localized ui strings for the userinterface.
+*/
+
+class ObjectNameProvider
+{
+public:
+ static OUString getName( ObjectType eObjectType, bool bPlural=false );
+ static OUString getAxisName( std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+ static OUString getGridName( std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+ static OUString getTitleName( std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+ static OUString getTitleNameByType( TitleHelper::eTitleType eType );
+
+ static OUString getNameForCID(
+ std::u16string_view rObjectCID,
+ const rtl::Reference<::chart::ChartModel>& xChartDocument );
+
+ static OUString getName_ObjectForSeries(
+ ObjectType eObjectType,
+ std::u16string_view rSeriesCID,
+ const rtl::Reference<::chart::ChartModel>& xChartDocument );
+ static OUString getName_ObjectForAllSeries( ObjectType eObjectType );
+
+ /** Provides help texts for the various chart elements.
+ The parameter rObjectCID has to be a ClassifiedIdentifier - see class ObjectIdentifier.
+ */
+ static OUString getHelpText( std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel>& xChartModel, bool bVerbose=false );
+
+ /** This is used for showing the currently selected object in the status bar
+ (command "Context")
+ */
+ static OUString getSelectedObjectText( std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel>& xChartDocument );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/PositionAndSizeHelper.hxx b/chart2/source/controller/inc/PositionAndSizeHelper.hxx
new file mode 100644
index 0000000000..0f79373d52
--- /dev/null
+++ b/chart2/source/controller/inc/PositionAndSizeHelper.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <ObjectIdentifier.hxx>
+
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::awt { struct Rectangle; }
+
+namespace chart
+{
+
+class PositionAndSizeHelper
+{
+public:
+ static bool moveObject( ObjectType eObjectType
+ , const css::uno::Reference< css::beans::XPropertySet >& xObjectProp
+ , const css::awt::Rectangle& rNewPositionAndSize
+ , const css::awt::Rectangle& rOldPositionAndSize
+ , const css::awt::Rectangle& rPageRectangle );
+
+ static bool moveObject( std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel
+ , const css::awt::Rectangle& rNewPositionAndSize
+ , const css::awt::Rectangle& rOldPositionAndSize
+ , const css::awt::Rectangle& rPageRectangle );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/RangeSelectionHelper.hxx b/chart2/source/controller/inc/RangeSelectionHelper.hxx
new file mode 100644
index 0000000000..36fe0db99c
--- /dev/null
+++ b/chart2/source/controller/inc/RangeSelectionHelper.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::beans { struct PropertyValue; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+
+namespace com::sun::star {
+ namespace sheet{
+ class XRangeSelection;
+ class XRangeSelectionListener;
+ }
+}
+
+namespace chart
+{
+class ChartModel;
+class RangeSelectionListenerParent;
+
+class RangeSelectionHelper
+{
+public:
+ explicit RangeSelectionHelper(
+ rtl::Reference<::chart::ChartModel> xChartDocument );
+ ~RangeSelectionHelper();
+
+ bool hasRangeSelection();
+ css::uno::Reference< css::sheet::XRangeSelection > const & getRangeSelection();
+ void raiseRangeSelectionDocument();
+ bool chooseRange(
+ const OUString & aCurrentRange,
+ const OUString & aUIString,
+ RangeSelectionListenerParent & rListenerParent );
+ void stopRangeListening( bool bRemoveListener = true );
+ bool verifyCellRange( const OUString & rRangeStr );
+ bool verifyArguments( const css::uno::Sequence< css::beans::PropertyValue >& rArguments );
+
+private:
+ css::uno::Reference< css::sheet::XRangeSelection >
+ m_xRangeSelection;
+
+ rtl::Reference<::chart::ChartModel> m_xChartDocument;
+
+ css::uno::Reference< css::sheet::XRangeSelectionListener >
+ m_xRangeSelectionListener;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/RangeSelectionListener.hxx b/chart2/source/controller/inc/RangeSelectionListener.hxx
new file mode 100644
index 0000000000..9117b4d9b2
--- /dev/null
+++ b/chart2/source/controller/inc/RangeSelectionListener.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ControllerLockGuard.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/sheet/XRangeSelectionListener.hpp>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::frame
+{
+class XModel;
+}
+
+namespace chart
+{
+class ChartModel;
+
+class RangeSelectionListenerParent
+{
+public:
+ virtual void listeningFinished(const OUString& rNewRange) = 0;
+ virtual void disposingRangeSelection() = 0;
+
+protected:
+ ~RangeSelectionListenerParent() {}
+};
+
+class RangeSelectionListener final
+ : public ::cppu::WeakImplHelper<css::sheet::XRangeSelectionListener>
+{
+public:
+ explicit RangeSelectionListener(
+ RangeSelectionListenerParent& rParent, OUString aInitialRange,
+ const rtl::Reference<::chart::ChartModel>& xModelToLockController);
+ virtual ~RangeSelectionListener() override;
+
+protected:
+ // ____ XRangeSelectionListener ____
+ virtual void SAL_CALL done(const css::sheet::RangeSelectionEvent& aEvent) override;
+ virtual void SAL_CALL aborted(const css::sheet::RangeSelectionEvent& aEvent) override;
+
+ // ____ XEventListener ____
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+private:
+ RangeSelectionListenerParent& m_rParent;
+ OUString m_aRange;
+ ControllerLockGuardUNO m_aControllerLockGuard;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/RegressionCurveItemConverter.hxx b/chart2/source/controller/inc/RegressionCurveItemConverter.hxx
new file mode 100644
index 0000000000..8c4262b55e
--- /dev/null
+++ b/chart2/source/controller/inc/RegressionCurveItemConverter.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::chart2 { class XRegressionCurveContainer; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace chart { class DataSeries; }
+class SdrModel;
+
+namespace chart::wrapper
+{
+
+class RegressionCurveItemConverter final : public ItemConverter
+{
+public:
+ RegressionCurveItemConverter(
+ const css::uno::Reference< css::beans::XPropertySet > & rPropertySet,
+ rtl::Reference< ::chart::DataSeries > xRegCurveCnt,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & xNamedPropertyContainerFactory );
+ virtual ~RegressionCurveItemConverter() override;
+
+ virtual void FillItemSet( SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplyItemSet( const SfxItemSet & rItemSet ) override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ std::shared_ptr< ItemConverter > m_spGraphicConverter;
+ rtl::Reference< ::chart::DataSeries > m_xCurveContainer;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/RegressionEquationItemConverter.hxx b/chart2/source/controller/inc/RegressionEquationItemConverter.hxx
new file mode 100644
index 0000000000..0b32e4b9ed
--- /dev/null
+++ b/chart2/source/controller/inc/RegressionEquationItemConverter.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+
+#include <vector>
+
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+
+class SdrModel;
+
+namespace chart::wrapper {
+
+class RegressionEquationItemConverter final : public ItemConverter
+{
+public:
+ RegressionEquationItemConverter(
+ const css::uno::Reference< css::beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & xNamedPropertyContainerFactory,
+ const css::awt::Size* pRefSize );
+
+ virtual ~RegressionEquationItemConverter() override;
+
+ virtual void FillItemSet( SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplyItemSet( const SfxItemSet & rItemSet ) override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ std::vector< std::unique_ptr<ItemConverter> > m_aConverters;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/SelectionHelper.hxx b/chart2/source/controller/inc/SelectionHelper.hxx
new file mode 100644
index 0000000000..ff0e95eee2
--- /dev/null
+++ b/chart2/source/controller/inc/SelectionHelper.hxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "DrawViewWrapper.hxx"
+#include <ObjectIdentifier.hxx>
+
+class SdrObject;
+
+namespace com::sun::star::drawing { class XShape; }
+
+namespace chart
+{
+
+class Selection
+{
+public: //methods
+ bool hasSelection() const;
+
+ OUString const & getSelectedCID() const;
+ css::uno::Reference< css::drawing::XShape > const & getSelectedAdditionalShape() const;
+ const ObjectIdentifier& getSelectedOID() const { return m_aSelectedOID;}
+
+ bool isResizeableObjectSelected() const;
+ bool isRotateableObjectSelected( const rtl::Reference<::chart::ChartModel>& xChartModel ) const;
+ bool isDragableObjectSelected() const;
+
+ bool isAdditionalShapeSelected() const;
+
+ //returns true if selection has changed
+ bool setSelection( const OUString& rCID );
+ bool setSelection( const css::uno::Reference< css::drawing::XShape >& xShape );
+
+ void clearSelection();
+
+ //returns true if the selection has changed
+ bool maybeSwitchSelectionAfterSingleClickWasEnsured();
+ void resetPossibleSelectionAfterSingleClickWasEnsured();
+
+ void remindSelectionBeforeMouseDown();
+ bool isSelectionDifferentFromBeforeMouseDown() const;
+
+ void adaptSelectionToNewPos( const Point& rMousePos, DrawViewWrapper const * pDrawViewWrapper
+ , bool bIsRightMouse, bool bWaitingForDoubleClick );
+
+ void applySelection( DrawViewWrapper* pDrawViewWrapper );
+
+private: //member
+ //the selection could be given by a CID or by a shape
+ //if m_aSelectedObjectCID is not empty this indicates the selection
+ //the content of m_xSelectedShape is ignored in that case
+ //the strings are used for autogenerated chart specific objects
+ //the shape reference is used for additional shapes
+ ObjectIdentifier m_aSelectedOID; //only single object selection so far
+ ObjectIdentifier m_aSelectedOID_beforeMouseDown;
+ ObjectIdentifier m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing;
+};
+
+class SelectionHelper final : public MarkHandleProvider
+{
+public:
+ static bool findNamedParent( SdrObject*& pInOutObject
+ , OUString& rOutName
+ , bool bGivenObjectMayBeResult );
+ static bool findNamedParent( SdrObject*& pInOutObject
+ , ObjectIdentifier& rOutObject
+ , bool bGivenObjectMayBeResult );
+ static SdrObject* getMarkHandlesObject( SdrObject* pObj );
+ static E3dScene* getSceneToRotate( SdrObject* pObj );
+ static bool isDragableObjectHitTwice( const Point& rMPos
+ , const OUString& rNameOfSelectedObject
+ , const DrawViewWrapper& rDrawViewWrapper );
+
+ static OUString getHitObjectCID(
+ const Point& rMPos,
+ DrawViewWrapper const & rDrawViewWrapper,
+ bool bGetDiagramInsteadOf_Wall=false );
+
+ static bool isRotateableObject( std::u16string_view rCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+
+ explicit SelectionHelper( SdrObject* pSelectedObj );
+ virtual ~SelectionHelper();
+
+ //MarkHandleProvider:
+ virtual bool getMarkHandles( SdrHdlList& rHdlList ) override;
+ virtual bool getFrameDragSingles() override;
+
+ SdrObject* getObjectToMark();//sets also internally the mark object
+ //-> getMarkHandles will behave different if this method has found a Mark Object different from m_pSelectedObj
+
+private:
+ SdrObject* m_pSelectedObj;//hit and logically selected object
+ SdrObject* m_pMarkObj;//object that is marked instead to have more pretty handles
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/SeriesOptionsItemConverter.hxx b/chart2/source/controller/inc/SeriesOptionsItemConverter.hxx
new file mode 100644
index 0000000000..b55457ac5b
--- /dev/null
+++ b/chart2/source/controller/inc/SeriesOptionsItemConverter.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+#include <com/sun/star/uno/Sequence.h>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::chart2 { class XCoordinateSystem; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace chart { class ChartModel; }
+namespace chart { class BaseCoordinateSystem; }
+namespace chart { class DataSeries; }
+
+namespace chart::wrapper
+{
+
+class SeriesOptionsItemConverter final : public ItemConverter
+{
+public:
+ SeriesOptionsItemConverter(
+ const rtl::Reference<::chart::ChartModel> & xChartModel,
+ css::uno::Reference< css::uno::XComponentContext > xContext,
+ const rtl::Reference<::chart::DataSeries> & rPropertySet,
+ SfxItemPool& rItemPool );
+ virtual ~SeriesOptionsItemConverter() override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+ css::uno::Reference< css::uno::XComponentContext> m_xCC;
+
+ bool m_bAttachToMainAxis;
+ bool m_bSupportingOverlapAndGapWidthProperties;
+ bool m_bSupportingBarConnectors;
+
+ sal_Int32 m_nBarOverlap;
+ sal_Int32 m_nGapWidth;
+ bool m_bConnectBars;
+
+ bool m_bSupportingAxisSideBySide;
+ bool m_bGroupBarsPerAxis;
+
+ bool m_bSupportingStartingAngle;
+ sal_Int32 m_nStartingAngle;
+
+ bool m_bClockwise;
+ rtl::Reference< ::chart::BaseCoordinateSystem > m_xCooSys;
+
+ css::uno::Sequence< sal_Int32 > m_aSupportedMissingValueTreatments;
+ sal_Int32 m_nMissingValueTreatment;
+
+ bool m_bSupportingPlottingOfHiddenCells;
+ bool m_bIncludeHiddenCells;
+
+ bool m_bHideLegendEntry;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/StatisticsItemConverter.hxx b/chart2/source/controller/inc/StatisticsItemConverter.hxx
new file mode 100644
index 0000000000..a6c56a2691
--- /dev/null
+++ b/chart2/source/controller/inc/StatisticsItemConverter.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::frame { class XModel; }
+namespace chart { class ChartModel; }
+
+namespace chart::wrapper
+{
+
+class StatisticsItemConverter final : public ItemConverter
+{
+public:
+ StatisticsItemConverter(
+ rtl::Reference<::chart::ChartModel> xChartModel,
+ const css::uno::Reference< css::beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool );
+ virtual ~StatisticsItemConverter() override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ rtl::Reference<::chart::ChartModel> m_xModel;
+};
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/TabPageNotifiable.hxx b/chart2/source/controller/inc/TabPageNotifiable.hxx
new file mode 100644
index 0000000000..a5da029810
--- /dev/null
+++ b/chart2/source/controller/inc/TabPageNotifiable.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+// color to use as foreground for an invalid range
+#define RANGE_SELECTION_INVALID_RANGE_FOREGROUND_COLOR COL_WHITE
+// color to use as background for an invalid range
+#define RANGE_SELECTION_INVALID_RANGE_BACKGROUND_COLOR Color(0xff6563)
+
+class BuilderPage;
+
+namespace chart
+{
+class SAL_LOPLUGIN_ANNOTATE("crosscast") TabPageNotifiable
+{
+public:
+ virtual void setInvalidPage(BuilderPage* pTabPage) = 0;
+ virtual void setValidPage(BuilderPage* pTabPage) = 0;
+
+protected:
+ ~TabPageNotifiable() {}
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/TextDirectionListBox.hxx b/chart2/source/controller/inc/TextDirectionListBox.hxx
new file mode 100644
index 0000000000..d346a23cb4
--- /dev/null
+++ b/chart2/source/controller/inc/TextDirectionListBox.hxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svx/frmdirlbox.hxx>
+
+namespace chart
+{
+class TextDirectionListBox final : public svx::FrameDirectionListBox
+{
+public:
+ explicit TextDirectionListBox(std::unique_ptr<weld::ComboBox> pControl);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/TextLabelItemConverter.hxx b/chart2/source/controller/inc/TextLabelItemConverter.hxx
new file mode 100644
index 0000000000..9df2a65e16
--- /dev/null
+++ b/chart2/source/controller/inc/TextLabelItemConverter.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+
+#include <com/sun/star/uno/Sequence.h>
+#include <rtl/ref.hxx>
+#include <vector>
+
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::frame { class XModel; }
+namespace chart { class ChartModel; }
+namespace chart { class DataSeries; }
+
+namespace chart::wrapper {
+
+class TextLabelItemConverter final : public ItemConverter
+{
+public:
+ TextLabelItemConverter(
+ const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const css::uno::Reference<css::beans::XPropertySet>& rPropertySet,
+ const rtl::Reference<::chart::DataSeries>& xSeries,
+ SfxItemPool& rItemPool,
+ const css::awt::Size* pRefSize,
+ bool bDataSeries,
+ sal_Int32 nNumberFormat,
+ sal_Int32 nPercentNumberFormat );
+
+ virtual ~TextLabelItemConverter() override;
+
+ virtual void FillItemSet( SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplyItemSet( const SfxItemSet & rItemSet ) override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ std::vector<std::unique_ptr<ItemConverter>> maConverters;
+ sal_Int32 mnNumberFormat;
+ sal_Int32 mnPercentNumberFormat;
+ css::uno::Sequence<sal_Int32> maAvailableLabelPlacements;
+
+ bool mbDataSeries:1;
+ bool mbForbidPercentValue:1;
+
+ rtl::Reference<::chart::DataSeries> m_xSeries;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/TimerTriggeredControllerLock.hxx b/chart2/source/controller/inc/TimerTriggeredControllerLock.hxx
new file mode 100644
index 0000000000..49541b1552
--- /dev/null
+++ b/chart2/source/controller/inc/TimerTriggeredControllerLock.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/timer.hxx>
+#include <rtl/ref.hxx>
+
+#include <memory>
+
+namespace com::sun::star::frame
+{
+class XModel;
+}
+namespace chart
+{
+class ControllerLockGuardUNO;
+}
+
+namespace chart
+{
+class ChartModel;
+
+class TimerTriggeredControllerLock final
+{
+public:
+ TimerTriggeredControllerLock(rtl::Reference<::chart::ChartModel> xModel);
+ ~TimerTriggeredControllerLock();
+
+ void startTimer();
+
+private:
+ rtl::Reference<::chart::ChartModel> m_xModel;
+ std::unique_ptr<ControllerLockGuardUNO> m_apControllerLockGuard;
+ AutoTimer m_aTimer;
+
+ DECL_LINK(TimerTimeout, Timer*, void);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/TitleDialogData.hxx b/chart2/source/controller/inc/TitleDialogData.hxx
new file mode 100644
index 0000000000..70b03c8a65
--- /dev/null
+++ b/chart2/source/controller/inc/TitleDialogData.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ReferenceSizeProvider.hxx>
+#include <memory>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+class ChartModel;
+
+struct TitleDialogData
+{
+ css::uno::Sequence< sal_Bool > aPossibilityList;
+ css::uno::Sequence< sal_Bool > aExistenceList;
+ css::uno::Sequence< OUString > aTextList;
+ std::unique_ptr< ReferenceSizeProvider > apReferenceSizeProvider;
+
+ TitleDialogData(std::unique_ptr<ReferenceSizeProvider> pReferenzeSizeProvider = nullptr);
+
+ void readFromModel( const rtl::Reference<::chart::ChartModel>& xChartModel );
+ /* return true if anything has changed;
+ when pOldState is NULL then all data are written to the model
+ */
+ bool writeDifferenceToModel( const rtl::Reference<::chart::ChartModel>& xChartModel
+ , const css::uno::Reference< css::uno::XComponentContext >& xContext
+ , const TitleDialogData* pOldState=nullptr );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/TitleItemConverter.hxx b/chart2/source/controller/inc/TitleItemConverter.hxx
new file mode 100644
index 0000000000..5a2686d628
--- /dev/null
+++ b/chart2/source/controller/inc/TitleItemConverter.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ItemConverter.hxx"
+
+#include <vector>
+
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+
+class SdrModel;
+
+namespace chart::wrapper {
+
+class TitleItemConverter final : public ItemConverter
+{
+public:
+ TitleItemConverter(
+ const css::uno::Reference<css::beans::XPropertySet>& rPropertySet,
+ SfxItemPool& rItemPool, SdrModel& rDrawModel,
+ const css::uno::Reference<css::lang::XMultiServiceFactory>& xNamedPropertyContainerFactory,
+ const css::awt::Size* pRefSize );
+
+ virtual ~TitleItemConverter() override;
+
+ virtual void FillItemSet( SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplyItemSet( const SfxItemSet & rItemSet ) override;
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+ virtual bool GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const override;
+
+ virtual void FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const override;
+ virtual bool ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet ) override;
+
+private:
+ std::vector< std::unique_ptr<ItemConverter> > m_aConverters;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/ViewElementListProvider.hxx b/chart2/source/controller/inc/ViewElementListProvider.hxx
new file mode 100644
index 0000000000..d8b8ffc427
--- /dev/null
+++ b/chart2/source/controller/inc/ViewElementListProvider.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <svx/xtable.hxx>
+
+class FontList;
+class SdrObjList;
+class SfxItemSet;
+
+namespace chart
+{
+
+class DrawModelWrapper;
+
+class ViewElementListProvider final
+{
+public:
+ ViewElementListProvider( DrawModelWrapper* pDrawModelWrapper );
+ ViewElementListProvider(ViewElementListProvider&&) noexcept;
+ ~ViewElementListProvider();
+
+ XColorListRef GetColorTable() const;
+ XDashListRef GetDashList() const;
+ XLineEndListRef GetLineEndList() const;
+ XGradientListRef GetGradientList() const;
+ XHatchListRef GetHatchList() const;
+ XBitmapListRef GetBitmapList() const;
+ XPatternListRef GetPatternList() const;
+
+ //create chartspecific symbols for linecharts
+ SdrObjList* GetSymbolList() const;
+ Graphic GetSymbolGraphic( sal_Int32 nStandardSymbol, const SfxItemSet* pSymbolShapeProperties ) const;
+
+ FontList* getFontList() const;
+ //SfxPrinter* getPrinter();
+
+private:
+ DrawModelWrapper* m_pDrawModelWrapper;
+ mutable std::unique_ptr<FontList> m_pFontList;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_ChartType.hxx b/chart2/source/controller/inc/dlg_ChartType.hxx
new file mode 100644
index 0000000000..02e6ac998b
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_ChartType.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::frame
+{
+class XModel;
+}
+
+namespace chart
+{
+class ChartModel;
+class ChartTypeTabPage;
+
+class ChartTypeDialog final : public weld::GenericDialogController
+{
+public:
+ ChartTypeDialog(weld::Window* pWindow, rtl::Reference<::chart::ChartModel> xChartModel);
+ virtual ~ChartTypeDialog() override;
+
+private:
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+ std::unique_ptr<weld::Container> m_xContentArea;
+ std::unique_ptr<ChartTypeTabPage> m_xChartTypeTabPage;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_ChartType_UNO.hxx b/chart2/source/controller/inc/dlg_ChartType_UNO.hxx
new file mode 100644
index 0000000000..4566ec7514
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_ChartType_UNO.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <comphelper/proparrhlp.hxx>
+#include <svtools/genericunodialog.hxx>
+
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::beans { class XPropertySetInfo; }
+
+namespace chart
+{
+class ChartModel;
+
+typedef ::svt::OGenericUnoDialog ChartTypeUnoDlg_BASE;
+class ChartTypeUnoDlg final : public ChartTypeUnoDlg_BASE
+ ,public ::comphelper::OPropertyArrayUsageHelper< ChartTypeUnoDlg >
+{
+public:
+ ChartTypeUnoDlg( const css::uno::Reference< css::uno::XComponentContext >& xContext );
+
+private:
+ virtual ~ChartTypeUnoDlg() override;
+
+ // OGenericUnoDialog overridables
+ virtual void implInitialize(const css::uno::Any& _rValue) override;
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) override;
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ ChartTypeUnoDlg(const ChartTypeUnoDlg&) = delete;
+ void operator =(const ChartTypeUnoDlg&) = delete;
+
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_CreationWizard.hxx b/chart2/source/controller/inc/dlg_CreationWizard.hxx
new file mode 100644
index 0000000000..1b782632f4
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_CreationWizard.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "TimerTriggeredControllerLock.hxx"
+#include "TabPageNotifiable.hxx"
+
+#include <rtl/ref.hxx>
+#include <vcl/roadmapwizard.hxx>
+
+#include <memory>
+
+namespace com::sun::star::chart2
+{
+class XChartDocument;
+}
+namespace com::sun::star::uno
+{
+class XComponentContext;
+}
+
+using vcl::WizardTypes::WizardState;
+
+namespace chart
+{
+class ChartModel;
+class ChartTypeTemplateProvider;
+class DialogModel;
+
+class CreationWizard final : public vcl::RoadmapWizardMachine, public TabPageNotifiable
+{
+public:
+ CreationWizard(weld::Window* pParent, const rtl::Reference<::chart::ChartModel>& xChartModel,
+ css::uno::Reference<css::uno::XComponentContext> xContext);
+
+ CreationWizard() = delete;
+ virtual ~CreationWizard() override;
+
+ // TabPageNotifiable
+ virtual void setInvalidPage(BuilderPage* pTabPage) override;
+ virtual void setValidPage(BuilderPage* pTabPage) override;
+
+protected:
+ virtual bool leaveState(WizardState _nState) override;
+ virtual WizardState determineNextState(WizardState nCurrentState) const override;
+ virtual void enterState(WizardState nState) override;
+
+ virtual OUString getStateDisplayName(WizardState nState) const override;
+
+private:
+ virtual std::unique_ptr<BuilderPage> createPage(WizardState nState) override;
+
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+ css::uno::Reference<css::uno::XComponentContext> m_xComponentContext;
+ ChartTypeTemplateProvider* m_pTemplateProvider;
+ std::unique_ptr<DialogModel> m_pDialogModel;
+
+ TimerTriggeredControllerLock m_aTimerTriggeredControllerLock;
+
+ bool m_bCanTravel;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_CreationWizard_UNO.hxx b/chart2/source/controller/inc/dlg_CreationWizard_UNO.hxx
new file mode 100644
index 0000000000..89b8cb5a08
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_CreationWizard_UNO.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/component.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
+#include <rtl/ref.hxx>
+
+#include "dlg_CreationWizard.hxx"
+#include <tools/link.hxx>
+
+namespace com::sun::star::awt { class XWindow; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+class VclWindowEvent;
+
+namespace chart
+{
+class ChartModel;
+
+class CreationWizardUnoDlg final : public cppu::BaseMutex
+ , public ::cppu::OComponentHelper
+ , public css::ui::dialogs::XAsynchronousExecutableDialog
+ , public css::lang::XServiceInfo
+ , public css::lang::XInitialization
+ , public css::frame::XTerminateListener
+ , public css::beans::XPropertySet
+{
+public:
+ CreationWizardUnoDlg() = delete;
+
+ CreationWizardUnoDlg( css::uno::Reference< css::uno::XComponentContext > xContext );
+ virtual ~CreationWizardUnoDlg() override;
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual css::uno::Any SAL_CALL queryAggregation( css::uno::Type const & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XAsynchronousExecutableDialog
+ virtual void SAL_CALL setDialogTitle( const OUString& aTitle ) override;
+ virtual void SAL_CALL startExecuteModal( const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& xListener ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ // XTerminateListener
+ virtual void SAL_CALL queryTermination( const css::lang::EventObject& Event ) override;
+ virtual void SAL_CALL notifyTermination( const css::lang::EventObject& Event ) override;
+
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ //XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+
+protected:
+ // ____ OComponentHelper ____
+ /// Called in dispose method after the listeners were notified.
+ virtual void SAL_CALL disposing() override;
+
+private:
+ void createDialogOnDemand();
+ DECL_STATIC_LINK(CreationWizardUnoDlg, InstallLOKNotifierHdl, void*, vcl::ILibreOfficeKitNotifier*);
+
+private:
+ rtl::Reference< ::chart::ChartModel > m_xChartModel;
+ css::uno::Reference< css::uno::XComponentContext> m_xCC;
+ css::uno::Reference< css::awt::XWindow > m_xParentWindow;
+
+ std::shared_ptr<CreationWizard> m_xDialog;
+ bool m_bUnlockControllersOnExecute;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_DataEditor.hxx b/chart2/source/controller/inc/dlg_DataEditor.hxx
new file mode 100644
index 0000000000..205e822a12
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_DataEditor.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+namespace comphelper { template <class Tp, class Arg> class mem_fun1_t; }
+
+namespace com::sun::star {
+ namespace chart2 {
+ class XChartDocument;
+ }
+}
+
+namespace chart
+{
+class ChartModel;
+class DataBrowser;
+
+class DataEditor final : public weld::GenericDialogController
+{
+public:
+ DataEditor(weld::Window* pParent,
+ rtl::Reference<::chart::ChartModel> xChartDoc,
+ const css::uno::Reference<css::uno::XComponentContext> & xContext);
+ virtual ~DataEditor() override;
+
+ DECL_LINK(CloseHdl, weld::Button&, void);
+
+ void SetReadOnly( bool bReadOnly );
+
+private:
+ bool m_bReadOnly;
+
+ rtl::Reference<::chart::ChartModel> m_xChartDoc;
+ css::uno::Reference<css::uno::XComponentContext> m_xContext;
+
+ std::unique_ptr<weld::Toolbar> m_xTbxData;
+ std::unique_ptr<weld::Button> m_xCloseBtn;
+ std::unique_ptr<weld::Container> m_xTable;
+ std::unique_ptr<weld::Container> m_xColumns;
+ std::unique_ptr<weld::Container> m_xColors;
+ css::uno::Reference<css::awt::XWindow> m_xTableCtrlParent;
+ VclPtr<DataBrowser> m_xBrwData;
+
+ /// handles actions of the toolbox
+ DECL_LINK( ToolboxHdl, const OUString&, void );
+ /// is called, if the cursor of the table has moved
+ DECL_LINK( BrowserCursorMovedHdl, DataBrowser*, void);
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_DataSource.hxx b/chart2/source/controller/inc/dlg_DataSource.hxx
new file mode 100644
index 0000000000..166131e30e
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_DataSource.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "TabPageNotifiable.hxx"
+#include <vcl/weld.hxx>
+#include <memory>
+
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::uno { class XComponentContext; }
+class BuilderPage;
+
+namespace chart
+{
+class ChartModel;
+class ChartTypeTemplateProvider;
+class DataSourceTabPage;
+class DialogModel;
+class RangeChooserTabPage;
+
+class DataSourceDialog final :
+ public weld::GenericDialogController,
+ public TabPageNotifiable
+{
+public:
+ explicit DataSourceDialog(
+ weld::Window * pParent,
+ const rtl::Reference<::chart::ChartModel> & xChartDocument );
+ virtual ~DataSourceDialog() override;
+
+ // from GenericDialogController base
+ virtual short run() override;
+
+ // TabPageNotifiable
+ virtual void setInvalidPage( BuilderPage * pTabPage ) override;
+ virtual void setValidPage( BuilderPage * pTabPage ) override;
+
+private:
+ DECL_LINK(ActivatePageHdl, const OUString&, void);
+ DECL_LINK(DeactivatePageHdl, const OUString&, bool);
+
+ std::unique_ptr< ChartTypeTemplateProvider > m_apDocTemplateProvider;
+ std::unique_ptr< DialogModel > m_apDialogModel;
+
+ std::unique_ptr<RangeChooserTabPage> m_xRangeChooserTabPage;
+ std::unique_ptr<DataSourceTabPage> m_xDataSourceTabPage;
+ bool m_bRangeChooserTabIsValid;
+ bool m_bDataSourceTabIsValid;
+ bool m_bTogglingEnabled;
+
+ std::unique_ptr<weld::Notebook> m_xTabControl;
+ std::unique_ptr<weld::Button> m_xBtnOK;
+
+ static sal_uInt16 m_nLastPageId;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_InsertAxis_Grid.hxx b/chart2/source/controller/inc/dlg_InsertAxis_Grid.hxx
new file mode 100644
index 0000000000..2b265c7d65
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_InsertAxis_Grid.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+namespace chart
+{
+struct InsertAxisOrGridDialogData
+{
+ css::uno::Sequence<sal_Bool> aPossibilityList;
+ css::uno::Sequence<sal_Bool> aExistenceList;
+
+ InsertAxisOrGridDialogData();
+};
+
+/*************************************************************************
+|*
+|* insert Axis dialog (also base for grid dialog)
+|*
+\************************************************************************/
+class SchAxisDlg : public weld::GenericDialogController
+{
+ std::unique_ptr<weld::CheckButton> m_xCbPrimaryX;
+ std::unique_ptr<weld::CheckButton> m_xCbPrimaryY;
+ std::unique_ptr<weld::CheckButton> m_xCbPrimaryZ;
+ std::unique_ptr<weld::CheckButton> m_xCbSecondaryX;
+ std::unique_ptr<weld::CheckButton> m_xCbSecondaryY;
+ std::unique_ptr<weld::CheckButton> m_xCbSecondaryZ;
+
+public:
+ SchAxisDlg(weld::Window* pParent, const InsertAxisOrGridDialogData& rInput,
+ bool bAxisDlg = true);
+ void getResult(InsertAxisOrGridDialogData& rOutput);
+};
+
+/*************************************************************************
+|*
+|* Grid dialog
+|*
+\************************************************************************/
+class SchGridDlg final : public SchAxisDlg
+{
+public:
+ SchGridDlg(weld::Window* pParent, const InsertAxisOrGridDialogData& rInput);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_InsertDataLabel.hxx b/chart2/source/controller/inc/dlg_InsertDataLabel.hxx
new file mode 100644
index 0000000000..7777db3c96
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_InsertDataLabel.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <svl/itemset.hxx>
+#include <memory>
+
+class SvNumberFormatter;
+
+namespace chart
+{
+class DataLabelResources;
+
+class DataLabelsDialog final : public weld::GenericDialogController
+{
+private:
+ std::unique_ptr<DataLabelResources> m_apDataLabelResources;
+
+public:
+ DataLabelsDialog(weld::Window* pParent, const SfxItemSet& rInAttrs,
+ SvNumberFormatter* pFormatter);
+ virtual ~DataLabelsDialog() override;
+
+ void FillItemSet(SfxItemSet& rOutAttrs);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_InsertDataTable.hxx b/chart2/source/controller/inc/dlg_InsertDataTable.hxx
new file mode 100644
index 0000000000..cd77099864
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_InsertDataTable.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include "res_DataTableProperties.hxx"
+
+namespace chart
+{
+/** The data table properties (data) used by the dialog */
+struct DataTableDialogData
+{
+ bool mbShow = true;
+ bool mbHorizontalBorders = false;
+ bool mbVerticalBorders = false;
+ bool mbOutline = false;
+ bool mbKeys = false;
+};
+
+/** The dialog to change the data table specific properties */
+class InsertDataTableDialog final : public weld::GenericDialogController
+{
+private:
+ DataTablePropertiesResources m_aDataTablePropertiesResources;
+ std::unique_ptr<weld::CheckButton> m_xCbShowDataTable;
+
+ DataTableDialogData m_aData;
+
+ DECL_LINK(ShowDataTableToggle, weld::Toggleable&, void);
+
+ void changeEnabled();
+
+public:
+ InsertDataTableDialog(weld::Window* pParent);
+
+ /** Set the initial state of the data table properties */
+ void init(DataTableDialogData const& rData);
+
+ /** Get the state of the data table properties from the dialog */
+ DataTableDialogData& getDataTableDialogData();
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_InsertErrorBars.hxx b/chart2/source/controller/inc/dlg_InsertErrorBars.hxx
new file mode 100644
index 0000000000..4f8e8d094a
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_InsertErrorBars.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include <vcl/weld.hxx>
+#include <svl/itemset.hxx>
+
+#include "res_ErrorBar.hxx"
+
+namespace com::sun::star::frame
+{
+class XModel;
+}
+
+namespace chart
+{
+class ChartView;
+
+class InsertErrorBarsDialog final : public weld::GenericDialogController
+{
+public:
+ InsertErrorBarsDialog(weld::Window* pParent, const SfxItemSet& rMyAttrs,
+ const rtl::Reference<::chart::ChartModel>& xChartDocument,
+ ErrorBarResources::tErrorBarType eType);
+
+ void SetAxisMinorStepWidthForErrorBarDecimals(double fMinorStepWidth);
+
+ static double
+ getAxisMinorStepWidthForErrorBarDecimals(const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const rtl::Reference<::chart::ChartView>& xChartView,
+ std::u16string_view rSelectedObjectCID);
+
+ void FillItemSet(SfxItemSet& rOutAttrs);
+
+private:
+ std::unique_ptr<ErrorBarResources> m_apErrorBarResources;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_InsertLegend.hxx b/chart2/source/controller/inc/dlg_InsertLegend.hxx
new file mode 100644
index 0000000000..0e2cccc380
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_InsertLegend.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <rtl/ref.hxx>
+
+#include <memory>
+
+#include "res_LegendPosition.hxx"
+
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+class ChartModel;
+
+class SchLegendDlg final : public weld::GenericDialogController
+{
+private:
+ std::unique_ptr<LegendPositionResources> m_xLegendPositionResources;
+
+public:
+ SchLegendDlg(weld::Window* pParent, const css::uno::Reference< css::uno::XComponentContext>& xCC);
+
+ void init( const rtl::Reference<::chart::ChartModel>& xChartModel );
+ void writeToModel( const rtl::Reference<::chart::ChartModel>& xChartModel ) const;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_InsertTitle.hxx b/chart2/source/controller/inc/dlg_InsertTitle.hxx
new file mode 100644
index 0000000000..096628529e
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_InsertTitle.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "res_Titles.hxx"
+#include <vcl/weld.hxx>
+#include <memory>
+
+namespace chart
+{
+class SchTitleDlg final : public weld::GenericDialogController
+{
+private:
+ std::unique_ptr<TitleResources> m_xTitleResources;
+
+public:
+ SchTitleDlg(weld::Window* pParent, const TitleDialogData& rInput);
+
+ void getResult(TitleDialogData& rOutput);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_ObjectProperties.hxx b/chart2/source/controller/inc/dlg_ObjectProperties.hxx
new file mode 100644
index 0000000000..621f096753
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_ObjectProperties.hxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ObjectIdentifier.hxx>
+#include <sfx2/tabdlg.hxx>
+#include <vcl/graph.hxx>
+
+namespace com::sun::star::util { class XNumberFormatsSupplier; }
+
+namespace chart
+{
+
+class ObjectPropertiesDialogParameter final
+{
+public:
+ ObjectPropertiesDialogParameter( OUString aObjectCID );
+ ~ObjectPropertiesDialogParameter();
+
+ void init( const rtl::Reference<::chart::ChartModel>& xModel );
+ ObjectType getObjectType() const { return m_eObjectType;}
+ const OUString& getLocalizedName() const { return m_aLocalizedName;}
+
+ bool HasGeometryProperties() const { return m_bHasGeometryProperties;}
+ bool HasStatisticProperties() const { return m_bHasStatisticProperties;}
+ bool ProvidesSecondaryYAxis() const { return m_bProvidesSecondaryYAxis;}
+ bool ProvidesOverlapAndGapWidth() const { return m_bProvidesOverlapAndGapWidth;}
+ bool ProvidesBarConnectors() const { return m_bProvidesBarConnectors;}
+ bool HasAreaProperties() const { return m_bHasAreaProperties;}
+ bool HasSymbolProperties() const { return m_bHasSymbolProperties;}
+ bool HasNumberProperties() const { return m_bHasNumberProperties;}
+ bool ProvidesStartingAngle() const { return m_bProvidesStartingAngle;}
+ bool ProvidesMissingValueTreatments() const { return m_bProvidesMissingValueTreatments;}
+ bool IsPieChartDataPoint() const { return m_bIsPieChartDataPoint;}
+
+ bool HasScaleProperties() const { return m_bHasScaleProperties;}
+ bool CanAxisLabelsBeStaggered() const { return m_bCanAxisLabelsBeStaggered;}
+ bool IsSupportingAxisPositioning() const { return m_bSupportingAxisPositioning;}
+ bool ShowAxisOrigin() const { return m_bShowAxisOrigin;}
+ bool IsCrossingAxisIsCategoryAxis() const { return m_bIsCrossingAxisIsCategoryAxis;}
+ bool IsSupportingCategoryPositioning() const { return m_bSupportingCategoryPositioning;}
+ const css::uno::Sequence< OUString >& GetCategories() const { return m_aCategories;}
+
+ const rtl::Reference<::chart::ChartModel>&
+ getDocument() const { return m_xChartDocument;}
+
+ bool IsComplexCategoriesAxis() const { return m_bComplexCategoriesAxis;}
+
+ sal_Int32 getNbPoints() const { return m_nNbPoints;}
+
+private:
+ OUString m_aObjectCID;
+ ObjectType m_eObjectType;
+ bool m_bAffectsMultipleObjects;//is true if more than one object of the given type will be changed (e.g. all axes or all titles)
+
+ OUString m_aLocalizedName;
+
+ bool m_bHasGeometryProperties;
+ bool m_bHasStatisticProperties;
+ bool m_bProvidesSecondaryYAxis;
+ bool m_bProvidesOverlapAndGapWidth;
+ bool m_bProvidesBarConnectors;
+ bool m_bHasAreaProperties;
+ bool m_bHasSymbolProperties;
+ bool m_bHasNumberProperties;
+ bool m_bProvidesStartingAngle;
+ bool m_bProvidesMissingValueTreatments;
+ bool m_bIsPieChartDataPoint;
+
+ bool m_bHasScaleProperties;
+ bool m_bCanAxisLabelsBeStaggered;
+
+ bool m_bSupportingAxisPositioning;
+ bool m_bShowAxisOrigin;
+ bool m_bIsCrossingAxisIsCategoryAxis;
+ bool m_bSupportingCategoryPositioning;
+ css::uno::Sequence< OUString > m_aCategories;
+
+ rtl::Reference<::chart::ChartModel> m_xChartDocument;
+
+ bool m_bComplexCategoriesAxis;
+
+ sal_Int32 m_nNbPoints;
+};
+
+/*************************************************************************
+|*
+|* dialog for properties of different chart object
+|*
+\************************************************************************/
+
+class ViewElementListProvider;
+
+class SchAttribTabDlg final : public SfxTabDialogController
+{
+private:
+ const ObjectPropertiesDialogParameter * const m_pParameter;
+ const ViewElementListProvider* const m_pViewElementListProvider;
+ SvNumberFormatter* m_pNumberFormatter;
+
+ std::optional<SfxItemSet> m_oSymbolShapeProperties;
+ std::optional<Graphic> m_oAutoSymbolGraphic;
+
+ double m_fAxisMinorStepWidthForErrorBarDecimals;
+ bool m_bOKPressed;
+
+ DECL_LINK(OKPressed, weld::Button&, void);
+
+ virtual void PageCreated(const OUString& rId, SfxTabPage& rPage) override;
+
+public:
+ SchAttribTabDlg(weld::Window* pParent, const SfxItemSet* pAttr,
+ const ObjectPropertiesDialogParameter* pDialogParameter,
+ const ViewElementListProvider* pViewElementListProvider,
+ const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier );
+ virtual ~SchAttribTabDlg() override;
+
+ //pSymbolShapeProperties: Properties to be set on the symbollist shapes
+ //pAutoSymbolGraphic: Graphic to be shown if AutoSymbol gets selected
+ void setSymbolInformation( SfxItemSet&& rSymbolShapeProperties, std::optional<Graphic> oAutoSymbolGraphic );
+
+ void SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth );
+
+ bool DialogWasClosedWithOK() const { return m_bOKPressed;}
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_ShapeFont.hxx b/chart2/source/controller/inc/dlg_ShapeFont.hxx
new file mode 100644
index 0000000000..cfeb002fb9
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_ShapeFont.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+namespace chart
+{
+class ViewElementListProvider;
+
+/** dialog for font properties of shapes
+ */
+class ShapeFontDialog final : public SfxTabDialogController
+{
+public:
+ ShapeFontDialog(weld::Window* pParent, const SfxItemSet* pAttr,
+ const ViewElementListProvider* pViewElementListProvider);
+
+private:
+ virtual void PageCreated(const OUString& rId, SfxTabPage& rPage) override;
+
+ const ViewElementListProvider* m_pViewElementListProvider;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_ShapeParagraph.hxx b/chart2/source/controller/inc/dlg_ShapeParagraph.hxx
new file mode 100644
index 0000000000..15d0c014d8
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_ShapeParagraph.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+
+namespace chart
+{
+/** dialog for paragraph properties of shapes
+ */
+class ShapeParagraphDialog final : public SfxTabDialogController
+{
+public:
+ ShapeParagraphDialog(weld::Window* pParent, const SfxItemSet* pAttr);
+
+private:
+ virtual void PageCreated(const OUString& rId, SfxTabPage& rPage) override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/dlg_View3D.hxx b/chart2/source/controller/inc/dlg_View3D.hxx
new file mode 100644
index 0000000000..66c4a8eaf4
--- /dev/null
+++ b/chart2/source/controller/inc/dlg_View3D.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <ControllerLockGuard.hxx>
+
+namespace com::sun::star::frame
+{
+class XModel;
+}
+
+namespace chart
+{
+class ThreeD_SceneGeometry_TabPage;
+class ThreeD_SceneAppearance_TabPage;
+class ThreeD_SceneIllumination_TabPage;
+
+class View3DDialog final : public weld::GenericDialogController
+{
+public:
+ View3DDialog(weld::Window* pWindow, const rtl::Reference<::chart::ChartModel>& xChartModel);
+ virtual ~View3DDialog() override;
+
+ virtual short run() override;
+
+private:
+ DECL_LINK(ActivatePageHdl, const OUString&, void);
+
+ ControllerLockHelper m_aControllerLocker;
+
+ static sal_uInt16 m_nLastPageId;
+
+ std::unique_ptr<weld::Notebook> m_xTabControl;
+ std::unique_ptr<ThreeD_SceneGeometry_TabPage> m_xGeometry;
+ std::unique_ptr<ThreeD_SceneAppearance_TabPage> m_xAppearance;
+ std::unique_ptr<ThreeD_SceneIllumination_TabPage> m_xIllumination;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/helpids.h b/chart2/source/controller/inc/helpids.h
new file mode 100644
index 0000000000..775ec1489b
--- /dev/null
+++ b/chart2/source/controller/inc/helpids.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+inline constexpr OUString HID_SCH_WIN_DOCUMENT = u"CHART2_HID_SCH_WIN_DOCUMENT"_ustr;
+inline constexpr OUString HID_SCH_ERROR_BARS_FROM_DATA = u"CHART2_SCH_ERROR_BARS_FROM_DATA"_ustr;
+
+
+
+inline constexpr OUString HID_SCH_WIZARD_ROADMAP = u"CHART2_HID_SCH_WIZARD_ROADMAP"_ustr;
+inline constexpr OUString HID_SCH_DATA_SERIES_LABEL = u"CHART2_HID_SCH_DATA_SERIES_LABEL"_ustr;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/res_DataTableProperties.hxx b/chart2/source/controller/inc/res_DataTableProperties.hxx
new file mode 100644
index 0000000000..4b2aaa4f2e
--- /dev/null
+++ b/chart2/source/controller/inc/res_DataTableProperties.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <svl/itemset.hxx>
+#include <vcl/weld.hxx>
+
+namespace chart
+{
+/** The shared UI elements for the data table properties */
+class DataTablePropertiesResources final
+{
+private:
+ std::unique_ptr<weld::CheckButton> m_xCbHorizontalBorder;
+ std::unique_ptr<weld::CheckButton> m_xCbVerticalBorder;
+ std::unique_ptr<weld::CheckButton> m_xCbOutilne;
+ std::unique_ptr<weld::CheckButton> m_xCbKeys;
+
+public:
+ DataTablePropertiesResources(weld::Builder& rBuilder);
+
+ void initFromItemSet(SfxItemSet const& rInAttrs);
+ bool writeToItemSet(SfxItemSet& rOutAttrs) const;
+ void setChecksSensitive(bool bSensitive);
+
+ bool getHorizontalBorder() { return m_xCbHorizontalBorder->get_active(); }
+ void setHorizontalBorder(bool bActive) { m_xCbHorizontalBorder->set_active(bActive); }
+
+ bool getVerticalBorder() { return m_xCbVerticalBorder->get_active(); }
+ void setVerticalBorder(bool bActive) { m_xCbVerticalBorder->set_active(bActive); }
+
+ bool getOutline() { return m_xCbOutilne->get_active(); }
+ void setOutline(bool bActive) { m_xCbOutilne->set_active(bActive); }
+
+ bool getKeys() { return m_xCbKeys->get_active(); }
+ void setKeys(bool bActive) { m_xCbKeys->set_active(bActive); }
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/res_ErrorBar.hxx b/chart2/source/controller/inc/res_ErrorBar.hxx
new file mode 100644
index 0000000000..c3521d5ba0
--- /dev/null
+++ b/chart2/source/controller/inc/res_ErrorBar.hxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include <tools/link.hxx>
+#include <svl/itemset.hxx>
+#include <svx/chrtitem.hxx>
+#include "RangeSelectionListener.hxx"
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace weld { class Builder; }
+namespace weld { class Button; }
+namespace weld { class CheckButton; }
+namespace weld { class ComboBox; }
+namespace weld { class DialogController; }
+namespace weld { class Entry; }
+namespace weld { class Frame; }
+namespace weld { class Image; }
+namespace weld { class Label; }
+namespace weld { class MetricSpinButton; }
+namespace weld { class RadioButton; }
+namespace weld { class Toggleable; }
+namespace weld { class Widget; }
+
+namespace chart
+{
+class ChartModel;
+class RangeSelectionHelper;
+
+class ErrorBarResources final : public RangeSelectionListenerParent
+{
+public:
+ enum tErrorBarType
+ {
+ ERROR_BAR_X,
+ ERROR_BAR_Y
+ };
+
+ ErrorBarResources(
+ weld::Builder* pParent, weld::DialogController* pControllerDialog, const SfxItemSet& rInAttrs, bool bNoneAvailable, chart::ErrorBarResources::tErrorBarType eType = ERROR_BAR_Y);
+ virtual ~ErrorBarResources();
+
+ void SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth );
+ void SetErrorBarType( tErrorBarType eNewType );
+ void SetChartDocumentForRangeChoosing(
+ const rtl::Reference<::chart::ChartModel> & xChartDocument );
+ void Reset(const SfxItemSet& rInAttrs);
+ void FillItemSet(SfxItemSet& rOutAttrs) const;
+
+ void FillValueSets();
+
+ // ____ RangeSelectionListenerParent ____
+ virtual void listeningFinished( const OUString & rNewRange ) override;
+ virtual void disposingRangeSelection() override;
+
+private:
+ SvxChartKindError m_eErrorKind;
+ SvxChartIndicate m_eIndicate;
+
+ bool m_bErrorKindUnique;
+ bool m_bIndicatorUnique;
+ bool m_bRangePosUnique;
+ bool m_bRangeNegUnique;
+
+ tErrorBarType m_eErrorBarType;
+ sal_uInt16 m_nConstDecimalDigits;
+ sal_Int64 m_nConstSpinSize;
+ double m_fPlusValue;
+ double m_fMinusValue;
+
+ weld::DialogController* m_pController;
+ std::unique_ptr< RangeSelectionHelper > m_apRangeSelectionHelper;
+ weld::Entry* m_pCurrentRangeChoosingField;
+ bool m_bHasInternalDataProvider;
+ bool m_bEnableDataTableDialog;
+
+
+ // category
+ std::unique_ptr<weld::RadioButton> m_xRbNone;
+ std::unique_ptr<weld::RadioButton> m_xRbConst;
+ std::unique_ptr<weld::RadioButton> m_xRbPercent;
+ std::unique_ptr<weld::RadioButton> m_xRbFunction;
+ std::unique_ptr<weld::RadioButton> m_xRbRange;
+ std::unique_ptr<weld::ComboBox> m_xLbFunction;
+
+ // parameters
+ std::unique_ptr<weld::Frame> m_xFlParameters;
+ std::unique_ptr<weld::Widget> m_xBxPositive;
+ std::unique_ptr<weld::MetricSpinButton> m_xMfPositive;
+ std::unique_ptr<weld::Entry> m_xEdRangePositive;
+ std::unique_ptr<weld::Button> m_xIbRangePositive;
+ std::unique_ptr<weld::Widget> m_xBxNegative;
+ std::unique_ptr<weld::MetricSpinButton> m_xMfNegative;
+ std::unique_ptr<weld::Entry> m_xEdRangeNegative;
+ std::unique_ptr<weld::Button> m_xIbRangeNegative;
+ std::unique_ptr<weld::CheckButton> m_xCbSyncPosNeg;
+
+ // indicator
+ std::unique_ptr<weld::RadioButton> m_xRbBoth;
+ std::unique_ptr<weld::RadioButton> m_xRbPositive;
+ std::unique_ptr<weld::RadioButton> m_xRbNegative;
+ std::unique_ptr<weld::Image> m_xFiBoth;
+ std::unique_ptr<weld::Image> m_xFiPositive;
+ std::unique_ptr<weld::Image> m_xFiNegative;
+
+ std::unique_ptr<weld::Label> m_xUIStringPos;
+ std::unique_ptr<weld::Label> m_xUIStringNeg;
+ std::unique_ptr<weld::Label> m_xUIStringRbRange;
+
+ DECL_LINK( CategoryChosen, weld::Toggleable&, void );
+ DECL_LINK( CategoryChosen2, weld::ComboBox&, void );
+ DECL_LINK( SynchronizePosAndNeg, weld::Toggleable&, void );
+ DECL_LINK( PosValueChanged, weld::MetricSpinButton&, void );
+ DECL_LINK( IndicatorChanged, weld::Toggleable&, void );
+ DECL_LINK( ChooseRange, weld::Button&, void );
+ DECL_LINK( RangeChanged, weld::Entry&, void );
+
+ void UpdateControlStates();
+ void isRangeFieldContentValid(weld::Entry& rEdit);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/res_LegendPosition.hxx b/chart2/source/controller/inc/res_LegendPosition.hxx
new file mode 100644
index 0000000000..80ccaa85da
--- /dev/null
+++ b/chart2/source/controller/inc/res_LegendPosition.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svl/itemset.hxx>
+#include <tools/link.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace weld { class Builder; }
+namespace weld { class CheckButton; }
+namespace weld { class RadioButton; }
+namespace weld { class Toggleable; }
+
+namespace chart
+{
+class ChartModel;
+
+class LegendPositionResources final
+{
+
+public:
+ //constructor without Display checkbox
+ LegendPositionResources(weld::Builder& rBuilder);
+ //constructor inclusive Display checkbox
+ LegendPositionResources(weld::Builder& rBuilder, css::uno::Reference<
+ css::uno::XComponentContext> xCC );
+ ~LegendPositionResources();
+
+ void writeToResources( const rtl::Reference<::chart::ChartModel>& xChartModel );
+ void writeToModel( const rtl::Reference<::chart::ChartModel>& xChartModel ) const;
+
+ void initFromItemSet( const SfxItemSet& rInAttrs );
+ void writeToItemSet( SfxItemSet& rOutAttrs ) const;
+
+ void SetChangeHdl( const Link<LinkParamNone*,void>& rLink );
+
+ DECL_LINK( PositionEnableHdl, weld::Toggleable&, void );
+ DECL_LINK( PositionChangeHdl, weld::Toggleable&, void );
+
+private:
+ void impl_setRadioButtonToggleHdl();
+ void PositionEnable();
+
+private:
+ css::uno::Reference< css::uno::XComponentContext> m_xCC;
+ Link<LinkParamNone*,void> m_aChangeLink;
+
+ std::unique_ptr<weld::CheckButton> m_xCbxShow;
+ std::unique_ptr<weld::RadioButton> m_xRbtLeft;
+ std::unique_ptr<weld::RadioButton> m_xRbtRight;
+ std::unique_ptr<weld::RadioButton> m_xRbtTop;
+ std::unique_ptr<weld::RadioButton> m_xRbtBottom;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/res_Titles.hxx b/chart2/source/controller/inc/res_Titles.hxx
new file mode 100644
index 0000000000..a7a2eba572
--- /dev/null
+++ b/chart2/source/controller/inc/res_Titles.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "TitleDialogData.hxx"
+
+template <typename Arg, typename Ret> class Link;
+namespace weld
+{
+class Builder;
+}
+namespace weld
+{
+class Entry;
+}
+namespace weld
+{
+class Label;
+}
+
+namespace chart
+{
+class TitleResources final
+{
+public:
+ TitleResources(weld::Builder& rParent, bool bShowSecondaryAxesTitle);
+ ~TitleResources();
+
+ void writeToResources(const TitleDialogData& rInput);
+ void readFromResources(TitleDialogData& rOutput);
+
+ void connect_changed(const Link<weld::Entry&, void>& rLink);
+ bool get_value_changed_from_saved() const;
+ void save_value();
+
+private:
+ std::unique_ptr<weld::Label> m_xFT_Main;
+ std::unique_ptr<weld::Label> m_xFT_Sub;
+ std::unique_ptr<weld::Entry> m_xEd_Main;
+ std::unique_ptr<weld::Entry> m_xEd_Sub;
+
+ std::unique_ptr<weld::Label> m_xFT_XAxis;
+ std::unique_ptr<weld::Label> m_xFT_YAxis;
+ std::unique_ptr<weld::Label> m_xFT_ZAxis;
+ std::unique_ptr<weld::Entry> m_xEd_XAxis;
+ std::unique_ptr<weld::Entry> m_xEd_YAxis;
+ std::unique_ptr<weld::Entry> m_xEd_ZAxis;
+
+ std::unique_ptr<weld::Label> m_xFT_SecondaryXAxis;
+ std::unique_ptr<weld::Label> m_xFT_SecondaryYAxis;
+ std::unique_ptr<weld::Entry> m_xEd_SecondaryXAxis;
+ std::unique_ptr<weld::Entry> m_xEd_SecondaryYAxis;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/inc/uiobject.hxx b/chart2/source/controller/inc/uiobject.hxx
new file mode 100644
index 0000000000..917ba322bf
--- /dev/null
+++ b/chart2/source/controller/inc/uiobject.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <memory>
+#include <vcl/uitest/uiobject.hxx>
+
+#include "ChartWindow.hxx"
+
+class ChartUIObject final : public UIObject
+{
+public:
+
+ ChartUIObject(const VclPtr<chart::ChartWindow>& xChartWindow,
+ OUString aCID);
+
+ StringMap get_state() override;
+
+ virtual void execute(const OUString& rAction,
+ const StringMap& rParameters) override;
+
+ virtual std::unique_ptr<UIObject> get_child(const OUString& rID) override;
+
+ virtual std::set<OUString> get_children() const override;
+
+ virtual OUString get_type() const override;
+
+private:
+
+ OUString maCID;
+ VclPtr<chart::ChartWindow> mxChartWindow;
+ std::vector<std::unique_ptr<OUString>> maCommands;
+
+ DECL_LINK(PostCommand, void*, void);
+};
+
+class ChartWindowUIObject final : public WindowUIObject
+{
+ VclPtr<chart::ChartWindow> mxChartWindow;
+
+public:
+
+ ChartWindowUIObject(const VclPtr<chart::ChartWindow>& xChartWindow);
+
+ virtual StringMap get_state() override;
+
+ virtual void execute(const OUString& rAction,
+ const StringMap& rParameters) override;
+
+ virtual std::unique_ptr<UIObject> get_child(const OUString& rID) override;
+
+ virtual std::set<OUString> get_children() const override;
+
+ static std::unique_ptr<UIObject> create(vcl::Window* pWindow);
+
+protected:
+
+ virtual OUString get_name() const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx b/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx
new file mode 100644
index 0000000000..79020e023a
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx
@@ -0,0 +1,989 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <AxisItemConverter.hxx>
+#include <ItemPropertyMap.hxx>
+#include <CharacterPropertyItemConverter.hxx>
+#include <GraphicPropertyItemConverter.hxx>
+#include <chartview/ChartSfxItemIds.hxx>
+#include <chartview/ExplicitScaleValues.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include "SchWhichPairs.hxx"
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <CommonConverters.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <Diagram.hxx>
+#include <unonames.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <memory>
+
+#include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
+#include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart/TimeInterval.hpp>
+#include <com/sun/star/chart2/XAxis.hpp>
+#include <com/sun/star/chart2/AxisOrientation.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+
+#include <osl/diagnose.h>
+#include <o3tl/any.hxx>
+#include <svl/eitem.hxx>
+#include <svx/chrtitem.hxx>
+#include <svx/sdangitm.hxx>
+#include <svl/intitem.hxx>
+#include <rtl/math.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::chart::TimeInterval;
+using ::com::sun::star::chart::TimeIncrement;
+
+namespace chart::wrapper {
+
+namespace {
+
+ItemPropertyMapType & lcl_GetAxisPropertyMap()
+{
+ static ItemPropertyMapType aAxisPropertyMap{
+ {SCHATTR_AXIS_SHOWDESCR, {"DisplayLabels", 0}},
+ {SCHATTR_AXIS_TICKS, {"MajorTickmarks", 0}},
+ {SCHATTR_AXIS_HELPTICKS, {"MinorTickmarks", 0}},
+ {SCHATTR_AXIS_LABEL_ORDER, {"ArrangeOrder", 0}},
+ {SCHATTR_TEXT_STACKED, {"StackCharacters", 0}},
+ {SCHATTR_AXIS_LABEL_BREAK, {"TextBreak", 0}},
+ {SCHATTR_AXIS_LABEL_OVERLAP, {"TextOverlap", 0}}};
+ return aAxisPropertyMap;
+};
+
+} // anonymous namespace
+
+AxisItemConverter::AxisItemConverter(
+ const Reference< beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const rtl::Reference<::chart::ChartModel> & xChartDoc,
+ ::chart::ExplicitScaleData const * pScale /* = NULL */,
+ ::chart::ExplicitIncrementData const * pIncrement /* = NULL */,
+ const awt::Size* pRefSize ) :
+ ItemConverter( rPropertySet, rItemPool ),
+ m_xChartDoc( xChartDoc )
+{
+ if( pScale )
+ m_pExplicitScale.reset( new ::chart::ExplicitScaleData( *pScale ) );
+ if( pIncrement )
+ m_pExplicitIncrement.reset( new ::chart::ExplicitIncrementData( *pIncrement ) );
+
+ m_aConverters.emplace_back( new GraphicPropertyItemConverter(
+ rPropertySet, rItemPool, rDrawModel,
+ xChartDoc,
+ GraphicObjectType::LineProperties ));
+ m_aConverters.emplace_back(
+ new CharacterPropertyItemConverter(rPropertySet, rItemPool, pRefSize, "ReferencePageSize"));
+
+ m_xAxis = dynamic_cast<::chart::Axis*>(rPropertySet.get());
+ assert(m_xAxis);
+}
+
+AxisItemConverter::~AxisItemConverter()
+{
+}
+
+void AxisItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
+{
+ for( const auto& pConv : m_aConverters )
+ pConv->FillItemSet( rOutItemSet );
+
+ // own items
+ ItemConverter::FillItemSet( rOutItemSet );
+}
+
+bool AxisItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
+{
+ bool bResult = false;
+
+ for( const auto& pConv : m_aConverters )
+ bResult = pConv->ApplyItemSet( rItemSet ) || bResult;
+
+ // own items
+ return ItemConverter::ApplyItemSet( rItemSet ) || bResult;
+}
+
+const WhichRangesContainer& AxisItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nAxisWhichPairs;
+}
+
+bool AxisItemConverter::GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const
+{
+ ItemPropertyMapType & rMap( lcl_GetAxisPropertyMap());
+ ItemPropertyMapType::const_iterator aIt( rMap.find( nWhichId ));
+
+ if( aIt == rMap.end())
+ return false;
+
+ rOutProperty =(*aIt).second;
+
+ return true;
+}
+
+static bool lcl_hasTimeIntervalValue( const uno::Any& rAny )
+{
+ bool bRet = false;
+ TimeInterval aValue;
+ if( rAny >>= aValue )
+ bRet = true;
+ return bRet;
+}
+
+void AxisItemConverter::FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
+{
+ if( !m_xAxis.is() )
+ return;
+
+ const chart2::ScaleData& rScale( m_xAxis->getScaleData() );
+ const chart2::IncrementData& rIncrement( rScale.IncrementData );
+ const uno::Sequence< chart2::SubIncrement >& rSubIncrements( rScale.IncrementData.SubIncrements );
+ const TimeIncrement& rTimeIncrement( rScale.TimeIncrement );
+ bool bDateAxis = (rScale.AxisType == chart2::AxisType::DATE);
+ if( m_pExplicitScale )
+ bDateAxis = (m_pExplicitScale->AxisType == chart2::AxisType::DATE);
+
+ switch( nWhichId )
+ {
+ case SCHATTR_AXIS_AUTO_MAX:
+ rOutItemSet.Put( SfxBoolItem( nWhichId, !hasDoubleValue(rScale.Maximum) ) );
+ break;
+
+ case SCHATTR_AXIS_MAX:
+ {
+ double fMax = 10.0;
+ if( rScale.Maximum >>= fMax )
+ rOutItemSet.Put( SvxDoubleItem( fMax, SCHATTR_AXIS_MAX ) );
+ else
+ {
+ if( m_pExplicitScale )
+ fMax = m_pExplicitScale->Maximum;
+ rOutItemSet.Put( SvxDoubleItem( fMax, SCHATTR_AXIS_MAX ) );
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_AUTO_MIN:
+ rOutItemSet.Put( SfxBoolItem( nWhichId, !hasDoubleValue(rScale.Minimum) ) );
+ break;
+
+ case SCHATTR_AXIS_MIN:
+ {
+ double fMin = 0.0;
+ if( rScale.Minimum >>= fMin )
+ rOutItemSet.Put( SvxDoubleItem( fMin, SCHATTR_AXIS_MIN ) );
+ else if( m_pExplicitScale )
+ rOutItemSet.Put( SvxDoubleItem( m_pExplicitScale->Minimum, SCHATTR_AXIS_MIN ));
+ }
+ break;
+
+ case SCHATTR_AXIS_LOGARITHM:
+ {
+ bool bValue = AxisHelper::isLogarithmic( rScale.Scaling );
+ rOutItemSet.Put( SfxBoolItem( nWhichId, bValue ));
+ }
+ break;
+
+ case SCHATTR_AXIS_REVERSE:
+ rOutItemSet.Put( SfxBoolItem( nWhichId, (rScale.Orientation == AxisOrientation_REVERSE) ));
+ break;
+
+ // Increment
+ case SCHATTR_AXIS_AUTO_STEP_MAIN:
+ if( bDateAxis )
+ rOutItemSet.Put( SfxBoolItem( nWhichId, !lcl_hasTimeIntervalValue(rTimeIncrement.MajorTimeInterval) ) );
+ else
+ rOutItemSet.Put( SfxBoolItem( nWhichId, !hasDoubleValue(rIncrement.Distance) ) );
+ break;
+
+ case SCHATTR_AXIS_MAIN_TIME_UNIT:
+ {
+ TimeInterval aTimeInterval;
+ if( rTimeIncrement.MajorTimeInterval >>= aTimeInterval )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, aTimeInterval.TimeUnit ) );
+ else if( m_pExplicitIncrement )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, m_pExplicitIncrement->MajorTimeInterval.TimeUnit ) );
+ }
+ break;
+
+ case SCHATTR_AXIS_STEP_MAIN:
+ if( bDateAxis )
+ {
+ TimeInterval aTimeInterval;
+ if( rTimeIncrement.MajorTimeInterval >>= aTimeInterval )
+ rOutItemSet.Put( SvxDoubleItem(aTimeInterval.Number, SCHATTR_AXIS_STEP_MAIN ));
+ else if( m_pExplicitIncrement )
+ rOutItemSet.Put( SvxDoubleItem( m_pExplicitIncrement->MajorTimeInterval.Number, SCHATTR_AXIS_STEP_MAIN ));
+ }
+ else
+ {
+ double fDistance = 1.0;
+ if( rIncrement.Distance >>= fDistance )
+ rOutItemSet.Put( SvxDoubleItem(fDistance, SCHATTR_AXIS_STEP_MAIN ));
+ else if( m_pExplicitIncrement )
+ rOutItemSet.Put( SvxDoubleItem( m_pExplicitIncrement->Distance, SCHATTR_AXIS_STEP_MAIN ));
+ }
+ break;
+
+ // SubIncrement
+ case SCHATTR_AXIS_AUTO_STEP_HELP:
+ if( bDateAxis )
+ rOutItemSet.Put( SfxBoolItem( nWhichId, !lcl_hasTimeIntervalValue(rTimeIncrement.MinorTimeInterval) ) );
+ else
+ rOutItemSet.Put( SfxBoolItem( nWhichId,
+ ! ( rSubIncrements.hasElements() && rSubIncrements[0].IntervalCount.hasValue() )));
+ break;
+
+ case SCHATTR_AXIS_HELP_TIME_UNIT:
+ {
+ TimeInterval aTimeInterval;
+ if( rTimeIncrement.MinorTimeInterval >>= aTimeInterval )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, aTimeInterval.TimeUnit ) );
+ else if( m_pExplicitIncrement )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, m_pExplicitIncrement->MinorTimeInterval.TimeUnit ) );
+ }
+ break;
+
+ case SCHATTR_AXIS_STEP_HELP:
+ if( bDateAxis )
+ {
+ TimeInterval aTimeInterval;
+ if( rTimeIncrement.MinorTimeInterval >>= aTimeInterval )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, aTimeInterval.Number ));
+ else if( m_pExplicitIncrement )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, m_pExplicitIncrement->MinorTimeInterval.Number ));
+ }
+ else
+ {
+ if( rSubIncrements.hasElements() && rSubIncrements[0].IntervalCount.hasValue())
+ {
+ rOutItemSet.Put( SfxInt32Item( nWhichId,
+ *o3tl::doAccess<sal_Int32>(
+ rSubIncrements[0].IntervalCount) ));
+ }
+ else
+ {
+ if( m_pExplicitIncrement && !m_pExplicitIncrement->SubIncrements.empty() )
+ {
+ rOutItemSet.Put( SfxInt32Item( nWhichId,
+ m_pExplicitIncrement->SubIncrements[0].IntervalCount ));
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_AUTO_TIME_RESOLUTION:
+ {
+ rOutItemSet.Put( SfxBoolItem( nWhichId,
+ !rTimeIncrement.TimeResolution.hasValue() ));
+ }
+ break;
+ case SCHATTR_AXIS_TIME_RESOLUTION:
+ {
+ sal_Int32 nTimeResolution=0;
+ if( rTimeIncrement.TimeResolution >>= nTimeResolution )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, nTimeResolution ) );
+ else if( m_pExplicitScale )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, m_pExplicitScale->TimeResolution ) );
+ }
+ break;
+
+ case SCHATTR_AXIS_AUTO_ORIGIN:
+ {
+ rOutItemSet.Put( SfxBoolItem( nWhichId, ( !hasDoubleValue(rScale.Origin) )));
+ }
+ break;
+
+ case SCHATTR_AXIS_ORIGIN:
+ {
+ double fOrigin = 0.0;
+ if( !(rScale.Origin >>= fOrigin) )
+ {
+ if( m_pExplicitScale )
+ fOrigin = m_pExplicitScale->Origin;
+ }
+ rOutItemSet.Put( SvxDoubleItem( fOrigin, SCHATTR_AXIS_ORIGIN ));
+ }
+ break;
+
+ case SCHATTR_AXIS_POSITION:
+ {
+ css::chart::ChartAxisPosition eAxisPos( css::chart::ChartAxisPosition_ZERO );
+ GetPropertySet()->getPropertyValue( "CrossoverPosition" ) >>= eAxisPos;
+ rOutItemSet.Put( SfxInt32Item( nWhichId, static_cast<sal_Int32>(eAxisPos) ) );
+ }
+ break;
+
+ case SCHATTR_AXIS_POSITION_VALUE:
+ {
+ double fValue = 0.0;
+ if( GetPropertySet()->getPropertyValue( "CrossoverValue" ) >>= fValue )
+ rOutItemSet.Put( SvxDoubleItem( fValue, SCHATTR_AXIS_POSITION_VALUE ) );
+ }
+ break;
+
+ case SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT:
+ {
+ //read only item
+ //necessary tp display the crossing value with an appropriate format
+
+ rtl::Reference< BaseCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(
+ m_xAxis, m_xChartDoc->getFirstChartDiagram() ) );
+
+ rtl::Reference< Axis > xCrossingMainAxis = AxisHelper::getCrossingMainAxis( m_xAxis, xCooSys );
+
+ sal_Int32 nFormatKey = ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
+ xCrossingMainAxis, xCooSys, m_xChartDoc);
+
+ rOutItemSet.Put( SfxUInt32Item( nWhichId, nFormatKey ));
+ }
+ break;
+
+ case SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION:
+ rOutItemSet.Put(SfxBoolItem(nWhichId, rScale.ShiftedCategoryPosition));
+ break;
+
+ case SCHATTR_AXIS_LABEL_POSITION:
+ {
+ css::chart::ChartAxisLabelPosition ePos( css::chart::ChartAxisLabelPosition_NEAR_AXIS );
+ GetPropertySet()->getPropertyValue( "LabelPosition" ) >>= ePos;
+ rOutItemSet.Put( SfxInt32Item( nWhichId, static_cast<sal_Int32>(ePos) ) );
+ }
+ break;
+
+ case SCHATTR_AXIS_MARK_POSITION:
+ {
+ css::chart::ChartAxisMarkPosition ePos( css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS );
+ GetPropertySet()->getPropertyValue( "MarkPosition" ) >>= ePos;
+ rOutItemSet.Put( SfxInt32Item( nWhichId, static_cast<sal_Int32>(ePos) ) );
+ }
+ break;
+
+ case SCHATTR_TEXT_DEGREES:
+ {
+ // convert double to int (times 100)
+ double fVal = 0;
+
+ if( GetPropertySet()->getPropertyValue( "TextRotation" ) >>= fVal )
+ {
+ rOutItemSet.Put( SdrAngleItem( SCHATTR_TEXT_DEGREES, Degree100(static_cast< sal_Int32 >(
+ ::rtl::math::round( fVal * 100.0 )) ) ));
+ }
+ }
+ break;
+
+ case SID_ATTR_NUMBERFORMAT_VALUE:
+ {
+ if( m_pExplicitScale )
+ {
+ rtl::Reference< BaseCoordinateSystem > xCooSys(
+ AxisHelper::getCoordinateSystemOfAxis(
+ m_xAxis, m_xChartDoc->getFirstChartDiagram() ) );
+
+ sal_Int32 nFormatKey = ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
+ m_xAxis, xCooSys, m_xChartDoc);
+
+ rOutItemSet.Put( SfxUInt32Item( nWhichId, nFormatKey ));
+ }
+ }
+ break;
+
+ case SID_ATTR_NUMBERFORMAT_SOURCE:
+ {
+ bool bLinkToSource = true;
+ GetPropertySet()->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource;
+ rOutItemSet.Put(SfxBoolItem(nWhichId, bLinkToSource));
+ }
+ break;
+
+ case SCHATTR_AXISTYPE:
+ rOutItemSet.Put( SfxInt32Item( nWhichId, rScale.AxisType ));
+ break;
+
+ case SCHATTR_AXIS_AUTO_DATEAXIS:
+ rOutItemSet.Put( SfxBoolItem( nWhichId, rScale.AutoDateAxis ));
+ break;
+
+ case SCHATTR_AXIS_ALLOW_DATEAXIS:
+ {
+ rtl::Reference< BaseCoordinateSystem > xCooSys(
+ AxisHelper::getCoordinateSystemOfAxis( m_xAxis, m_xChartDoc->getFirstChartDiagram() ) );
+ sal_Int32 nDimensionIndex=0; sal_Int32 nAxisIndex=0;
+ AxisHelper::getIndicesForAxis(m_xAxis, xCooSys, nDimensionIndex, nAxisIndex );
+ bool bChartTypeAllowsDateAxis = ChartTypeHelper::isSupportingDateAxis( AxisHelper::getChartTypeByIndex( xCooSys, 0 ), nDimensionIndex );
+ rOutItemSet.Put( SfxBoolItem( nWhichId, bChartTypeAllowsDateAxis ));
+ }
+ break;
+ }
+}
+
+static bool lcl_isDateAxis( const SfxItemSet & rItemSet )
+{
+ sal_Int32 nAxisType = rItemSet.Get( SCHATTR_AXISTYPE ).GetValue();//css::chart2::AxisType
+ return (nAxisType == chart2::AxisType::DATE);
+}
+
+static bool lcl_isAutoMajor( const SfxItemSet & rItemSet )
+{
+ bool bRet = rItemSet.Get( SCHATTR_AXIS_AUTO_STEP_MAIN ).GetValue();
+ return bRet;
+}
+
+static bool lcl_isAutoMinor( const SfxItemSet & rItemSet )
+{
+ bool bRet = rItemSet.Get( SCHATTR_AXIS_AUTO_STEP_HELP ).GetValue();
+ return bRet;
+}
+
+bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
+{
+ if( !m_xAxis.is() )
+ return false;
+
+ chart2::ScaleData aScale( m_xAxis->getScaleData() );
+
+ bool bSetScale = false;
+ bool bChangedOtherwise = false;
+
+ uno::Any aValue;
+
+ switch( nWhichId )
+ {
+ case SCHATTR_AXIS_AUTO_MAX:
+ if( static_cast< const SfxBoolItem & >(rItemSet.Get( nWhichId )).GetValue() )
+ {
+ aScale.Maximum.clear();
+ bSetScale = true;
+ }
+ // else SCHATTR_AXIS_MAX must have some value
+ break;
+
+ case SCHATTR_AXIS_MAX:
+ // only if auto if false
+ if( ! (rItemSet.Get( SCHATTR_AXIS_AUTO_MAX ).GetValue() ))
+ {
+ rItemSet.Get( nWhichId ).QueryValue( aValue );
+
+ if( aScale.Maximum != aValue )
+ {
+ aScale.Maximum = aValue;
+ bSetScale = true;
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_AUTO_MIN:
+ if( static_cast< const SfxBoolItem & >(rItemSet.Get( nWhichId )).GetValue() )
+ {
+ aScale.Minimum.clear();
+ bSetScale = true;
+ }
+ // else SCHATTR_AXIS_MIN must have some value
+ break;
+
+ case SCHATTR_AXIS_MIN:
+ // only if auto if false
+ if( ! (rItemSet.Get( SCHATTR_AXIS_AUTO_MIN ).GetValue() ))
+ {
+ rItemSet.Get( nWhichId ).QueryValue( aValue );
+
+ if( aScale.Minimum != aValue )
+ {
+ aScale.Minimum = aValue;
+ bSetScale = true;
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_LOGARITHM:
+ {
+ bool bWasLogarithm = AxisHelper::isLogarithmic( aScale.Scaling );
+
+ if( static_cast< const SfxBoolItem & >(rItemSet.Get( nWhichId )).GetValue() )
+ {
+ // logarithm is true
+ if( ! bWasLogarithm )
+ {
+ aScale.Scaling = AxisHelper::createLogarithmicScaling( 10.0 );
+ bSetScale = true;
+ }
+ }
+ else
+ {
+ // logarithm is false => linear scaling
+ if( bWasLogarithm )
+ {
+ aScale.Scaling = AxisHelper::createLinearScaling();
+ bSetScale = true;
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_REVERSE:
+ {
+ bool bWasReverse = ( aScale.Orientation == AxisOrientation_REVERSE );
+ bool bNewReverse = static_cast< const SfxBoolItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ if( bWasReverse != bNewReverse )
+ {
+ aScale.Orientation = bNewReverse ? AxisOrientation_REVERSE : AxisOrientation_MATHEMATICAL;
+ bSetScale = true;
+ }
+ }
+ break;
+
+ // Increment
+ case SCHATTR_AXIS_AUTO_STEP_MAIN:
+ if( lcl_isAutoMajor(rItemSet) )
+ {
+ aScale.IncrementData.Distance.clear();
+ aScale.TimeIncrement.MajorTimeInterval.clear();
+ bSetScale = true;
+ }
+ // else SCHATTR_AXIS_STEP_MAIN must have some value
+ break;
+
+ case SCHATTR_AXIS_MAIN_TIME_UNIT:
+ if( !lcl_isAutoMajor(rItemSet) )
+ {
+ if( rItemSet.Get( nWhichId ).QueryValue( aValue ) )
+ {
+ TimeInterval aTimeInterval;
+ aScale.TimeIncrement.MajorTimeInterval >>= aTimeInterval;
+ aValue >>= aTimeInterval.TimeUnit;
+ aScale.TimeIncrement.MajorTimeInterval <<= aTimeInterval;
+ bSetScale = true;
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_STEP_MAIN:
+ // only if auto if false
+ if( !lcl_isAutoMajor(rItemSet) )
+ {
+ rItemSet.Get( nWhichId ).QueryValue( aValue );
+ if( lcl_isDateAxis(rItemSet) )
+ {
+ double fValue = 1.0;
+ if( aValue >>= fValue )
+ {
+ TimeInterval aTimeInterval;
+ aScale.TimeIncrement.MajorTimeInterval >>= aTimeInterval;
+ aTimeInterval.Number = static_cast<sal_Int32>(fValue);
+ aScale.TimeIncrement.MajorTimeInterval <<= aTimeInterval;
+ bSetScale = true;
+ }
+ }
+ else if( aScale.IncrementData.Distance != aValue )
+ {
+ aScale.IncrementData.Distance = aValue;
+ bSetScale = true;
+ }
+ }
+ break;
+
+ // SubIncrement
+ case SCHATTR_AXIS_AUTO_STEP_HELP:
+ if( lcl_isAutoMinor(rItemSet) )
+ {
+ if( aScale.IncrementData.SubIncrements.hasElements() &&
+ aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue() )
+ {
+ aScale.IncrementData.SubIncrements.getArray()[0].IntervalCount.clear();
+ bSetScale = true;
+ }
+ if( aScale.TimeIncrement.MinorTimeInterval.hasValue() )
+ {
+ aScale.TimeIncrement.MinorTimeInterval.clear();
+ bSetScale = true;
+ }
+ }
+ // else SCHATTR_AXIS_STEP_MAIN must have some value
+ break;
+
+ case SCHATTR_AXIS_HELP_TIME_UNIT:
+ if( !lcl_isAutoMinor(rItemSet) )
+ {
+ if( rItemSet.Get( nWhichId ).QueryValue( aValue ) )
+ {
+ TimeInterval aTimeInterval;
+ aScale.TimeIncrement.MinorTimeInterval >>= aTimeInterval;
+ aValue >>= aTimeInterval.TimeUnit;
+ aScale.TimeIncrement.MinorTimeInterval <<= aTimeInterval;
+ bSetScale = true;
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_STEP_HELP:
+ // only if auto is false
+ if( !lcl_isAutoMinor(rItemSet) )
+ {
+ rItemSet.Get( nWhichId ).QueryValue( aValue );
+ if( lcl_isDateAxis(rItemSet) )
+ {
+ TimeInterval aTimeInterval;
+ aScale.TimeIncrement.MinorTimeInterval >>= aTimeInterval;
+ aValue >>= aTimeInterval.Number;
+ aScale.TimeIncrement.MinorTimeInterval <<= aTimeInterval;
+ bSetScale = true;
+ }
+ else if( aScale.IncrementData.SubIncrements.hasElements() )
+ {
+ if( ! aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue() ||
+ aScale.IncrementData.SubIncrements[0].IntervalCount != aValue )
+ {
+ OSL_ASSERT( aValue.getValueTypeClass() == uno::TypeClass_LONG );
+ aScale.IncrementData.SubIncrements.getArray()[0].IntervalCount = aValue;
+ bSetScale = true;
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_AUTO_TIME_RESOLUTION:
+ if( static_cast< const SfxBoolItem & >( rItemSet.Get( nWhichId )).GetValue() )
+ {
+ aScale.TimeIncrement.TimeResolution.clear();
+ bSetScale = true;
+ }
+ break;
+ case SCHATTR_AXIS_TIME_RESOLUTION:
+ // only if auto is false
+ if( ! ( rItemSet.Get( SCHATTR_AXIS_AUTO_TIME_RESOLUTION ).GetValue() ))
+ {
+ rItemSet.Get( nWhichId ).QueryValue( aValue );
+
+ if( aScale.TimeIncrement.TimeResolution != aValue )
+ {
+ aScale.TimeIncrement.TimeResolution = aValue;
+ bSetScale = true;
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_AUTO_ORIGIN:
+ {
+ if( static_cast< const SfxBoolItem & >(rItemSet.Get( nWhichId )).GetValue() )
+ {
+ aScale.Origin.clear();
+ bSetScale = true;
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_ORIGIN:
+ {
+ // only if auto is false
+ if( ! (rItemSet.Get( SCHATTR_AXIS_AUTO_ORIGIN ).GetValue() ))
+ {
+ rItemSet.Get( nWhichId ).QueryValue( aValue );
+
+ if( aScale.Origin != aValue )
+ {
+ aScale.Origin = aValue;
+ bSetScale = true;
+
+ if( !AxisHelper::isAxisPositioningEnabled() )
+ {
+ //keep old and new settings for axis positioning in sync somehow
+ rtl::Reference< BaseCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(
+ m_xAxis, m_xChartDoc->getFirstChartDiagram() ) );
+
+ sal_Int32 nDimensionIndex=0;
+ sal_Int32 nAxisIndex=0;
+ if( AxisHelper::getIndicesForAxis( m_xAxis, xCooSys, nDimensionIndex, nAxisIndex ) && nAxisIndex==0 )
+ {
+ rtl::Reference< Axis > xCrossingMainAxis = AxisHelper::getCrossingMainAxis( m_xAxis, xCooSys );
+ if( xCrossingMainAxis.is() )
+ {
+ double fValue = 0.0;
+ if( aValue >>= fValue )
+ {
+ xCrossingMainAxis->setPropertyValue( "CrossoverPosition" , uno::Any( css::chart::ChartAxisPosition_VALUE ));
+ xCrossingMainAxis->setPropertyValue( "CrossoverValue" , uno::Any( fValue ));
+ }
+ else
+ xCrossingMainAxis->setPropertyValue( "CrossoverPosition" , uno::Any( css::chart::ChartAxisPosition_START ));
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_POSITION:
+ {
+ css::chart::ChartAxisPosition eAxisPos =
+ static_cast<css::chart::ChartAxisPosition>(static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue());
+
+ css::chart::ChartAxisPosition eOldAxisPos( css::chart::ChartAxisPosition_ZERO );
+ bool bPropExisted = ( GetPropertySet()->getPropertyValue( "CrossoverPosition" ) >>= eOldAxisPos );
+
+ if( !bPropExisted || ( eOldAxisPos != eAxisPos ))
+ {
+ GetPropertySet()->setPropertyValue( "CrossoverPosition" , uno::Any( eAxisPos ));
+ bChangedOtherwise = true;
+
+ //move the parallel axes to the other side if necessary
+ if( eAxisPos==css::chart::ChartAxisPosition_START || eAxisPos==css::chart::ChartAxisPosition_END )
+ {
+ rtl::Reference<Diagram> xDiagram = m_xChartDoc->getFirstChartDiagram();
+ rtl::Reference< Axis > xParallelAxis = AxisHelper::getParallelAxis( m_xAxis, xDiagram );
+ if( xParallelAxis.is() )
+ {
+ css::chart::ChartAxisPosition eOtherPos;
+ if( xParallelAxis->getPropertyValue( "CrossoverPosition" ) >>= eOtherPos )
+ {
+ if( eOtherPos == eAxisPos )
+ {
+ css::chart::ChartAxisPosition eOppositePos =
+ (eAxisPos==css::chart::ChartAxisPosition_START)
+ ? css::chart::ChartAxisPosition_END
+ : css::chart::ChartAxisPosition_START;
+ xParallelAxis->setPropertyValue( "CrossoverPosition" , uno::Any( eOppositePos ));
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_POSITION_VALUE:
+ {
+ double fValue = static_cast< const SvxDoubleItem & >( rItemSet.Get( nWhichId )).GetValue();
+
+ double fOldValue = 0.0;
+ bool bPropExisted = ( GetPropertySet()->getPropertyValue( "CrossoverValue" ) >>= fOldValue );
+
+ if( !bPropExisted || ( fOldValue != fValue ))
+ {
+ GetPropertySet()->setPropertyValue( "CrossoverValue" , uno::Any( fValue ));
+ bChangedOtherwise = true;
+
+ //keep old and new settings for axis positioning in sync somehow
+ {
+ rtl::Reference< BaseCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(
+ m_xAxis, m_xChartDoc->getFirstChartDiagram() ) );
+
+ sal_Int32 nDimensionIndex=0;
+ sal_Int32 nAxisIndex=0;
+ if( AxisHelper::getIndicesForAxis( m_xAxis, xCooSys, nDimensionIndex, nAxisIndex ) && nAxisIndex==0 )
+ {
+ Reference< chart2::XAxis > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( m_xAxis, xCooSys ) );
+ if( xCrossingMainAxis.is() )
+ {
+ ScaleData aCrossingScale( xCrossingMainAxis->getScaleData() );
+ aCrossingScale.Origin <<= fValue;
+ xCrossingMainAxis->setScaleData(aCrossingScale);
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION:
+ {
+ bool bNewValue = static_cast<const SfxBoolItem &> (rItemSet.Get(nWhichId)).GetValue();
+ bool bOldValue = aScale.ShiftedCategoryPosition;
+ if (bOldValue != bNewValue)
+ {
+ aScale.ShiftedCategoryPosition = bNewValue;
+ bSetScale = true;
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_LABEL_POSITION:
+ {
+ css::chart::ChartAxisLabelPosition ePos =
+ static_cast<css::chart::ChartAxisLabelPosition>(static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue());
+
+ css::chart::ChartAxisLabelPosition eOldPos( css::chart::ChartAxisLabelPosition_NEAR_AXIS );
+ bool bPropExisted = ( GetPropertySet()->getPropertyValue( "LabelPosition" ) >>= eOldPos );
+
+ if( !bPropExisted || ( eOldPos != ePos ))
+ {
+ GetPropertySet()->setPropertyValue( "LabelPosition" , uno::Any( ePos ));
+ bChangedOtherwise = true;
+
+ //move the parallel axes to the other side if necessary
+ if( ePos==css::chart::ChartAxisLabelPosition_OUTSIDE_START || ePos==css::chart::ChartAxisLabelPosition_OUTSIDE_END )
+ {
+ rtl::Reference<Diagram> xDiagram = m_xChartDoc->getFirstChartDiagram();
+ rtl::Reference< Axis > xParallelAxis = AxisHelper::getParallelAxis( m_xAxis, xDiagram );
+ if( xParallelAxis.is() )
+ {
+ css::chart::ChartAxisLabelPosition eOtherPos;
+ if( xParallelAxis->getPropertyValue( "LabelPosition" ) >>= eOtherPos )
+ {
+ if( eOtherPos == ePos )
+ {
+ css::chart::ChartAxisLabelPosition eOppositePos =
+ (ePos==css::chart::ChartAxisLabelPosition_OUTSIDE_START)
+ ? css::chart::ChartAxisLabelPosition_OUTSIDE_END
+ : css::chart::ChartAxisLabelPosition_OUTSIDE_START;
+ xParallelAxis->setPropertyValue( "LabelPosition" , uno::Any( eOppositePos ));
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_AXIS_MARK_POSITION:
+ {
+ css::chart::ChartAxisMarkPosition ePos =
+ static_cast<css::chart::ChartAxisMarkPosition>(static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue());
+
+ css::chart::ChartAxisMarkPosition eOldPos( css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS );
+ bool bPropExisted = ( GetPropertySet()->getPropertyValue( "MarkPosition" ) >>= eOldPos );
+
+ if( !bPropExisted || ( eOldPos != ePos ))
+ {
+ GetPropertySet()->setPropertyValue( "MarkPosition" , uno::Any( ePos ));
+ bChangedOtherwise = true;
+ }
+ }
+ break;
+
+ case SCHATTR_TEXT_DEGREES:
+ {
+ double fVal = toDegrees(rItemSet.Get(SCHATTR_TEXT_DEGREES).GetValue());
+ double fOldVal = 0.0;
+ bool bPropExisted =
+ ( GetPropertySet()->getPropertyValue( "TextRotation" ) >>= fOldVal );
+
+ if( ! bPropExisted || fOldVal != fVal )
+ {
+ GetPropertySet()->setPropertyValue( "TextRotation" , uno::Any( fVal ));
+ bChangedOtherwise = true;
+ }
+ }
+ break;
+
+ case SID_ATTR_NUMBERFORMAT_VALUE:
+ {
+ if( m_pExplicitScale )
+ {
+ bool bUseSourceFormat =
+ rItemSet.Get( SID_ATTR_NUMBERFORMAT_SOURCE ).GetValue();
+
+ if( ! bUseSourceFormat )
+ {
+ sal_Int32 nFmt = static_cast< sal_Int32 >(
+ static_cast< const SfxUInt32Item & >(
+ rItemSet.Get( nWhichId )).GetValue());
+
+ aValue <<= nFmt;
+ if (GetPropertySet()->getPropertyValue(CHART_UNONAME_NUMFMT) != aValue)
+ {
+ GetPropertySet()->setPropertyValue(CHART_UNONAME_NUMFMT , aValue);
+ bChangedOtherwise = true;
+ }
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_NUMBERFORMAT_SOURCE:
+ {
+ bool bUseSourceFormat =
+ static_cast< const SfxBoolItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ GetPropertySet()->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(bUseSourceFormat));
+
+ bool bNumberFormatIsSet = GetPropertySet()->getPropertyValue(CHART_UNONAME_NUMFMT).hasValue();
+
+ bChangedOtherwise = (bUseSourceFormat == bNumberFormatIsSet);
+ if( bChangedOtherwise )
+ {
+ if( ! bUseSourceFormat )
+ {
+ SfxItemState aState = rItemSet.GetItemState( SID_ATTR_NUMBERFORMAT_VALUE );
+ if( aState == SfxItemState::SET )
+ {
+ sal_Int32 nFormatKey = static_cast< sal_Int32 >(
+ rItemSet.Get( SID_ATTR_NUMBERFORMAT_VALUE ).GetValue());
+ aValue <<= nFormatKey;
+ }
+ else
+ {
+ rtl::Reference< BaseCoordinateSystem > xCooSys =
+ AxisHelper::getCoordinateSystemOfAxis(
+ m_xAxis, m_xChartDoc->getFirstChartDiagram() );
+
+ sal_Int32 nFormatKey = ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
+ m_xAxis, xCooSys, m_xChartDoc);
+
+ aValue <<= nFormatKey;
+ }
+ }
+ // else set a void Any
+ GetPropertySet()->setPropertyValue(CHART_UNONAME_NUMFMT , aValue);
+ }
+ }
+ break;
+
+ case SCHATTR_AXISTYPE:
+ {
+ sal_Int32 nNewAxisType = static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue();//css::chart2::AxisType
+ aScale.AxisType = nNewAxisType;
+ bSetScale = true;
+ }
+ break;
+
+ case SCHATTR_AXIS_AUTO_DATEAXIS:
+ {
+ bool bNewValue = static_cast< const SfxBoolItem & >( rItemSet.Get( nWhichId )).GetValue();
+ bool bOldValue = aScale.AutoDateAxis;
+ if( bOldValue != bNewValue )
+ {
+ aScale.AutoDateAxis = bNewValue;
+ bSetScale = true;
+ }
+ }
+ break;
+ }
+
+ if( bSetScale )
+ m_xAxis->setScaleData( aScale );
+
+ return (bSetScale || bChangedOtherwise);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx b/chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx
new file mode 100644
index 0000000000..ee498d4f4a
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/CharacterPropertyItemConverter.cxx
@@ -0,0 +1,557 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <CharacterPropertyItemConverter.hxx>
+#include "SchWhichPairs.hxx"
+#include <ItemPropertyMap.hxx>
+#include <RelativeSizeHelper.hxx>
+#include <editeng/memberids.h>
+#include <editeng/eeitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <o3tl/any.hxx>
+#include <svl/stritem.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/chart2/XFormattedString.hpp>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart::wrapper {
+
+namespace {
+
+ItemPropertyMapType & lcl_GetCharacterPropertyPropertyMap()
+{
+ static ItemPropertyMapType aCharacterPropertyMap{
+ {EE_CHAR_COLOR, {"CharColor", 0}},
+ {EE_CHAR_LANGUAGE, {"CharLocale", MID_LANG_LOCALE}},
+ {EE_CHAR_LANGUAGE_CJK, {"CharLocaleAsian", MID_LANG_LOCALE}},
+ {EE_CHAR_LANGUAGE_CTL, {"CharLocaleComplex", MID_LANG_LOCALE}},
+
+ {EE_CHAR_STRIKEOUT, {"CharStrikeout", MID_CROSS_OUT}},
+ {EE_CHAR_WLM, {"CharWordMode", 0}},
+ {EE_CHAR_SHADOW, {"CharShadowed", 0}},
+ {EE_CHAR_RELIEF, {"CharRelief", 0}},
+ {EE_CHAR_OUTLINE, {"CharContoured", 0}},
+ {EE_CHAR_EMPHASISMARK, {"CharEmphasis", 0}},
+
+ {EE_PARA_WRITINGDIR, {"WritingMode", 0}},
+
+ {EE_PARA_ASIANCJKSPACING, {"ParaIsCharacterDistance", 0}}};
+
+ return aCharacterPropertyMap;
+}
+} // anonymous namespace
+
+CharacterPropertyItemConverter::CharacterPropertyItemConverter(
+ const uno::Reference< beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool ) :
+ ItemConverter( rPropertySet, rItemPool )
+{}
+
+CharacterPropertyItemConverter::CharacterPropertyItemConverter(
+ const uno::Reference< beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool,
+ const awt::Size* pRefSize,
+ OUString aRefSizePropertyName,
+ const uno::Reference< beans::XPropertySet > & rRefSizePropSet ) :
+ ItemConverter( rPropertySet, rItemPool ),
+ m_aRefSizePropertyName(std::move( aRefSizePropertyName )),
+ m_xRefSizePropSet( rRefSizePropSet.is() ? rRefSizePropSet : rPropertySet )
+{
+ if (pRefSize)
+ m_pRefSize = *pRefSize;
+}
+
+CharacterPropertyItemConverter::~CharacterPropertyItemConverter()
+{}
+
+const WhichRangesContainer& CharacterPropertyItemConverter::GetWhichPairs() const
+{
+ return nCharacterPropertyWhichPairs;
+}
+
+bool CharacterPropertyItemConverter::GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const
+{
+ ItemPropertyMapType & rMap( lcl_GetCharacterPropertyPropertyMap());
+ ItemPropertyMapType::const_iterator aIt( rMap.find( nWhichId ));
+
+ if( aIt == rMap.end())
+ return false;
+
+ rOutProperty =(*aIt).second;
+ return true;
+}
+
+void CharacterPropertyItemConverter::FillSpecialItem(
+ sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
+{
+ switch( nWhichId )
+ {
+ case EE_CHAR_FONTINFO:
+ case EE_CHAR_FONTINFO_CJK:
+ case EE_CHAR_FONTINFO_CTL:
+ {
+ OUString aPostfix;
+ if( nWhichId == EE_CHAR_FONTINFO_CJK )
+ aPostfix = "Asian";
+ else if( nWhichId == EE_CHAR_FONTINFO_CTL )
+ aPostfix = "Complex";
+
+ SvxFontItem aItem( nWhichId );
+
+ aItem.PutValue( GetPropertySet()->getPropertyValue( "CharFontName" + aPostfix),
+ MID_FONT_FAMILY_NAME );
+ aItem.PutValue( GetPropertySet()->getPropertyValue( "CharFontFamily" + aPostfix),
+ MID_FONT_FAMILY );
+ aItem.PutValue( GetPropertySet()->getPropertyValue( "CharFontStyleName" + aPostfix),
+ MID_FONT_STYLE_NAME );
+ aItem.PutValue( GetPropertySet()->getPropertyValue( "CharFontCharSet" + aPostfix),
+ MID_FONT_CHAR_SET );
+ aItem.PutValue( GetPropertySet()->getPropertyValue( "CharFontPitch" + aPostfix),
+ MID_FONT_PITCH );
+
+ rOutItemSet.Put( aItem );
+ }
+ break;
+
+ case EE_CHAR_UNDERLINE:
+ {
+ SvxUnderlineItem aItem(LINESTYLE_NONE, EE_CHAR_UNDERLINE);
+ bool bModified = false;
+
+ uno::Any aValue( GetPropertySet()->getPropertyValue( "CharUnderline" ));
+ if( aValue.hasValue())
+ {
+ aItem.PutValue( aValue, MID_TL_STYLE );
+ bModified = true;
+ }
+
+ aValue = GetPropertySet()->getPropertyValue( "CharUnderlineHasColor" );
+ if( aValue.hasValue() && *o3tl::doAccess<bool>(aValue) )
+ {
+ aItem.PutValue( aValue, MID_TL_HASCOLOR );
+ bModified = true;
+ }
+
+ aValue = GetPropertySet()->getPropertyValue( "CharUnderlineColor" );
+ if( aValue.hasValue())
+ {
+ aItem.PutValue( aValue, MID_TL_COLOR );
+ bModified = true;
+ }
+
+ if( bModified )
+ rOutItemSet.Put( aItem );
+ }
+ break;
+
+ case EE_CHAR_OVERLINE:
+ {
+ SvxOverlineItem aItem( LINESTYLE_NONE, EE_CHAR_OVERLINE );
+ bool bModified = false;
+
+ uno::Any aValue( GetPropertySet()->getPropertyValue( "CharOverline" ) );
+ if ( aValue.hasValue() )
+ {
+ aItem.PutValue( aValue, MID_TL_STYLE );
+ bModified = true;
+ }
+
+ aValue = GetPropertySet()->getPropertyValue( "CharOverlineHasColor" );
+ if ( aValue.hasValue() && *o3tl::doAccess<bool>(aValue) )
+ {
+ aItem.PutValue( aValue, MID_TL_HASCOLOR );
+ bModified = true;
+ }
+
+ aValue = GetPropertySet()->getPropertyValue( "CharOverlineColor" );
+ if ( aValue.hasValue() )
+ {
+ aItem.PutValue( aValue, MID_TL_COLOR );
+ bModified = true;
+ }
+
+ if ( bModified )
+ {
+ rOutItemSet.Put( aItem );
+ }
+ }
+ break;
+
+ case EE_CHAR_ITALIC:
+ case EE_CHAR_ITALIC_CJK:
+ case EE_CHAR_ITALIC_CTL:
+ {
+ OUString aPostfix;
+ if( nWhichId == EE_CHAR_ITALIC_CJK )
+ aPostfix = "Asian";
+ else if( nWhichId == EE_CHAR_ITALIC_CTL )
+ aPostfix = "Complex";
+
+ SvxPostureItem aItem( ITALIC_NONE, nWhichId );
+
+ uno::Any aValue( GetPropertySet()->getPropertyValue( "CharPosture" + aPostfix));
+ if( aValue.hasValue())
+ {
+ aItem.PutValue( aValue, MID_POSTURE );
+ rOutItemSet.Put( aItem );
+ }
+ }
+ break;
+
+ case EE_CHAR_WEIGHT:
+ case EE_CHAR_WEIGHT_CJK:
+ case EE_CHAR_WEIGHT_CTL:
+ {
+ OUString aPostfix;
+ if( nWhichId == EE_CHAR_WEIGHT_CJK )
+ aPostfix = "Asian";
+ else if( nWhichId == EE_CHAR_WEIGHT_CTL )
+ aPostfix = "Complex";
+
+ SvxWeightItem aItem( WEIGHT_NORMAL, nWhichId );
+
+ uno::Any aValue( GetPropertySet()->getPropertyValue( "CharWeight" + aPostfix));
+ if( aValue.hasValue())
+ {
+ aItem.PutValue( aValue, MID_WEIGHT );
+ rOutItemSet.Put( aItem );
+ }
+ }
+ break;
+
+ case EE_CHAR_FONTHEIGHT:
+ case EE_CHAR_FONTHEIGHT_CJK:
+ case EE_CHAR_FONTHEIGHT_CTL:
+ {
+ OUString aPostfix;
+ if( nWhichId == EE_CHAR_FONTHEIGHT_CJK )
+ aPostfix = "Asian";
+ else if( nWhichId == EE_CHAR_FONTHEIGHT_CTL )
+ aPostfix = "Complex";
+
+ SvxFontHeightItem aItem( 240, 100, nWhichId );
+
+ try
+ {
+ uno::Any aValue( GetPropertySet()->getPropertyValue( "CharHeight" + aPostfix ));
+ float fHeight;
+ if( aValue >>= fHeight )
+ {
+ if (m_pRefSize)
+ {
+ awt::Size aOldRefSize;
+ if( GetRefSizePropertySet()->getPropertyValue( m_aRefSizePropertyName ) >>= aOldRefSize )
+ {
+ // calculate font height in view
+ fHeight = static_cast< float >(
+ RelativeSizeHelper::calculate( fHeight, aOldRefSize, *m_pRefSize ));
+ aValue <<= fHeight;
+ }
+ }
+
+ aItem.PutValue( aValue, MID_FONTHEIGHT );
+ rOutItemSet.Put( aItem );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ break;
+
+ case SID_CHAR_DLG_PREVIEW_STRING:
+ {
+ uno::Reference< chart2::XFormattedString > xFormattedString( GetPropertySet(), uno::UNO_QUERY );
+ if( xFormattedString.is() )
+ {
+ OUString aString = xFormattedString->getString();
+ rOutItemSet.Put( SfxStringItem( nWhichId, aString ) );
+ }
+ else
+ rOutItemSet.Put( SfxStringItem( nWhichId, OUString() ) );
+ }
+ break;
+
+ case EE_PARA_FORBIDDENRULES:
+ case EE_PARA_HANGINGPUNCTUATION:
+ rOutItemSet.DisableItem( nWhichId );
+ break;
+ }
+}
+
+bool CharacterPropertyItemConverter::ApplySpecialItem(
+ sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
+{
+ bool bChanged = false;
+ uno::Any aValue;
+
+ switch( nWhichId )
+ {
+ case EE_CHAR_FONTINFO:
+ case EE_CHAR_FONTINFO_CJK:
+ case EE_CHAR_FONTINFO_CTL:
+ {
+ OUString aPostfix;
+ if( nWhichId == EE_CHAR_FONTINFO_CJK )
+ aPostfix = "Asian";
+ else if( nWhichId == EE_CHAR_FONTINFO_CTL )
+ aPostfix = "Complex";
+
+ const SvxFontItem & rItem =
+ static_cast< const SvxFontItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.QueryValue( aValue, MID_FONT_FAMILY_NAME ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "CharFontName" + aPostfix ))
+ {
+ GetPropertySet()->setPropertyValue( "CharFontName" + aPostfix, aValue );
+ bChanged = true;
+ }
+ }
+ if( rItem.QueryValue( aValue, MID_FONT_FAMILY ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "CharFontFamily" + aPostfix ))
+ {
+ GetPropertySet()->setPropertyValue( "CharFontFamily" + aPostfix, aValue );
+ bChanged = true;
+ }
+ }
+ if( rItem.QueryValue( aValue, MID_FONT_STYLE_NAME ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "CharFontStyleName" + aPostfix ))
+ {
+ GetPropertySet()->setPropertyValue( "CharFontStyleName" + aPostfix, aValue );
+ bChanged = true;
+ }
+ }
+ if( rItem.QueryValue( aValue, MID_FONT_CHAR_SET ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "CharFontCharSet" + aPostfix ))
+ {
+ GetPropertySet()->setPropertyValue( "CharFontCharSet" + aPostfix, aValue );
+ bChanged = true;
+ }
+ }
+ if( rItem.QueryValue( aValue, MID_FONT_PITCH ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "CharFontPitch" + aPostfix ))
+ {
+ GetPropertySet()->setPropertyValue( "CharFontPitch" + aPostfix, aValue );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case EE_CHAR_UNDERLINE:
+ {
+ const SvxUnderlineItem & rItem =
+ static_cast< const SvxUnderlineItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.QueryValue( aValue, MID_TL_STYLE ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "CharUnderline" ))
+ {
+ GetPropertySet()->setPropertyValue( "CharUnderline" , aValue );
+ bChanged = true;
+ }
+ }
+
+ if( rItem.QueryValue( aValue, MID_TL_COLOR ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "CharUnderlineColor" ))
+ {
+ GetPropertySet()->setPropertyValue( "CharUnderlineColor" , aValue );
+ bChanged = true;
+ }
+ }
+
+ if( rItem.QueryValue( aValue, MID_TL_HASCOLOR ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "CharUnderlineHasColor" ))
+ {
+ GetPropertySet()->setPropertyValue( "CharUnderlineHasColor" , aValue );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case EE_CHAR_OVERLINE:
+ {
+ const SvxOverlineItem& rItem = static_cast< const SvxOverlineItem & >( rItemSet.Get( nWhichId ) );
+
+ if ( rItem.QueryValue( aValue, MID_TL_STYLE ) )
+ {
+ if ( aValue != GetPropertySet()->getPropertyValue( "CharOverline" ) )
+ {
+ GetPropertySet()->setPropertyValue( "CharOverline" , aValue );
+ bChanged = true;
+ }
+ }
+
+ if ( rItem.QueryValue( aValue, MID_TL_COLOR ) )
+ {
+ if ( aValue != GetPropertySet()->getPropertyValue( "CharOverlineColor" ) )
+ {
+ GetPropertySet()->setPropertyValue( "CharOverlineColor" , aValue );
+ bChanged = true;
+ }
+ }
+
+ if ( rItem.QueryValue( aValue, MID_TL_HASCOLOR ) )
+ {
+ if ( aValue != GetPropertySet()->getPropertyValue( "CharOverlineHasColor" ) )
+ {
+ GetPropertySet()->setPropertyValue( "CharOverlineHasColor" , aValue );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case EE_CHAR_ITALIC:
+ case EE_CHAR_ITALIC_CJK:
+ case EE_CHAR_ITALIC_CTL:
+ {
+ OUString aPostfix;
+ if( nWhichId == EE_CHAR_ITALIC_CJK )
+ aPostfix = "Asian";
+ else if( nWhichId == EE_CHAR_ITALIC_CTL )
+ aPostfix = "Complex";
+
+ const SvxPostureItem & rItem =
+ static_cast< const SvxPostureItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.QueryValue( aValue, MID_POSTURE ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "CharPosture" + aPostfix))
+ {
+ GetPropertySet()->setPropertyValue( "CharPosture" + aPostfix, aValue );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case EE_CHAR_WEIGHT:
+ case EE_CHAR_WEIGHT_CJK:
+ case EE_CHAR_WEIGHT_CTL:
+ {
+ OUString aPostfix;
+ if( nWhichId == EE_CHAR_WEIGHT_CJK )
+ aPostfix = "Asian" ;
+ else if( nWhichId == EE_CHAR_WEIGHT_CTL )
+ aPostfix = "Complex";
+
+ const SvxWeightItem & rItem =
+ static_cast< const SvxWeightItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.QueryValue( aValue, MID_WEIGHT ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "CharWeight" + aPostfix))
+ {
+ GetPropertySet()->setPropertyValue( "CharWeight" + aPostfix, aValue );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case EE_CHAR_FONTHEIGHT:
+ case EE_CHAR_FONTHEIGHT_CJK:
+ case EE_CHAR_FONTHEIGHT_CTL:
+ {
+ OUString aPostfix;
+ if( nWhichId == EE_CHAR_FONTHEIGHT_CJK )
+ aPostfix = "Asian";
+ else if( nWhichId == EE_CHAR_FONTHEIGHT_CTL )
+ aPostfix = "Complex";
+
+ const SvxFontHeightItem & rItem =
+ static_cast< const SvxFontHeightItem & >(
+ rItemSet.Get( nWhichId ));
+
+ try
+ {
+ if( rItem.QueryValue( aValue, MID_FONTHEIGHT ) )
+ {
+ bool bSetValue = false;
+ if( aValue != GetPropertySet()->getPropertyValue( "CharHeight" + aPostfix ))
+ bSetValue = true;
+ else
+ {
+ if (m_pRefSize)
+ {
+ awt::Size aNewRefSize = *m_pRefSize;
+ awt::Size aOldRefSize;
+ if( GetRefSizePropertySet()->getPropertyValue( m_aRefSizePropertyName ) >>= aOldRefSize )
+ {
+ if( aNewRefSize.Width != aOldRefSize.Width
+ || aNewRefSize.Height != aOldRefSize.Height )
+ bSetValue = true;
+ }
+ }
+ }
+ if( bSetValue )
+ {
+ // set new reference size only if there was a reference size before (auto-scaling on)
+ if (m_pRefSize && GetRefSizePropertySet()->getPropertyValue( m_aRefSizePropertyName ).hasValue())
+ {
+ GetRefSizePropertySet()->setPropertyValue(
+ m_aRefSizePropertyName, uno::Any(*m_pRefSize));
+ }
+
+ GetPropertySet()->setPropertyValue( "CharHeight" + aPostfix, aValue );
+ bChanged = true;
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ break;
+ }
+
+ return bChanged;
+}
+
+const uno::Reference<beans::XPropertySet>& CharacterPropertyItemConverter::GetRefSizePropertySet() const
+{
+ return m_xRefSizePropSet;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx
new file mode 100644
index 0000000000..8ac9b33cdb
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx
@@ -0,0 +1,829 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DataPointItemConverter.hxx>
+#include "SchWhichPairs.hxx"
+#include <ItemPropertyMap.hxx>
+
+#include <GraphicPropertyItemConverter.hxx>
+#include <CharacterPropertyItemConverter.hxx>
+#include <StatisticsItemConverter.hxx>
+#include <SeriesOptionsItemConverter.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DataSeriesProperties.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <comphelper/sequence.hxx>
+#include <svx/xflclit.hxx>
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <svl/stritem.hxx>
+#include <editeng/brushitem.hxx>
+#include <svl/ilstitem.hxx>
+#include <svx/sdangitm.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <vcl/graph.hxx>
+#include <rtl/math.hxx>
+
+#include <svx/tabline.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart::DataSeriesProperties;
+using ::com::sun::star::uno::Reference;
+
+namespace chart::wrapper {
+
+namespace {
+
+ItemPropertyMapType & lcl_GetDataPointPropertyMap()
+{
+ static ItemPropertyMapType aDataPointPropertyMap{
+ {SCHATTR_STYLE_SHAPE, {"Geometry3D", 0}}};
+ return aDataPointPropertyMap;
+};
+
+sal_Int32 lcl_getSymbolStyleForSymbol( const chart2::Symbol & rSymbol )
+{
+ sal_Int32 nStyle = SVX_SYMBOLTYPE_UNKNOWN;
+ switch( rSymbol.Style )
+ {
+ case chart2::SymbolStyle_NONE:
+ nStyle = SVX_SYMBOLTYPE_NONE;
+ break;
+ case chart2::SymbolStyle_AUTO:
+ nStyle = SVX_SYMBOLTYPE_AUTO;
+ break;
+ case chart2::SymbolStyle_GRAPHIC:
+ nStyle = SVX_SYMBOLTYPE_BRUSHITEM;
+ break;
+ case chart2::SymbolStyle_STANDARD:
+ nStyle = rSymbol.StandardSymbol;
+ break;
+
+ case chart2::SymbolStyle_POLYGON:
+ // to avoid warning
+ case chart2::SymbolStyle::SymbolStyle_MAKE_FIXED_SIZE:
+ // nothing
+ break;
+ }
+ return nStyle;
+}
+
+bool lcl_NumberFormatFromItemToPropertySet( sal_uInt16 nWhichId, const SfxItemSet & rItemSet, const uno::Reference< beans::XPropertySet > & xPropertySet, bool bOverwriteAttributedDataPointsAlso )
+{
+ bool bChanged = false;
+ if( !xPropertySet.is() )
+ return bChanged;
+ OUString aPropertyName = (nWhichId==SID_ATTR_NUMBERFORMAT_VALUE) ? CHART_UNONAME_NUMFMT : OUString( "PercentageNumberFormat" );
+ sal_uInt16 nSourceWhich = (nWhichId==SID_ATTR_NUMBERFORMAT_VALUE) ? SID_ATTR_NUMBERFORMAT_SOURCE : SCHATTR_PERCENT_NUMBERFORMAT_SOURCE;
+
+ if( rItemSet.GetItemState( nSourceWhich ) != SfxItemState::SET )
+ return bChanged;
+
+ uno::Any aValue;
+ bool bUseSourceFormat = static_cast< const SfxBoolItem & >(
+ rItemSet.Get( nSourceWhich )).GetValue();
+ if( !bUseSourceFormat )
+ {
+ SfxItemState aState = rItemSet.GetItemState( nWhichId );
+ if( aState == SfxItemState::SET )
+ {
+ sal_Int32 nFmt = static_cast< sal_Int32 >(
+ static_cast< const SfxUInt32Item & >(
+ rItemSet.Get( nWhichId )).GetValue());
+ aValue <<= nFmt;
+ }
+ else
+ return bChanged;
+ }
+
+ uno::Any aOldValue( xPropertySet->getPropertyValue(aPropertyName) );
+ if( bOverwriteAttributedDataPointsAlso )
+ {
+ rtl::Reference< DataSeries > xSeries( dynamic_cast<DataSeries*>(xPropertySet.get()) );
+ if( aValue != aOldValue ||
+ ::chart::DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries, aPropertyName, aOldValue ) )
+ {
+ ::chart::DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, aPropertyName, aValue );
+ bChanged = true;
+ }
+ }
+ else if( aOldValue != aValue )
+ {
+ xPropertySet->setPropertyValue(aPropertyName, aValue );
+ bChanged = true;
+ }
+ return bChanged;
+}
+
+bool lcl_UseSourceFormatFromItemToPropertySet( sal_uInt16 nWhichId, const SfxItemSet & rItemSet, const uno::Reference< beans::XPropertySet > & xPropertySet, bool bOverwriteAttributedDataPointsAlso )
+{
+ bool bChanged = false;
+ if( !xPropertySet.is() )
+ return bChanged;
+ OUString aPropertyName = (nWhichId==SID_ATTR_NUMBERFORMAT_SOURCE) ? CHART_UNONAME_NUMFMT : OUString( "PercentageNumberFormat" );
+ sal_uInt16 nFormatWhich = (nWhichId==SID_ATTR_NUMBERFORMAT_SOURCE) ? SID_ATTR_NUMBERFORMAT_VALUE : SCHATTR_PERCENT_NUMBERFORMAT_VALUE;
+
+ if( rItemSet.GetItemState( nWhichId ) != SfxItemState::SET )
+ return bChanged;
+
+ uno::Any aNewValue;
+ bool bUseSourceFormat = static_cast< const SfxBoolItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ xPropertySet->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(bUseSourceFormat));
+ if( !bUseSourceFormat )
+ {
+ SfxItemState aState = rItemSet.GetItemState( nFormatWhich );
+ if( aState == SfxItemState::SET )
+ {
+ sal_Int32 nFormatKey = static_cast< sal_Int32 >(
+ static_cast< const SfxUInt32Item & >(
+ rItemSet.Get( nFormatWhich )).GetValue());
+ aNewValue <<= nFormatKey;
+ }
+ else
+ return bChanged;
+ }
+
+ uno::Any aOldValue( xPropertySet->getPropertyValue(aPropertyName) );
+ if( bOverwriteAttributedDataPointsAlso )
+ {
+ rtl::Reference< DataSeries > xSeries( dynamic_cast<DataSeries*>(xPropertySet.get()) );
+ if( aNewValue != aOldValue ||
+ ::chart::DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries, aPropertyName, aOldValue ) )
+ {
+ ::chart::DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, aPropertyName, aNewValue );
+ bChanged = true;
+ }
+ }
+ else if( aOldValue != aNewValue )
+ {
+ xPropertySet->setPropertyValue( aPropertyName, aNewValue );
+ bChanged = true;
+ }
+
+ return bChanged;
+}
+
+} // anonymous namespace
+
+DataPointItemConverter::DataPointItemConverter(
+ const rtl::Reference<::chart::ChartModel> & xChartModel,
+ const uno::Reference< uno::XComponentContext > & xContext,
+ const uno::Reference< beans::XPropertySet > & rPropertySet,
+ const rtl::Reference< DataSeries > & xSeries,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const uno::Reference<lang::XMultiServiceFactory>& xNamedPropertyContainerFactory,
+ GraphicObjectType eMapTo,
+ const awt::Size* pRefSize,
+ bool bDataSeries,
+ bool bUseSpecialFillColor,
+ sal_Int32 nSpecialFillColor,
+ bool bOverwriteLabelsForAttributedDataPointsAlso,
+ sal_Int32 nNumberFormat,
+ sal_Int32 nPercentNumberFormat,
+ sal_Int32 nPointIndex ) :
+ ItemConverter( rPropertySet, rItemPool ),
+ m_bDataSeries( bDataSeries ),
+ m_bOverwriteLabelsForAttributedDataPointsAlso(m_bDataSeries && bOverwriteLabelsForAttributedDataPointsAlso),
+ m_bUseSpecialFillColor(bUseSpecialFillColor),
+ m_nSpecialFillColor(ColorTransparency, nSpecialFillColor),
+ m_nNumberFormat(nNumberFormat),
+ m_nPercentNumberFormat(nPercentNumberFormat),
+ m_bForbidPercentValue(true),
+ m_bHideLegendEntry(false),
+ m_nPointIndex(nPointIndex),
+ m_xSeries(xSeries)
+{
+ m_aConverters.emplace_back( new GraphicPropertyItemConverter(
+ rPropertySet, rItemPool, rDrawModel, xNamedPropertyContainerFactory, eMapTo ));
+ m_aConverters.emplace_back( new CharacterPropertyItemConverter(rPropertySet, rItemPool, pRefSize, "ReferencePageSize"));
+ if( bDataSeries )
+ {
+ assert(dynamic_cast<DataSeries*>(rPropertySet.get()));
+ m_aConverters.emplace_back( new StatisticsItemConverter( xChartModel, rPropertySet, rItemPool ));
+ m_aConverters.emplace_back( new SeriesOptionsItemConverter( xChartModel, xContext,
+ dynamic_cast<DataSeries*>(rPropertySet.get()), rItemPool ));
+ }
+
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeOfSeries( xSeries ) );
+ bool bFound = false;
+ bool bAmbiguous = false;
+ bool bSwapXAndY = xDiagram->getVertical( bFound, bAmbiguous );
+ m_aAvailableLabelPlacements = ChartTypeHelper::getSupportedLabelPlacements( xChartType, bSwapXAndY, xSeries );
+
+ m_bForbidPercentValue = ChartTypeHelper::getAxisType( xChartType, 0 ) != AxisType::CATEGORY;
+
+ if (bDataSeries)
+ return;
+
+ uno::Sequence<sal_Int32> deletedLegendEntriesSeq;
+ // "DeletedLegendEntries"
+ xSeries->getFastPropertyValue(PROP_DATASERIES_DELETED_LEGEND_ENTRIES) >>= deletedLegendEntriesSeq;
+ for (const auto& deletedLegendEntry : std::as_const(deletedLegendEntriesSeq))
+ {
+ if (nPointIndex == deletedLegendEntry)
+ {
+ m_bHideLegendEntry = true;
+ break;
+ }
+ }
+}
+
+DataPointItemConverter::~DataPointItemConverter()
+{
+}
+
+void DataPointItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
+{
+ for( const auto& pConv : m_aConverters )
+ pConv->FillItemSet( rOutItemSet );
+
+ // own items
+ ItemConverter::FillItemSet( rOutItemSet );
+
+ if( m_bUseSpecialFillColor )
+ {
+ Color aColor(m_nSpecialFillColor);
+ rOutItemSet.Put( XFillColorItem( OUString(), aColor ) );
+ }
+}
+
+bool DataPointItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
+{
+ bool bResult = false;
+
+ for( const auto& pConv : m_aConverters )
+ bResult = pConv->ApplyItemSet( rItemSet ) || bResult;
+
+ // own items
+ return ItemConverter::ApplyItemSet( rItemSet ) || bResult;
+}
+
+const WhichRangesContainer& DataPointItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ if( m_bDataSeries )
+ return nRowWhichPairs;
+ return nDataPointWhichPairs;
+}
+
+bool DataPointItemConverter::GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const
+{
+ ItemPropertyMapType & rMap( lcl_GetDataPointPropertyMap());
+ ItemPropertyMapType::const_iterator aIt( rMap.find( nWhichId ));
+
+ if( aIt == rMap.end())
+ return false;
+
+ rOutProperty =(*aIt).second;
+ return true;
+}
+
+bool DataPointItemConverter::ApplySpecialItem(
+ sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
+{
+ bool bChanged = false;
+
+ switch( nWhichId )
+ {
+ case SCHATTR_DATADESCR_SHOW_NUMBER:
+ case SCHATTR_DATADESCR_SHOW_PERCENTAGE:
+ case SCHATTR_DATADESCR_SHOW_CATEGORY:
+ case SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME:
+ case SCHATTR_DATADESCR_SHOW_SYMBOL:
+ {
+ const SfxBoolItem & rItem = static_cast< const SfxBoolItem & >( rItemSet.Get( nWhichId ));
+
+ uno::Any aOldValue = GetPropertySet()->getPropertyValue(CHART_UNONAME_LABEL);
+ chart2::DataPointLabel aLabel;
+ if( aOldValue >>= aLabel )
+ {
+ sal_Bool& rValue = (nWhichId==SCHATTR_DATADESCR_SHOW_NUMBER) ? aLabel.ShowNumber : (
+ (nWhichId==SCHATTR_DATADESCR_SHOW_PERCENTAGE) ? aLabel.ShowNumberInPercent : (
+ (nWhichId==SCHATTR_DATADESCR_SHOW_CATEGORY) ? aLabel.ShowCategoryName : (
+ (nWhichId==SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME) ? aLabel.ShowSeriesName : aLabel.ShowLegendSymbol )));
+ bool bOldValue = rValue;
+ rValue = rItem.GetValue();
+ if( m_bOverwriteLabelsForAttributedDataPointsAlso )
+ {
+ rtl::Reference<DataSeries> xSeries(dynamic_cast<DataSeries*>(GetPropertySet().get()));
+ if( bOldValue != bool(rValue) ||
+ DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries, CHART_UNONAME_LABEL , aOldValue ) )
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, CHART_UNONAME_LABEL , uno::Any( aLabel ) );
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, CHART_UNONAME_CUSTOM_LABEL_FIELDS, uno::Any() );
+ bChanged = true;
+ }
+ }
+ else if( bOldValue != bool(rValue) )
+ {
+ GetPropertySet()->setPropertyValue(CHART_UNONAME_LABEL , uno::Any(aLabel));
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_NUMBERFORMAT_VALUE:
+ case SCHATTR_PERCENT_NUMBERFORMAT_VALUE: //fall through intended
+ {
+ bChanged = lcl_NumberFormatFromItemToPropertySet( nWhichId, rItemSet, GetPropertySet(), m_bOverwriteLabelsForAttributedDataPointsAlso );
+ }
+ break;
+
+ case SID_ATTR_NUMBERFORMAT_SOURCE:
+ case SCHATTR_PERCENT_NUMBERFORMAT_SOURCE: //fall through intended
+ {
+ bChanged = lcl_UseSourceFormatFromItemToPropertySet( nWhichId, rItemSet, GetPropertySet(), m_bOverwriteLabelsForAttributedDataPointsAlso );
+ }
+ break;
+
+ case SCHATTR_DATADESCR_SEPARATOR:
+ {
+ OUString aNewValue = static_cast< const SfxStringItem & >( rItemSet.Get( nWhichId )).GetValue();
+ try
+ {
+ OUString aOldValue;
+ GetPropertySet()->getPropertyValue( "LabelSeparator" ) >>= aOldValue;
+ if( m_bOverwriteLabelsForAttributedDataPointsAlso )
+ {
+ rtl::Reference<DataSeries> xSeries(dynamic_cast<DataSeries*>(GetPropertySet().get()));
+ if( aOldValue != aNewValue ||
+ DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries, "LabelSeparator" , uno::Any( aOldValue ) ) )
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "LabelSeparator" , uno::Any( aNewValue ) );
+ bChanged = true;
+ }
+ }
+ else if( aOldValue != aNewValue )
+ {
+ GetPropertySet()->setPropertyValue( "LabelSeparator" , uno::Any( aNewValue ));
+ bChanged = true;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+
+ case SCHATTR_DATADESCR_WRAP_TEXT:
+ {
+
+ try
+ {
+ bool bNew = static_cast< const SfxBoolItem & >( rItemSet.Get( nWhichId )).GetValue();
+ bool bOld = false;
+ GetPropertySet()->getPropertyValue( "TextWordWrap" ) >>= bOld;
+ if( m_bOverwriteLabelsForAttributedDataPointsAlso )
+ {
+ rtl::Reference<DataSeries> xSeries(dynamic_cast<DataSeries*>(GetPropertySet().get()));
+ if( bOld!=bNew ||
+ DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries, "TextWordWrap", uno::Any( bOld ) ) )
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "TextWordWrap", uno::Any( bNew ) );
+ bChanged = true;
+ }
+ }
+ else if( bOld!=bNew )
+ {
+ GetPropertySet()->setPropertyValue( "TextWordWrap", uno::Any( bNew ));
+ bChanged = true;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+
+ case SCHATTR_DATADESCR_PLACEMENT:
+ {
+
+ try
+ {
+ sal_Int32 nNew = static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue();
+ sal_Int32 nOld = -1;
+ RelativePosition aCustomLabelPosition;
+ GetPropertySet()->getPropertyValue("LabelPlacement") >>= nOld;
+ if( m_bOverwriteLabelsForAttributedDataPointsAlso )
+ {
+ rtl::Reference<DataSeries> xSeries(dynamic_cast<DataSeries*>(GetPropertySet().get()));
+ if( nOld!=nNew ||
+ DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries, "LabelPlacement" , uno::Any( nOld ) ) )
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "LabelPlacement" , uno::Any( nNew ) );
+ bChanged = true;
+ }
+ }
+ else if( nOld!=nNew || (GetPropertySet()->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition) )
+ {
+ GetPropertySet()->setPropertyValue("LabelPlacement", uno::Any(nNew));
+ GetPropertySet()->setPropertyValue("CustomLabelPosition", uno::Any());
+ bChanged = true;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+
+ case SCHATTR_STYLE_SYMBOL:
+ {
+ sal_Int32 nStyle =
+ static_cast< const SfxInt32Item & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ chart2::Symbol aSymbol;
+
+ GetPropertySet()->getPropertyValue( "Symbol" ) >>= aSymbol;
+ sal_Int32 nOldStyle = lcl_getSymbolStyleForSymbol( aSymbol );
+
+ if( nStyle != nOldStyle )
+ {
+ bool bDeleteSymbol = false;
+ switch( nStyle )
+ {
+ case SVX_SYMBOLTYPE_NONE:
+ aSymbol.Style = chart2::SymbolStyle_NONE;
+ break;
+ case SVX_SYMBOLTYPE_AUTO:
+ aSymbol.Style = chart2::SymbolStyle_AUTO;
+ break;
+ case SVX_SYMBOLTYPE_BRUSHITEM:
+ aSymbol.Style = chart2::SymbolStyle_GRAPHIC;
+ break;
+ case SVX_SYMBOLTYPE_UNKNOWN:
+ bDeleteSymbol = true;
+ break;
+
+ default:
+ aSymbol.Style = chart2::SymbolStyle_STANDARD;
+ aSymbol.StandardSymbol = nStyle;
+ }
+
+ if( bDeleteSymbol )
+ GetPropertySet()->setPropertyValue( "Symbol" , uno::Any());
+ else
+ GetPropertySet()->setPropertyValue( "Symbol" , uno::Any( aSymbol ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_SYMBOL_SIZE:
+ {
+ Size aSize = static_cast< const SvxSizeItem & >(
+ rItemSet.Get( nWhichId )).GetSize();
+ chart2::Symbol aSymbol;
+
+ GetPropertySet()->getPropertyValue( "Symbol" ) >>= aSymbol;
+ if( aSize.getWidth() != aSymbol.Size.Width ||
+ aSize.getHeight() != aSymbol.Size.Height )
+ {
+ aSymbol.Size.Width = aSize.getWidth();
+ aSymbol.Size.Height = aSize.getHeight();
+
+ GetPropertySet()->setPropertyValue( "Symbol" , uno::Any( aSymbol ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_SYMBOL_BRUSH:
+ {
+ const SvxBrushItem & rBrshItem( static_cast< const SvxBrushItem & >(
+ rItemSet.Get( nWhichId )));
+ uno::Any aXGraphicAny;
+ const Graphic *pGraphic( rBrshItem.GetGraphic());
+ if( pGraphic )
+ {
+ uno::Reference< graphic::XGraphic > xGraphic( pGraphic->GetXGraphic());
+ if( xGraphic.is())
+ {
+ aXGraphicAny <<= xGraphic;
+ chart2::Symbol aSymbol;
+ GetPropertySet()->getPropertyValue( "Symbol" ) >>= aSymbol;
+ if( aSymbol.Graphic != xGraphic )
+ {
+ aSymbol.Graphic = xGraphic;
+ GetPropertySet()->setPropertyValue( "Symbol" , uno::Any( aSymbol ));
+ bChanged = true;
+ }
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_TEXT_DEGREES:
+ {
+ double fValue = toDegrees(rItemSet.Get(SCHATTR_TEXT_DEGREES).GetValue());
+ double fOldValue = 0.0;
+ bool bPropExisted =
+ ( GetPropertySet()->getPropertyValue( "TextRotation" ) >>= fOldValue );
+
+ if( ! bPropExisted || fOldValue != fValue )
+ {
+ GetPropertySet()->setPropertyValue( "TextRotation" , uno::Any( fValue ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY:
+ {
+ bool bHideLegendEntry = static_cast<const SfxBoolItem &>(rItemSet.Get(nWhichId)).GetValue();
+ if (bHideLegendEntry != m_bHideLegendEntry)
+ {
+ uno::Sequence<sal_Int32> deletedLegendEntriesSeq;
+ // "DeletedLegendEntries"
+ m_xSeries->getFastPropertyValue(PROP_DATASERIES_DELETED_LEGEND_ENTRIES) >>= deletedLegendEntriesSeq;
+ std::vector<sal_Int32> deletedLegendEntries;
+ for (const auto& deletedLegendEntry : std::as_const(deletedLegendEntriesSeq))
+ {
+ if (bHideLegendEntry || m_nPointIndex != deletedLegendEntry)
+ deletedLegendEntries.push_back(deletedLegendEntry);
+ }
+ if (bHideLegendEntry)
+ deletedLegendEntries.push_back(m_nPointIndex);
+ // "DeletedLegendEntries"
+ m_xSeries->setFastPropertyValue(PROP_DATASERIES_DELETED_LEGEND_ENTRIES, uno::Any(comphelper::containerToSequence(deletedLegendEntries)));
+ }
+ }
+ break;
+
+ case SCHATTR_DATADESCR_CUSTOM_LEADER_LINES:
+ {
+ try
+ {
+ bool bNew = static_cast<const SfxBoolItem&>(rItemSet.Get(nWhichId)).GetValue();
+ bool bOld = true;
+ if( (m_xSeries->getPropertyValue("ShowCustomLeaderLines") >>= bOld) && bOld != bNew )
+ {
+ m_xSeries->setPropertyValue("ShowCustomLeaderLines", uno::Any(bNew));
+ bChanged = true;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ }
+ break;
+ }
+
+ return bChanged;
+}
+
+void DataPointItemConverter::FillSpecialItem(
+ sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
+{
+ switch( nWhichId )
+ {
+ case SCHATTR_DATADESCR_SHOW_NUMBER:
+ case SCHATTR_DATADESCR_SHOW_PERCENTAGE:
+ case SCHATTR_DATADESCR_SHOW_CATEGORY:
+ case SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME:
+ case SCHATTR_DATADESCR_SHOW_SYMBOL:
+ {
+ chart2::DataPointLabel aLabel;
+ if (GetPropertySet()->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel)
+ {
+ bool bValue = (nWhichId==SCHATTR_DATADESCR_SHOW_NUMBER) ? aLabel.ShowNumber : (
+ (nWhichId==SCHATTR_DATADESCR_SHOW_PERCENTAGE) ? aLabel.ShowNumberInPercent : (
+ (nWhichId==SCHATTR_DATADESCR_SHOW_CATEGORY) ? aLabel.ShowCategoryName : (
+ (nWhichId==SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME) ? aLabel.ShowSeriesName : aLabel.ShowLegendSymbol )));
+
+ rOutItemSet.Put( SfxBoolItem( nWhichId, bValue ));
+
+ if( m_bOverwriteLabelsForAttributedDataPointsAlso )
+ {
+ if( DataSeriesHelper::hasAttributedDataPointDifferentValue(
+ dynamic_cast<DataSeries*>(GetPropertySet().get()), CHART_UNONAME_LABEL , uno::Any(aLabel) ) )
+ {
+ rOutItemSet.InvalidateItem(nWhichId);
+ }
+ }
+ }
+ }
+ break;
+
+ case SID_ATTR_NUMBERFORMAT_VALUE:
+ {
+ sal_Int32 nKey = 0;
+ if (!(GetPropertySet()->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nKey))
+ nKey = m_nNumberFormat;
+ rOutItemSet.Put( SfxUInt32Item( nWhichId, nKey ));
+ }
+ break;
+
+ case SCHATTR_PERCENT_NUMBERFORMAT_VALUE:
+ {
+ sal_Int32 nKey = 0;
+ if( !(GetPropertySet()->getPropertyValue( "PercentageNumberFormat" ) >>= nKey) )
+ nKey = m_nPercentNumberFormat;
+ rOutItemSet.Put( SfxUInt32Item( nWhichId, nKey ));
+ }
+ break;
+
+ case SID_ATTR_NUMBERFORMAT_SOURCE:
+ {
+ bool bUseSourceFormat = false;
+ try
+ {
+ GetPropertySet()->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bUseSourceFormat;
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ bool bNumberFormatIsSet = GetPropertySet()->getPropertyValue(CHART_UNONAME_NUMFMT).hasValue() && !bUseSourceFormat;
+ rOutItemSet.Put( SfxBoolItem( nWhichId, ! bNumberFormatIsSet ));
+ }
+ break;
+ case SCHATTR_PERCENT_NUMBERFORMAT_SOURCE:
+ {
+ bool bUseSourceFormat = false;
+ try
+ {
+ GetPropertySet()->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bUseSourceFormat;
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ bool bNumberFormatIsSet = GetPropertySet()->getPropertyValue( "PercentageNumberFormat" ).hasValue() && !bUseSourceFormat;
+ rOutItemSet.Put( SfxBoolItem( nWhichId, ! bNumberFormatIsSet ));
+ }
+ break;
+
+ case SCHATTR_DATADESCR_SEPARATOR:
+ {
+ try
+ {
+ OUString aValue;
+ GetPropertySet()->getPropertyValue( "LabelSeparator" ) >>= aValue;
+ rOutItemSet.Put( SfxStringItem( nWhichId, aValue ));
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+
+ case SCHATTR_DATADESCR_WRAP_TEXT:
+ {
+ try
+ {
+ bool bValue = false;
+ GetPropertySet()->getPropertyValue( "TextWordWrap" ) >>= bValue;
+ rOutItemSet.Put( SfxBoolItem( nWhichId, bValue ));
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+
+ case SCHATTR_DATADESCR_PLACEMENT:
+ {
+ try
+ {
+ sal_Int32 nPlacement=0;
+ RelativePosition aCustomLabelPosition;
+ if( !m_bOverwriteLabelsForAttributedDataPointsAlso && (GetPropertySet()->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition) )
+ rOutItemSet.Put(SfxInt32Item(nWhichId, css::chart::DataLabelPlacement::CUSTOM));
+ else if( GetPropertySet()->getPropertyValue( "LabelPlacement" ) >>= nPlacement )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, nPlacement ));
+ else if( m_aAvailableLabelPlacements.hasElements() )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, m_aAvailableLabelPlacements[0] ));
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+
+ case SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS:
+ {
+ rOutItemSet.Put( SfxIntegerListItem( nWhichId, m_aAvailableLabelPlacements ) );
+ }
+ break;
+
+ case SCHATTR_DATADESCR_NO_PERCENTVALUE:
+ {
+ rOutItemSet.Put( SfxBoolItem( nWhichId, m_bForbidPercentValue ));
+ }
+ break;
+
+ case SCHATTR_DATADESCR_CUSTOM_LEADER_LINES:
+ {
+ try
+ {
+ bool bValue = true;
+ if( m_xSeries->getPropertyValue( "ShowCustomLeaderLines" ) >>= bValue )
+ rOutItemSet.Put(SfxBoolItem(nWhichId, bValue));
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ }
+ break;
+
+ case SCHATTR_STYLE_SYMBOL:
+ {
+ chart2::Symbol aSymbol;
+ if( GetPropertySet()->getPropertyValue( "Symbol" ) >>= aSymbol )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, lcl_getSymbolStyleForSymbol( aSymbol ) ));
+ }
+ break;
+
+ case SCHATTR_SYMBOL_SIZE:
+ {
+ chart2::Symbol aSymbol;
+ if( GetPropertySet()->getPropertyValue( "Symbol" ) >>= aSymbol )
+ rOutItemSet.Put(
+ SvxSizeItem( nWhichId, Size( aSymbol.Size.Width, aSymbol.Size.Height ) ));
+ }
+ break;
+
+ case SCHATTR_SYMBOL_BRUSH:
+ {
+ chart2::Symbol aSymbol;
+ if(( GetPropertySet()->getPropertyValue( "Symbol" ) >>= aSymbol )
+ && aSymbol.Graphic.is() )
+ {
+ rOutItemSet.Put( SvxBrushItem( Graphic( aSymbol.Graphic ), GPOS_MM, SCHATTR_SYMBOL_BRUSH ));
+ }
+ }
+ break;
+
+ case SCHATTR_TEXT_DEGREES:
+ {
+ double fValue = 0;
+
+ if( GetPropertySet()->getPropertyValue( "TextRotation" ) >>= fValue )
+ {
+ rOutItemSet.Put( SdrAngleItem( SCHATTR_TEXT_DEGREES, Degree100(static_cast< sal_Int32 >(
+ ::rtl::math::round( fValue * 100.0 ) ) )));
+ }
+ }
+ break;
+
+ case SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY:
+ {
+ rOutItemSet.Put(SfxBoolItem(nWhichId, m_bHideLegendEntry));
+ break;
+ }
+ break;
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/DataTableItemConverter.cxx b/chart2/source/controller/itemsetwrapper/DataTableItemConverter.cxx
new file mode 100644
index 0000000000..62a5e2b039
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/DataTableItemConverter.cxx
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <DataTableItemConverter.hxx>
+#include <ItemPropertyMap.hxx>
+#include <CharacterPropertyItemConverter.hxx>
+#include <GraphicPropertyItemConverter.hxx>
+#include <chartview/ChartSfxItemIds.hxx>
+#include <chartview/ExplicitScaleValues.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include "SchWhichPairs.hxx"
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <CommonConverters.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <Diagram.hxx>
+#include <unonames.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <memory>
+
+#include <osl/diagnose.h>
+#include <o3tl/any.hxx>
+#include <svl/eitem.hxx>
+#include <svx/chrtitem.hxx>
+#include <svx/sdangitm.hxx>
+#include <svl/intitem.hxx>
+#include <rtl/math.hxx>
+
+using namespace css;
+
+namespace chart::wrapper
+{
+namespace
+{
+ItemPropertyMapType& lclDataTablePropertyMap()
+{
+ static ItemPropertyMapType aPropertyMap{
+ { SCHATTR_DATA_TABLE_HORIZONTAL_BORDER, { "HBorder", 0 } },
+ { SCHATTR_DATA_TABLE_VERTICAL_BORDER, { "VBorder", 0 } },
+ { SCHATTR_DATA_TABLE_OUTLINE, { "Outline", 0 } },
+ { SCHATTR_DATA_TABLE_KEYS, { "Keys", 0 } },
+ };
+ return aPropertyMap;
+};
+}
+
+DataTableItemConverter::DataTableItemConverter(
+ const uno::Reference<beans::XPropertySet>& rPropertySet, SfxItemPool& rItemPool,
+ SdrModel& rDrawModel, const rtl::Reference<::chart::ChartModel>& xChartDoc)
+ : ItemConverter(rPropertySet, rItemPool)
+{
+ m_aConverters.emplace_back(new GraphicPropertyItemConverter(
+ rPropertySet, rItemPool, rDrawModel, xChartDoc, GraphicObjectType::LineProperties));
+ m_aConverters.emplace_back(new CharacterPropertyItemConverter(rPropertySet, rItemPool));
+}
+
+DataTableItemConverter::~DataTableItemConverter() = default;
+
+void DataTableItemConverter::FillItemSet(SfxItemSet& rOutItemSet) const
+{
+ for (const auto& pConv : m_aConverters)
+ {
+ pConv->FillItemSet(rOutItemSet);
+ }
+
+ // own items
+ ItemConverter::FillItemSet(rOutItemSet);
+}
+
+bool DataTableItemConverter::ApplyItemSet(const SfxItemSet& rItemSet)
+{
+ bool bResult = false;
+
+ for (const auto& pConv : m_aConverters)
+ {
+ bResult = pConv->ApplyItemSet(rItemSet) || bResult;
+ }
+
+ // own items
+ return ItemConverter::ApplyItemSet(rItemSet) || bResult;
+}
+
+const WhichRangesContainer& DataTableItemConverter::GetWhichPairs() const
+{
+ return nDataTableWhichPairs;
+}
+
+bool DataTableItemConverter::GetItemProperty(tWhichIdType nWhichId,
+ tPropertyNameWithMemberId& rOutProperty) const
+{
+ ItemPropertyMapType& rMap(lclDataTablePropertyMap());
+ auto aIt = rMap.find(nWhichId);
+ if (aIt == rMap.cend())
+ return false;
+
+ rOutProperty = (*aIt).second;
+
+ return true;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/ErrorBarItemConverter.cxx b/chart2/source/controller/itemsetwrapper/ErrorBarItemConverter.cxx
new file mode 100644
index 0000000000..33e09062a9
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/ErrorBarItemConverter.cxx
@@ -0,0 +1,434 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ErrorBarItemConverter.hxx>
+#include "SchWhichPairs.hxx"
+#include <StatisticsHelper.hxx>
+
+#include <GraphicPropertyItemConverter.hxx>
+
+#include <svl/stritem.hxx>
+#include <svx/chrtitem.hxx>
+#include <rtl/math.hxx>
+
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+
+void lcl_getErrorValues( const uno::Reference< beans::XPropertySet > & xErrorBarProp,
+ double & rOutPosError, double & rOutNegError )
+{
+ if( ! xErrorBarProp.is())
+ return;
+
+ try
+ {
+ xErrorBarProp->getPropertyValue( "PositiveError" ) >>= rOutPosError;
+ xErrorBarProp->getPropertyValue( "NegativeError" ) >>= rOutNegError;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void lcl_getErrorIndicatorValues(
+ const uno::Reference< beans::XPropertySet > & xErrorBarProp,
+ bool & rOutShowPosError, bool & rOutShowNegError )
+{
+ if( ! xErrorBarProp.is())
+ return;
+
+ try
+ {
+ xErrorBarProp->getPropertyValue( "ShowPositiveError" ) >>= rOutShowPosError;
+ xErrorBarProp->getPropertyValue( "ShowNegativeError" ) >>= rOutShowNegError;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+ErrorBarItemConverter::ErrorBarItemConverter(
+ uno::Reference< frame::XModel > xModel,
+ const uno::Reference< beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory ) :
+ ItemConverter( rPropertySet, rItemPool ),
+ m_spGraphicConverter( std::make_shared<GraphicPropertyItemConverter>(
+ rPropertySet, rItemPool, rDrawModel,
+ xNamedPropertyContainerFactory,
+ GraphicObjectType::LineProperties )),
+ m_xModel(std::move( xModel ))
+{}
+
+ErrorBarItemConverter::~ErrorBarItemConverter()
+{}
+
+void ErrorBarItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
+{
+ m_spGraphicConverter->FillItemSet( rOutItemSet );
+
+ // own items
+ ItemConverter::FillItemSet( rOutItemSet );
+}
+
+bool ErrorBarItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
+{
+ bool bResult = m_spGraphicConverter->ApplyItemSet( rItemSet );
+
+ // own items
+ return ItemConverter::ApplyItemSet( rItemSet ) || bResult;
+}
+
+const WhichRangesContainer& ErrorBarItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nErrorBarWhichPairs;
+}
+
+bool ErrorBarItemConverter::GetItemProperty(
+ tWhichIdType /* nWhichId */,
+ tPropertyNameWithMemberId & /* rOutProperty */ ) const
+{
+ return false;
+}
+
+bool ErrorBarItemConverter::ApplySpecialItem(
+ sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
+{
+ bool bChanged = false;
+
+ switch( nWhichId )
+ {
+ // Attention !!! This case must be passed before SCHATTR_STAT_PERCENT,
+ // SCHATTR_STAT_BIGERROR, SCHATTR_STAT_CONSTPLUS,
+ // SCHATTR_STAT_CONSTMINUS and SCHATTR_STAT_INDICATE
+ case SCHATTR_STAT_KIND_ERROR:
+ {
+ uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
+
+ SvxChartKindError eErrorKind =
+ static_cast< const SvxChartKindErrorItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+
+ if( !xErrorBarProp.is() && eErrorKind == SvxChartKindError::NONE)
+ {
+ //nothing to do
+ }
+ else
+ {
+ sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
+
+ switch( eErrorKind )
+ {
+ case SvxChartKindError::NONE:
+ nStyle = css::chart::ErrorBarStyle::NONE; break;
+ case SvxChartKindError::Variant:
+ nStyle = css::chart::ErrorBarStyle::VARIANCE; break;
+ case SvxChartKindError::Sigma:
+ nStyle = css::chart::ErrorBarStyle::STANDARD_DEVIATION; break;
+ case SvxChartKindError::Percent:
+ nStyle = css::chart::ErrorBarStyle::RELATIVE; break;
+ case SvxChartKindError::BigError:
+ nStyle = css::chart::ErrorBarStyle::ERROR_MARGIN; break;
+ case SvxChartKindError::Const:
+ nStyle = css::chart::ErrorBarStyle::ABSOLUTE; break;
+ case SvxChartKindError::StdError:
+ nStyle = css::chart::ErrorBarStyle::STANDARD_ERROR; break;
+ case SvxChartKindError::Range:
+ nStyle = css::chart::ErrorBarStyle::FROM_DATA; break;
+ }
+
+ xErrorBarProp->setPropertyValue( "ErrorBarStyle" , uno::Any( nStyle ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_PERCENT:
+ case SCHATTR_STAT_BIGERROR:
+ {
+ OSL_FAIL( "Deprecated item" );
+ uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
+
+ double fValue =
+ static_cast< const SvxDoubleItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
+
+ if( ! ( ::rtl::math::approxEqual( fPos, fValue ) &&
+ ::rtl::math::approxEqual( fNeg, fValue )))
+ {
+ xErrorBarProp->setPropertyValue( "PositiveError" , uno::Any( fValue ));
+ xErrorBarProp->setPropertyValue( "NegativeError" , uno::Any( fValue ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_CONSTPLUS:
+ {
+ double fValue =
+ static_cast< const SvxDoubleItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
+
+ if( ! ::rtl::math::approxEqual( fPos, fValue ))
+ {
+ GetPropertySet()->setPropertyValue( "PositiveError" , uno::Any( fValue ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_CONSTMINUS:
+ {
+ uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
+
+ double fValue =
+ static_cast< const SvxDoubleItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
+
+ if( ! ::rtl::math::approxEqual( fNeg, fValue ))
+ {
+ xErrorBarProp->setPropertyValue( "NegativeError" , uno::Any( fValue ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_INDICATE:
+ {
+ uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
+
+ SvxChartIndicate eIndicate =
+ static_cast< const SvxChartIndicateItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+
+ bool bNewIndPos = (eIndicate == SvxChartIndicate::Both || eIndicate == SvxChartIndicate::Up );
+ bool bNewIndNeg = (eIndicate == SvxChartIndicate::Both || eIndicate == SvxChartIndicate::Down );
+
+ bool bShowPos(false), bShowNeg(false);
+ lcl_getErrorIndicatorValues( xErrorBarProp, bShowPos, bShowNeg );
+
+ if( bShowPos != bNewIndPos ||
+ bShowNeg != bNewIndNeg )
+ {
+ xErrorBarProp->setPropertyValue( "ShowPositiveError" , uno::Any( bNewIndPos ));
+ xErrorBarProp->setPropertyValue( "ShowNegativeError" , uno::Any( bNewIndNeg ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_RANGE_POS:
+ case SCHATTR_STAT_RANGE_NEG:
+ {
+ // @todo: also be able to deal with x-error bars
+ const bool bYError =
+ rItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+
+ uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY );
+ uno::Reference< chart2::XChartDocument > xChartDoc( m_xModel, uno::UNO_QUERY );
+ uno::Reference< chart2::data::XDataProvider > xDataProvider;
+
+ if( xChartDoc.is())
+ xDataProvider.set( xChartDoc->getDataProvider());
+ if( xErrorBarSource.is() && xDataProvider.is())
+ {
+ OUString aNewRange( static_cast< const SfxStringItem & >( rItemSet.Get( nWhichId )).GetValue());
+ bool bApplyNewRange = false;
+
+ bool bIsPositiveValue( nWhichId == SCHATTR_STAT_RANGE_POS );
+ if( xChartDoc->hasInternalDataProvider())
+ {
+ if( !aNewRange.isEmpty())
+ {
+ uno::Reference< chart2::data::XDataSequence > xSeq(
+ StatisticsHelper::getErrorDataSequenceFromDataSource(
+ xErrorBarSource, bIsPositiveValue, bYError ));
+ if( ! xSeq.is())
+ {
+ // no data range for error bars yet => create
+ uno::Reference< chart2::XInternalDataProvider > xIntDataProvider( xDataProvider, uno::UNO_QUERY );
+ OSL_ASSERT( xIntDataProvider.is());
+ if( xIntDataProvider.is())
+ {
+ xIntDataProvider->appendSequence();
+ aNewRange = "last";
+ bApplyNewRange = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ uno::Reference< chart2::data::XDataSequence > xSeq(
+ StatisticsHelper::getErrorDataSequenceFromDataSource(
+ xErrorBarSource, bIsPositiveValue, bYError ));
+ bApplyNewRange =
+ ! ( xSeq.is() && (aNewRange == xSeq->getSourceRangeRepresentation()));
+ }
+
+ if( bApplyNewRange )
+ StatisticsHelper::setErrorDataSequence(
+ xErrorBarSource, xDataProvider, aNewRange, bIsPositiveValue, bYError );
+ }
+ }
+ break;
+ }
+
+ return bChanged;
+}
+
+void ErrorBarItemConverter::FillSpecialItem(
+ sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
+{
+ switch( nWhichId )
+ {
+ case SCHATTR_STAT_KIND_ERROR:
+ {
+ SvxChartKindError eErrorKind = SvxChartKindError::NONE;
+ uno::Reference< beans::XPropertySet > xErrorBarProp( GetPropertySet());
+
+ sal_Int32 nStyle = 0;
+ if( xErrorBarProp->getPropertyValue( "ErrorBarStyle" ) >>= nStyle )
+ {
+ switch( nStyle )
+ {
+ case css::chart::ErrorBarStyle::NONE:
+ break;
+ case css::chart::ErrorBarStyle::VARIANCE:
+ eErrorKind = SvxChartKindError::Variant; break;
+ case css::chart::ErrorBarStyle::STANDARD_DEVIATION:
+ eErrorKind = SvxChartKindError::Sigma; break;
+ case css::chart::ErrorBarStyle::ABSOLUTE:
+ eErrorKind = SvxChartKindError::Const; break;
+ case css::chart::ErrorBarStyle::RELATIVE:
+ eErrorKind = SvxChartKindError::Percent; break;
+ case css::chart::ErrorBarStyle::ERROR_MARGIN:
+ eErrorKind = SvxChartKindError::BigError; break;
+ case css::chart::ErrorBarStyle::STANDARD_ERROR:
+ eErrorKind = SvxChartKindError::StdError; break;
+ case css::chart::ErrorBarStyle::FROM_DATA:
+ eErrorKind = SvxChartKindError::Range; break;
+ }
+ }
+ rOutItemSet.Put( SvxChartKindErrorItem( eErrorKind, SCHATTR_STAT_KIND_ERROR ));
+ }
+ break;
+
+ case SCHATTR_STAT_PERCENT:
+ {
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
+ rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, SCHATTR_STAT_PERCENT ));
+ }
+ break;
+
+ case SCHATTR_STAT_BIGERROR:
+ {
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
+ rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, SCHATTR_STAT_BIGERROR ));
+ }
+ break;
+
+ case SCHATTR_STAT_CONSTPLUS:
+ {
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
+ rOutItemSet.Put( SvxDoubleItem( fPos, SCHATTR_STAT_CONSTPLUS ));
+ }
+ break;
+
+ case SCHATTR_STAT_CONSTMINUS:
+ {
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( GetPropertySet(), fPos, fNeg );
+ rOutItemSet.Put( SvxDoubleItem( fNeg, SCHATTR_STAT_CONSTMINUS ));
+ }
+ break;
+
+ case SCHATTR_STAT_INDICATE:
+ {
+ SvxChartIndicate eIndicate = SvxChartIndicate::Both;
+ bool bShowPos(false), bShowNeg(false);
+ lcl_getErrorIndicatorValues( GetPropertySet(), bShowPos, bShowNeg );
+
+ if( bShowPos )
+ {
+ if( bShowNeg )
+ eIndicate = SvxChartIndicate::Both;
+ else
+ eIndicate = SvxChartIndicate::Up;
+ }
+ else
+ {
+ if( bShowNeg )
+ eIndicate = SvxChartIndicate::Down;
+ else
+ eIndicate = SvxChartIndicate::NONE;
+ }
+ rOutItemSet.Put( SvxChartIndicateItem( eIndicate, SCHATTR_STAT_INDICATE ));
+ }
+ break;
+
+ case SCHATTR_STAT_RANGE_POS:
+ case SCHATTR_STAT_RANGE_NEG:
+ {
+ const bool bYError =
+ rOutItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+
+ uno::Reference< chart2::data::XDataSource > xErrorBarSource( GetPropertySet(), uno::UNO_QUERY );
+ if( xErrorBarSource.is())
+ {
+ uno::Reference< chart2::data::XDataSequence > xSeq(
+ StatisticsHelper::getErrorDataSequenceFromDataSource(
+ xErrorBarSource, (nWhichId == SCHATTR_STAT_RANGE_POS), bYError ));
+ if( xSeq.is())
+ rOutItemSet.Put( SfxStringItem( nWhichId, xSeq->getSourceRangeRepresentation()));
+ }
+ }
+ break;
+ }
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/GraphicPropertyItemConverter.cxx b/chart2/source/controller/itemsetwrapper/GraphicPropertyItemConverter.cxx
new file mode 100644
index 0000000000..ac0b961ba2
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/GraphicPropertyItemConverter.cxx
@@ -0,0 +1,752 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <GraphicPropertyItemConverter.hxx>
+#include "SchWhichPairs.hxx"
+#include <ItemPropertyMap.hxx>
+#include <PropertyHelper.hxx>
+#include <CommonConverters.hxx>
+#include <editeng/memberids.h>
+#include <svx/unomid.hxx>
+#include <svx/xflbmtit.hxx>
+#include <svx/xflbstit.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/xflftrit.hxx>
+#include <svx/xlndsit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xfltrit.hxx>
+#include <svx/xlntrit.hxx>
+#include <svx/xgrscit.hxx>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart::wrapper {
+
+namespace {
+
+ItemPropertyMapType & lcl_GetDataPointFilledPropertyMap()
+{
+ static ItemPropertyMapType aDataPointPropertyFilledMap{
+ {XATTR_FILLSTYLE, {"FillStyle", 0}},
+ {XATTR_FILLCOLOR, {"Color", 0}},
+ {XATTR_LINECOLOR, {"BorderColor", 0}},
+ {XATTR_LINESTYLE, {"BorderStyle", 0}},
+ {XATTR_LINEWIDTH, {"BorderWidth", 0}},
+ {XATTR_FILLBACKGROUND, {"FillBackground", 0}},
+ {XATTR_FILLBMP_POS, {"FillBitmapRectanglePoint", 0}},
+ {XATTR_FILLBMP_SIZEX, {"FillBitmapSizeX", 0}},
+ {XATTR_FILLBMP_SIZEY, {"FillBitmapSizeY", 0}},
+ {XATTR_FILLBMP_SIZELOG, {"FillBitmapLogicalSize", 0}},
+ {XATTR_FILLBMP_TILEOFFSETX, {"FillBitmapOffsetX", 0}},
+ {XATTR_FILLBMP_TILEOFFSETY, {"FillBitmapOffsetY", 0}},
+ {XATTR_FILLBMP_POSOFFSETX, {"FillBitmapPositionOffsetX", 0}},
+ {XATTR_FILLBMP_POSOFFSETY, {"FillBitmapPositionOffsetY", 0}}};
+ return aDataPointPropertyFilledMap;
+}
+ItemPropertyMapType & lcl_GetDataPointLinePropertyMap()
+{
+ static ItemPropertyMapType aDataPointPropertyLineMap{
+ {XATTR_LINECOLOR, {"Color", 0}},
+ {XATTR_LINESTYLE, {"LineStyle", 0}},
+ {XATTR_LINEWIDTH, {"LineWidth", 0}},
+ {XATTR_LINECAP, {"LineCap", 0}}};
+ return aDataPointPropertyLineMap;
+}
+ItemPropertyMapType & lcl_GetLinePropertyMap()
+{
+ static ItemPropertyMapType aLinePropertyMap{
+ {XATTR_LINESTYLE, {"LineStyle", 0}},
+ {XATTR_LINEWIDTH, {"LineWidth", 0}},
+ {XATTR_LINECOLOR, {"LineColor", 0}},
+ {XATTR_LINEJOINT, {"LineJoint", 0}},
+ {XATTR_LINECAP, {"LineCap", 0}}};
+ return aLinePropertyMap;
+}
+ItemPropertyMapType & lcl_GetFillPropertyMap()
+{
+ static ItemPropertyMapType aFillPropertyMap{
+ {XATTR_FILLSTYLE, {"FillStyle", 0}},
+ {XATTR_FILLCOLOR, {"FillColor", 0}},
+ {XATTR_FILLBACKGROUND, {"FillBackground", 0}},
+ {XATTR_FILLBMP_POS, {"FillBitmapRectanglePoint", 0}},
+ {XATTR_FILLBMP_SIZEX, {"FillBitmapSizeX", 0}},
+ {XATTR_FILLBMP_SIZEY, {"FillBitmapSizeY", 0}},
+ {XATTR_FILLBMP_SIZELOG, {"FillBitmapLogicalSize", 0}},
+ {XATTR_FILLBMP_TILEOFFSETX, {"FillBitmapOffsetX", 0}},
+ {XATTR_FILLBMP_TILEOFFSETY, {"FillBitmapOffsetY", 0}},
+ {XATTR_FILLBMP_POSOFFSETX, {"FillBitmapPositionOffsetX", 0}},
+ {XATTR_FILLBMP_POSOFFSETY, {"FillBitmapPositionOffsetY", 0}}};
+ return aFillPropertyMap;
+}
+
+bool lcl_supportsFillProperties( ::chart::wrapper::GraphicObjectType eType )
+{
+ return ( eType == ::chart::wrapper::GraphicObjectType::FilledDataPoint ||
+ eType == ::chart::wrapper::GraphicObjectType::LineAndFillProperties );
+}
+
+bool lcl_SetContentForNamedProperty(
+ const uno::Reference< lang::XMultiServiceFactory > & xFactory,
+ const OUString & rTableName,
+ NameOrIndex & rItem, sal_uInt8 nMemberId )
+{
+ bool bResult = false;
+ if( xFactory.is())
+ {
+ OUString aPropertyValue( rItem.GetName());
+ uno::Reference< container::XNameAccess > xNameAcc(
+ xFactory->createInstance( rTableName ),
+ uno::UNO_QUERY );
+ if( xNameAcc.is() &&
+ xNameAcc->hasByName( aPropertyValue ))
+ {
+ rItem.PutValue( xNameAcc->getByName( aPropertyValue ), nMemberId );
+ bResult = true;
+ }
+ }
+ return bResult;
+}
+
+} // anonymous namespace
+
+GraphicPropertyItemConverter::GraphicPropertyItemConverter(
+ const uno::Reference<
+ beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ uno::Reference< lang::XMultiServiceFactory > xNamedPropertyContainerFactory,
+ GraphicObjectType eObjectType /* = FILL_PROPERTIES */ ) :
+ ItemConverter( rPropertySet, rItemPool ),
+ m_GraphicObjectType( eObjectType ),
+ m_rDrawModel( rDrawModel ),
+ m_xNamedPropertyTableFactory(std::move( xNamedPropertyContainerFactory ))
+{}
+
+GraphicPropertyItemConverter::~GraphicPropertyItemConverter()
+{}
+
+const WhichRangesContainer& GraphicPropertyItemConverter::GetWhichPairs() const
+{
+ switch( m_GraphicObjectType )
+ {
+ case GraphicObjectType::LineDataPoint:
+ case GraphicObjectType::FilledDataPoint:
+ return nRowWhichPairs;
+ case GraphicObjectType::LineProperties:
+ return nLinePropertyWhichPairs;
+ case GraphicObjectType::LineAndFillProperties:
+ return nLineAndFillPropertyWhichPairs;
+ }
+
+ static const WhichRangesContainer empty;
+ return empty;
+}
+
+bool GraphicPropertyItemConverter::GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const
+{
+ ItemPropertyMapType::const_iterator aEndIt;
+ ItemPropertyMapType::const_iterator aIt;
+
+ switch( m_GraphicObjectType )
+ {
+ case GraphicObjectType::LineDataPoint:
+ aEndIt = lcl_GetDataPointLinePropertyMap().end();
+ aIt = lcl_GetDataPointLinePropertyMap().find( nWhichId );
+ break;
+ case GraphicObjectType::FilledDataPoint:
+ aEndIt = lcl_GetDataPointFilledPropertyMap().end();
+ aIt = lcl_GetDataPointFilledPropertyMap().find( nWhichId );
+ break;
+ case GraphicObjectType::LineProperties:
+ aEndIt = lcl_GetLinePropertyMap().end();
+ aIt = lcl_GetLinePropertyMap().find( nWhichId );
+ break;
+
+ case GraphicObjectType::LineAndFillProperties:
+ // line
+ aEndIt = lcl_GetLinePropertyMap().end();
+ aIt = lcl_GetLinePropertyMap().find( nWhichId );
+
+ // not found => try fill
+ if( aIt == aEndIt )
+ {
+ aEndIt = lcl_GetFillPropertyMap().end();
+ aIt = lcl_GetFillPropertyMap().find( nWhichId );
+ }
+ break;
+ }
+
+ if( aIt == aEndIt )
+ return false;
+
+ rOutProperty =(*aIt).second;
+ return true;
+}
+
+void GraphicPropertyItemConverter::FillSpecialItem(
+ sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
+{
+ switch( nWhichId )
+ {
+ // bitmap property
+ case XATTR_FILLBMP_TILE:
+ case XATTR_FILLBMP_STRETCH:
+ {
+ drawing::BitmapMode aMode = drawing::BitmapMode_REPEAT;
+ if( GetPropertySet()->getPropertyValue( "FillBitmapMode" ) >>= aMode )
+ {
+ rOutItemSet.Put( XFillBmpTileItem( aMode == drawing::BitmapMode_REPEAT ));
+ rOutItemSet.Put( XFillBmpStretchItem( aMode == drawing::BitmapMode_STRETCH ));
+ }
+ }
+ break;
+
+ case XATTR_FILLFLOATTRANSPARENCE:
+ try
+ {
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "TransparencyGradientName" )
+ : OUString( "FillTransparenceGradientName" );
+
+ uno::Any aValue( GetPropertySet()->getPropertyValue( aPropName ));
+ if( aValue.hasValue())
+ {
+ XFillFloatTransparenceItem aItem;
+ aItem.PutValue( aValue, MID_NAME );
+
+ lcl_SetContentForNamedProperty(
+ m_xNamedPropertyTableFactory, "com.sun.star.drawing.TransparencyGradientTable" ,
+ aItem, MID_FILLGRADIENT );
+
+ // this is important to enable the item
+ OUString aName;
+ if( (aValue >>= aName) &&
+ !aName.isEmpty())
+ {
+ aItem.SetEnabled( true );
+ rOutItemSet.Put( aItem );
+ }
+ }
+ }
+ }
+ catch( const beans::UnknownPropertyException & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ break;
+
+ case XATTR_GRADIENTSTEPCOUNT:
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "GradientStepCount" )
+ : OUString( "FillGradientStepCount" );
+
+ uno::Any aValue( GetPropertySet()->getPropertyValue( aPropName ) );
+ if( hasLongOrShortValue(aValue) )
+ {
+ sal_Int16 nStepCount = getShortForLongAlso(aValue);
+ rOutItemSet.Put( XGradientStepCountItem( nStepCount ));
+ }
+ }
+ break;
+
+ case XATTR_LINEDASH:
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "BorderDashName" )
+ : OUString( "LineDashName" );
+
+ XLineDashItem aItem;
+ aItem.PutValue( GetPropertySet()->getPropertyValue( aPropName ), MID_NAME );
+
+ lcl_SetContentForNamedProperty(
+ m_xNamedPropertyTableFactory, "com.sun.star.drawing.DashTable" ,
+ aItem, MID_LINEDASH );
+
+ // translate model name to UI-name for predefined entries, so
+ // that the correct entry is chosen in the list of UI-names
+ std::unique_ptr<XLineDashItem> pItemToPut = aItem.checkForUniqueItem( & m_rDrawModel );
+
+ if(pItemToPut)
+ rOutItemSet.Put( std::move(pItemToPut) );
+ else
+ rOutItemSet.Put(aItem);
+ }
+ break;
+
+ case XATTR_FILLGRADIENT:
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "GradientName" )
+ : OUString( "FillGradientName" );
+
+ XFillGradientItem aItem;
+ aItem.PutValue( GetPropertySet()->getPropertyValue( aPropName ), MID_NAME );
+
+ lcl_SetContentForNamedProperty(
+ m_xNamedPropertyTableFactory, "com.sun.star.drawing.GradientTable" ,
+ aItem, MID_FILLGRADIENT );
+
+ // translate model name to UI-name for predefined entries, so
+ // that the correct entry is chosen in the list of UI-names
+ std::unique_ptr<XFillGradientItem> pItemToPut = aItem.checkForUniqueItem( & m_rDrawModel );
+
+ if(pItemToPut)
+ rOutItemSet.Put(std::move(pItemToPut) );
+ else
+ rOutItemSet.Put(aItem);
+ }
+ break;
+
+ case XATTR_FILLHATCH:
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "HatchName" )
+ : OUString( "FillHatchName" );
+
+ XFillHatchItem aItem;
+ aItem.PutValue( GetPropertySet()->getPropertyValue( aPropName ), MID_NAME );
+
+ lcl_SetContentForNamedProperty(
+ m_xNamedPropertyTableFactory, "com.sun.star.drawing.HatchTable" ,
+ aItem, MID_FILLHATCH );
+
+ // translate model name to UI-name for predefined entries, so
+ // that the correct entry is chosen in the list of UI-names
+ std::unique_ptr<XFillHatchItem> pItemToPut = aItem.checkForUniqueItem( & m_rDrawModel );
+
+ if(pItemToPut)
+ rOutItemSet.Put( std::move(pItemToPut) );
+ else
+ rOutItemSet.Put(aItem);
+ }
+ break;
+
+ case XATTR_FILLBITMAP:
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ XFillBitmapItem aItem;
+ aItem.PutValue( GetPropertySet()->getPropertyValue( "FillBitmapName" ), MID_NAME );
+
+ lcl_SetContentForNamedProperty(
+ m_xNamedPropertyTableFactory, "com.sun.star.drawing.BitmapTable" ,
+ aItem, MID_BITMAP );
+
+ // translate model name to UI-name for predefined entries, so
+ // that the correct entry is chosen in the list of UI-names
+ std::unique_ptr<XFillBitmapItem> pItemToPut = aItem.checkForUniqueItem( & m_rDrawModel );
+
+ if(pItemToPut)
+ rOutItemSet.Put( std::move(pItemToPut) );
+ else
+ rOutItemSet.Put(aItem);
+ }
+ break;
+
+ // hack, because QueryValue of XLineTransparenceItem returns sal_Int32
+ // instead of sal_Int16
+ case XATTR_LINETRANSPARENCE:
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "BorderTransparency" )
+ : (m_GraphicObjectType == GraphicObjectType::LineDataPoint)
+ ? OUString( "Transparency" )
+ : OUString( "LineTransparence" );
+
+ XLineTransparenceItem aItem;
+ aItem.PutValue( GetPropertySet()->getPropertyValue( aPropName ), 0 );
+
+ rOutItemSet.Put( aItem );
+ }
+ break;
+
+ // hack, because QueryValue of XFillTransparenceItem returns sal_Int32
+ // instead of sal_Int16
+ case XATTR_FILLTRANSPARENCE:
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "Transparency" )
+ : OUString( "FillTransparence" );
+
+ XFillTransparenceItem aItem;
+ aItem.PutValue( GetPropertySet()->getPropertyValue( aPropName ), 0 );
+
+ rOutItemSet.Put( aItem );
+ }
+ break;
+ }
+}
+
+bool GraphicPropertyItemConverter::ApplySpecialItem(
+ sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
+{
+ bool bChanged = false;
+ uno::Any aValue;
+
+ switch( nWhichId )
+ {
+ // bitmap property
+ case XATTR_FILLBMP_STRETCH:
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ static constexpr OUString aModePropName(u"FillBitmapMode"_ustr);
+ bool bStretched = rItemSet.Get( XATTR_FILLBMP_STRETCH ).GetValue();
+ drawing::BitmapMode aMode =
+ (bStretched ? drawing::BitmapMode_STRETCH : drawing::BitmapMode_NO_REPEAT);
+ drawing::BitmapMode aOtherMode = drawing::BitmapMode_NO_REPEAT;
+
+ aValue <<= aMode;
+ GetPropertySet()->getPropertyValue( aModePropName ) >>= aOtherMode;
+
+ // don't overwrite if it has been set to BitmapMode_REPEAT (= tiled) already
+ // XATTR_FILLBMP_STRETCH and XATTR_FILLBMP_TILE often come in pairs, tdf#104658
+ if( aMode != aOtherMode && aOtherMode != drawing::BitmapMode_REPEAT )
+ {
+ GetPropertySet()->setPropertyValue( aModePropName, aValue );
+ bChanged = true;
+ }
+ }
+ break;
+
+ case XATTR_FILLBMP_TILE:
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ static constexpr OUString aModePropName(u"FillBitmapMode"_ustr);
+ bool bTiled = rItemSet.Get( XATTR_FILLBMP_TILE ).GetValue();
+ drawing::BitmapMode aMode =
+ (bTiled ? drawing::BitmapMode_REPEAT : drawing::BitmapMode_NO_REPEAT);
+
+ aValue <<= aMode;
+ if( aValue != GetPropertySet()->getPropertyValue( aModePropName ))
+ {
+ GetPropertySet()->setPropertyValue( aModePropName, aValue );
+ bChanged = true;
+ }
+ }
+ break;
+
+ case XATTR_FILLFLOATTRANSPARENCE:
+ try
+ {
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "TransparencyGradientName" )
+ : OUString( "FillTransparenceGradientName" );
+
+ const XFillFloatTransparenceItem & rItem =
+ static_cast< const XFillFloatTransparenceItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.IsEnabled() &&
+ rItem.QueryValue( aValue, MID_NAME ))
+ {
+ uno::Any aGradient;
+ rItem.QueryValue( aGradient, MID_FILLGRADIENT );
+
+ // add TransparencyGradient to list if it does not already exist
+ OUString aPreferredName;
+ aValue >>= aPreferredName;
+ aValue <<= PropertyHelper::addTransparencyGradientUniqueNameToTable(
+ aGradient, m_xNamedPropertyTableFactory, aPreferredName );
+
+ if( aValue != GetPropertySet()->getPropertyValue( aPropName ))
+ {
+ GetPropertySet()->setPropertyValue( aPropName, aValue );
+ bChanged = true;
+ }
+ }
+ else
+ {
+ OUString aName;
+ if( ( GetPropertySet()->getPropertyValue( aPropName ) >>= aName )
+ && !aName.isEmpty() )
+ {
+ uno::Reference< beans::XPropertyState > xState( GetPropertySet(), uno::UNO_QUERY );
+ if( xState.is())
+ xState->setPropertyToDefault( aPropName );
+ bChanged = true;
+ }
+ }
+ }
+ }
+ catch( const beans::UnknownPropertyException & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ break;
+
+ case XATTR_GRADIENTSTEPCOUNT:
+ {
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "GradientStepCount" )
+ : OUString( "FillGradientStepCount" );
+
+ sal_Int16 nStepCount = static_cast< const XGradientStepCountItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+
+ aValue <<= nStepCount;
+ if( aValue != GetPropertySet()->getPropertyValue( aPropName ))
+ {
+ GetPropertySet()->setPropertyValue( aPropName, aValue );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case XATTR_LINEDASH:
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "BorderDashName" )
+ : OUString( "LineDashName" );
+
+ const XLineDashItem & rItem =
+ static_cast< const XLineDashItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.QueryValue( aValue, MID_NAME ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( aPropName ))
+ {
+ // add LineDash to list
+ uno::Any aLineDash;
+ rItem.QueryValue( aLineDash, MID_LINEDASH );
+ OUString aPreferredName;
+ aValue >>= aPreferredName;
+ aValue <<= PropertyHelper::addLineDashUniqueNameToTable(
+ aLineDash, m_xNamedPropertyTableFactory, aPreferredName );
+
+ GetPropertySet()->setPropertyValue( aPropName, aValue );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case XATTR_FILLGRADIENT:
+ {
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "GradientName" )
+ : OUString( "FillGradientName" );
+
+ const XFillGradientItem & rItem =
+ static_cast< const XFillGradientItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.QueryValue( aValue, MID_NAME ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( aPropName ))
+ {
+ // add Gradient to list
+ uno::Any aGradient;
+ rItem.QueryValue( aGradient, MID_FILLGRADIENT );
+ OUString aPreferredName;
+ aValue >>= aPreferredName;
+ aValue <<= PropertyHelper::addGradientUniqueNameToTable(
+ aGradient, m_xNamedPropertyTableFactory, aPreferredName );
+
+ GetPropertySet()->setPropertyValue( aPropName, aValue );
+ bChanged = true;
+ }
+ }
+ }
+ }
+ break;
+
+ case XATTR_FILLHATCH:
+ {
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "HatchName" )
+ : OUString( "FillHatchName" );
+
+ const XFillHatchItem & rItem =
+ static_cast< const XFillHatchItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.QueryValue( aValue, MID_NAME ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( aPropName ))
+ {
+ // add Hatch to list
+ uno::Any aHatch;
+ rItem.QueryValue( aHatch, MID_FILLHATCH );
+ OUString aPreferredName;
+ aValue >>= aPreferredName;
+ aValue <<= PropertyHelper::addHatchUniqueNameToTable(
+ aHatch, m_xNamedPropertyTableFactory, aPreferredName );
+
+ GetPropertySet()->setPropertyValue( aPropName, aValue );
+ bChanged = true;
+ }
+ }
+ }
+ }
+ break;
+
+ case XATTR_FILLBITMAP:
+ {
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ const XFillBitmapItem & rItem =
+ static_cast< const XFillBitmapItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.QueryValue( aValue, MID_NAME ))
+ {
+ if( aValue != GetPropertySet()->getPropertyValue( "FillBitmapName" ))
+ {
+ // add Bitmap to list
+ uno::Any aBitmap;
+ rItem.QueryValue(aBitmap, MID_BITMAP);
+ OUString aPreferredName;
+ aValue >>= aPreferredName;
+ aValue <<= PropertyHelper::addBitmapUniqueNameToTable(
+ aBitmap, m_xNamedPropertyTableFactory, aPreferredName );
+
+ GetPropertySet()->setPropertyValue( "FillBitmapName" , aValue );
+ bChanged = true;
+ }
+ }
+ }
+ }
+ break;
+
+ // hack, because QueryValue of XLineTransparenceItem returns sal_Int32
+ // instead of sal_Int16
+ case XATTR_LINETRANSPARENCE:
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "BorderTransparency" )
+ : (m_GraphicObjectType == GraphicObjectType::LineDataPoint)
+ ? OUString( "Transparency" )
+ : OUString( "LineTransparence" );
+
+ const XLineTransparenceItem & rItem =
+ static_cast< const XLineTransparenceItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.QueryValue( aValue ))
+ {
+ OSL_ENSURE( ! aValue.isExtractableTo(
+ cppu::UnoType<sal_Int16>::get()),
+ "TransparenceItem QueryValue bug is fixed. Remove hack." );
+ sal_Int32 nValue = 0;
+ if( aValue >>= nValue )
+ {
+ OSL_ENSURE( nValue < SAL_MAX_INT16, "Transparency value too large" );
+ sal_Int16 nValueToSet( static_cast< sal_Int16 >( nValue ));
+ aValue <<= nValueToSet;
+
+ GetPropertySet()->setPropertyValue( aPropName, aValue );
+ bChanged = true;
+ }
+ else
+ {
+ OSL_FAIL( "Wrong type in Transparency Any" );
+ }
+ }
+ }
+ break;
+
+ // hack, because QueryValue of XFillTransparenceItem returns sal_Int32
+ // instead of sal_Int16
+ case XATTR_FILLTRANSPARENCE:
+ if( lcl_supportsFillProperties( m_GraphicObjectType ))
+ {
+ OUString aPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "Transparency" )
+ : OUString( "FillTransparence" );
+
+ const XFillTransparenceItem & rItem =
+ static_cast< const XFillTransparenceItem & >(
+ rItemSet.Get( nWhichId ));
+
+ if( rItem.QueryValue( aValue ))
+ {
+ OSL_ENSURE( ! aValue.isExtractableTo(
+ cppu::UnoType<sal_Int16>::get()),
+ "TransparenceItem QueryValue bug is fixed. Remove hack." );
+ sal_Int32 nValue = 0;
+ if( aValue >>= nValue )
+ {
+ OSL_ENSURE( nValue < SAL_MAX_INT16, "Transparency value too large" );
+ sal_Int16 nValueToSet( static_cast< sal_Int16 >( nValue ));
+ aValue <<= nValueToSet;
+
+ GetPropertySet()->setPropertyValue( aPropName, aValue );
+ // if linear or no transparence is set, delete the gradient
+ OUString aTransGradPropName =
+ (m_GraphicObjectType == GraphicObjectType::FilledDataPoint)
+ ? OUString( "TransparencyGradientName" )
+ : OUString( "FillTransparenceGradientName" );
+ GetPropertySet()->setPropertyValue(
+ aTransGradPropName, uno::Any( OUString() ));
+
+ bChanged = true;
+ }
+ else
+ {
+ OSL_FAIL( "Wrong type in Transparency Any" );
+ }
+ }
+ }
+ break;
+ }
+
+ return bChanged;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/ItemConverter.cxx b/chart2/source/controller/itemsetwrapper/ItemConverter.cxx
new file mode 100644
index 0000000000..d4578313e8
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/ItemConverter.cxx
@@ -0,0 +1,223 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ItemConverter.hxx>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <osl/diagnose.h>
+#include <svl/itempool.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/whiter.hxx>
+#include <svx/svxids.hrc>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+namespace chart::wrapper {
+
+ItemConverter::ItemConverter(
+ uno::Reference< beans::XPropertySet > xPropertySet,
+ SfxItemPool& rItemPool ) :
+ m_xPropertySet(std::move( xPropertySet )),
+ m_rItemPool( rItemPool )
+{
+ resetPropertySet( m_xPropertySet );
+}
+
+ItemConverter::~ItemConverter()
+{
+ stopAllComponentListening();
+}
+
+void ItemConverter::resetPropertySet(
+ const uno::Reference< beans::XPropertySet > & xPropSet )
+{
+ if( !xPropSet.is())
+ return;
+
+ stopAllComponentListening();
+ m_xPropertySet = xPropSet;
+ m_xPropertySetInfo = m_xPropertySet->getPropertySetInfo();
+
+ uno::Reference< lang::XComponent > xComp( m_xPropertySet, uno::UNO_QUERY );
+ if( xComp.is())
+ {
+ // method of base class ::utl::OEventListenerAdapter
+ startComponentListening( xComp );
+ }
+}
+
+SfxItemSet ItemConverter::CreateEmptyItemSet() const
+{
+ return SfxItemSet( GetItemPool(), GetWhichPairs() );
+}
+
+void ItemConverter::_disposing( const lang::EventObject& )
+{
+}
+
+void ItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
+{
+ const WhichRangesContainer& pRanges = rOutItemSet.GetRanges();
+ tPropertyNameWithMemberId aProperty;
+ SfxItemPool & rPool = GetItemPool();
+
+ assert(!pRanges.empty());
+ OSL_ASSERT( m_xPropertySetInfo.is());
+ OSL_ASSERT( m_xPropertySet.is());
+
+ for(const auto& rPair : pRanges)
+ {
+ sal_uInt16 nBeg = rPair.first;
+ sal_uInt16 nEnd = rPair.second;
+
+ OSL_ASSERT( nBeg <= nEnd );
+ for( sal_uInt16 nWhich = nBeg; nWhich <= nEnd; ++nWhich )
+ {
+ if( GetItemProperty( nWhich, aProperty ))
+ {
+ // put the Property into the itemset
+ std::unique_ptr<SfxPoolItem> pItem(rPool.GetDefaultItem( nWhich ).Clone());
+
+ if( pItem )
+ {
+ try
+ {
+ if( pItem->PutValue( m_xPropertySet->getPropertyValue( aProperty.first ),
+ aProperty.second // nMemberId
+ ))
+ {
+ pItem->SetWhich(nWhich);
+ rOutItemSet.Put( std::move(pItem) );
+ }
+ }
+ catch( const beans::UnknownPropertyException & )
+ {
+ TOOLS_WARN_EXCEPTION( "chart2", "unknown Property: " << aProperty.first);
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ FillSpecialItem( nWhich, rOutItemSet );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ }
+}
+
+void ItemConverter::FillSpecialItem(
+ sal_uInt16 /*nWhichId*/, SfxItemSet & /*rOutItemSet*/ ) const
+{
+ OSL_FAIL( "ItemConverter: Unhandled special item found!" );
+}
+
+bool ItemConverter::ApplySpecialItem(
+ sal_uInt16 /*nWhichId*/, const SfxItemSet & /*rItemSet*/ )
+{
+ OSL_FAIL( "ItemConverter: Unhandled special item found!" );
+ return false;
+}
+
+bool ItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
+{
+ OSL_ASSERT( m_xPropertySet.is());
+
+ bool bItemsChanged = false;
+ SfxItemIter aIter( rItemSet );
+ tPropertyNameWithMemberId aProperty;
+ uno::Any aValue;
+
+ for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
+ {
+ if( aIter.GetItemState( false ) == SfxItemState::SET )
+ {
+ if( GetItemProperty( pItem->Which(), aProperty ))
+ {
+ pItem->QueryValue( aValue, aProperty.second /* nMemberId */ );
+
+ try
+ {
+ if( aValue != m_xPropertySet->getPropertyValue( aProperty.first ))
+ {
+ m_xPropertySet->setPropertyValue( aProperty.first, aValue );
+ bItemsChanged = true;
+ }
+ }
+ catch( const beans::UnknownPropertyException & )
+ {
+ TOOLS_WARN_EXCEPTION( "chart2", "unknown Property: " << aProperty.first);
+ }
+ catch( const uno::Exception & )
+ {
+ TOOLS_WARN_EXCEPTION( "chart2", "" );
+ }
+ }
+ else
+ {
+ bItemsChanged = ApplySpecialItem( pItem->Which(), rItemSet ) || bItemsChanged;
+ }
+ }
+ }
+
+ return bItemsChanged;
+}
+
+void ItemConverter::InvalidateUnequalItems( SfxItemSet &rDestSet, const SfxItemSet &rSourceSet )
+{
+ SfxWhichIter aIter (rSourceSet);
+ sal_uInt16 nWhich = aIter.FirstWhich ();
+ const SfxPoolItem *pPoolItem = nullptr;
+
+ while (nWhich)
+ {
+ SfxItemState nSourceItemState = aIter.GetItemState(true, &pPoolItem);
+ if ((nSourceItemState == SfxItemState::SET) &&
+ (rDestSet.GetItemState(nWhich, true, &pPoolItem) == SfxItemState::SET))
+ {
+ if (rSourceSet.Get(nWhich) != rDestSet.Get(nWhich))
+ {
+ if( nWhich != SID_CHAR_DLG_PREVIEW_STRING )
+ {
+ rDestSet.InvalidateItem(nWhich);
+ }
+ }
+ }
+ else if( nSourceItemState == SfxItemState::DONTCARE )
+ rDestSet.InvalidateItem(nWhich);
+
+ nWhich = aIter.NextWhich ();
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/LegendItemConverter.cxx b/chart2/source/controller/itemsetwrapper/LegendItemConverter.cxx
new file mode 100644
index 0000000000..cf2d2e69bb
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/LegendItemConverter.cxx
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <LegendItemConverter.hxx>
+#include "SchWhichPairs.hxx"
+#include <GraphicPropertyItemConverter.hxx>
+#include <CharacterPropertyItemConverter.hxx>
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart/ChartLegendExpansion.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <svl/intitem.hxx>
+#include <svl/eitem.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+namespace chart::wrapper
+{
+
+LegendItemConverter::LegendItemConverter(
+ const css::uno::Reference< css::beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory,
+ const awt::Size* pRefSize ) :
+ ItemConverter( rPropertySet, rItemPool )
+{
+ m_aConverters.emplace_back( new GraphicPropertyItemConverter(
+ rPropertySet, rItemPool, rDrawModel, xNamedPropertyContainerFactory,
+ GraphicObjectType::LineAndFillProperties ));
+ m_aConverters.emplace_back( new CharacterPropertyItemConverter(
+ rPropertySet, rItemPool, pRefSize,
+ "ReferencePageSize" ));
+}
+
+LegendItemConverter::~LegendItemConverter()
+{
+}
+
+void LegendItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
+{
+ for( const auto& pConv : m_aConverters )
+ pConv->FillItemSet( rOutItemSet );
+
+ // own items
+ ItemConverter::FillItemSet( rOutItemSet );
+}
+
+bool LegendItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
+{
+ bool bResult = false;
+
+ for( const auto& pConv : m_aConverters )
+ bResult = pConv->ApplyItemSet( rItemSet ) || bResult;
+
+ // own items
+ return ItemConverter::ApplyItemSet( rItemSet ) || bResult;
+}
+
+const WhichRangesContainer& LegendItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nLegendWhichPairs;
+}
+
+bool LegendItemConverter::GetItemProperty( tWhichIdType /*nWhichId*/, tPropertyNameWithMemberId & /*rOutProperty*/ ) const
+{
+ // No own (non-special) properties
+ return false;
+}
+
+bool LegendItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet& rInItemSet )
+{
+ bool bChanged = false;
+
+ switch( nWhichId )
+ {
+ case SCHATTR_LEGEND_SHOW:
+ {
+ if( const SfxBoolItem* pShowItem = rInItemSet.GetItemIfSet( SCHATTR_LEGEND_SHOW ) )
+ {
+ bool bShow = pShowItem->GetValue();
+ bool bWasShown = true;
+ if( ! (GetPropertySet()->getPropertyValue( "Show" ) >>= bWasShown) ||
+ ( bWasShown != bShow ))
+ {
+ GetPropertySet()->setPropertyValue( "Show" , uno::Any( bShow ));
+ bChanged = true;
+ }
+ }
+
+ }
+ break;
+ case SCHATTR_LEGEND_POS:
+ {
+ if( const SfxInt32Item* pPosItem = rInItemSet.GetItemIfSet( SCHATTR_LEGEND_POS ) )
+ {
+ chart2::LegendPosition eNewPos = static_cast<chart2::LegendPosition>(pPosItem->GetValue());
+
+ css::chart::ChartLegendExpansion eExpansion = css::chart::ChartLegendExpansion_HIGH;
+ switch( eNewPos )
+ {
+ case chart2::LegendPosition_LINE_START:
+ case chart2::LegendPosition_LINE_END:
+ eExpansion = css::chart::ChartLegendExpansion_HIGH;
+ break;
+ case chart2::LegendPosition_PAGE_START:
+ case chart2::LegendPosition_PAGE_END:
+ eExpansion = css::chart::ChartLegendExpansion_WIDE;
+ break;
+ default:
+ break;
+ }
+
+ try
+ {
+ chart2::LegendPosition eOldPos;
+ if( ! ( GetPropertySet()->getPropertyValue( "AnchorPosition" ) >>= eOldPos ) ||
+ ( eOldPos != eNewPos ))
+ {
+ GetPropertySet()->setPropertyValue( "AnchorPosition" , uno::Any( eNewPos ));
+ GetPropertySet()->setPropertyValue( "Expansion" , uno::Any( eExpansion ));
+ GetPropertySet()->setPropertyValue( "RelativePosition" , uno::Any());
+ bChanged = true;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ break;
+ case SCHATTR_LEGEND_NO_OVERLAY:
+ {
+ if(const SfxBoolItem* pNoOverlayItem = rInItemSet.GetItemIfSet(SCHATTR_LEGEND_NO_OVERLAY))
+ {
+ bool bOverlay = !pNoOverlayItem->GetValue();
+ bool bOldOverlay = false;
+ if(!(GetPropertySet()->getPropertyValue("Overlay") >>= bOldOverlay) ||
+ (bOldOverlay != bOverlay))
+ {
+ GetPropertySet()->setPropertyValue("Overlay", uno::Any(bOverlay));
+ bChanged = true;
+ }
+ }
+
+ }
+ break;
+ }
+
+ return bChanged;
+}
+
+void LegendItemConverter::FillSpecialItem(
+ sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
+{
+ switch( nWhichId )
+ {
+ case SCHATTR_LEGEND_SHOW:
+ {
+ bool bShow = true;
+ GetPropertySet()->getPropertyValue( "Show" ) >>= bShow;
+ rOutItemSet.Put( SfxBoolItem(SCHATTR_LEGEND_SHOW, bShow) );
+ }
+ break;
+ case SCHATTR_LEGEND_POS:
+ {
+ chart2::LegendPosition eLegendPos( chart2::LegendPosition_LINE_END );
+ GetPropertySet()->getPropertyValue( "AnchorPosition" ) >>= eLegendPos;
+ rOutItemSet.Put( SfxInt32Item(SCHATTR_LEGEND_POS, static_cast<sal_Int32>(eLegendPos) ) );
+ }
+ break;
+ case SCHATTR_LEGEND_NO_OVERLAY:
+ {
+ bool bOverlay = false;
+ GetPropertySet()->getPropertyValue("Overlay") >>= bOverlay;
+ rOutItemSet.Put(SfxBoolItem(SCHATTR_LEGEND_NO_OVERLAY, !bOverlay));
+ }
+ break;
+ }
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/MultipleChartConverters.cxx b/chart2/source/controller/itemsetwrapper/MultipleChartConverters.cxx
new file mode 100644
index 0000000000..12630b7084
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/MultipleChartConverters.cxx
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <MultipleChartConverters.hxx>
+
+#include "SchWhichPairs.hxx"
+#include <AxisItemConverter.hxx>
+#include <StatisticsItemConverter.hxx>
+#include <GraphicPropertyItemConverter.hxx>
+#include <DataPointItemConverter.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <Diagram.hxx>
+#include <DataSeries.hxx>
+#include <GridProperties.hxx>
+#include <TitleHelper.hxx>
+#include <TitleItemConverter.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <com/sun/star/chart2/XTitle.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart::wrapper {
+
+AllAxisItemConverter::AllAxisItemConverter(
+ const rtl::Reference<::chart::ChartModel> & xChartModel,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const awt::Size* pRefSize )
+ : MultipleItemConverter( rItemPool )
+{
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ const std::vector< rtl::Reference< Axis > > aElementList = AxisHelper::getAllAxesOfDiagram( xDiagram );
+ for( rtl::Reference< Axis > const & axis : aElementList )
+ {
+ uno::Reference< beans::XPropertySet > xObjectProperties(axis);
+ m_aConverters.emplace_back( new ::chart::wrapper::AxisItemConverter(
+ xObjectProperties, rItemPool, rDrawModel,
+ xChartModel, nullptr, nullptr,
+ pRefSize));
+ }
+}
+
+AllAxisItemConverter::~AllAxisItemConverter()
+{
+}
+
+const WhichRangesContainer& AllAxisItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nAllAxisWhichPairs;
+}
+
+AllGridItemConverter::AllGridItemConverter(
+ const rtl::Reference<::chart::ChartModel> & xChartModel,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory )
+ : MultipleItemConverter( rItemPool )
+{
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ std::vector< rtl::Reference< GridProperties > > aElementList( AxisHelper::getAllGrids( xDiagram ) );
+ for( rtl::Reference< GridProperties > const & xObjectProperties : aElementList )
+ {
+ m_aConverters.emplace_back( new ::chart::wrapper::GraphicPropertyItemConverter(
+ xObjectProperties, rItemPool, rDrawModel, xNamedPropertyContainerFactory,
+ ::chart::wrapper::GraphicObjectType::LineProperties ) );
+ }
+}
+
+AllGridItemConverter::~AllGridItemConverter()
+{
+}
+
+const WhichRangesContainer& AllGridItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nGridWhichPairs;
+}
+
+AllDataLabelItemConverter::AllDataLabelItemConverter(
+ const rtl::Reference<::chart::ChartModel> & xChartModel,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory )
+ : MultipleItemConverter( rItemPool )
+{
+ std::vector< rtl::Reference< DataSeries > > aSeriesList =
+ ::chart::ChartModelHelper::getDataSeries( xChartModel );
+
+ for (auto const& series : aSeriesList)
+ {
+ uno::Reference< uno::XComponentContext> xContext;//do not need Context for label properties
+
+ sal_Int32 nNumberFormat=ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( series );
+ sal_Int32 nPercentNumberFormat=ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
+ series,xChartModel);
+
+ m_aConverters.emplace_back(
+ new ::chart::wrapper::DataPointItemConverter(
+ xChartModel, xContext, series, series, rItemPool, rDrawModel,
+ xNamedPropertyContainerFactory, GraphicObjectType::FilledDataPoint,
+ nullptr, true, false, 0, true, nNumberFormat, nPercentNumberFormat));
+ }
+}
+
+AllDataLabelItemConverter::~AllDataLabelItemConverter()
+{
+}
+
+const WhichRangesContainer& AllDataLabelItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nDataLabelWhichPairs;
+}
+
+AllTitleItemConverter::AllTitleItemConverter(
+ const rtl::Reference<::chart::ChartModel> & xChartModel,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory )
+ : MultipleItemConverter( rItemPool )
+{
+ for(sal_Int32 nTitle = TitleHelper::TITLE_BEGIN; nTitle < TitleHelper::NORMAL_TITLE_END; nTitle++ )
+ {
+ rtl::Reference< Title > xTitle( TitleHelper::getTitle( TitleHelper::eTitleType(nTitle), xChartModel ) );
+ if(!xTitle.is())
+ continue;
+ uno::Reference< beans::XPropertySet > xObjectProperties( xTitle );
+ m_aConverters.emplace_back(
+ new ::chart::wrapper::TitleItemConverter(
+ xObjectProperties, rItemPool, rDrawModel, xNamedPropertyContainerFactory, nullptr));
+ }
+}
+
+AllTitleItemConverter::~AllTitleItemConverter()
+{
+}
+
+const WhichRangesContainer& AllTitleItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nTitleWhichPairs;
+}
+
+AllSeriesStatisticsConverter::AllSeriesStatisticsConverter(
+ const rtl::Reference<::chart::ChartModel> & xChartModel,
+ SfxItemPool& rItemPool )
+ : MultipleItemConverter( rItemPool )
+{
+ std::vector< rtl::Reference< DataSeries > > aSeriesList =
+ ::chart::ChartModelHelper::getDataSeries( xChartModel );
+
+ for (auto const& series : aSeriesList)
+ {
+ m_aConverters.emplace_back( new ::chart::wrapper::StatisticsItemConverter(
+ xChartModel, series, rItemPool ));
+ }
+}
+
+AllSeriesStatisticsConverter::~AllSeriesStatisticsConverter()
+{}
+
+const WhichRangesContainer& AllSeriesStatisticsConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nStatWhichPairs;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/MultipleItemConverter.cxx b/chart2/source/controller/itemsetwrapper/MultipleItemConverter.cxx
new file mode 100644
index 0000000000..5937575cc7
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/MultipleItemConverter.cxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <MultipleItemConverter.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+namespace chart::wrapper {
+
+MultipleItemConverter::MultipleItemConverter( SfxItemPool& rItemPool )
+ : ItemConverter( nullptr, rItemPool )
+{
+}
+MultipleItemConverter::~MultipleItemConverter()
+{
+}
+
+void MultipleItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
+{
+ auto aIter = m_aConverters.begin();
+ auto aEnd = m_aConverters.end();
+ if( aIter != aEnd )
+ {
+ (*aIter)->FillItemSet( rOutItemSet );
+ ++aIter;
+ }
+ for( ; aIter != aEnd; ++aIter )
+ {
+ SfxItemSet aSet = CreateEmptyItemSet();
+ (*aIter)->FillItemSet( aSet );
+ InvalidateUnequalItems( rOutItemSet, aSet );
+ }
+ // no own items
+}
+
+bool MultipleItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
+{
+ bool bResult = false;
+
+ for( const auto& pConv : m_aConverters )
+ bResult = pConv->ApplyItemSet( rItemSet ) || bResult;
+
+ // no own items
+ return bResult;
+}
+
+bool MultipleItemConverter::GetItemProperty( tWhichIdType /*nWhichId*/, tPropertyNameWithMemberId & /*rOutProperty*/ ) const
+{
+ return false;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx b/chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx
new file mode 100644
index 0000000000..da521d874d
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx
@@ -0,0 +1,351 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <RegressionCurveItemConverter.hxx>
+#include "SchWhichPairs.hxx"
+#include <GraphicPropertyItemConverter.hxx>
+#include <DataSeries.hxx>
+
+#include <com/sun/star/chart2/XRegressionCurve.hpp>
+#include <osl/diagnose.h>
+
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/stritem.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+template <class T, class D>
+bool lclConvertToPropertySet(const SfxItemSet& rItemSet, sal_uInt16 nWhichId, const uno::Reference<beans::XPropertySet>& xProperties, const OUString& aPropertyID)
+{
+ OSL_ASSERT(xProperties.is());
+ if( xProperties.is() )
+ {
+ T aValue = static_cast<T>(static_cast<const D&>(rItemSet.Get( nWhichId )).GetValue());
+ T aOldValue = aValue;
+ bool aSuccess = xProperties->getPropertyValue( aPropertyID ) >>= aOldValue;
+ if (!aSuccess || aOldValue != aValue)
+ {
+ xProperties->setPropertyValue( aPropertyID , uno::Any( aValue ));
+ return true;
+ }
+ }
+ return false;
+}
+
+template <class T, class D>
+void lclConvertToItemSet(SfxItemSet& rItemSet, sal_uInt16 nWhichId, const uno::Reference<beans::XPropertySet>& xProperties, const OUString& aPropertyID)
+{
+ OSL_ASSERT(xProperties.is());
+ if( xProperties.is() )
+ {
+ T aValue = static_cast<T>(static_cast<const D&>(rItemSet.Get( nWhichId )).GetValue());
+ if(xProperties->getPropertyValue( aPropertyID ) >>= aValue)
+ {
+ rItemSet.Put(D( nWhichId, aValue ));
+ }
+ }
+}
+
+void lclConvertToItemSetDouble(SfxItemSet& rItemSet, TypedWhichId<SvxDoubleItem> nWhichId, const uno::Reference<beans::XPropertySet>& xProperties, const OUString& aPropertyID)
+{
+ OSL_ASSERT(xProperties.is());
+ if( xProperties.is() )
+ {
+ double aValue = rItemSet.Get( nWhichId ).GetValue();
+ if(xProperties->getPropertyValue( aPropertyID ) >>= aValue)
+ {
+ rItemSet.Put(SvxDoubleItem( aValue, nWhichId ));
+ }
+ }
+}
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+RegressionCurveItemConverter::RegressionCurveItemConverter(
+ const uno::Reference< beans::XPropertySet >& rPropertySet,
+ rtl::Reference< DataSeries > xContainer,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory ) :
+ ItemConverter( rPropertySet, rItemPool ),
+ m_spGraphicConverter( std::make_shared<GraphicPropertyItemConverter>(
+ rPropertySet, rItemPool, rDrawModel,
+ xNamedPropertyContainerFactory,
+ GraphicObjectType::LineProperties )),
+ m_xCurveContainer(std::move( xContainer ))
+{}
+
+RegressionCurveItemConverter::~RegressionCurveItemConverter()
+{}
+
+void RegressionCurveItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
+{
+ m_spGraphicConverter->FillItemSet( rOutItemSet );
+
+ // own items
+ ItemConverter::FillItemSet( rOutItemSet );
+}
+
+bool RegressionCurveItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
+{
+ bool bResult = m_spGraphicConverter->ApplyItemSet( rItemSet );
+
+ // own items
+ return ItemConverter::ApplyItemSet( rItemSet ) || bResult;
+}
+
+const WhichRangesContainer& RegressionCurveItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nRegressionCurveWhichPairs;
+}
+
+bool RegressionCurveItemConverter::GetItemProperty(
+ tWhichIdType /* nWhichId */, tPropertyNameWithMemberId & /* rOutProperty */ ) const
+{
+ // No own (non-special) properties
+ return false;
+}
+
+bool RegressionCurveItemConverter::ApplySpecialItem(
+ sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
+{
+ uno::Reference< chart2::XRegressionCurve > xCurve( GetPropertySet(), uno::UNO_QUERY );
+ bool bChanged = false;
+
+ OSL_ASSERT(xCurve.is());
+ if(!xCurve.is())
+ return false;
+
+ switch( nWhichId )
+ {
+ case SCHATTR_REGRESSION_TYPE:
+ {
+ SvxChartRegress eRegress = RegressionCurveHelper::getRegressionType(xCurve);
+ SvxChartRegress eNewRegress = static_cast< const SvxChartRegressItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ if( eRegress != eNewRegress )
+ {
+ // note that changing the regression type changes the object
+ // for which this converter was created. Not optimal, but
+ // currently the only way to handle the type in the
+ // regression curve properties dialog
+ xCurve = RegressionCurveHelper::changeRegressionCurveType(
+ eNewRegress,
+ m_xCurveContainer,
+ xCurve);
+ uno::Reference<beans::XPropertySet> xProperties( xCurve, uno::UNO_QUERY );
+ resetPropertySet( xProperties );
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_REGRESSION_DEGREE:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+ bChanged = lclConvertToPropertySet<sal_Int32, SfxInt32Item>(rItemSet, nWhichId, xProperties, "PolynomialDegree");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_PERIOD:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+ bChanged = lclConvertToPropertySet<sal_Int32, SfxInt32Item>(rItemSet, nWhichId, xProperties, "MovingAveragePeriod");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+ bChanged = lclConvertToPropertySet<double, SvxDoubleItem>(rItemSet, nWhichId, xProperties, "ExtrapolateForward");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+ bChanged = lclConvertToPropertySet<double, SvxDoubleItem>(rItemSet, nWhichId, xProperties, "ExtrapolateBackward");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SET_INTERCEPT:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+ bChanged = lclConvertToPropertySet<bool, SfxBoolItem>(rItemSet, nWhichId, xProperties, "ForceIntercept");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_INTERCEPT_VALUE:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+ bChanged = lclConvertToPropertySet<double, SvxDoubleItem>(rItemSet, nWhichId, xProperties, "InterceptValue");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_CURVE_NAME:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+ bChanged = lclConvertToPropertySet<OUString, SfxStringItem>(rItemSet, nWhichId, xProperties, "CurveName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_MOVING_TYPE:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+ bChanged = lclConvertToPropertySet<sal_Int32, SfxInt32Item>(rItemSet, nWhichId, xProperties, "MovingAverageType");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SHOW_EQUATION:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties());
+ bChanged = lclConvertToPropertySet<bool, SfxBoolItem>(rItemSet, nWhichId, xEqProp, "ShowEquation");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_XNAME:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties());
+ bChanged = lclConvertToPropertySet<OUString, SfxStringItem>(rItemSet, nWhichId, xEqProp, "XName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_YNAME:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties());
+ bChanged = lclConvertToPropertySet<OUString, SfxStringItem>(rItemSet, nWhichId, xEqProp, "YName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SHOW_COEFF:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties());
+ bChanged = lclConvertToPropertySet<bool, SfxBoolItem>(rItemSet, nWhichId, xEqProp, "ShowCorrelationCoefficient");
+ }
+ break;
+
+ }
+ return bChanged;
+}
+
+void RegressionCurveItemConverter::FillSpecialItem(sal_uInt16 nWhichId, SfxItemSet& rOutItemSet ) const
+{
+ uno::Reference<chart2::XRegressionCurve> xCurve(GetPropertySet(), uno::UNO_QUERY);
+ OSL_ASSERT(xCurve.is());
+ if(!xCurve.is())
+ return;
+
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+
+ switch( nWhichId )
+ {
+ case SCHATTR_REGRESSION_TYPE:
+ {
+ SvxChartRegress eRegress = RegressionCurveHelper::getRegressionType(xCurve);
+ rOutItemSet.Put( SvxChartRegressItem( eRegress, SCHATTR_REGRESSION_TYPE ));
+ }
+ break;
+
+ case SCHATTR_REGRESSION_DEGREE:
+ {
+ lclConvertToItemSet<sal_Int32, SfxInt32Item>(rOutItemSet, nWhichId, xProperties, "PolynomialDegree");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_PERIOD:
+ {
+ lclConvertToItemSet<sal_Int32, SfxInt32Item>(rOutItemSet, nWhichId, xProperties, "MovingAveragePeriod");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD:
+ {
+ lclConvertToItemSetDouble(rOutItemSet, SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD, xProperties, "ExtrapolateForward");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD:
+ {
+ lclConvertToItemSetDouble(rOutItemSet, SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD, xProperties, "ExtrapolateBackward");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SET_INTERCEPT:
+ {
+ lclConvertToItemSet<bool, SfxBoolItem>(rOutItemSet, nWhichId, xProperties, "ForceIntercept");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_INTERCEPT_VALUE:
+ {
+ lclConvertToItemSetDouble(rOutItemSet, SCHATTR_REGRESSION_INTERCEPT_VALUE, xProperties, "InterceptValue");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_CURVE_NAME:
+ {
+ lclConvertToItemSet<OUString, SfxStringItem>(rOutItemSet, nWhichId, xProperties, "CurveName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_MOVING_TYPE:
+ {
+ lclConvertToItemSet<sal_Int32, SfxInt32Item>(rOutItemSet, nWhichId, xProperties, "MovingAverageType");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SHOW_EQUATION:
+ {
+ lclConvertToItemSet<bool, SfxBoolItem>(rOutItemSet, nWhichId, xCurve->getEquationProperties(), "ShowEquation");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_XNAME:
+ {
+ lclConvertToItemSet<OUString, SfxStringItem>(rOutItemSet, nWhichId, xCurve->getEquationProperties(), "XName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_YNAME:
+ {
+ lclConvertToItemSet<OUString, SfxStringItem>(rOutItemSet, nWhichId, xCurve->getEquationProperties(), "YName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SHOW_COEFF:
+ {
+ lclConvertToItemSet<bool, SfxBoolItem>(rOutItemSet, nWhichId, xCurve->getEquationProperties(), "ShowCorrelationCoefficient");
+ }
+ break;
+ }
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/RegressionEquationItemConverter.cxx b/chart2/source/controller/itemsetwrapper/RegressionEquationItemConverter.cxx
new file mode 100644
index 0000000000..22fc379b2a
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/RegressionEquationItemConverter.cxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RegressionEquationItemConverter.hxx>
+#include "SchWhichPairs.hxx"
+#include <ItemPropertyMap.hxx>
+#include <GraphicPropertyItemConverter.hxx>
+#include <CharacterPropertyItemConverter.hxx>
+#include <unonames.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <svl/intitem.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+namespace chart::wrapper {
+
+namespace {
+
+ItemPropertyMapType & lcl_GetEquationPropertyMap()
+{
+ static ItemPropertyMapType aEquationPropertyMap;
+
+ return aEquationPropertyMap;
+};
+
+} // anonymous namespace
+
+RegressionEquationItemConverter::RegressionEquationItemConverter(
+ const css::uno::Reference< css::beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory,
+ const awt::Size* pRefSize ) :
+ ItemConverter( rPropertySet, rItemPool )
+{
+ m_aConverters.emplace_back( new GraphicPropertyItemConverter(
+ rPropertySet, rItemPool, rDrawModel,
+ xNamedPropertyContainerFactory,
+ GraphicObjectType::LineAndFillProperties ));
+
+ m_aConverters.emplace_back(
+ new CharacterPropertyItemConverter(rPropertySet, rItemPool, pRefSize, "ReferencePageSize"));
+}
+
+RegressionEquationItemConverter::~RegressionEquationItemConverter()
+{
+}
+
+void RegressionEquationItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
+{
+ for( const auto& pConv : m_aConverters )
+ pConv->FillItemSet( rOutItemSet );
+
+ // own items
+ ItemConverter::FillItemSet( rOutItemSet );
+}
+
+bool RegressionEquationItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
+{
+ bool bResult = false;
+
+ for( const auto& pConv : m_aConverters )
+ bResult = pConv->ApplyItemSet( rItemSet );
+
+ // own items
+ return ItemConverter::ApplyItemSet( rItemSet ) || bResult;
+}
+
+const WhichRangesContainer& RegressionEquationItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nRegEquationWhichPairs;
+}
+
+bool RegressionEquationItemConverter::GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const
+{
+ ItemPropertyMapType & rMap( lcl_GetEquationPropertyMap());
+ ItemPropertyMapType::const_iterator aIt( rMap.find( nWhichId ));
+
+ if( aIt == rMap.end())
+ return false;
+
+ rOutProperty =(*aIt).second;
+ return true;
+}
+
+bool RegressionEquationItemConverter::ApplySpecialItem(
+ sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
+{
+ bool bChanged = false;
+
+ switch( nWhichId )
+ {
+ case SID_ATTR_NUMBERFORMAT_VALUE:
+ {
+ uno::Any aValue( static_cast< sal_Int32 >(
+ static_cast< const SfxUInt32Item & >(
+ rItemSet.Get( nWhichId )).GetValue()));
+ if (GetPropertySet()->getPropertyValue(CHART_UNONAME_NUMFMT) != aValue)
+ {
+ GetPropertySet()->setPropertyValue(CHART_UNONAME_NUMFMT, aValue);
+ bChanged = true;
+ }
+ }
+ break;
+ }
+
+ return bChanged;
+}
+
+void RegressionEquationItemConverter::FillSpecialItem(
+ sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
+{
+ switch( nWhichId )
+ {
+ case SID_ATTR_NUMBERFORMAT_VALUE:
+ {
+ sal_Int32 nFormatKey = 0;
+ if (GetPropertySet()->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nFormatKey)
+ {
+ rOutItemSet.Put( SfxUInt32Item( nWhichId, nFormatKey ));
+ }
+ }
+ break;
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx b/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx
new file mode 100644
index 0000000000..676527f3fe
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svl/whichranges.hxx>
+#include <svx/svxids.hrc>
+#include <svx/xdef.hxx>
+#include <svx/svddef.hxx>
+#include <editeng/eeitem.hxx>
+
+#include <chartview/ChartSfxItemIds.hxx>
+
+const WhichRangesContainer nTitleWhichPairs(svl::Items<
+ SCHATTR_TEXT_START, SCHATTR_TEXT_END,
+ XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, // 1018 - 1046 svx/xdef.hxx
+ SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST, // 1067 - 1078 svx/svddef.hxx
+ EE_ITEMS_START, EE_ITEMS_END, // Characters
+ SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING // Characters
+>);
+
+const WhichRangesContainer nAxisWhichPairs(svl::Items<
+ SCHATTR_TEXT_START, SCHATTR_TEXT_END,
+ SCHATTR_AXIS_START, SCHATTR_AXIS_END,
+ XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx
+ EE_ITEMS_START, EE_ITEMS_END, // Characters
+ SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_VALUE, // 10585 - 10585 svx/svxids.hrc
+ SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE, // 11432 svx/svxids.hrc
+ SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING // Characters
+>);
+
+const WhichRangesContainer nAllAxisWhichPairs(svl::Items<
+ SCHATTR_TEXT_START, SCHATTR_TEXT_END,
+ SCHATTR_AXIS_LABEL_START, SCHATTR_AXIS_LABEL_END,
+ XATTR_LINE_FIRST, XATTR_LINE_LAST,
+ EE_ITEMS_START, EE_ITEMS_END, // Characters
+ SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING // Characters
+>);
+
+const WhichRangesContainer nGridWhichPairs(svl::Items<
+ XATTR_LINE_FIRST, XATTR_LINE_LAST // 1000 - 1016 svx/xdef.hxx
+>);
+
+const WhichRangesContainer nLegendWhichPairs(svl::Items<
+ SCHATTR_LEGEND_START, SCHATTR_LEGEND_END, // 3 - 3 sch/schattr.hxx
+ XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, // 1018 - 1046 svx/xdef.hxx
+ SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST, // 1067 - 1078 svx/svddef.hxx
+ EE_ITEMS_START, EE_ITEMS_END, // Characters
+ SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING // Characters
+>);
+
+const WhichRangesContainer nDataLabelWhichPairs(svl::Items<
+ SCHATTR_DATADESCR_START, SCHATTR_DATADESCR_END,
+ SCHATTR_TEXT_DEGREES,SCHATTR_TEXT_DEGREES,
+ EE_PARA_WRITINGDIR,EE_PARA_WRITINGDIR,
+ SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO, /* 10585 - 10585 svx/svxids.hrc */
+ SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE /* 11432 svx/svxids.hrc */
+>);
+
+const WhichRangesContainer nDataPointWhichPairs(svl::Items<
+ SCHATTR_DATADESCR_START, SCHATTR_DATADESCR_END, /* 1 - 2 sch/schattr.hxx*/
+ SCHATTR_TEXT_DEGREES, SCHATTR_TEXT_DEGREES,
+ SCHATTR_STYLE_START,SCHATTR_STYLE_END, /* 59 - 68 sch/schattr.hxx*/
+ SCHATTR_SYMBOL_BRUSH,SCHATTR_SYMBOL_BRUSH, /* 94 sch/schattr.hxx*/
+ SCHATTR_SYMBOL_SIZE,SCHATTR_SYMBOL_SIZE, /* 97 sch/schattr.hxx*/
+ SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY,
+ XATTR_LINE_FIRST, XATTR_LINE_LAST, /* 1000 - 1016 svx/xdef.hxx */
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, /* 1018 - 1046 svx/xdef.hxx */
+ SDRATTR_3D_FIRST, SDRATTR_3D_LAST, /* 1244 - 1334 svx/svddef.hxx */
+ EE_ITEMS_START, EE_ITEMS_END, /* 3994 - 4037 editeng/eeitem.hxx */
+ SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO, /* 10585 - 10585 svx/svxids.hrc */
+ SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE, /* 11432 svx/svxids.hrc */
+ SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING
+>);
+
+const WhichRangesContainer nTextLabelWhichPairs(svl::Items<
+ SCHATTR_DATADESCR_START, SCHATTR_DATADESCR_END,
+ SCHATTR_TEXT_DEGREES, SCHATTR_TEXT_DEGREES,
+ SCHATTR_STYLE_SYMBOL, SCHATTR_STYLE_SYMBOL,
+ SCHATTR_SYMBOL_BRUSH, SCHATTR_SYMBOL_BRUSH,
+ SCHATTR_SYMBOL_SIZE, SCHATTR_SYMBOL_SIZE,
+ XATTR_LINESTYLE, XATTR_LINECOLOR,
+ XATTR_LINETRANSPARENCE, XATTR_LINETRANSPARENCE,
+ EE_ITEMS_START, EE_ITEMS_END,
+ SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO,
+ SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE,
+ SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING
+>);
+
+const WhichRangesContainer nSeriesOptionsWhichPairs(svl::Items<
+ SCHATTR_AXIS,SCHATTR_AXIS, /* 69 sch/schattr.hxx*/
+ SCHATTR_BAR_OVERLAP,SCHATTR_BAR_CONNECT, /* 98 - 100 (incl. SCHATTR_GAPWIDTH) */
+ SCHATTR_GROUP_BARS_PER_AXIS,SCHATTR_AXIS_FOR_ALL_SERIES
+>);
+
+// nDataPointWhichPairs + nSeriesOptionsWhichPairs
+const WhichRangesContainer nRowWhichPairs(svl::Items<
+ SCHATTR_DATADESCR_START, SCHATTR_DATADESCR_END, /* 1 - 2 sch/schattr.hxx*/
+ SCHATTR_TEXT_DEGREES, SCHATTR_TEXT_DEGREES,
+ SCHATTR_STYLE_START,SCHATTR_STYLE_END, /* 59 - 68 sch/schattr.hxx*/
+ SCHATTR_AXIS,SCHATTR_AXIS, /* 69 sch/schattr.hxx*/
+ SCHATTR_SYMBOL_BRUSH,SCHATTR_SYMBOL_BRUSH, /* 94 sch/schattr.hxx*/
+ SCHATTR_SYMBOL_SIZE,SCHATTR_SYMBOL_SIZE, /* 97 sch/schattr.hxx*/
+ SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY,
+ SCHATTR_BAR_OVERLAP,SCHATTR_BAR_CONNECT, /* 98 - 100 (incl. SCHATTR_GAPWIDTH) */
+ SCHATTR_GROUP_BARS_PER_AXIS,SCHATTR_AXIS_FOR_ALL_SERIES,
+ XATTR_LINE_FIRST, XATTR_LINE_LAST, /* 1000 - 1016 svx/xdef.hxx */
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, /* 1018 - 1046 svx/xdef.hxx */
+ SDRATTR_3D_FIRST, SDRATTR_3D_LAST, /* 1244 - 1334 svx/svddef.hxx */
+ EE_ITEMS_START, EE_ITEMS_END, /* 3994 - 4037 editeng/eeitem.hxx */
+ SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO, /* 10585 - 10585 svx/svxids.hrc */
+ SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE, /* 11432 svx/svxids.hrc */
+ SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING
+>);
+
+const WhichRangesContainer nStatWhichPairs(svl::Items<
+ SCHATTR_STAT_START, SCHATTR_STAT_END, // 45 - 52 sch/schattr.hxx
+ SCHATTR_REGRESSION_START, SCHATTR_REGRESSION_END // 108 - 109
+>);
+
+const WhichRangesContainer nErrorBarWhichPairs(svl::Items<
+ SCHATTR_STAT_START, SCHATTR_STAT_END, // 45 - 52 sch/schattr.hxx
+ XATTR_LINE_FIRST, XATTR_LINE_LAST // 1000 - 1016 svx/xdef.hxx
+>);
+
+// for CharacterProperties
+
+const WhichRangesContainer nCharacterPropertyWhichPairs(svl::Items<
+ EE_ITEMS_START, EE_ITEMS_END, // Characters
+ SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING // Characters
+>);
+
+const WhichRangesContainer nLinePropertyWhichPairs(svl::Items<
+ XATTR_LINE_FIRST, XATTR_LINE_LAST // 1000 - 1016 svx/xdef.hxx
+>);
+
+const WhichRangesContainer nLineAndFillPropertyWhichPairs(svl::Items<
+ XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, // 1000 - 1016 svx/xdef.hxx
+ SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST // 1067 - 1078 svx/svddef.hxx
+>);
+
+const WhichRangesContainer nRegressionCurveWhichPairs(svl::Items<
+ SCHATTR_REGRESSION_START, SCHATTR_REGRESSION_END, // 108 - 109
+ XATTR_LINE_FIRST, XATTR_LINE_LAST // 1000 - 1016 svx/xdef.hxx
+>);
+
+const WhichRangesContainer nRegEquationWhichPairs(svl::Items<
+ XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, // 1018 - 1046 svx/xdef.hxx
+ SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST, // 1067 - 1078 svx/svddef.hxx
+ EE_ITEMS_START, EE_ITEMS_END, // Characters
+ SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_VALUE, // 10585 - 10585 svx/svxids.hrc
+ SID_CHAR_DLG_PREVIEW_STRING, SID_CHAR_DLG_PREVIEW_STRING // Characters
+>);
+
+const WhichRangesContainer nDataTableWhichPairs(svl::Items<
+ SCHATTR_DATA_TABLE_START, SCHATTR_DATA_TABLE_END,
+ XATTR_LINE_FIRST, XATTR_LINE_LAST, // 1000 - 1016 svx/xdef.hxx
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, // 1018 - 1046 svx/xdef.hxx
+ EE_ITEMS_START, EE_ITEMS_END
+>);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/SeriesOptionsItemConverter.cxx b/chart2/source/controller/itemsetwrapper/SeriesOptionsItemConverter.cxx
new file mode 100644
index 0000000000..b0ae879ed5
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/SeriesOptionsItemConverter.cxx
@@ -0,0 +1,434 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <SeriesOptionsItemConverter.hxx>
+#include "SchWhichPairs.hxx"
+
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ChartTypeHelper.hxx>
+#include <DataSeriesHelper.hxx>
+#include <ChartModel.hxx>
+#include <BaseCoordinateSystem.hxx>
+
+#include <com/sun/star/chart2/XDataSeries.hpp>
+
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/ilstitem.hxx>
+#include <svx/sdangitm.hxx>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+namespace chart::wrapper
+{
+
+SeriesOptionsItemConverter::SeriesOptionsItemConverter(
+ const rtl::Reference<::chart::ChartModel>& xChartModel
+ , uno::Reference< uno::XComponentContext > xContext
+ , const rtl::Reference< ::chart::DataSeries >& xDataSeries
+ , SfxItemPool& rItemPool )
+ : ItemConverter( xDataSeries, rItemPool )
+ , m_xChartModel(xChartModel)
+ , m_xCC(std::move(xContext))
+ , m_bAttachToMainAxis(true)
+ , m_bSupportingOverlapAndGapWidthProperties(false)
+ , m_bSupportingBarConnectors(false)
+ , m_nBarOverlap(0)
+ , m_nGapWidth(100)
+ , m_bConnectBars(false)
+ , m_bSupportingAxisSideBySide(false)
+ , m_bGroupBarsPerAxis(true)
+ , m_bSupportingStartingAngle(false)
+ , m_nStartingAngle(90)
+ , m_bClockwise(false)
+ , m_nMissingValueTreatment(0)
+ , m_bSupportingPlottingOfHiddenCells(false)
+ , m_bIncludeHiddenCells(true)
+ , m_bHideLegendEntry(false)
+{
+ try
+ {
+ m_bAttachToMainAxis = DiagramHelper::isSeriesAttachedToMainAxis( xDataSeries );
+
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeOfSeries( xDataSeries ) );
+
+ m_xCooSys = DataSeriesHelper::getCoordinateSystemOfSeries( xDataSeries, xDiagram );
+ if( m_xCooSys.is() )
+ {
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( 1, 0, m_xCooSys );
+ chart2::ScaleData aScale( xAxis->getScaleData() );
+ m_bClockwise = (aScale.Orientation == chart2::AxisOrientation_REVERSE);
+ }
+
+ sal_Int32 nDimensionCount = xDiagram->getDimension();
+ m_bSupportingOverlapAndGapWidthProperties = ChartTypeHelper::isSupportingOverlapAndGapWidthProperties( xChartType, nDimensionCount );
+
+ if( m_bSupportingOverlapAndGapWidthProperties )
+ {
+
+ sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
+
+ uno::Sequence< sal_Int32 > aBarPositionSequence;
+ if( xChartType.is() )
+ {
+ if( xChartType->getPropertyValue( "OverlapSequence" ) >>= aBarPositionSequence )
+ {
+ if( nAxisIndex >= 0 && nAxisIndex < aBarPositionSequence.getLength() )
+ m_nBarOverlap = aBarPositionSequence[nAxisIndex];
+ }
+ if( xChartType->getPropertyValue( "GapwidthSequence" ) >>= aBarPositionSequence )
+ {
+ if( nAxisIndex >= 0 && nAxisIndex < aBarPositionSequence.getLength() )
+ m_nGapWidth = aBarPositionSequence[nAxisIndex];
+ }
+ }
+ }
+
+ m_bSupportingBarConnectors = ChartTypeHelper::isSupportingBarConnectors( xChartType, nDimensionCount );
+ if( m_bSupportingBarConnectors && xDiagram.is() )
+ {
+ xDiagram->getPropertyValue( "ConnectBars" ) >>= m_bConnectBars;
+ }
+
+ m_bSupportingAxisSideBySide = ChartTypeHelper::isSupportingAxisSideBySide( xChartType, nDimensionCount );
+ if( m_bSupportingAxisSideBySide && xDiagram.is() )
+ {
+ xDiagram->getPropertyValue( "GroupBarsPerAxis" ) >>= m_bGroupBarsPerAxis;
+ }
+
+ m_bSupportingStartingAngle = ChartTypeHelper::isSupportingStartingAngle( xChartType );
+ if( m_bSupportingStartingAngle )
+ {
+ xDiagram->getPropertyValue( "StartingAngle" ) >>= m_nStartingAngle;
+ }
+
+ m_aSupportedMissingValueTreatments = ChartTypeHelper::getSupportedMissingValueTreatments( xChartType );
+ m_nMissingValueTreatment = xDiagram->getCorrectedMissingValueTreatment( xChartType );
+
+ uno::Reference< beans::XPropertySet > xProp( m_xChartModel->getDataProvider(), uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ try
+ {
+ //test whether the data provider offers this property
+ xProp->getPropertyValue( "IncludeHiddenCells" );
+ //if not exception is thrown the property is offered
+ m_bSupportingPlottingOfHiddenCells = true;
+ xDiagram->getPropertyValue( "IncludeHiddenCells" ) >>= m_bIncludeHiddenCells;
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ }
+ }
+
+ m_bHideLegendEntry = !xDataSeries->getPropertyValue("ShowLegendEntry").get<bool>();
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+SeriesOptionsItemConverter::~SeriesOptionsItemConverter()
+{
+}
+
+const WhichRangesContainer& SeriesOptionsItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nSeriesOptionsWhichPairs;
+}
+
+bool SeriesOptionsItemConverter::GetItemProperty( tWhichIdType /*nWhichId*/, tPropertyNameWithMemberId & /*rOutProperty*/ ) const
+{
+ return false;
+}
+
+bool SeriesOptionsItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
+{
+ bool bChanged = false;
+ switch( nWhichId )
+ {
+ case SCHATTR_AXIS:
+ {
+ sal_Int32 nItemValue = static_cast< const SfxInt32Item & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ bool bAttachToMainAxis = nItemValue == CHART_AXIS_PRIMARY_Y;
+ if( bAttachToMainAxis != m_bAttachToMainAxis )
+ {
+ //change model:
+ rtl::Reference<DataSeries> xDataSeries = dynamic_cast<DataSeries*>( GetPropertySet().get() );
+ bChanged = m_xChartModel->getFirstChartDiagram()->attachSeriesToAxis( bAttachToMainAxis, xDataSeries
+ , m_xCC );
+
+ if( bChanged )
+ m_bAttachToMainAxis = bAttachToMainAxis;
+ }
+ }
+ break;
+
+ case SCHATTR_BAR_OVERLAP:
+ case SCHATTR_BAR_GAPWIDTH:
+ {
+ if( m_bSupportingOverlapAndGapWidthProperties )
+ {
+ sal_Int32& rBarPosition = ( nWhichId == SCHATTR_BAR_OVERLAP ) ? m_nBarOverlap : m_nGapWidth;
+ rBarPosition = static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue();
+
+ OUString aPropName("GapwidthSequence" );
+ if( nWhichId == SCHATTR_BAR_OVERLAP )
+ aPropName = "OverlapSequence";
+
+ rtl::Reference< DataSeries > xDataSeries( dynamic_cast<DataSeries*>(GetPropertySet().get()) );
+ rtl::Reference< Diagram > xDiagram( m_xChartModel->getFirstChartDiagram() );
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeOfSeries( xDataSeries ) );
+ if( xChartType.is() )
+ {
+ sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
+ uno::Sequence< sal_Int32 > aBarPositionSequence;
+ if( xChartType->getPropertyValue( aPropName ) >>= aBarPositionSequence )
+ {
+ bool bGroupBarsPerAxis = rItemSet.Get( SCHATTR_GROUP_BARS_PER_AXIS ).GetValue();
+ if(!bGroupBarsPerAxis)
+ {
+ //set the same value for all axes
+ for( auto & pos : asNonConstRange(aBarPositionSequence) )
+ pos = rBarPosition;
+ }
+ else if( nAxisIndex >= 0 && nAxisIndex < aBarPositionSequence.getLength() )
+ aBarPositionSequence.getArray()[nAxisIndex] = rBarPosition;
+
+ xChartType->setPropertyValue( aPropName, uno::Any(aBarPositionSequence) );
+ bChanged = true;
+ }
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_BAR_CONNECT:
+ {
+ m_bConnectBars = static_cast< const SfxBoolItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ if( m_bSupportingBarConnectors )
+ {
+ bool bOldConnectBars = false;
+ rtl::Reference< Diagram > xDiagramProperties( m_xChartModel->getFirstChartDiagram() );
+ if( xDiagramProperties.is() &&
+ (xDiagramProperties->getPropertyValue( "ConnectBars" ) >>= bOldConnectBars) &&
+ bOldConnectBars != m_bConnectBars )
+ {
+ xDiagramProperties->setPropertyValue( "ConnectBars" , uno::Any(m_bConnectBars) );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_GROUP_BARS_PER_AXIS:
+ {
+ m_bGroupBarsPerAxis = static_cast< const SfxBoolItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ if( m_bSupportingAxisSideBySide )
+ {
+ bool bOldGroupBarsPerAxis = true;
+ rtl::Reference< Diagram > xDiagramProperties( m_xChartModel->getFirstChartDiagram() );
+ if( xDiagramProperties.is() &&
+ (xDiagramProperties->getPropertyValue( "GroupBarsPerAxis" ) >>= bOldGroupBarsPerAxis) &&
+ bOldGroupBarsPerAxis != m_bGroupBarsPerAxis )
+ {
+ xDiagramProperties->setPropertyValue( "GroupBarsPerAxis" , uno::Any(m_bGroupBarsPerAxis) );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_STARTING_ANGLE:
+ {
+ if( m_bSupportingStartingAngle )
+ {
+ m_nStartingAngle = static_cast< const SdrAngleItem & >( rItemSet.Get( nWhichId )).GetValue().get() / 100;
+ rtl::Reference< Diagram > xDiagramProperties( m_xChartModel->getFirstChartDiagram() );
+ if( xDiagramProperties.is() )
+ {
+ xDiagramProperties->setPropertyValue( "StartingAngle" , uno::Any(m_nStartingAngle) );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_CLOCKWISE:
+ {
+ bool bClockwise = static_cast< const SfxBoolItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ if( m_xCooSys.is() )
+ {
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( 1, 0, m_xCooSys );
+ if( xAxis.is() )
+ {
+ chart2::ScaleData aScaleData( xAxis->getScaleData() );
+ aScaleData.Orientation = bClockwise ? chart2::AxisOrientation_REVERSE : chart2::AxisOrientation_MATHEMATICAL;
+ xAxis->setScaleData( aScaleData );
+ bChanged = true;
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_MISSING_VALUE_TREATMENT:
+ {
+ if( m_aSupportedMissingValueTreatments.hasElements() )
+ {
+ sal_Int32 nNew = static_cast< const SfxInt32Item & >( rItemSet.Get( nWhichId )).GetValue();
+ if( m_nMissingValueTreatment != nNew )
+ {
+ try
+ {
+ rtl::Reference< Diagram > xDiagramProperties( m_xChartModel->getFirstChartDiagram() );
+ if( xDiagramProperties.is() )
+ {
+ xDiagramProperties->setPropertyValue( "MissingValueTreatment" , uno::Any( nNew ));
+ bChanged = true;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ }
+ }
+ break;
+ case SCHATTR_INCLUDE_HIDDEN_CELLS:
+ {
+ if( m_bSupportingPlottingOfHiddenCells )
+ {
+ bool bIncludeHiddenCells = static_cast<const SfxBoolItem &>(rItemSet.Get(nWhichId)).GetValue();
+ if (bIncludeHiddenCells != m_bIncludeHiddenCells)
+ {
+ if (m_xChartModel)
+ bChanged = ChartModelHelper::setIncludeHiddenCells( bIncludeHiddenCells, *m_xChartModel );
+ }
+ }
+ }
+ break;
+ case SCHATTR_HIDE_LEGEND_ENTRY:
+ {
+ bool bHideLegendEntry = static_cast<const SfxBoolItem &>(rItemSet.Get(nWhichId)).GetValue();
+ if (bHideLegendEntry != m_bHideLegendEntry)
+ {
+ GetPropertySet()->setPropertyValue("ShowLegendEntry", css::uno::Any(!bHideLegendEntry));
+ }
+ }
+ break;
+ }
+ return bChanged;
+}
+
+void SeriesOptionsItemConverter::FillSpecialItem(
+ sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
+{
+ switch( nWhichId )
+ {
+ case SCHATTR_AXIS:
+ {
+ sal_Int32 nItemValue = m_bAttachToMainAxis ? CHART_AXIS_PRIMARY_Y : CHART_AXIS_SECONDARY_Y;
+ rOutItemSet.Put( SfxInt32Item(nWhichId,nItemValue ) );
+ break;
+ }
+ case SCHATTR_BAR_OVERLAP:
+ {
+ if( m_bSupportingOverlapAndGapWidthProperties )
+ rOutItemSet.Put( SfxInt32Item(nWhichId,m_nBarOverlap) );
+ break;
+ }
+ case SCHATTR_BAR_GAPWIDTH:
+ {
+ if( m_bSupportingOverlapAndGapWidthProperties )
+ rOutItemSet.Put( SfxInt32Item(nWhichId,m_nGapWidth) );
+ break;
+ }
+ case SCHATTR_BAR_CONNECT:
+ {
+ if( m_bSupportingBarConnectors )
+ rOutItemSet.Put( SfxBoolItem(nWhichId,m_bConnectBars));
+ break;
+ }
+ case SCHATTR_GROUP_BARS_PER_AXIS:
+ {
+ if( m_bSupportingAxisSideBySide )
+ rOutItemSet.Put( SfxBoolItem(nWhichId,m_bGroupBarsPerAxis) );
+ break;
+ }
+ case SCHATTR_AXIS_FOR_ALL_SERIES:
+ {
+ break;
+ }
+ case SCHATTR_STARTING_ANGLE:
+ {
+ if( m_bSupportingStartingAngle )
+ rOutItemSet.Put( SdrAngleItem(SCHATTR_STARTING_ANGLE, Degree100(m_nStartingAngle*100)) );
+ break;
+ }
+ case SCHATTR_CLOCKWISE:
+ {
+ rOutItemSet.Put( SfxBoolItem(nWhichId,m_bClockwise) );
+ break;
+ }
+ case SCHATTR_MISSING_VALUE_TREATMENT:
+ {
+ if( m_aSupportedMissingValueTreatments.hasElements() )
+ rOutItemSet.Put( SfxInt32Item( nWhichId, m_nMissingValueTreatment ));
+ break;
+ }
+ case SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS:
+ {
+ rOutItemSet.Put( SfxIntegerListItem( nWhichId, m_aSupportedMissingValueTreatments ) );
+ break;
+ }
+ case SCHATTR_INCLUDE_HIDDEN_CELLS:
+ {
+ if( m_bSupportingPlottingOfHiddenCells )
+ rOutItemSet.Put( SfxBoolItem(nWhichId, m_bIncludeHiddenCells) );
+ break;
+ }
+ case SCHATTR_HIDE_LEGEND_ENTRY:
+ {
+ rOutItemSet.Put(SfxBoolItem(nWhichId, m_bHideLegendEntry));
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/StatisticsItemConverter.cxx b/chart2/source/controller/itemsetwrapper/StatisticsItemConverter.cxx
new file mode 100644
index 0000000000..c725972c24
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/StatisticsItemConverter.cxx
@@ -0,0 +1,859 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <StatisticsItemConverter.hxx>
+#include "SchWhichPairs.hxx"
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <ErrorBar.hxx>
+#include <StatisticsHelper.hxx>
+#include <ChartModel.hxx>
+#include <unonames.hxx>
+
+#include <svl/stritem.hxx>
+#include <svx/chrtitem.hxx>
+#include <svl/intitem.hxx>
+#include <rtl/math.hxx>
+
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+
+uno::Reference< beans::XPropertySet > lcl_GetErrorBar(
+ const uno::Reference< beans::XPropertySet > & xProp, bool bYError )
+{
+ uno::Reference< beans::XPropertySet > xResult;
+
+ if( xProp.is())
+ try
+ {
+ ( xProp->getPropertyValue( bYError ? CHART_UNONAME_ERRORBAR_Y : CHART_UNONAME_ERRORBAR_X ) >>= xResult );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+uno::Reference< beans::XPropertySet > lcl_GetDefaultErrorBar()
+{
+ return uno::Reference< beans::XPropertySet >( new ::chart::ErrorBar );
+}
+
+void lcl_getErrorValues( const uno::Reference< beans::XPropertySet > & xErrorBarProp,
+ double & rOutPosError, double & rOutNegError )
+{
+ if( ! xErrorBarProp.is())
+ return;
+
+ try
+ {
+ xErrorBarProp->getPropertyValue( "PositiveError" ) >>= rOutPosError;
+ xErrorBarProp->getPropertyValue( "NegativeError" ) >>= rOutNegError;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void lcl_getErrorIndicatorValues(
+ const uno::Reference< beans::XPropertySet > & xErrorBarProp,
+ bool & rOutShowPosError, bool & rOutShowNegError )
+{
+ if( ! xErrorBarProp.is())
+ return;
+
+ try
+ {
+ xErrorBarProp->getPropertyValue( "ShowPositiveError" ) >>= rOutShowPosError;
+ xErrorBarProp->getPropertyValue( "ShowNegativeError" ) >>= rOutShowNegError;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+uno::Reference< beans::XPropertySet > lcl_getEquationProperties(
+ const uno::Reference< beans::XPropertySet > & xSeriesPropSet, const SfxItemSet * pItemSet )
+{
+ bool bEquationExists = true;
+
+ // ensure that a trendline is on
+ if( pItemSet )
+ {
+ if( const SvxChartRegressItem* pRegressionItem = pItemSet->GetItemIfSet( SCHATTR_REGRESSION_TYPE ) )
+ {
+ SvxChartRegress eRegress = pRegressionItem->GetValue();
+ bEquationExists = ( eRegress != SvxChartRegress::NONE );
+ }
+ }
+
+ if( bEquationExists )
+ {
+ uno::Reference< chart2::XRegressionCurveContainer > xRegCnt( xSeriesPropSet, uno::UNO_QUERY );
+ rtl::Reference< ::chart::RegressionCurveModel > xCurve =
+ ::chart::RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCnt );
+ if( xCurve.is())
+ {
+ return xCurve->getEquationProperties();
+ }
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+uno::Reference< beans::XPropertySet > lcl_getCurveProperties(
+ const uno::Reference< beans::XPropertySet > & xSeriesPropSet, const SfxItemSet * pItemSet )
+{
+ bool bExists = true;
+
+ // ensure that a trendline is on
+ if( pItemSet )
+ {
+ if( const SvxChartRegressItem* pRegressionItem = pItemSet->GetItemIfSet( SCHATTR_REGRESSION_TYPE ) )
+ {
+ SvxChartRegress eRegress = pRegressionItem->GetValue();
+ bExists = ( eRegress != SvxChartRegress::NONE );
+ }
+ }
+
+ if( bExists )
+ {
+ uno::Reference< chart2::XRegressionCurveContainer > xRegCnt( xSeriesPropSet, uno::UNO_QUERY );
+ uno::Reference< chart2::XRegressionCurve > xCurve(
+ ::chart::RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCnt ));
+ if( xCurve.is())
+ {
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+ return xProperties;
+ }
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+template <class T, class D>
+bool lclConvertToPropertySet(const SfxItemSet& rItemSet, sal_uInt16 nWhichId, const uno::Reference<beans::XPropertySet>& xProperties, const OUString& aPropertyID)
+{
+ OSL_ASSERT(xProperties.is());
+ if( xProperties.is() )
+ {
+ T aValue = static_cast<T>(static_cast<const D&>(rItemSet.Get( nWhichId )).GetValue());
+ T aOldValue = aValue;
+ bool aSuccess = xProperties->getPropertyValue( aPropertyID ) >>= aOldValue;
+ if (!aSuccess || aOldValue != aValue)
+ {
+ xProperties->setPropertyValue( aPropertyID , uno::Any( aValue ));
+ return true;
+ }
+ }
+ return false;
+}
+
+template <class T, class D>
+void lclConvertToItemSet(SfxItemSet& rItemSet, sal_uInt16 nWhichId, const uno::Reference<beans::XPropertySet>& xProperties, const OUString& aPropertyID)
+{
+ OSL_ASSERT(xProperties.is());
+ if( xProperties.is() )
+ {
+ T aValue = static_cast<T>(static_cast<const D&>(rItemSet.Get( nWhichId )).GetValue());
+ if(xProperties->getPropertyValue( aPropertyID ) >>= aValue)
+ {
+ rItemSet.Put(D( nWhichId, aValue ));
+ }
+ }
+}
+
+void lclConvertToItemSetDouble(SfxItemSet& rItemSet, TypedWhichId<SvxDoubleItem> nWhichId, const uno::Reference<beans::XPropertySet>& xProperties, const OUString& aPropertyID)
+{
+ OSL_ASSERT(xProperties.is());
+ if( xProperties.is() )
+ {
+ double aValue = rItemSet.Get( nWhichId ).GetValue();
+ if(xProperties->getPropertyValue( aPropertyID ) >>= aValue)
+ {
+ rItemSet.Put(SvxDoubleItem( aValue, nWhichId ));
+ }
+ }
+}
+
+} // anonymous namespace
+
+namespace chart::wrapper
+{
+
+StatisticsItemConverter::StatisticsItemConverter(
+ rtl::Reference<::chart::ChartModel> xModel,
+ const uno::Reference< beans::XPropertySet > & rPropertySet,
+ SfxItemPool& rItemPool ) :
+ ItemConverter( rPropertySet, rItemPool ),
+ m_xModel(std::move( xModel ))
+{
+}
+
+StatisticsItemConverter::~StatisticsItemConverter()
+{
+}
+
+const WhichRangesContainer& StatisticsItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nStatWhichPairs;
+}
+
+bool StatisticsItemConverter::GetItemProperty(
+ tWhichIdType /* nWhichId */,
+ tPropertyNameWithMemberId & /* rOutProperty */ ) const
+{
+ return false;
+}
+
+bool StatisticsItemConverter::ApplySpecialItem(
+ sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
+{
+ bool bChanged = false;
+
+ switch( nWhichId )
+ {
+ case SCHATTR_STAT_AVERAGE:
+ {
+ uno::Reference< chart2::XRegressionCurveContainer > xRegCnt(
+ GetPropertySet(), uno::UNO_QUERY );
+ bool bOldHasMeanValueLine = RegressionCurveHelper::hasMeanValueLine( xRegCnt );
+
+ bool bNewHasMeanValueLine =
+ static_cast< const SfxBoolItem & >( rItemSet.Get( nWhichId )).GetValue();
+
+ if( bOldHasMeanValueLine != bNewHasMeanValueLine )
+ {
+ if( ! bNewHasMeanValueLine )
+ RegressionCurveHelper::removeMeanValueLine( xRegCnt );
+ else
+ RegressionCurveHelper::addMeanValueLine( xRegCnt, GetPropertySet() );
+ bChanged = true;
+ }
+ }
+ break;
+
+ // Attention !!! This case must be passed before SCHATTR_STAT_PERCENT,
+ // SCHATTR_STAT_BIGERROR, SCHATTR_STAT_CONSTPLUS,
+ // SCHATTR_STAT_CONSTMINUS and SCHATTR_STAT_INDICATE
+ case SCHATTR_STAT_KIND_ERROR:
+ {
+ bool bYError =
+ rItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+
+ uno::Reference< beans::XPropertySet > xErrorBarProp(
+ lcl_GetErrorBar( GetPropertySet(), bYError ));
+
+ SvxChartKindError eErrorKind =
+ static_cast< const SvxChartKindErrorItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+
+ if( !xErrorBarProp.is() && eErrorKind == SvxChartKindError::NONE)
+ {
+ //nothing to do
+ }
+ else
+ {
+ sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
+
+ switch( eErrorKind )
+ {
+ case SvxChartKindError::NONE:
+ nStyle = css::chart::ErrorBarStyle::NONE; break;
+ case SvxChartKindError::Variant:
+ nStyle = css::chart::ErrorBarStyle::VARIANCE; break;
+ case SvxChartKindError::Sigma:
+ nStyle = css::chart::ErrorBarStyle::STANDARD_DEVIATION; break;
+ case SvxChartKindError::Percent:
+ nStyle = css::chart::ErrorBarStyle::RELATIVE; break;
+ case SvxChartKindError::BigError:
+ nStyle = css::chart::ErrorBarStyle::ERROR_MARGIN; break;
+ case SvxChartKindError::Const:
+ nStyle = css::chart::ErrorBarStyle::ABSOLUTE; break;
+ case SvxChartKindError::StdError:
+ nStyle = css::chart::ErrorBarStyle::STANDARD_ERROR; break;
+ case SvxChartKindError::Range:
+ nStyle = css::chart::ErrorBarStyle::FROM_DATA; break;
+ }
+
+ if( !xErrorBarProp.is() )
+ {
+ xErrorBarProp = lcl_GetDefaultErrorBar();
+ GetPropertySet()->setPropertyValue( bYError ? CHART_UNONAME_ERRORBAR_Y : CHART_UNONAME_ERRORBAR_X,
+ uno::Any( xErrorBarProp ));
+ }
+
+ xErrorBarProp->setPropertyValue( "ErrorBarStyle" , uno::Any( nStyle ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_PERCENT:
+ case SCHATTR_STAT_BIGERROR:
+ {
+ OSL_FAIL( "Deprecated item" );
+ bool bYError =
+ rItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+
+ uno::Reference< beans::XPropertySet > xErrorBarProp(
+ lcl_GetErrorBar( GetPropertySet(), bYError));
+ bool bOldHasErrorBar = xErrorBarProp.is();
+
+ double fValue =
+ static_cast< const SvxDoubleItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
+
+ if( bOldHasErrorBar &&
+ ! ( ::rtl::math::approxEqual( fPos, fValue ) &&
+ ::rtl::math::approxEqual( fNeg, fValue )))
+ {
+ xErrorBarProp->setPropertyValue( "PositiveError" , uno::Any( fValue ));
+ xErrorBarProp->setPropertyValue( "NegativeError" , uno::Any( fValue ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_CONSTPLUS:
+ {
+ bool bYError =
+ rItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+
+ uno::Reference< beans::XPropertySet > xErrorBarProp(
+ lcl_GetErrorBar( GetPropertySet(),bYError));
+ bool bOldHasErrorBar = xErrorBarProp.is();
+
+ double fValue =
+ static_cast< const SvxDoubleItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
+
+ if( bOldHasErrorBar &&
+ ! ::rtl::math::approxEqual( fPos, fValue ))
+ {
+ xErrorBarProp->setPropertyValue( "PositiveError" , uno::Any( fValue ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_CONSTMINUS:
+ {
+ bool bYError =
+ rItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+ uno::Reference< beans::XPropertySet > xErrorBarProp(
+ lcl_GetErrorBar( GetPropertySet(),bYError));
+ bool bOldHasErrorBar = xErrorBarProp.is();
+
+ double fValue =
+ static_cast< const SvxDoubleItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
+
+ if( bOldHasErrorBar &&
+ ! ::rtl::math::approxEqual( fNeg, fValue ))
+ {
+ xErrorBarProp->setPropertyValue( "NegativeError" , uno::Any( fValue ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_REGRESSION_TYPE:
+ {
+ SvxChartRegress eRegress =
+ static_cast< const SvxChartRegressItem& >(
+ rItemSet.Get( nWhichId )).GetValue();
+
+ uno::Reference< chart2::XRegressionCurve > xCurve( GetPropertySet(), uno::UNO_QUERY );
+ uno::Reference< chart2::XRegressionCurveContainer > xContainer( GetPropertySet(), uno::UNO_QUERY );
+
+ if( eRegress == SvxChartRegress::NONE )
+ {
+ if ( xContainer.is() )
+ {
+ xContainer->removeRegressionCurve( xCurve );
+ bChanged = true;
+ }
+ }
+ else
+ {
+ if ( xCurve.is() )
+ {
+ SvxChartRegress eOldRegress(
+ RegressionCurveHelper::getRegressionType(xCurve));
+
+ if( eOldRegress != eRegress )
+ {
+ xCurve = RegressionCurveHelper::changeRegressionCurveType(
+ eRegress,
+ xContainer,
+ xCurve);
+ uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY );
+ resetPropertySet( xProperties );
+ bChanged = true;
+ }
+ }
+ }
+ }
+ break;
+
+ case SCHATTR_REGRESSION_DEGREE:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<sal_Int32, SfxInt32Item>(rItemSet, nWhichId, xProperties, "PolynomialDegree");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_PERIOD:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<sal_Int32, SfxInt32Item>(rItemSet, nWhichId, xProperties, "MovingAveragePeriod");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_MOVING_TYPE:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<sal_Int32, SfxInt32Item>(rItemSet, nWhichId, xProperties, "MovingAverageType");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<double, SvxDoubleItem>(rItemSet, nWhichId, xProperties, "ExtrapolateForward");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<double, SvxDoubleItem>(rItemSet, nWhichId, xProperties, "ExtrapolateBackward");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SET_INTERCEPT:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<bool, SfxBoolItem>(rItemSet, nWhichId, xProperties, "ForceIntercept");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_INTERCEPT_VALUE:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<double, SvxDoubleItem>(rItemSet, nWhichId, xProperties, "InterceptValue");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_CURVE_NAME:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<OUString, SfxStringItem>(rItemSet, nWhichId, xProperties, "CurveName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SHOW_EQUATION:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<bool, SfxBoolItem>(rItemSet, nWhichId, xEqProp, "ShowEquation");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_XNAME:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<OUString, SfxStringItem>(rItemSet, nWhichId, xEqProp, "XName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_YNAME:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<OUString, SfxStringItem>(rItemSet, nWhichId, xEqProp, "YName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SHOW_COEFF:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), &rItemSet ));
+ bChanged = lclConvertToPropertySet<bool, SfxBoolItem>(rItemSet, nWhichId, xEqProp, "ShowCorrelationCoefficient");
+ }
+ break;
+
+ case SCHATTR_STAT_INDICATE:
+ {
+ bool bYError =
+ rItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+ uno::Reference< beans::XPropertySet > xErrorBarProp(
+ lcl_GetErrorBar( GetPropertySet(),bYError));
+ bool bOldHasErrorBar = xErrorBarProp.is();
+
+ SvxChartIndicate eIndicate =
+ static_cast< const SvxChartIndicateItem & >(
+ rItemSet.Get( nWhichId )).GetValue();
+
+ bool bNewIndPos = (eIndicate == SvxChartIndicate::Both || eIndicate == SvxChartIndicate::Up );
+ bool bNewIndNeg = (eIndicate == SvxChartIndicate::Both || eIndicate == SvxChartIndicate::Down );
+
+ bool bShowPos(false), bShowNeg(false);
+ lcl_getErrorIndicatorValues( xErrorBarProp, bShowPos, bShowNeg );
+
+ if( bOldHasErrorBar &&
+ ( bShowPos != bNewIndPos ||
+ bShowNeg != bNewIndNeg ))
+ {
+ xErrorBarProp->setPropertyValue( "ShowPositiveError" , uno::Any( bNewIndPos ));
+ xErrorBarProp->setPropertyValue( "ShowNegativeError" , uno::Any( bNewIndNeg ));
+ bChanged = true;
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_RANGE_POS:
+ case SCHATTR_STAT_RANGE_NEG:
+ {
+ const bool bYError =
+ rItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+ uno::Reference< chart2::data::XDataSource > xErrorBarSource( lcl_GetErrorBar( GetPropertySet(), bYError),
+ uno::UNO_QUERY );
+ uno::Reference< chart2::data::XDataProvider > xDataProvider;
+
+ if( m_xModel.is())
+ xDataProvider.set( m_xModel->getDataProvider());
+ if( xErrorBarSource.is() && xDataProvider.is())
+ {
+ OUString aNewRange( static_cast< const SfxStringItem & >( rItemSet.Get( nWhichId )).GetValue());
+ bool bApplyNewRange = false;
+
+ bool bIsPositiveValue( nWhichId == SCHATTR_STAT_RANGE_POS );
+ if( m_xModel->hasInternalDataProvider())
+ {
+ if( !aNewRange.isEmpty())
+ {
+ uno::Reference< chart2::data::XDataSequence > xSeq(
+ StatisticsHelper::getErrorDataSequenceFromDataSource(
+ xErrorBarSource, bIsPositiveValue, bYError ));
+ if( ! xSeq.is())
+ {
+ // no data range for error bars yet => create
+ uno::Reference< chart2::XInternalDataProvider > xIntDataProvider( xDataProvider, uno::UNO_QUERY );
+ OSL_ASSERT( xIntDataProvider.is());
+ if( xIntDataProvider.is())
+ {
+ xIntDataProvider->appendSequence();
+ aNewRange = "last";
+ bApplyNewRange = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ uno::Reference< chart2::data::XDataSequence > xSeq(
+ StatisticsHelper::getErrorDataSequenceFromDataSource(
+ xErrorBarSource, bIsPositiveValue, bYError ));
+ bApplyNewRange =
+ ! ( xSeq.is() && (aNewRange == xSeq->getSourceRangeRepresentation()));
+ }
+
+ if( bApplyNewRange )
+ StatisticsHelper::setErrorDataSequence(
+ xErrorBarSource, xDataProvider, aNewRange, bIsPositiveValue, bYError );
+ }
+ }
+ break;
+ }
+
+ return bChanged;
+}
+
+void StatisticsItemConverter::FillSpecialItem(
+ sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
+{
+ switch( nWhichId )
+ {
+ case SCHATTR_STAT_AVERAGE:
+ rOutItemSet.Put(
+ SfxBoolItem( nWhichId,
+ RegressionCurveHelper::hasMeanValueLine(
+ uno::Reference< chart2::XRegressionCurveContainer >(
+ GetPropertySet(), uno::UNO_QUERY ))));
+ break;
+
+ case SCHATTR_STAT_KIND_ERROR:
+ {
+ bool bYError =
+ rOutItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+ SvxChartKindError eErrorKind = SvxChartKindError::NONE;
+ uno::Reference< beans::XPropertySet > xErrorBarProp(
+ lcl_GetErrorBar( GetPropertySet(), bYError));
+ if( xErrorBarProp.is() )
+ {
+ sal_Int32 nStyle = 0;
+ if( xErrorBarProp->getPropertyValue( "ErrorBarStyle" ) >>= nStyle )
+ {
+ switch( nStyle )
+ {
+ case css::chart::ErrorBarStyle::NONE:
+ break;
+ case css::chart::ErrorBarStyle::VARIANCE:
+ eErrorKind = SvxChartKindError::Variant; break;
+ case css::chart::ErrorBarStyle::STANDARD_DEVIATION:
+ eErrorKind = SvxChartKindError::Sigma; break;
+ case css::chart::ErrorBarStyle::ABSOLUTE:
+ eErrorKind = SvxChartKindError::Const; break;
+ case css::chart::ErrorBarStyle::RELATIVE:
+ eErrorKind = SvxChartKindError::Percent; break;
+ case css::chart::ErrorBarStyle::ERROR_MARGIN:
+ eErrorKind = SvxChartKindError::BigError; break;
+ case css::chart::ErrorBarStyle::STANDARD_ERROR:
+ eErrorKind = SvxChartKindError::StdError; break;
+ case css::chart::ErrorBarStyle::FROM_DATA:
+ eErrorKind = SvxChartKindError::Range; break;
+ }
+ }
+ }
+ rOutItemSet.Put( SvxChartKindErrorItem( eErrorKind, SCHATTR_STAT_KIND_ERROR ));
+ }
+ break;
+
+ case SCHATTR_STAT_PERCENT:
+ {
+ bool bYError =
+ rOutItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+ uno::Reference< beans::XPropertySet > xErrorBarProp( lcl_GetErrorBar( GetPropertySet(),bYError));
+ if( xErrorBarProp.is())
+ {
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
+ rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, SCHATTR_STAT_PERCENT ));
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_BIGERROR:
+ {
+ bool bYError =
+ rOutItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+ uno::Reference< beans::XPropertySet > xErrorBarProp( lcl_GetErrorBar( GetPropertySet(),bYError));
+ if( xErrorBarProp.is())
+ {
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
+ rOutItemSet.Put( SvxDoubleItem( ( fPos + fNeg ) / 2.0, SCHATTR_STAT_BIGERROR ));
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_CONSTPLUS:
+ {
+ bool bYError =
+ rOutItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+ uno::Reference< beans::XPropertySet > xErrorBarProp( lcl_GetErrorBar( GetPropertySet(),bYError));
+ if( xErrorBarProp.is())
+ {
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
+ rOutItemSet.Put( SvxDoubleItem( fPos, SCHATTR_STAT_CONSTPLUS ));
+ }
+ }
+ break;
+
+ case SCHATTR_STAT_CONSTMINUS:
+ {
+ bool bYError =
+ rOutItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+ uno::Reference< beans::XPropertySet > xErrorBarProp( lcl_GetErrorBar( GetPropertySet(),bYError));
+ if( xErrorBarProp.is())
+ {
+ double fPos(0.0), fNeg(0.0);
+ lcl_getErrorValues( xErrorBarProp, fPos, fNeg );
+ rOutItemSet.Put( SvxDoubleItem( fNeg, SCHATTR_STAT_CONSTMINUS ));
+ }
+ }
+ break;
+
+ case SCHATTR_REGRESSION_TYPE:
+ {
+ SvxChartRegress eRegress =
+ RegressionCurveHelper::getFirstRegressTypeNotMeanValueLine(
+ uno::Reference< chart2::XRegressionCurveContainer >(
+ GetPropertySet(), uno::UNO_QUERY ) );
+ rOutItemSet.Put( SvxChartRegressItem( eRegress, SCHATTR_REGRESSION_TYPE ));
+ }
+ break;
+
+ case SCHATTR_REGRESSION_DEGREE:
+ {
+
+ uno::Reference<beans::XPropertySet> xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSet<sal_Int32, SfxInt32Item>(rOutItemSet, nWhichId, xProperties, "PolynomialDegree");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_PERIOD:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSet<sal_Int32, SfxInt32Item>(rOutItemSet, nWhichId, xProperties, "MovingAveragePeriod");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_MOVING_TYPE:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSet<sal_Int32, SfxInt32Item>(rOutItemSet, nWhichId, xProperties, "MovingAverageType");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSetDouble(rOutItemSet, SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD, xProperties, "ExtrapolateForward");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSetDouble(rOutItemSet, SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD, xProperties, "ExtrapolateBackward");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SET_INTERCEPT:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSet<bool, SfxBoolItem>(rOutItemSet, nWhichId, xProperties, "ForceIntercept");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_INTERCEPT_VALUE:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSetDouble(rOutItemSet, SCHATTR_REGRESSION_INTERCEPT_VALUE, xProperties, "InterceptValue");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_CURVE_NAME:
+ {
+ uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSet<OUString, SfxStringItem>(rOutItemSet, nWhichId, xProperties, "CurveName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SHOW_EQUATION:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSet<bool, SfxBoolItem>(rOutItemSet, nWhichId, xEqProp, "ShowEquation");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_XNAME:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSet<OUString, SfxStringItem>(rOutItemSet, nWhichId, xEqProp, "XName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_YNAME:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSet<OUString, SfxStringItem>(rOutItemSet, nWhichId, xEqProp, "YName");
+ }
+ break;
+
+ case SCHATTR_REGRESSION_SHOW_COEFF:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), nullptr ));
+ lclConvertToItemSet<bool, SfxBoolItem>(rOutItemSet, nWhichId, xEqProp, "ShowCorrelationCoefficient");
+ }
+ break;
+
+ case SCHATTR_STAT_INDICATE:
+ {
+ bool bYError =
+ rOutItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+ uno::Reference< beans::XPropertySet > xErrorBarProp( lcl_GetErrorBar( GetPropertySet(),bYError));
+ SvxChartIndicate eIndicate = SvxChartIndicate::Both;
+ if( xErrorBarProp.is())
+ {
+ bool bShowPos(false), bShowNeg(false);
+ lcl_getErrorIndicatorValues( xErrorBarProp, bShowPos, bShowNeg );
+
+ if( bShowPos )
+ {
+ if( bShowNeg )
+ eIndicate = SvxChartIndicate::Both;
+ else
+ eIndicate = SvxChartIndicate::Up;
+ }
+ else
+ {
+ if( bShowNeg )
+ eIndicate = SvxChartIndicate::Down;
+ else
+ eIndicate = SvxChartIndicate::NONE;
+ }
+ }
+ rOutItemSet.Put( SvxChartIndicateItem( eIndicate, SCHATTR_STAT_INDICATE ));
+ }
+ break;
+
+ case SCHATTR_STAT_RANGE_POS:
+ case SCHATTR_STAT_RANGE_NEG:
+ {
+ bool bYError =
+ rOutItemSet.Get(SCHATTR_STAT_ERRORBAR_TYPE).GetValue();
+ uno::Reference< chart2::data::XDataSource > xErrorBarSource( lcl_GetErrorBar( GetPropertySet(),bYError),
+ uno::UNO_QUERY );
+ if( xErrorBarSource.is())
+ {
+ uno::Reference< chart2::data::XDataSequence > xSeq(
+ StatisticsHelper::getErrorDataSequenceFromDataSource(
+ xErrorBarSource, (nWhichId == SCHATTR_STAT_RANGE_POS), bYError ));
+ if( xSeq.is())
+ rOutItemSet.Put( SfxStringItem( nWhichId, xSeq->getSourceRangeRepresentation()));
+ }
+ }
+ break;
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx b/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx
new file mode 100644
index 0000000000..4d2e6749f1
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/TextLabelItemConverter.cxx
@@ -0,0 +1,723 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TextLabelItemConverter.hxx>
+#include <CharacterPropertyItemConverter.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ItemPropertyMap.hxx>
+#include "SchWhichPairs.hxx"
+#include <unonames.hxx>
+
+#include <editeng/brushitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/ilstitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/stritem.hxx>
+#include <svx/tabline.hxx>
+#include <svx/sdangitm.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <vcl/graph.hxx>
+#include <rtl/math.hxx>
+
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <memory>
+
+using namespace com::sun::star;
+using namespace com::sun::star::chart2;
+using com::sun::star::uno::Reference;
+
+namespace chart::wrapper {
+
+namespace {
+
+const ItemPropertyMapType& getTextLabelPropertyMap()
+{
+ static ItemPropertyMapType aMap{
+ {XATTR_LINESTYLE, {CHART_UNONAME_LABEL_BORDER_STYLE, 0}},
+ {XATTR_LINEWIDTH, {CHART_UNONAME_LABEL_BORDER_WIDTH, 0}},
+ {XATTR_LINEDASH, {CHART_UNONAME_LABEL_BORDER_DASH, 0}},
+ {XATTR_LINECOLOR, {CHART_UNONAME_LABEL_BORDER_COLOR, 0}},
+ {XATTR_LINETRANSPARENCE, {CHART_UNONAME_LABEL_BORDER_TRANS, 0}}};
+ return aMap;
+};
+
+sal_Int32 getSymbolStyleForSymbol( const chart2::Symbol& rSymbol )
+{
+ sal_Int32 nStyle = SVX_SYMBOLTYPE_UNKNOWN;
+ switch (rSymbol.Style)
+ {
+ case chart2::SymbolStyle_NONE:
+ nStyle = SVX_SYMBOLTYPE_NONE;
+ break;
+ case chart2::SymbolStyle_AUTO:
+ nStyle = SVX_SYMBOLTYPE_AUTO;
+ break;
+ case chart2::SymbolStyle_GRAPHIC:
+ nStyle = SVX_SYMBOLTYPE_BRUSHITEM;
+ break;
+ case chart2::SymbolStyle_STANDARD:
+ nStyle = rSymbol.StandardSymbol;
+ break;
+ case chart2::SymbolStyle_POLYGON:
+ default:
+ ;
+ }
+ return nStyle;
+}
+
+bool numberFormatFromItemToPropertySet(
+ sal_uInt16 nWhichId, const SfxItemSet& rItemSet, const uno::Reference<beans::XPropertySet>& xPropertySet,
+ bool bOverwriteDataPoints )
+{
+ bool bChanged = false;
+ if (!xPropertySet.is())
+ return bChanged;
+
+ OUString aPropertyName = (nWhichId == SID_ATTR_NUMBERFORMAT_VALUE) ? CHART_UNONAME_NUMFMT : OUString("PercentageNumberFormat");
+ sal_uInt16 nSourceWhich = (nWhichId == SID_ATTR_NUMBERFORMAT_VALUE) ? SID_ATTR_NUMBERFORMAT_SOURCE : SCHATTR_PERCENT_NUMBERFORMAT_SOURCE;
+
+ if (rItemSet.GetItemState(nSourceWhich) != SfxItemState::SET)
+ return bChanged;
+
+ uno::Any aValue;
+ bool bUseSourceFormat = static_cast<const SfxBoolItem&>(rItemSet.Get(nSourceWhich)).GetValue();
+ if (!bUseSourceFormat)
+ {
+ SfxItemState aState = rItemSet.GetItemState(nWhichId);
+ if (aState == SfxItemState::SET)
+ {
+ sal_Int32 nFmt = static_cast<sal_Int32>(
+ static_cast<const SfxUInt32Item&>(
+ rItemSet.Get(nWhichId)).GetValue());
+ aValue <<= nFmt;
+ }
+ else
+ return bChanged;
+ }
+
+ uno::Any aOldValue = xPropertySet->getPropertyValue(aPropertyName);
+ if (bOverwriteDataPoints)
+ {
+ rtl::Reference<DataSeries> xSeries( dynamic_cast<DataSeries*>(xPropertySet.get()) );
+ if (aValue != aOldValue ||
+ ::chart::DataSeriesHelper::hasAttributedDataPointDifferentValue(xSeries, aPropertyName, aOldValue))
+ {
+ ::chart::DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(xSeries, aPropertyName, aValue);
+ bChanged = true;
+ }
+ }
+ else if (aOldValue != aValue)
+ {
+ xPropertySet->setPropertyValue(aPropertyName, aValue);
+ bChanged = true;
+ }
+ return bChanged;
+}
+
+bool useSourceFormatFromItemToPropertySet(
+ sal_uInt16 nWhichId, const SfxItemSet& rItemSet, const uno::Reference<beans::XPropertySet>& xPropertySet,
+ bool bOverwriteDataPoints )
+{
+ bool bChanged = false;
+ if (!xPropertySet.is())
+ return bChanged;
+ OUString aPropertyName = (nWhichId == SID_ATTR_NUMBERFORMAT_SOURCE) ? CHART_UNONAME_NUMFMT : OUString("PercentageNumberFormat");
+ sal_uInt16 nFormatWhich = (nWhichId == SID_ATTR_NUMBERFORMAT_SOURCE) ? SID_ATTR_NUMBERFORMAT_VALUE : SCHATTR_PERCENT_NUMBERFORMAT_VALUE;
+
+ if (rItemSet.GetItemState(nWhichId) != SfxItemState::SET)
+ return bChanged;
+
+ uno::Any aNewValue;
+ bool bUseSourceFormat = static_cast<const SfxBoolItem&>(
+ rItemSet.Get(nWhichId)).GetValue();
+ xPropertySet->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(bUseSourceFormat));
+ if (!bUseSourceFormat)
+ {
+ SfxItemState aState = rItemSet.GetItemState(nFormatWhich);
+ if (aState == SfxItemState::SET)
+ {
+ sal_Int32 nFormatKey = static_cast<sal_Int32>(
+ static_cast<const SfxUInt32Item&>(
+ rItemSet.Get(nFormatWhich)).GetValue());
+ aNewValue <<= nFormatKey;
+ }
+ else
+ return bChanged;
+ }
+
+ uno::Any aOldValue(xPropertySet->getPropertyValue(aPropertyName));
+ if (bOverwriteDataPoints)
+ {
+ rtl::Reference<DataSeries> xSeries(dynamic_cast<DataSeries*>(xPropertySet.get()));
+ if (aNewValue != aOldValue ||
+ ::chart::DataSeriesHelper::hasAttributedDataPointDifferentValue(xSeries, aPropertyName, aOldValue))
+ {
+ ::chart::DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(xSeries, aPropertyName, aNewValue);
+ bChanged = true;
+ }
+ }
+ else if (aOldValue != aNewValue)
+ {
+ xPropertySet->setPropertyValue(aPropertyName, aNewValue);
+ bChanged = true;
+ }
+
+ return bChanged;
+}
+
+} // anonymous namespace
+
+TextLabelItemConverter::TextLabelItemConverter(
+ const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const uno::Reference<beans::XPropertySet>& rPropertySet,
+ const rtl::Reference<DataSeries>& xSeries,
+ SfxItemPool& rItemPool, const awt::Size* pRefSize,
+ bool bDataSeries, sal_Int32 nNumberFormat, sal_Int32 nPercentNumberFormat ) :
+ ItemConverter(rPropertySet, rItemPool),
+ mnNumberFormat(nNumberFormat),
+ mnPercentNumberFormat(nPercentNumberFormat),
+ mbDataSeries(bDataSeries),
+ mbForbidPercentValue(true),
+ m_xSeries(xSeries)
+{
+ maConverters.emplace_back(new CharacterPropertyItemConverter(rPropertySet, rItemPool, pRefSize, "ReferencePageSize"));
+
+ rtl::Reference< Diagram > xDiagram(xChartModel->getFirstChartDiagram());
+ rtl::Reference< ChartType > xChartType(xDiagram->getChartTypeOfSeries(xSeries));
+ bool bFound = false;
+ bool bAmbiguous = false;
+ bool bSwapXAndY = xDiagram->getVertical(bFound, bAmbiguous);
+ maAvailableLabelPlacements = ChartTypeHelper::getSupportedLabelPlacements(xChartType, bSwapXAndY, xSeries);
+
+ mbForbidPercentValue = ChartTypeHelper::getAxisType(xChartType, 0) != AxisType::CATEGORY;
+}
+
+TextLabelItemConverter::~TextLabelItemConverter()
+{
+}
+
+void TextLabelItemConverter::FillItemSet( SfxItemSet& rOutItemSet ) const
+{
+ for( const auto& pConv : maConverters )
+ pConv->FillItemSet( rOutItemSet );
+
+ // own items
+ ItemConverter::FillItemSet(rOutItemSet);
+}
+
+bool TextLabelItemConverter::ApplyItemSet( const SfxItemSet& rItemSet )
+{
+ bool bResult = false;
+
+ for( const auto& pConv: maConverters )
+ bResult = pConv->ApplyItemSet( rItemSet ) || bResult;
+
+ // own items
+ return ItemConverter::ApplyItemSet(rItemSet) || bResult;
+}
+
+const WhichRangesContainer& TextLabelItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nTextLabelWhichPairs;
+}
+
+bool TextLabelItemConverter::GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId& rOutProperty ) const
+{
+ const ItemPropertyMapType& rMap = getTextLabelPropertyMap();
+ ItemPropertyMapType::const_iterator it = rMap.find(nWhichId);
+
+ if (it == rMap.end())
+ return false;
+
+ rOutProperty = it->second;
+ return true;
+}
+
+bool TextLabelItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet& rItemSet )
+{
+ bool bChanged = false;
+
+ switch (nWhichId)
+ {
+ case SCHATTR_DATADESCR_SHOW_NUMBER:
+ case SCHATTR_DATADESCR_SHOW_PERCENTAGE:
+ case SCHATTR_DATADESCR_SHOW_CATEGORY:
+ case SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME:
+ case SCHATTR_DATADESCR_SHOW_SYMBOL:
+ {
+ const SfxBoolItem& rItem = static_cast<const SfxBoolItem&>(rItemSet.Get(nWhichId));
+
+ uno::Any aOldValue = GetPropertySet()->getPropertyValue(CHART_UNONAME_LABEL);
+ chart2::DataPointLabel aLabel;
+ if (aOldValue >>= aLabel)
+ {
+ sal_Bool& rValue = (nWhichId == SCHATTR_DATADESCR_SHOW_NUMBER) ? aLabel.ShowNumber : (
+ (nWhichId == SCHATTR_DATADESCR_SHOW_PERCENTAGE) ? aLabel.ShowNumberInPercent : (
+ (nWhichId == SCHATTR_DATADESCR_SHOW_CATEGORY) ? aLabel.ShowCategoryName :
+ (nWhichId == SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME) ? aLabel.ShowSeriesName : aLabel.ShowLegendSymbol));
+ bool bOldValue = rValue;
+ rValue = rItem.GetValue();
+ if (mbDataSeries)
+ {
+ rtl::Reference<DataSeries> xSeries(dynamic_cast<DataSeries*>(GetPropertySet().get()));
+ if (bOldValue != bool(rValue) ||
+ DataSeriesHelper::hasAttributedDataPointDifferentValue(xSeries, CHART_UNONAME_LABEL, aOldValue))
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(xSeries, CHART_UNONAME_LABEL, uno::Any(aLabel));
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(xSeries, CHART_UNONAME_CUSTOM_LABEL_FIELDS, uno::Any());
+ bChanged = true;
+ }
+ }
+ else if (bOldValue != bool(rValue))
+ {
+ GetPropertySet()->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabel));
+ bChanged = true;
+ }
+ }
+ }
+ break;
+ case SID_ATTR_NUMBERFORMAT_VALUE:
+ case SCHATTR_PERCENT_NUMBERFORMAT_VALUE: //fall through intended
+ {
+ bChanged = numberFormatFromItemToPropertySet(nWhichId, rItemSet, GetPropertySet(), mbDataSeries);
+ }
+ break;
+ case SID_ATTR_NUMBERFORMAT_SOURCE:
+ case SCHATTR_PERCENT_NUMBERFORMAT_SOURCE: //fall through intended
+ {
+ bChanged = useSourceFormatFromItemToPropertySet(nWhichId, rItemSet, GetPropertySet(), mbDataSeries);
+ }
+ break;
+ case SCHATTR_DATADESCR_SEPARATOR:
+ {
+ OUString aNewValue = static_cast<const SfxStringItem&>(rItemSet.Get(nWhichId)).GetValue();
+ try
+ {
+ OUString aOldValue;
+ GetPropertySet()->getPropertyValue("LabelSeparator") >>= aOldValue;
+ if (mbDataSeries)
+ {
+ rtl::Reference<DataSeries> xSeries(dynamic_cast<DataSeries*>(GetPropertySet().get()));
+ if (aOldValue != aNewValue ||
+ DataSeriesHelper::hasAttributedDataPointDifferentValue(xSeries, "LabelSeparator", uno::Any(aOldValue)))
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(xSeries, "LabelSeparator", uno::Any(aNewValue));
+ bChanged = true;
+ }
+ }
+ else if (aOldValue != aNewValue)
+ {
+ GetPropertySet()->setPropertyValue("LabelSeparator", uno::Any(aNewValue));
+ bChanged = true;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ }
+ break;
+ case SCHATTR_DATADESCR_WRAP_TEXT:
+ {
+
+ try
+ {
+ bool bNew = static_cast< const SfxBoolItem & >( rItemSet.Get( nWhichId )).GetValue();
+ bool bOld = false;
+ GetPropertySet()->getPropertyValue( "TextWordWrap" ) >>= bOld;
+ if( mbDataSeries )
+ {
+ rtl::Reference< DataSeries > xSeries( dynamic_cast<DataSeries*>(GetPropertySet().get()) );
+ if( bOld!=bNew ||
+ DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries, "TextWordWrap", uno::Any( bOld ) ) )
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "TextWordWrap", uno::Any( bNew ) );
+ bChanged = true;
+ }
+ }
+ else if( bOld!=bNew )
+ {
+ GetPropertySet()->setPropertyValue( "TextWordWrap", uno::Any( bNew ));
+ bChanged = true;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+ case SCHATTR_DATADESCR_PLACEMENT:
+ {
+ try
+ {
+ sal_Int32 nNew = static_cast<const SfxInt32Item&>(rItemSet.Get(nWhichId)).GetValue();
+ sal_Int32 nOld = -1;
+ RelativePosition aCustomLabelPosition;
+ GetPropertySet()->getPropertyValue("LabelPlacement") >>= nOld;
+ if (mbDataSeries)
+ {
+ rtl::Reference<DataSeries> xSeries(dynamic_cast<DataSeries*>(GetPropertySet().get()));
+ if (nOld != nNew ||
+ DataSeriesHelper::hasAttributedDataPointDifferentValue(xSeries, "LabelPlacement", uno::Any(nOld)))
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(xSeries, "LabelPlacement", uno::Any(nNew));
+ bChanged = true;
+ }
+ }
+ else if (nOld != nNew || (GetPropertySet()->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition))
+ {
+ GetPropertySet()->setPropertyValue("LabelPlacement", uno::Any(nNew));
+ GetPropertySet()->setPropertyValue("CustomLabelPosition", uno::Any());
+ bChanged = true;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+ case SCHATTR_STYLE_SYMBOL:
+ {
+ sal_Int32 nStyle =
+ static_cast<const SfxInt32Item&>(
+ rItemSet.Get(nWhichId)).GetValue();
+ chart2::Symbol aSymbol;
+
+ GetPropertySet()->getPropertyValue("Symbol") >>= aSymbol;
+ sal_Int32 nOldStyle = getSymbolStyleForSymbol(aSymbol);
+
+ if (nStyle != nOldStyle)
+ {
+ bool bDeleteSymbol = false;
+ switch (nStyle)
+ {
+ case SVX_SYMBOLTYPE_NONE:
+ aSymbol.Style = chart2::SymbolStyle_NONE;
+ break;
+ case SVX_SYMBOLTYPE_AUTO:
+ aSymbol.Style = chart2::SymbolStyle_AUTO;
+ break;
+ case SVX_SYMBOLTYPE_BRUSHITEM:
+ aSymbol.Style = chart2::SymbolStyle_GRAPHIC;
+ break;
+ case SVX_SYMBOLTYPE_UNKNOWN:
+ bDeleteSymbol = true;
+ break;
+
+ default:
+ aSymbol.Style = chart2::SymbolStyle_STANDARD;
+ aSymbol.StandardSymbol = nStyle;
+ }
+
+ if (bDeleteSymbol)
+ GetPropertySet()->setPropertyValue("Symbol", uno::Any());
+ else
+ GetPropertySet()->setPropertyValue("Symbol", uno::Any(aSymbol));
+ bChanged = true;
+ }
+ }
+ break;
+ case SCHATTR_SYMBOL_SIZE:
+ {
+ Size aSize = static_cast<const SvxSizeItem&>(
+ rItemSet.Get(nWhichId)).GetSize();
+ chart2::Symbol aSymbol;
+
+ GetPropertySet()->getPropertyValue("Symbol") >>= aSymbol;
+ if (aSize.getWidth() != aSymbol.Size.Width ||
+ aSize.getHeight() != aSymbol.Size.Height)
+ {
+ aSymbol.Size.Width = aSize.getWidth();
+ aSymbol.Size.Height = aSize.getHeight();
+
+ GetPropertySet()->setPropertyValue("Symbol", uno::Any(aSymbol));
+ bChanged = true;
+ }
+ }
+ break;
+ case SCHATTR_SYMBOL_BRUSH:
+ {
+ const SvxBrushItem& rBrshItem(static_cast<const SvxBrushItem&>(
+ rItemSet.Get(nWhichId)));
+ uno::Any aXGraphicAny;
+ const Graphic* pGraphic(rBrshItem.GetGraphic());
+ if (pGraphic)
+ {
+ uno::Reference<graphic::XGraphic> xGraphic(pGraphic->GetXGraphic());
+ if (xGraphic.is())
+ {
+ aXGraphicAny <<= xGraphic;
+ chart2::Symbol aSymbol;
+ GetPropertySet()->getPropertyValue("Symbol") >>= aSymbol;
+ if (aSymbol.Graphic != xGraphic)
+ {
+ aSymbol.Graphic = xGraphic;
+ GetPropertySet()->setPropertyValue("Symbol", uno::Any(aSymbol));
+ bChanged = true;
+ }
+ }
+ }
+ }
+ break;
+ case SCHATTR_TEXT_DEGREES:
+ {
+ double fValue = static_cast<double>(
+ static_cast<const SdrAngleItem&>(
+ rItemSet.Get(nWhichId)).GetValue().get()) / 100.0;
+ double fOldValue = 0.0;
+ bool bPropExisted =
+ (GetPropertySet()->getPropertyValue("TextRotation") >>= fOldValue);
+
+ if (!bPropExisted || fOldValue != fValue)
+ {
+ GetPropertySet()->setPropertyValue("TextRotation", uno::Any(fValue));
+ bChanged = true;
+ }
+ }
+ break;
+ case SCHATTR_DATADESCR_CUSTOM_LEADER_LINES:
+ {
+ try
+ {
+ bool bNew = static_cast<const SfxBoolItem&>(rItemSet.Get(nWhichId)).GetValue();
+ bool bOld = true;
+ if( (m_xSeries->getPropertyValue("ShowCustomLeaderLines") >>= bOld) && bOld != bNew )
+ {
+ m_xSeries->setPropertyValue("ShowCustomLeaderLines", uno::Any(bNew));
+ bChanged = true;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ }
+ break;
+ }
+
+ return bChanged;
+}
+
+void TextLabelItemConverter::FillSpecialItem( sal_uInt16 nWhichId, SfxItemSet& rOutItemSet ) const
+{
+ switch (nWhichId)
+ {
+ case SCHATTR_DATADESCR_SHOW_NUMBER:
+ case SCHATTR_DATADESCR_SHOW_PERCENTAGE:
+ case SCHATTR_DATADESCR_SHOW_CATEGORY:
+ case SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME:
+ case SCHATTR_DATADESCR_SHOW_SYMBOL:
+ {
+ chart2::DataPointLabel aLabel;
+ if (GetPropertySet()->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel)
+ {
+ bool bValue = (nWhichId == SCHATTR_DATADESCR_SHOW_NUMBER) ? aLabel.ShowNumber : (
+ (nWhichId == SCHATTR_DATADESCR_SHOW_PERCENTAGE) ? aLabel.ShowNumberInPercent : (
+ (nWhichId == SCHATTR_DATADESCR_SHOW_CATEGORY) ? aLabel.ShowCategoryName : (
+ (nWhichId == SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME) ? aLabel.ShowSeriesName : aLabel.ShowLegendSymbol)));
+
+ rOutItemSet.Put(SfxBoolItem(nWhichId, bValue));
+
+ if (mbDataSeries)
+ {
+ if (DataSeriesHelper::hasAttributedDataPointDifferentValue(
+ dynamic_cast<DataSeries*>(GetPropertySet().get()), CHART_UNONAME_LABEL, uno::Any(aLabel)))
+ {
+ rOutItemSet.InvalidateItem(nWhichId);
+ }
+ }
+ }
+ }
+ break;
+ case SID_ATTR_NUMBERFORMAT_VALUE:
+ {
+ sal_Int32 nKey = 0;
+ if (!(GetPropertySet()->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nKey))
+ nKey = mnNumberFormat;
+ rOutItemSet.Put(SfxUInt32Item(nWhichId, nKey));
+ }
+ break;
+ case SCHATTR_PERCENT_NUMBERFORMAT_VALUE:
+ {
+ sal_Int32 nKey = 0;
+ if (!(GetPropertySet()->getPropertyValue("PercentageNumberFormat") >>= nKey))
+ nKey = mnPercentNumberFormat;
+ rOutItemSet.Put(SfxUInt32Item(nWhichId, nKey));
+ }
+ break;
+ case SID_ATTR_NUMBERFORMAT_SOURCE:
+ {
+ bool bUseSourceFormat = false;
+ try
+ {
+ GetPropertySet()->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bUseSourceFormat;
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ bool bNumberFormatIsSet = GetPropertySet()->getPropertyValue(CHART_UNONAME_NUMFMT).hasValue() && !bUseSourceFormat;
+ rOutItemSet.Put(SfxBoolItem(nWhichId, !bNumberFormatIsSet));
+ }
+ break;
+ case SCHATTR_PERCENT_NUMBERFORMAT_SOURCE:
+ {
+ bool bUseSourceFormat = false;
+ try
+ {
+ GetPropertySet()->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bUseSourceFormat;
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ bool bNumberFormatIsSet = GetPropertySet()->getPropertyValue("PercentageNumberFormat").hasValue() && !bUseSourceFormat;
+ rOutItemSet.Put(SfxBoolItem(nWhichId, !bNumberFormatIsSet));
+ }
+ break;
+ case SCHATTR_DATADESCR_SEPARATOR:
+ {
+ try
+ {
+ OUString aValue;
+ GetPropertySet()->getPropertyValue("LabelSeparator") >>= aValue;
+ rOutItemSet.Put(SfxStringItem(nWhichId, aValue));
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+ case SCHATTR_DATADESCR_WRAP_TEXT:
+ {
+ try
+ {
+ bool bValue = false;
+ GetPropertySet()->getPropertyValue( "TextWordWrap" ) >>= bValue;
+ rOutItemSet.Put( SfxBoolItem( nWhichId, bValue ));
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+ case SCHATTR_DATADESCR_PLACEMENT:
+ {
+ try
+ {
+ sal_Int32 nPlacement = 0;
+ RelativePosition aCustomLabelPosition;
+ if (!mbDataSeries && (GetPropertySet()->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition))
+ rOutItemSet.Put(SfxInt32Item(nWhichId, css::chart::DataLabelPlacement::CUSTOM));
+ else if (GetPropertySet()->getPropertyValue("LabelPlacement") >>= nPlacement)
+ rOutItemSet.Put(SfxInt32Item(nWhichId, nPlacement));
+ else if (maAvailableLabelPlacements.hasElements())
+ rOutItemSet.Put(SfxInt32Item(nWhichId, maAvailableLabelPlacements[0]));
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ break;
+ case SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS:
+ {
+ rOutItemSet.Put(SfxIntegerListItem(nWhichId, maAvailableLabelPlacements));
+ }
+ break;
+ case SCHATTR_DATADESCR_NO_PERCENTVALUE:
+ {
+ rOutItemSet.Put(SfxBoolItem(nWhichId, mbForbidPercentValue));
+ }
+ break;
+ case SCHATTR_DATADESCR_CUSTOM_LEADER_LINES:
+ {
+ try
+ {
+ bool bValue = true;
+ if( m_xSeries->getPropertyValue( "ShowCustomLeaderLines" ) >>= bValue )
+ rOutItemSet.Put(SfxBoolItem(nWhichId, bValue));
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ }
+ break;
+ case SCHATTR_STYLE_SYMBOL:
+ {
+ chart2::Symbol aSymbol;
+ if (GetPropertySet()->getPropertyValue("Symbol") >>= aSymbol)
+ rOutItemSet.Put(SfxInt32Item(nWhichId, getSymbolStyleForSymbol(aSymbol)));
+ }
+ break;
+ case SCHATTR_SYMBOL_SIZE:
+ {
+ chart2::Symbol aSymbol;
+ if (GetPropertySet()->getPropertyValue("Symbol") >>= aSymbol)
+ rOutItemSet.Put(
+ SvxSizeItem(nWhichId, Size(aSymbol.Size.Width, aSymbol.Size.Height)));
+ }
+ break;
+ case SCHATTR_SYMBOL_BRUSH:
+ {
+ chart2::Symbol aSymbol;
+ if ((GetPropertySet()->getPropertyValue("Symbol") >>= aSymbol)
+ && aSymbol.Graphic.is())
+ {
+ rOutItemSet.Put(
+ SvxBrushItem(Graphic(aSymbol.Graphic), GPOS_MM, SCHATTR_SYMBOL_BRUSH));
+ }
+ }
+ break;
+ case SCHATTR_TEXT_DEGREES:
+ {
+ double fValue = 0;
+
+ if (GetPropertySet()->getPropertyValue("TextRotation") >>= fValue)
+ {
+ rOutItemSet.Put(
+ SdrAngleItem(SCHATTR_TEXT_DEGREES, Degree100(static_cast<sal_Int32>(rtl::math::round(fValue * 100.0)))));
+ }
+ }
+ break;
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/itemsetwrapper/TitleItemConverter.cxx b/chart2/source/controller/itemsetwrapper/TitleItemConverter.cxx
new file mode 100644
index 0000000000..7a3f57af57
--- /dev/null
+++ b/chart2/source/controller/itemsetwrapper/TitleItemConverter.cxx
@@ -0,0 +1,210 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TitleItemConverter.hxx>
+#include "SchWhichPairs.hxx"
+#include <ItemPropertyMap.hxx>
+#include <GraphicPropertyItemConverter.hxx>
+#include <CharacterPropertyItemConverter.hxx>
+#include <MultipleItemConverter.hxx>
+#include <svx/sdangitm.hxx>
+#include <rtl/math.hxx>
+
+#include <com/sun/star/chart2/XTitle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+namespace chart::wrapper {
+
+namespace {
+
+ItemPropertyMapType & lcl_GetTitlePropertyMap()
+{
+ static ItemPropertyMapType aTitlePropertyMap{
+ {SCHATTR_TEXT_STACKED, {"StackCharacters", 0}}};
+ return aTitlePropertyMap;
+};
+
+class FormattedStringsConverter : public MultipleItemConverter
+{
+public:
+ FormattedStringsConverter(
+ const uno::Sequence< uno::Reference< chart2::XFormattedString > > & aStrings,
+ SfxItemPool & rItemPool,
+ const awt::Size* pRefSize,
+ const uno::Reference< beans::XPropertySet > & xParentProp );
+
+protected:
+ virtual const WhichRangesContainer& GetWhichPairs() const override;
+};
+
+} // anonymous namespace
+
+FormattedStringsConverter::FormattedStringsConverter(
+ const uno::Sequence< uno::Reference< chart2::XFormattedString > > & aStrings,
+ SfxItemPool & rItemPool,
+ const awt::Size* pRefSize,
+ const uno::Reference< beans::XPropertySet > & xParentProp ) :
+ MultipleItemConverter( rItemPool )
+{
+ bool bHasRefSize = (pRefSize && xParentProp.is());
+ for( uno::Reference< chart2::XFormattedString > const & formattedStr : aStrings )
+ {
+ uno::Reference< beans::XPropertySet > xProp( formattedStr, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ if( bHasRefSize )
+ m_aConverters.emplace_back(
+ new CharacterPropertyItemConverter(
+ xProp, rItemPool, pRefSize, "ReferencePageSize", xParentProp));
+ else
+ m_aConverters.emplace_back( new CharacterPropertyItemConverter( xProp, rItemPool ));
+ }
+ }
+}
+
+const WhichRangesContainer& FormattedStringsConverter::GetWhichPairs() const
+{
+ return nCharacterPropertyWhichPairs;
+}
+
+TitleItemConverter::TitleItemConverter(
+ const uno::Reference<beans::XPropertySet> & rPropertySet,
+ SfxItemPool& rItemPool,
+ SdrModel& rDrawModel,
+ const uno::Reference< lang::XMultiServiceFactory > & xNamedPropertyContainerFactory,
+ const awt::Size* pRefSize ) :
+ ItemConverter( rPropertySet, rItemPool )
+{
+ m_aConverters.emplace_back( new GraphicPropertyItemConverter(
+ rPropertySet, rItemPool, rDrawModel,
+ xNamedPropertyContainerFactory,
+ GraphicObjectType::LineAndFillProperties ));
+
+ // CharacterProperties are not at the title but at its contained XFormattedString objects
+ // take the first formatted string in the sequence
+ uno::Reference< chart2::XTitle > xTitle( rPropertySet, uno::UNO_QUERY );
+ if( xTitle.is())
+ {
+ uno::Sequence< uno::Reference< chart2::XFormattedString > > aStringSeq( xTitle->getText());
+ if( aStringSeq.hasElements() )
+ {
+ m_aConverters.emplace_back(
+ new FormattedStringsConverter( aStringSeq, rItemPool, pRefSize, rPropertySet ));
+ }
+ }
+}
+
+TitleItemConverter::~TitleItemConverter()
+{
+}
+
+void TitleItemConverter::FillItemSet( SfxItemSet & rOutItemSet ) const
+{
+ for( const auto& pConv : m_aConverters )
+ pConv->FillItemSet( rOutItemSet );
+
+ // own items
+ ItemConverter::FillItemSet( rOutItemSet );
+}
+
+bool TitleItemConverter::ApplyItemSet( const SfxItemSet & rItemSet )
+{
+ bool bResult = false;
+
+ for( const auto& pConv : m_aConverters )
+ bResult = pConv->ApplyItemSet( rItemSet ) || bResult;
+
+ // own items
+ return ItemConverter::ApplyItemSet( rItemSet ) || bResult;
+}
+
+const WhichRangesContainer& TitleItemConverter::GetWhichPairs() const
+{
+ // must span all used items!
+ return nTitleWhichPairs;
+}
+
+bool TitleItemConverter::GetItemProperty( tWhichIdType nWhichId, tPropertyNameWithMemberId & rOutProperty ) const
+{
+ ItemPropertyMapType & rMap( lcl_GetTitlePropertyMap());
+ ItemPropertyMapType::const_iterator aIt( rMap.find( nWhichId ));
+
+ if( aIt == rMap.end())
+ return false;
+
+ rOutProperty =(*aIt).second;
+ return true;
+}
+
+bool TitleItemConverter::ApplySpecialItem(
+ sal_uInt16 nWhichId, const SfxItemSet & rItemSet )
+{
+ bool bChanged = false;
+
+ switch( nWhichId )
+ {
+ case SCHATTR_TEXT_DEGREES:
+ {
+ // convert int to double (divided by 100)
+ double fVal = static_cast< double >(
+ static_cast< const SdrAngleItem & >(
+ rItemSet.Get( nWhichId )).GetValue().get()) / 100.0;
+ double fOldVal = 0.0;
+ bool bPropExisted =
+ ( GetPropertySet()->getPropertyValue( "TextRotation" ) >>= fOldVal );
+
+ if( ! bPropExisted || fOldVal != fVal )
+ {
+ GetPropertySet()->setPropertyValue( "TextRotation" , uno::Any( fVal ));
+ bChanged = true;
+ }
+ }
+ break;
+ }
+
+ return bChanged;
+}
+
+void TitleItemConverter::FillSpecialItem(
+ sal_uInt16 nWhichId, SfxItemSet & rOutItemSet ) const
+{
+ switch( nWhichId )
+ {
+ case SCHATTR_TEXT_DEGREES:
+ {
+ // convert double to int (times 100)
+ double fVal = 0;
+
+ if( GetPropertySet()->getPropertyValue( "TextRotation" ) >>= fVal )
+ {
+ rOutItemSet.Put( SdrAngleItem( SCHATTR_TEXT_DEGREES, Degree100(static_cast< sal_Int32 >(
+ ::rtl::math::round( fVal * 100.0 ) ) )));
+ }
+ }
+ break;
+ }
+}
+
+} // namespace chart::wrapper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartController.cxx b/chart2/source/controller/main/ChartController.cxx
new file mode 100644
index 0000000000..666d6b6367
--- /dev/null
+++ b/chart2/source/controller/main/ChartController.cxx
@@ -0,0 +1,1655 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <sal/config.h>
+
+#include <config_wasm_strip.h>
+#include <ChartController.hxx>
+#include <ChartView.hxx>
+#include <servicenames.hxx>
+#include <ResId.hxx>
+#include <dlg_DataSource.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include "ControllerCommandDispatch.hxx"
+#include <DataSeries.hxx>
+#include <Diagram.hxx>
+#include <strings.hrc>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <ChartViewHelper.hxx>
+
+#include <ChartWindow.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <DrawViewWrapper.hxx>
+#include <ObjectIdentifier.hxx>
+#include <DiagramHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include "UndoGuard.hxx"
+#include "ChartDropTargetHelper.hxx"
+
+#include <dlg_ChartType.hxx>
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+#include <AccessibleChartView.hxx>
+#endif
+#include "DrawCommandDispatch.hxx"
+#include "ShapeController.hxx"
+#include "UndoActions.hxx"
+#include <ViewElementListProvider.hxx>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <BaseCoordinateSystem.hxx>
+
+#include <com/sun/star/awt/XVclWindowPeer.hpp>
+#include <com/sun/star/frame/XController2.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <com/sun/star/util/XModeChangeBroadcaster.hpp>
+#include <com/sun/star/frame/LayoutManagerEvents.hpp>
+#include <com/sun/star/frame/XLayoutManagerEventBroadcaster.hpp>
+#include <com/sun/star/ui/XSidebar.hpp>
+#include <com/sun/star/chart2/XDataProviderAccess.hpp>
+#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
+
+#include <sal/log.hxx>
+#include <tools/debug.hxx>
+#include <svx/sidebar/SelectionChangeHandler.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <osl/mutex.hxx>
+#include <comphelper/lok.hxx>
+
+#include <sfx2/sidebar/SidebarController.hxx>
+
+#include <com/sun/star/frame/XLayoutManager.hpp>
+
+// this is needed to properly destroy the unique_ptr to the AcceleratorExecute
+// object in the DTOR
+#include <svtools/acceleratorexecute.hxx>
+#include <svx/ActionDescriptionProvider.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+// enable the following define to let the controller listen to model changes and
+// react on this by rebuilding the view
+#define TEST_ENABLE_MODIFY_LISTENER
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+ChartController::ChartController(uno::Reference<uno::XComponentContext> xContext) :
+ m_aLifeTimeManager( nullptr ),
+ m_bSuspended( false ),
+ m_xCC(std::move(xContext)),
+ m_aModel( nullptr, m_aModelMutex ),
+ m_eDragMode(SdrDragMode::Move),
+ m_aDoubleClickTimer("chart2 ChartController m_aDoubleClickTimer"),
+ m_bWaitingForDoubleClick(false),
+ m_bWaitingForMouseUp(false),
+ m_bFieldButtonDown(false),
+ m_bConnectingToView(false),
+ m_bDisposed(false),
+ m_aDispatchContainer( m_xCC ),
+ m_eDrawMode( CHARTDRAW_SELECT ),
+ mpSelectionChangeHandler(new svx::sidebar::SelectionChangeHandler(
+ [this]() { return this->GetContextName(); },
+ this, vcl::EnumContext::Context::Cell))
+{
+ m_aDoubleClickTimer.SetInvokeHandler( LINK( this, ChartController, DoubleClickWaitingHdl ) );
+}
+
+ChartController::~ChartController()
+{
+ stopDoubleClickWaiting();
+}
+
+ChartController::TheModel::TheModel( rtl::Reference<::chart::ChartModel> xModel ) :
+ m_xModel(std::move( xModel )),
+ m_bOwnership( true )
+{
+}
+
+ChartController::TheModel::~TheModel()
+{
+}
+
+void ChartController::TheModel::addListener( ChartController* pController )
+{
+ if(m_xModel)
+ {
+ //if you need to be able to veto against the destruction of the model
+ // you must add as a close listener
+
+ //otherwise you 'can' add as closelistener or 'must' add as dispose event listener
+
+ m_xModel->addCloseListener(
+ static_cast<util::XCloseListener*>(pController) );
+ }
+}
+
+void ChartController::TheModel::removeListener( ChartController* pController )
+{
+ if(m_xModel)
+ m_xModel->removeCloseListener(
+ static_cast<util::XCloseListener*>(pController) );
+}
+
+void ChartController::TheModel::tryTermination()
+{
+ if(!m_bOwnership)
+ return;
+
+ try
+ {
+ if(m_xModel.is())
+ {
+ try
+ {
+ //@todo ? are we allowed to use sal_True here if we have the explicit ownership?
+ //I think yes, because there might be other CloseListeners later in the list which might be interested still
+ //but make sure that we do not throw the CloseVetoException here ourselves
+ //so stop listening before trying to terminate or check the source of queryclosing event
+ m_xModel->close(true);
+
+ m_bOwnership = false;
+ }
+ catch( const util::CloseVetoException& )
+ {
+ //since we have indicated to give up the ownership with parameter true in close call
+ //the one who has thrown the CloseVetoException is the new owner
+
+ SAL_WARN_IF( m_bOwnership, "chart2.main", "a well known owner has caught a CloseVetoException after calling close(true)");
+ m_bOwnership = false;
+ return;
+ }
+
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION( "chart2", "Termination of model failed" );
+ }
+}
+
+ChartController::TheModelRef::TheModelRef( TheModel* pTheModel, osl::Mutex& rMutex ) :
+ m_rModelMutex(rMutex)
+{
+ osl::Guard< osl::Mutex > aGuard( m_rModelMutex );
+ m_xTheModel = pTheModel;
+}
+ChartController::TheModelRef::TheModelRef( const TheModelRef& rTheModel, ::osl::Mutex& rMutex ) :
+ m_rModelMutex(rMutex)
+{
+ osl::Guard< osl::Mutex > aGuard( m_rModelMutex );
+ m_xTheModel = rTheModel.m_xTheModel;
+}
+ChartController::TheModelRef& ChartController::TheModelRef::operator=(TheModel* pTheModel)
+{
+ osl::Guard< osl::Mutex > aGuard( m_rModelMutex );
+ m_xTheModel = pTheModel;
+ return *this;
+}
+ChartController::TheModelRef& ChartController::TheModelRef::operator=(const TheModelRef& rTheModel)
+{
+ osl::Guard< osl::Mutex > aGuard( m_rModelMutex );
+ m_xTheModel = rTheModel.operator->();
+ return *this;
+}
+ChartController::TheModelRef::~TheModelRef()
+{
+ osl::Guard< osl::Mutex > aGuard( m_rModelMutex );
+ m_xTheModel.clear();
+}
+bool ChartController::TheModelRef::is() const
+{
+ return m_xTheModel.is();
+}
+
+namespace {
+
+rtl::Reference<ChartType> getChartType(const rtl::Reference<ChartModel>& xChartDoc)
+{
+ rtl::Reference<Diagram > xDiagram = xChartDoc->getFirstChartDiagram();
+ if (!xDiagram.is())
+ return nullptr;
+
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & xCooSysSequence( xDiagram->getBaseCoordinateSystems());
+ if (xCooSysSequence.empty())
+ return nullptr;
+
+ return xCooSysSequence[0]->getChartTypes2()[0];
+}
+
+}
+
+OUString ChartController::GetContextName()
+{
+ if (m_bDisposed)
+ return OUString();
+
+ uno::Any aAny = getSelection();
+ if (!aAny.hasValue())
+ return "Chart";
+
+ OUString aCID;
+ aAny >>= aCID;
+
+ if (aCID.isEmpty())
+ return "Chart";
+
+ ObjectType eObjectID = ObjectIdentifier::getObjectType(aCID);
+ switch (eObjectID)
+ {
+ case OBJECTTYPE_DATA_SERIES:
+ return "Series";
+ case OBJECTTYPE_DATA_ERRORS_X:
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ return "ErrorBar";
+ case OBJECTTYPE_AXIS:
+ return "Axis";
+ case OBJECTTYPE_GRID:
+ return "Grid";
+ case OBJECTTYPE_DIAGRAM:
+ {
+ rtl::Reference<ChartType> xChartType = getChartType(getChartModel());
+ if (xChartType.is() && xChartType->getChartType() == "com.sun.star.chart2.PieChartType")
+ return "ChartElements";
+ break;
+ }
+ case OBJECTTYPE_DATA_CURVE:
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ return "Trendline";
+ default:
+ break;
+ }
+
+ return "Chart";
+}
+
+// private methods
+
+bool ChartController::impl_isDisposedOrSuspended() const
+{
+ if( m_aLifeTimeManager.impl_isDisposed() )
+ return true;
+
+ if( m_bSuspended )
+ {
+ OSL_FAIL( "This Controller is suspended" );
+ return true;
+ }
+ return false;
+}
+
+namespace {
+
+uno::Reference<ui::XSidebar> getSidebarFromModel(const uno::Reference<frame::XModel>& xModel)
+{
+ uno::Reference<container::XChild> xChild(xModel, uno::UNO_QUERY);
+ if (!xChild.is())
+ return nullptr;
+
+ uno::Reference<frame::XModel> xParent (xChild->getParent(), uno::UNO_QUERY);
+ if (!xParent.is())
+ return nullptr;
+
+ uno::Reference<frame::XController2> xController(xParent->getCurrentController(), uno::UNO_QUERY);
+ if (!xController.is())
+ return nullptr;
+
+ uno::Reference<ui::XSidebarProvider> xSidebarProvider = xController->getSidebar();
+ if (!xSidebarProvider.is())
+ return nullptr;
+
+ return xSidebarProvider->getSidebar();
+}
+
+}
+
+// XController
+
+void SAL_CALL ChartController::attachFrame(
+ const uno::Reference<frame::XFrame>& xFrame )
+{
+ SolarMutexGuard aGuard;
+
+ if( impl_isDisposedOrSuspended() ) //@todo? allow attaching the frame while suspended?
+ return; //behave passive if already disposed or suspended
+
+ if(m_xFrame.is()) //what happens, if we do have a Frame already??
+ {
+ //@todo? throw exception?
+ OSL_FAIL( "there is already a frame attached to the controller" );
+ return;
+ }
+
+ //--attach frame
+ m_xFrame = xFrame; //the frameloader is responsible to call xFrame->setComponent
+
+ // Only notify after setting the frame, otherwise notification will fail
+ mpSelectionChangeHandler->Connect();
+
+ uno::Reference<ui::XSidebar> xSidebar = getSidebarFromModel(getChartModel());
+ if (xSidebar.is())
+ {
+ auto pSidebar = dynamic_cast<sfx2::sidebar::SidebarController*>(xSidebar.get());
+ assert(pSidebar);
+ pSidebar->registerSidebarForFrame(this);
+ pSidebar->updateModel(getChartModel());
+ css::lang::EventObject aEvent;
+ mpSelectionChangeHandler->selectionChanged(aEvent);
+ }
+
+ //add as disposelistener to the frame (due to persistent reference) ??...:
+
+ //the frame is considered to be owner of this controller and will live longer than we do
+ //the frame or the disposer of the frame has the duty to call suspend and dispose on this object
+ //so we do not need to add as lang::XEventListener for DisposingEvents right?
+
+ //@todo nothing right???
+
+ //create view @todo is this the correct place here??
+
+ vcl::Window* pParent = nullptr;
+ //get the window parent from the frame to use as parent for our new window
+ if(xFrame.is())
+ {
+ uno::Reference<awt::XWindow> xContainerWindow = xFrame->getContainerWindow();
+ if (xContainerWindow)
+ xContainerWindow->setVisible(true);
+ pParent = VCLUnoHelper::GetWindow( xContainerWindow );
+ }
+
+ {
+ // calls to VCL
+ SolarMutexGuard aSolarGuard;
+ auto pChartWindow = VclPtr<ChartWindow>::Create(this,pParent,pParent?pParent->GetStyle():0);
+ pChartWindow->SetBackground();//no Background
+ m_xViewWindow.set( pChartWindow->GetComponentInterface(), uno::UNO_QUERY );
+ pChartWindow->Show();
+ m_apDropTargetHelper.reset(
+ new ChartDropTargetHelper( pChartWindow->GetDropTarget(), getChartModel()));
+
+ impl_createDrawViewController();
+ }
+
+ //create the menu
+ {
+ uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
+ if( xPropSet.is() )
+ {
+ try
+ {
+ uno::Reference< css::frame::XLayoutManager > xLayoutManager;
+ xPropSet->getPropertyValue( "LayoutManager" ) >>= xLayoutManager;
+ if ( xLayoutManager.is() )
+ {
+ xLayoutManager->lock();
+ xLayoutManager->requestElement( "private:resource/menubar/menubar" );
+ //@todo: createElement should become unnecessary, remove when #i79198# is fixed
+ xLayoutManager->createElement( "private:resource/toolbar/standardbar" );
+ xLayoutManager->requestElement( "private:resource/toolbar/standardbar" );
+ //@todo: createElement should become unnecessary, remove when #i79198# is fixed
+ xLayoutManager->createElement( "private:resource/toolbar/toolbar" );
+ xLayoutManager->requestElement( "private:resource/toolbar/toolbar" );
+
+ // #i12587# support for shapes in chart
+ xLayoutManager->createElement( "private:resource/toolbar/drawbar" );
+ xLayoutManager->requestElement( "private:resource/toolbar/drawbar" );
+
+ xLayoutManager->requestElement( "private:resource/statusbar/statusbar" );
+ xLayoutManager->unlock();
+
+ // add as listener to get notified when
+ m_xLayoutManagerEventBroadcaster.set( xLayoutManager, uno::UNO_QUERY );
+ if( m_xLayoutManagerEventBroadcaster.is())
+ m_xLayoutManagerEventBroadcaster->addLayoutManagerEventListener( this );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+}
+
+//XModeChangeListener
+void SAL_CALL ChartController::modeChanged( const util::ModeChangeEvent& rEvent )
+{
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+ //adjust controller to view status changes
+
+ if( rEvent.NewMode == "dirty" )
+ {
+ //the view has become dirty, we should repaint it if we have a window
+ if( pChartWindow )
+ pChartWindow->ForceInvalidate();
+ }
+ else if( rEvent.NewMode == "invalid" )
+ {
+ //the view is about to become invalid so end all actions on it
+ impl_invalidateAccessible();
+ if( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() )
+ this->EndTextEdit();
+ if( m_pDrawViewWrapper )
+ {
+ m_pDrawViewWrapper->UnmarkAll();
+ m_pDrawViewWrapper->HideSdrPage();
+ }
+ }
+ else
+ {
+ //the view was rebuild so we can start some actions on it again
+ if( !m_bConnectingToView )
+ {
+ if(pChartWindow && m_aModel.is() )
+ {
+ m_bConnectingToView = true;
+
+ GetDrawModelWrapper();
+ if(m_pDrawModelWrapper)
+ {
+ {
+ if( m_pDrawViewWrapper )
+ m_pDrawViewWrapper->ReInit();
+ }
+
+ //reselect object
+ if( m_aSelection.hasSelection() )
+ this->impl_selectObjectAndNotiy();
+ else
+ ChartModelHelper::triggerRangeHighlighting( getChartModel() );
+
+ impl_initializeAccessible();
+
+ {
+ if( pChartWindow )
+ pChartWindow->Invalidate();
+ }
+ }
+
+ m_bConnectingToView = false;
+ }
+ }
+ }
+}
+
+sal_Bool SAL_CALL ChartController::attachModel( const uno::Reference< frame::XModel > & xModel )
+{
+ impl_invalidateAccessible();
+
+ //is called to attach the controller to a new model.
+ //return true if attach was successfully, false otherwise (e.g. if you do not work with a model)
+
+ SolarMutexResettableGuard aGuard;
+ if( impl_isDisposedOrSuspended() ) //@todo? allow attaching a new model while suspended?
+ return false; //behave passive if already disposed or suspended
+ aGuard.clear();
+
+ ::chart::ChartModel* pChartModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
+ assert(!xModel || pChartModel);
+
+ TheModelRef aNewModelRef( new TheModel(pChartModel), m_aModelMutex);
+ TheModelRef aOldModelRef(m_aModel,m_aModelMutex);
+ m_aModel = aNewModelRef;
+
+ //--handle relations to the old model if any
+ if( aOldModelRef.is() )
+ {
+ if( m_xChartView.is() )
+ m_xChartView->removeModeChangeListener(this);
+ m_pDrawModelWrapper.reset();
+
+ aOldModelRef->removeListener( this );
+ #ifdef TEST_ENABLE_MODIFY_LISTENER
+ if( aOldModelRef->getModel().is())
+ aOldModelRef->getModel()->removeModifyListener( this );
+#endif
+ }
+
+ //--handle relations to the new model
+ aNewModelRef->addListener( this );
+
+ aGuard.reset(); // lock for m_aDispatchContainer access
+ // set new model at dispatchers
+ m_aDispatchContainer.setModel( aNewModelRef->getModel());
+ rtl::Reference<ControllerCommandDispatch> pDispatch = new ControllerCommandDispatch( m_xCC, this, &m_aDispatchContainer );
+ pDispatch->initialize();
+
+ // the dispatch container will return "this" for all commands returned by
+ // impl_getAvailableCommands(). That means, for those commands dispatch()
+ // is called here at the ChartController.
+ m_aDispatchContainer.setChartDispatch( pDispatch, o3tl::sorted_vector(impl_getAvailableCommands()) );
+
+ rtl::Reference<DrawCommandDispatch> pDrawDispatch = new DrawCommandDispatch( m_xCC, this );
+ pDrawDispatch->initialize();
+ m_aDispatchContainer.setDrawCommandDispatch( pDrawDispatch.get() );
+
+ rtl::Reference<ShapeController> pShapeController = new ShapeController( m_xCC, this );
+ pShapeController->initialize();
+ m_aDispatchContainer.setShapeController( pShapeController.get() );
+ aGuard.clear();
+
+#ifdef TEST_ENABLE_MODIFY_LISTENER
+ if( aNewModelRef->getModel().is())
+ aNewModelRef->getModel()->addModifyListener( this );
+#endif
+
+ // #i119999# Do not do this per default to allow the user to deselect the chart OLE with a single press to ESC
+ // select chart area per default:
+ // select( uno::Any( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) );
+
+ rtl::Reference< ChartModel > xFact = getChartModel();
+ if( xFact.is())
+ {
+ m_xChartView = dynamic_cast<::chart::ChartView*>(xFact->createInstance( CHART_VIEW_SERVICE_NAME ).get());
+ GetDrawModelWrapper();
+ m_xChartView->addModeChangeListener(this);
+ }
+
+ //the frameloader is responsible to call xModel->connectController
+ {
+ SolarMutexGuard aGuard2;
+ auto pChartWindow(GetChartWindow());
+ if( pChartWindow )
+ pChartWindow->Invalidate();
+ }
+
+ m_xUndoManager.set( getChartModel()->getUndoManager(), uno::UNO_SET_THROW );
+
+ return true;
+}
+
+uno::Reference< frame::XFrame > SAL_CALL ChartController::getFrame()
+{
+ //provides access to owner frame of this controller
+ //return the frame containing this controller
+
+ return m_xFrame;
+}
+
+uno::Reference< frame::XModel > SAL_CALL ChartController::getModel()
+{
+ return getChartModel();
+}
+
+rtl::Reference<::chart::ChartModel> ChartController::getChartModel()
+{
+ //provides access to currently attached model
+ //returns the currently attached model
+
+ //return nothing, if you do not have a model
+ TheModelRef aModelRef( m_aModel, m_aModelMutex);
+ if(aModelRef.is())
+ return aModelRef->getModel();
+
+ return nullptr;
+}
+
+rtl::Reference<::chart::Diagram> ChartController::getFirstDiagram()
+{
+ return getChartModel()->getFirstChartDiagram();
+}
+
+uno::Any SAL_CALL ChartController::getViewData()
+{
+ //provides access to current view status
+ //set of data that can be used to restore the current view status at later time
+ // by using XController::restoreViewData()
+
+ SolarMutexGuard aGuard;
+ if( impl_isDisposedOrSuspended() )
+ return uno::Any(); //behave passive if already disposed or suspended //@todo? or throw an exception??
+
+ //-- collect current view state
+ uno::Any aRet;
+ //// @todo integrate specialized implementation
+
+ return aRet;
+}
+
+void SAL_CALL ChartController::restoreViewData(
+ const uno::Any& /* Value */ )
+{
+ //restores the view status using the data gotten from a previous call to XController::getViewData()
+
+ SolarMutexGuard aGuard;
+ if( impl_isDisposedOrSuspended() )
+ return; //behave passive if already disposed or suspended //@todo? or throw an exception??
+
+ //// @todo integrate specialized implementation
+}
+
+sal_Bool SAL_CALL ChartController::suspend( sal_Bool bSuspend )
+{
+ //is called to prepare the controller for closing the view
+ //bSuspend==true: force the controller to suspend his work
+ //bSuspend==false try to reactivate the controller
+ //returns true if request was accepted and of course successfully finished, false otherwise
+
+ //we may show dialogs here to ask the user for saving changes ... @todo?
+
+ SolarMutexGuard aGuard;
+ if( m_aLifeTimeManager.impl_isDisposed() )
+ return false; //behave passive if already disposed, return false because request was not accepted //@todo? correct
+
+ if(bool(bSuspend) == m_bSuspended)
+ {
+ OSL_FAIL( "new suspend mode equals old suspend mode" );
+ return true;
+ }
+
+ //change suspend mode
+ m_bSuspended = bSuspend;
+ return true;
+}
+
+// css::frame::XController2
+
+css::uno::Reference<css::awt::XWindow> SAL_CALL ChartController::getComponentWindow()
+{
+ // it is a special characteristic of ChartController
+ // that it simultaneously provides the XWindow functionality
+ return this;
+}
+
+OUString SAL_CALL ChartController::getViewControllerName() { return {}; }
+
+css::uno::Sequence<css::beans::PropertyValue> SAL_CALL ChartController::getCreationArguments()
+{
+ return {};
+}
+
+css::uno::Reference<css::ui::XSidebarProvider> SAL_CALL ChartController::getSidebar() { return {}; }
+
+void ChartController::impl_createDrawViewController()
+{
+ SolarMutexGuard aGuard;
+ if(!m_pDrawViewWrapper)
+ {
+ if( m_pDrawModelWrapper )
+ {
+ bool bLokCalcGlobalRTL = false;
+ if(comphelper::LibreOfficeKit::isActive() && AllSettings::GetLayoutRTL())
+ {
+ rtl::Reference< ChartModel > xChartModel = getChartModel();
+ if (xChartModel.is())
+ {
+ uno::Reference<css::sheet::XSpreadsheetDocument> xSSDoc(xChartModel->getParent(), uno::UNO_QUERY);
+ if (xSSDoc.is())
+ bLokCalcGlobalRTL = true;
+ }
+ }
+
+ m_pDrawViewWrapper.reset( new DrawViewWrapper(m_pDrawModelWrapper->getSdrModel(),GetChartWindow()->GetOutDev()) );
+ m_pDrawViewWrapper->SetNegativeX(bLokCalcGlobalRTL);
+ m_pDrawViewWrapper->attachParentReferenceDevice( getChartModel() );
+ }
+ }
+}
+
+void ChartController::impl_deleteDrawViewController()
+{
+ if( m_pDrawViewWrapper )
+ {
+ SolarMutexGuard aGuard;
+ if( m_pDrawViewWrapper->IsTextEdit() )
+ this->EndTextEdit();
+ m_pDrawViewWrapper.reset();
+ }
+}
+
+// XComponent (base of XController)
+
+void SAL_CALL ChartController::dispose()
+{
+ m_bDisposed = true;
+
+ mpSelectionChangeHandler->selectionChanged(css::lang::EventObject());
+ mpSelectionChangeHandler->Disconnect();
+
+ if (getModel().is())
+ {
+ uno::Reference<ui::XSidebar> xSidebar = getSidebarFromModel(getChartModel());
+ if (sfx2::sidebar::SidebarController* pSidebar = dynamic_cast<sfx2::sidebar::SidebarController*>(xSidebar.get()))
+ {
+ pSidebar->unregisterSidebarForFrame(this);
+ }
+ }
+
+ try
+ {
+ //This object should release all resources and references in the
+ //easiest possible manner
+ //This object must notify all registered listeners using the method
+ //<member>XEventListener::disposing</member>
+
+ //hold no mutex
+ if( !m_aLifeTimeManager.dispose() )
+ return;
+
+// OSL_ENSURE( m_bSuspended, "dispose was called but controller is not suspended" );
+
+ this->stopDoubleClickWaiting();
+
+ //end range highlighting
+ if( m_aModel.is())
+ {
+ uno::Reference< view::XSelectionChangeListener > xSelectionChangeListener;
+ rtl::Reference< ChartModel > xDataReceiver = getChartModel();
+ if( xDataReceiver.is() )
+ xSelectionChangeListener.set( xDataReceiver->getRangeHighlighter(), uno::UNO_QUERY );
+ if( xSelectionChangeListener.is() )
+ {
+ uno::Reference< frame::XController > xController( this );
+ lang::EventObject aEvent( xController );
+ xSelectionChangeListener->disposing( aEvent );
+ }
+ }
+
+ //--release all resources and references
+ {
+ if( m_xChartView.is() )
+ m_xChartView->removeModeChangeListener(this);
+
+ impl_invalidateAccessible();
+ SolarMutexGuard aSolarGuard;
+ impl_deleteDrawViewController();
+ m_pDrawModelWrapper.reset();
+
+ m_apDropTargetHelper.reset();
+
+ //the accessible view is disposed within window destructor of m_pChartWindow
+ if(m_xViewWindow.is())
+ m_xViewWindow->dispose(); //ChartWindow is deleted via UNO due to dispose of m_xViewWindow (triggered by Framework (Controller pretends to be XWindow also))
+ m_xChartView.clear();
+ }
+
+ // remove as listener to layout manager events
+ if( m_xLayoutManagerEventBroadcaster.is())
+ {
+ m_xLayoutManagerEventBroadcaster->removeLayoutManagerEventListener( this );
+ m_xLayoutManagerEventBroadcaster.clear();
+ }
+
+ m_xFrame.clear();
+ m_xUndoManager.clear();
+
+ TheModelRef aModelRef( m_aModel, m_aModelMutex);
+ m_aModel = nullptr;
+
+ if( aModelRef.is())
+ {
+ uno::Reference< frame::XModel > xModel( aModelRef->getModel() );
+ if(xModel.is())
+ xModel->disconnectController( uno::Reference< frame::XController >( this ));
+
+ aModelRef->removeListener( this );
+#ifdef TEST_ENABLE_MODIFY_LISTENER
+ try
+ {
+ if( aModelRef->getModel().is())
+ aModelRef->getModel()->removeModifyListener( this );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+#endif
+ aModelRef->tryTermination();
+ }
+
+ //// @todo integrate specialized implementation
+ //e.g. release further resources and references
+
+ SolarMutexGuard g;
+ m_aDispatchContainer.DisposeAndClear();
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ assert(!m_xChartView.is());
+ }
+ }
+
+void SAL_CALL ChartController::addEventListener(
+ const uno::Reference<lang::XEventListener>& xListener )
+{
+ if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode?
+ return; //behave passive if already disposed or suspended
+
+ //--add listener
+ std::unique_lock aGuard2(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aEventListeners.addInterface( aGuard2, xListener );
+}
+
+void SAL_CALL ChartController::removeEventListener(
+ const uno::Reference<lang::XEventListener>& xListener )
+{
+ SolarMutexGuard aGuard;
+ if( m_aLifeTimeManager.impl_isDisposed(false) )
+ return; //behave passive if already disposed or suspended
+
+ //--remove listener
+ std::unique_lock aGuard2(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aEventListeners.removeInterface( aGuard2, xListener );
+}
+
+// util::XCloseListener
+void SAL_CALL ChartController::queryClosing(
+ const lang::EventObject& rSource,
+ sal_Bool /*bGetsOwnership*/ )
+{
+ //do not use the m_aControllerMutex here because this call is not allowed to block
+
+ TheModelRef aModelRef( m_aModel, m_aModelMutex);
+
+ if( !aModelRef.is() )
+ return;
+
+ if( uno::Reference<XInterface>(static_cast<cppu::OWeakObject*>(aModelRef->getModel().get())) != rSource.Source )
+ {
+ OSL_FAIL( "queryClosing was called on a controller from an unknown source" );
+ return;
+ }
+
+ //@ todo prepare to closing model -> don't start any further hindering actions
+}
+
+void SAL_CALL ChartController::notifyClosing(
+ const lang::EventObject& rSource )
+{
+ //Listener should deregister himself and release all references to the closing object.
+
+ TheModelRef aModelRef( m_aModel, m_aModelMutex);
+ if( !impl_releaseThisModel( rSource.Source ) )
+ return;
+
+ //--stop listening to the closing model
+ aModelRef->removeListener( this );
+
+ // #i79087# If the model using this controller is closed, the frame is
+ // expected to be closed as well
+ Reference< util::XCloseable > xFrameCloseable( m_xFrame, uno::UNO_QUERY );
+ if( xFrameCloseable.is())
+ {
+ try
+ {
+ xFrameCloseable->close( false /* DeliverOwnership */ );
+ m_xFrame.clear();
+ }
+ catch( const util::CloseVetoException & )
+ {
+ // closing was vetoed
+ }
+ }
+}
+
+bool ChartController::impl_releaseThisModel(
+ const uno::Reference< uno::XInterface > & xModel )
+{
+ bool bReleaseModel = false;
+ {
+ ::osl::Guard< ::osl::Mutex > aGuard( m_aModelMutex );
+ if( m_aModel.is() && uno::Reference< uno::XInterface >(static_cast<cppu::OWeakObject*>(m_aModel->getModel().get())) == xModel )
+ {
+ m_aModel = nullptr;
+ m_xUndoManager.clear();
+ bReleaseModel = true;
+ }
+ }
+ if( bReleaseModel )
+ {
+ SolarMutexGuard g;
+ m_aDispatchContainer.setModel( nullptr );
+ }
+ return bReleaseModel;
+}
+
+// util::XEventListener (base of XCloseListener)
+void SAL_CALL ChartController::disposing(
+ const lang::EventObject& rSource )
+{
+ if( !impl_releaseThisModel( rSource.Source ))
+ {
+ if( rSource.Source == m_xLayoutManagerEventBroadcaster )
+ m_xLayoutManagerEventBroadcaster.clear();
+ }
+}
+
+void SAL_CALL ChartController::layoutEvent(
+ const lang::EventObject& aSource,
+ sal_Int16 eLayoutEvent,
+ const uno::Any& /* aInfo */ )
+{
+ if( eLayoutEvent == frame::LayoutManagerEvents::MERGEDMENUBAR )
+ {
+ Reference< frame::XLayoutManager > xLM( aSource.Source, uno::UNO_QUERY );
+ if( xLM.is())
+ {
+ xLM->createElement( "private:resource/statusbar/statusbar" );
+ xLM->requestElement( "private:resource/statusbar/statusbar" );
+ }
+ }
+}
+
+// XDispatchProvider (required interface)
+
+namespace
+{
+
+bool lcl_isFormatObjectCommand( std::u16string_view aCommand )
+{
+ return aCommand == u"MainTitle"
+ || aCommand == u"SubTitle"
+ || aCommand == u"XTitle"
+ || aCommand == u"YTitle"
+ || aCommand == u"ZTitle"
+ || aCommand == u"SecondaryXTitle"
+ || aCommand == u"SecondaryYTitle"
+ || aCommand == u"AllTitles"
+ || aCommand == u"DiagramAxisX"
+ || aCommand == u"DiagramAxisY"
+ || aCommand == u"DiagramAxisZ"
+ || aCommand == u"DiagramAxisA"
+ || aCommand == u"DiagramAxisB"
+ || aCommand == u"DiagramAxisAll"
+ || aCommand == u"DiagramGridXMain"
+ || aCommand == u"DiagramGridYMain"
+ || aCommand == u"DiagramGridZMain"
+ || aCommand == u"DiagramGridXHelp"
+ || aCommand == u"DiagramGridYHelp"
+ || aCommand == u"DiagramGridZHelp"
+ || aCommand == u"DiagramGridAll"
+
+ || aCommand == u"DiagramWall"
+ || aCommand == u"DiagramFloor"
+ || aCommand == u"DiagramArea"
+ || aCommand == u"Legend"
+
+ || aCommand == u"FormatWall"
+ || aCommand == u"FormatFloor"
+ || aCommand == u"FormatChartArea"
+ || aCommand == u"FormatLegend"
+
+ || aCommand == u"FormatTitle"
+ || aCommand == u"FormatAxis"
+ || aCommand == u"FormatDataSeries"
+ || aCommand == u"FormatDataPoint"
+ || aCommand == u"FormatDataLabels"
+ || aCommand == u"FormatDataLabel"
+ || aCommand == u"FormatXErrorBars"
+ || aCommand == u"FormatYErrorBars"
+ || aCommand == u"FormatMeanValue"
+ || aCommand == u"FormatTrendline"
+ || aCommand == u"FormatTrendlineEquation"
+ || aCommand == u"FormatStockLoss"
+ || aCommand == u"FormatStockGain"
+ || aCommand == u"FormatMajorGrid"
+ || aCommand == u"FormatMinorGrid";
+}
+
+} // anonymous namespace
+
+uno::Reference<frame::XDispatch> SAL_CALL
+ ChartController::queryDispatch(
+ const util::URL& rURL,
+ const OUString& rTargetFrameName,
+ sal_Int32 /* nSearchFlags */)
+{
+ SolarMutexGuard aGuard;
+
+ if ( !m_aLifeTimeManager.impl_isDisposed() && getModel().is() )
+ {
+ if( !rTargetFrameName.isEmpty() && rTargetFrameName == "_self" )
+ return m_aDispatchContainer.getDispatchForURL( rURL );
+ }
+ return uno::Reference< frame::XDispatch > ();
+}
+
+uno::Sequence<uno::Reference<frame::XDispatch > >
+ ChartController::queryDispatches(
+ const uno::Sequence<frame::DispatchDescriptor>& xDescripts )
+{
+ SolarMutexGuard g;
+
+ if ( !m_aLifeTimeManager.impl_isDisposed() )
+ {
+ return m_aDispatchContainer.getDispatchesForURLs( xDescripts );
+ }
+ return uno::Sequence<uno::Reference<frame::XDispatch > > ();
+}
+
+// frame::XDispatch
+
+void SAL_CALL ChartController::dispatch(
+ const util::URL& rURL,
+ const uno::Sequence< beans::PropertyValue >& rArgs )
+{
+ OUString aCommand = rURL.Path;
+
+ if(aCommand == "LOKSetTextSelection")
+ {
+ if (rArgs.getLength() == 3)
+ {
+ sal_Int32 nType = -1;
+ rArgs[0].Value >>= nType;
+ sal_Int32 nX = 0;
+ rArgs[1].Value >>= nX;
+ sal_Int32 nY = 0;
+ rArgs[2].Value >>= nY;
+ executeDispatch_LOKSetTextSelection(nType, nX, nY);
+ }
+ }
+ else if (aCommand == "LOKTransform")
+ {
+ if (rArgs[0].Name == "Action")
+ {
+ OUString sAction;
+ if ((rArgs[0].Value >>= sAction) && sAction == "PieSegmentDragging")
+ {
+ if (rArgs[1].Name == "Offset")
+ {
+ sal_Int32 nOffset;
+ if (rArgs[1].Value >>= nOffset)
+ {
+ this->executeDispatch_LOKPieSegmentDragging(nOffset);
+ }
+ }
+ }
+ }
+ else
+ {
+ this->executeDispatch_PositionAndSize(&rArgs);
+ }
+ }
+ else if(aCommand == "FillColor")
+ {
+ if (rArgs.getLength() > 0)
+ {
+ sal_uInt32 nColor;
+ if (rArgs[0].Value >>= nColor)
+ this->executeDispatch_FillColor(nColor);
+ }
+ }
+ else if(aCommand == "XLineColor")
+ {
+ if (rArgs.getLength() > 0)
+ {
+ sal_Int32 nColor = -1;
+ rArgs[0].Value >>= nColor;
+ this->executeDispatch_LineColor(nColor);
+ }
+ }
+ else if(aCommand == "LineWidth")
+ {
+ if (rArgs.getLength() > 0)
+ {
+ sal_Int32 nWidth = -1;
+ rArgs[0].Value >>= nWidth;
+ this->executeDispatch_LineWidth(nWidth);
+ }
+ }
+ else if(aCommand.startsWith("FillGradient"))
+ {
+ this->executeDispatch_FillGradient(aCommand.subView(aCommand.indexOf('=') + 1));
+ }
+ else if(aCommand == "Paste")
+ this->executeDispatch_Paste();
+ else if(aCommand == "Copy" )
+ this->executeDispatch_Copy();
+ else if(aCommand == "Cut" )
+ this->executeDispatch_Cut();
+ else if(aCommand == "DataRanges" )
+ this->executeDispatch_SourceData();
+ else if(aCommand == "Update" ) //Update Chart
+ {
+ ChartViewHelper::setViewToDirtyState( getChartModel() );
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+ if( pChartWindow )
+ pChartWindow->Invalidate();
+ }
+ else if(aCommand == "DiagramData" )
+ this->executeDispatch_EditData();
+ //insert objects
+ else if( aCommand == "InsertTitles"
+ || aCommand == "InsertMenuTitles")
+ this->executeDispatch_InsertTitles();
+ else if( aCommand == "InsertMenuLegend" )
+ this->executeDispatch_OpenLegendDialog();
+ else if( aCommand == "InsertLegend" )
+ this->executeDispatch_InsertLegend();
+ else if( aCommand == "DeleteLegend" )
+ this->executeDispatch_DeleteLegend();
+ else if( aCommand == "InsertMenuDataLabels" )
+ this->executeDispatch_InsertMenu_DataLabels();
+ else if( aCommand == "InsertMenuAxes"
+ || aCommand == "InsertRemoveAxes" )
+ this->executeDispatch_InsertAxes();
+ else if( aCommand == "InsertMenuGrids" )
+ this->executeDispatch_InsertGrid();
+ else if( aCommand == "InsertMenuTrendlines" )
+ this->executeDispatch_InsertMenu_Trendlines();
+ else if( aCommand == "InsertMenuMeanValues" )
+ this->executeDispatch_InsertMenu_MeanValues();
+ else if( aCommand == "InsertMenuXErrorBars" )
+ this->executeDispatch_InsertErrorBars(false);
+ else if( aCommand == "InsertMenuYErrorBars" )
+ this->executeDispatch_InsertErrorBars(true);
+ else if( aCommand == "InsertMenuDataTable" )
+ this->executeDispatch_OpenInsertDataTableDialog();
+ else if( aCommand == "InsertSymbol" )
+ this->executeDispatch_InsertSpecialCharacter();
+ else if( aCommand == "InsertTrendline" )
+ this->executeDispatch_InsertTrendline();
+ else if( aCommand == "DeleteTrendline" )
+ this->executeDispatch_DeleteTrendline();
+ else if( aCommand == "InsertMeanValue" )
+ this->executeDispatch_InsertMeanValue();
+ else if( aCommand == "DeleteMeanValue" )
+ this->executeDispatch_DeleteMeanValue();
+ else if( aCommand == "InsertXErrorBars" )
+ this->executeDispatch_InsertErrorBars(false);
+ else if( aCommand == "InsertYErrorBars" )
+ this->executeDispatch_InsertErrorBars(true);
+ else if( aCommand == "DeleteXErrorBars" )
+ this->executeDispatch_DeleteErrorBars(false);
+ else if( aCommand == "DeleteYErrorBars" )
+ this->executeDispatch_DeleteErrorBars(true);
+ else if( aCommand == "InsertTrendlineEquation" )
+ this->executeDispatch_InsertTrendlineEquation();
+ else if( aCommand == "DeleteTrendlineEquation" )
+ this->executeDispatch_DeleteTrendlineEquation();
+ else if( aCommand == "InsertTrendlineEquationAndR2" )
+ this->executeDispatch_InsertTrendlineEquation( true );
+ else if( aCommand == "InsertR2Value" )
+ this->executeDispatch_InsertR2Value();
+ else if( aCommand == "DeleteR2Value")
+ this->executeDispatch_DeleteR2Value();
+ else if( aCommand == "InsertDataLabels" )
+ this->executeDispatch_InsertDataLabels();
+ else if( aCommand == "InsertDataLabel" )
+ this->executeDispatch_InsertDataLabel();
+ else if( aCommand == "DeleteDataLabels")
+ this->executeDispatch_DeleteDataLabels();
+ else if( aCommand == "DeleteDataLabel" )
+ this->executeDispatch_DeleteDataLabel();
+ else if( aCommand == "ResetAllDataPoints" )
+ this->executeDispatch_ResetAllDataPoints();
+ else if( aCommand == "ResetDataPoint" )
+ this->executeDispatch_ResetDataPoint();
+ else if( aCommand == "InsertAxis" )
+ this->executeDispatch_InsertAxis();
+ else if( aCommand == "InsertMajorGrid" )
+ this->executeDispatch_InsertMajorGrid();
+ else if( aCommand == "InsertMinorGrid" )
+ this->executeDispatch_InsertMinorGrid();
+ else if( aCommand == "InsertAxisTitle" )
+ this->executeDispatch_InsertAxisTitle();
+ else if( aCommand == "DeleteAxis" )
+ this->executeDispatch_DeleteAxis();
+ else if( aCommand == "DeleteMajorGrid")
+ this->executeDispatch_DeleteMajorGrid();
+ else if( aCommand == "DeleteMinorGrid" )
+ this->executeDispatch_DeleteMinorGrid();
+ else if( aCommand == "InsertDataTable" )
+ this->executeDispatch_InsertDataTable();
+ else if( aCommand == "DeleteDataTable" )
+ this->executeDispatch_DeleteDataTable();
+ //format objects
+ else if( aCommand == "FormatSelection" )
+ this->executeDispatch_ObjectProperties();
+ else if( aCommand == "TransformDialog" )
+ {
+ if ( isShapeContext() )
+ {
+ this->impl_ShapeControllerDispatch( rURL, rArgs );
+ }
+ else
+ {
+ this->executeDispatch_PositionAndSize();
+ }
+ }
+ else if( lcl_isFormatObjectCommand(aCommand) )
+ this->executeDispatch_FormatObject(rURL.Path);
+ //more format
+ else if( aCommand == "DiagramType" )
+ this->executeDispatch_ChartType();
+ else if( aCommand == "View3D" )
+ this->executeDispatch_View3D();
+ else if ( aCommand == "Forward" )
+ {
+ if ( isShapeContext() )
+ {
+ this->impl_ShapeControllerDispatch( rURL, rArgs );
+ }
+ else
+ {
+ this->executeDispatch_MoveSeries( true );
+ }
+ }
+ else if ( aCommand == "Backward" )
+ {
+ if ( isShapeContext() )
+ {
+ this->impl_ShapeControllerDispatch( rURL, rArgs );
+ }
+ else
+ {
+ this->executeDispatch_MoveSeries( false );
+ }
+ }
+ else if( aCommand == "NewArrangement")
+ this->executeDispatch_NewArrangement();
+ else if( aCommand == "ToggleLegend" )
+ this->executeDispatch_ToggleLegend();
+ else if( aCommand == "ToggleGridHorizontal" )
+ this->executeDispatch_ToggleGridHorizontal();
+ else if( aCommand == "ToggleGridVertical" )
+ this->executeDispatch_ToggleGridVertical();
+ else if( aCommand == "ScaleText" )
+ this->executeDispatch_ScaleText();
+ else if( aCommand == "StatusBarVisible" )
+ {
+ // workaround: this should not be necessary.
+ uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY );
+ if( xPropSet.is() )
+ {
+ uno::Reference< css::frame::XLayoutManager > xLayoutManager;
+ xPropSet->getPropertyValue( "LayoutManager" ) >>= xLayoutManager;
+ if ( xLayoutManager.is() )
+ {
+ bool bIsVisible( xLayoutManager->isElementVisible( "private:resource/statusbar/statusbar" ));
+ if( bIsVisible )
+ {
+ xLayoutManager->hideElement( "private:resource/statusbar/statusbar" );
+ xLayoutManager->destroyElement( "private:resource/statusbar/statusbar" );
+ }
+ else
+ {
+ xLayoutManager->createElement( "private:resource/statusbar/statusbar" );
+ xLayoutManager->showElement( "private:resource/statusbar/statusbar" );
+ }
+ // @todo: update menu state (checkmark next to "Statusbar").
+ }
+ }
+ }
+}
+
+void SAL_CALL ChartController::addStatusListener(
+ const uno::Reference<frame::XStatusListener >& /* xControl */,
+ const util::URL& /* aURL */ )
+{
+ //@todo
+}
+
+void SAL_CALL ChartController::removeStatusListener(
+ const uno::Reference<frame::XStatusListener >& /* xControl */,
+ const util::URL& /* aURL */ )
+{
+ //@todo
+}
+
+// XContextMenuInterception (optional interface)
+void SAL_CALL ChartController::registerContextMenuInterceptor(
+ const uno::Reference< ui::XContextMenuInterceptor >& /* xInterceptor */)
+{
+ //@todo
+}
+
+void SAL_CALL ChartController::releaseContextMenuInterceptor(
+ const uno::Reference< ui::XContextMenuInterceptor > & /* xInterceptor */)
+{
+ //@todo
+}
+
+// ____ XEmbeddedClient ____
+// implementation see: ChartController_EditData.cxx
+
+void ChartController::executeDispatch_ChartType()
+{
+ UndoLiveUpdateGuard aUndoGuard(
+ SchResId( STR_ACTION_EDIT_CHARTTYPE ), m_xUndoManager );
+
+ SolarMutexGuard aSolarGuard;
+ //prepare and open dialog
+ ChartTypeDialog aDlg(GetChartFrame(), getChartModel());
+ if (aDlg.run() == RET_OK)
+ {
+ impl_adaptDataSeriesAutoResize();
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_SourceData()
+{
+ //convert properties to ItemSet
+ rtl::Reference< ::chart::ChartModel > xChartDoc = getChartModel();
+ OSL_ENSURE( xChartDoc.is(), "Invalid XChartDocument" );
+ if( !xChartDoc.is() )
+ return;
+
+ // If there is a data table we should ask user if we really want to destroy it
+ // and switch to data ranges.
+ ChartModel& rModel = *xChartDoc;
+ if ( rModel.hasInternalDataProvider() )
+ {
+ // Check if we will able to create data provider later
+ css::uno::Reference< com::sun::star::chart2::XDataProviderAccess > xCreatorDoc(
+ rModel.getParent(), uno::UNO_QUERY);
+ if (!xCreatorDoc.is())
+ return;
+
+ SolarMutexGuard aSolarGuard;
+
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetChartFrame(),
+ VclMessageType::Question, VclButtonsType::YesNo, SchResId(STR_DLG_REMOVE_DATA_TABLE)));
+ // If "No" then just return
+ if (xQueryBox->run() == RET_NO)
+ return;
+
+ // Remove data table
+ rModel.removeDataProviders();
+
+ // Ask parent document to create new data provider
+
+ uno::Reference< data::XDataProvider > xDataProvider = xCreatorDoc->createDataProvider();
+ SAL_WARN_IF( !xDataProvider.is(), "chart2.main", "Data provider was not created" );
+ if (xDataProvider.is())
+ {
+ rModel.attachDataProvider(xDataProvider);
+ }
+ }
+
+ UndoLiveUpdateGuard aUndoGuard(
+ SchResId(STR_ACTION_EDIT_DATA_RANGES), m_xUndoManager);
+
+ SolarMutexGuard aSolarGuard;
+ ::chart::DataSourceDialog aDlg(GetChartFrame(), xChartDoc);
+ if (aDlg.run() == RET_OK)
+ {
+ impl_adaptDataSeriesAutoResize();
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_MoveSeries( bool bForward )
+{
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+
+ //get selected series
+ OUString aObjectCID(m_aSelection.getSelectedCID());
+ rtl::Reference< DataSeries > xGivenDataSeries = ObjectIdentifier::getDataSeriesForCID( //yyy todo also legend entries and labels?
+ aObjectCID, getChartModel() );
+
+ UndoGuardWithSelection aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ (bForward ? ActionDescriptionProvider::ActionType::MoveToTop : ActionDescriptionProvider::ActionType::MoveToBottom),
+ SchResId(STR_OBJECT_DATASERIES)),
+ m_xUndoManager );
+
+ bool bChanged = getFirstDiagram()->moveSeries( xGivenDataSeries, bForward );
+ if( bChanged )
+ {
+ m_aSelection.setSelection( ObjectIdentifier::getMovedSeriesCID( aObjectCID, bForward ) );
+ aUndoGuard.commit();
+ }
+}
+
+// ____ XModifyListener ____
+void SAL_CALL ChartController::modified(
+ const lang::EventObject& /* aEvent */ )
+{
+ // the source can also be a subobject of the ChartModel
+ // @todo: change the source in ChartModel to always be the model itself ?
+ //todo? update menu states ?
+}
+
+void ChartController::NotifyUndoActionHdl( std::unique_ptr<SdrUndoAction> pUndoAction )
+{
+ ENSURE_OR_RETURN_VOID( pUndoAction, "invalid Undo action" );
+
+ OUString aObjectCID = m_aSelection.getSelectedCID();
+ if ( !aObjectCID.isEmpty() )
+ return;
+
+ try
+ {
+ rtl::Reference< ChartModel > xSuppUndo = getChartModel();
+ const Reference< document::XUndoManager > xUndoManager( xSuppUndo->getUndoManager(), uno::UNO_SET_THROW );
+ const Reference< document::XUndoAction > xAction( new impl::ShapeUndoElement( std::move(pUndoAction) ) );
+ xUndoManager->addUndoAction( xAction );
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+DrawModelWrapper* ChartController::GetDrawModelWrapper()
+{
+ if( !m_pDrawModelWrapper )
+ {
+ if( m_xChartView )
+ m_pDrawModelWrapper = m_xChartView->getDrawModelWrapper();
+ if ( m_pDrawModelWrapper )
+ {
+ m_pDrawModelWrapper->getSdrModel().SetNotifyUndoActionHdl(
+ std::bind(&ChartController::NotifyUndoActionHdl, this, std::placeholders::_1) );
+ }
+ }
+ return m_pDrawModelWrapper.get();
+}
+
+DrawViewWrapper* ChartController::GetDrawViewWrapper()
+{
+ if ( !m_pDrawViewWrapper )
+ {
+ impl_createDrawViewController();
+ }
+ return m_pDrawViewWrapper.get();
+}
+
+
+ChartWindow* ChartController::GetChartWindow() const
+{
+ // clients getting the naked VCL Window from UNO should always have the
+ // solar mutex (and keep it over the lifetime of this ptr), as VCL might
+ // might deinit otherwise
+ DBG_TESTSOLARMUTEX();
+ if(!m_xViewWindow.is())
+ return nullptr;
+ return dynamic_cast<ChartWindow*>(VCLUnoHelper::GetWindow(m_xViewWindow));
+}
+
+weld::Window* ChartController::GetChartFrame()
+{
+ // clients getting the naked VCL Window from UNO should always have the
+ // solar mutex (and keep it over the lifetime of this ptr), as VCL might
+ // might deinit otherwise
+ DBG_TESTSOLARMUTEX();
+ return Application::GetFrameWeld(m_xViewWindow);
+}
+
+bool ChartController::isAdditionalShapeSelected() const
+{
+ return m_aSelection.isAdditionalShapeSelected();
+}
+
+void ChartController::SetAndApplySelection(const Reference<drawing::XShape>& rxShape)
+{
+ if(rxShape.is())
+ {
+ m_aSelection.setSelection(rxShape);
+ m_aSelection.applySelection(GetDrawViewWrapper());
+ }
+}
+
+
+
+uno::Reference< XAccessible > ChartController::CreateAccessible()
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ rtl::Reference< AccessibleChartView > xResult = new AccessibleChartView( GetDrawViewWrapper() );
+ impl_initializeAccessible( *xResult );
+ return xResult;
+#else
+ return uno::Reference< XAccessible >();
+#endif
+}
+
+void ChartController::impl_invalidateAccessible()
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+ if( pChartWindow )
+ {
+ Reference< XInterface > xInit( pChartWindow->GetAccessible(false) );
+ if(xInit.is())
+ {
+ //empty arguments -> invalid accessible
+ dynamic_cast<AccessibleChartView&>(*xInit).initialize();
+ }
+ }
+#endif
+}
+void ChartController::impl_initializeAccessible()
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+ if( !pChartWindow )
+ return;
+ Reference< XInterface > xInit( pChartWindow->GetAccessible(false) );
+ if(xInit.is())
+ impl_initializeAccessible( dynamic_cast<AccessibleChartView&>(*xInit) );
+#endif
+}
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+void ChartController::impl_initializeAccessible( AccessibleChartView& rAccChartView )
+{
+ uno::Reference< XAccessible > xParent;
+ {
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+ if( pChartWindow )
+ {
+ vcl::Window* pParentWin( pChartWindow->GetAccessibleParentWindow());
+ if( pParentWin )
+ xParent.set( pParentWin->GetAccessible());
+ }
+ }
+
+ rAccChartView.initialize(*this, getChartModel(), m_xChartView, xParent, m_xViewWindow);
+}
+#else
+void ChartController::impl_initializeAccessible( AccessibleChartView& /* rAccChartView */) {}
+#endif
+
+const o3tl::sorted_vector< OUString >& ChartController::impl_getAvailableCommands()
+{
+ static const o3tl::sorted_vector< OUString > s_AvailableCommands {
+ // commands for container forward
+ "AddDirect", "NewDoc", "Open",
+ "Save", "SaveAs", "SendMail",
+ "EditDoc", "ExportDirectToPDF", "PrintDefault",
+
+ // own commands
+ "Cut", "Copy", "Paste",
+ "DataRanges", "DiagramData",
+ // insert objects
+ "InsertMenuTitles", "InsertTitles",
+ "InsertMenuLegend", "InsertLegend", "DeleteLegend",
+ "InsertMenuDataLabels",
+ "InsertMenuAxes", "InsertRemoveAxes", "InsertMenuGrids",
+ "InsertSymbol",
+ "InsertTrendlineEquation", "InsertTrendlineEquationAndR2",
+ "InsertR2Value", "DeleteR2Value",
+ "InsertMenuTrendlines", "InsertTrendline",
+ "InsertMenuMeanValues", "InsertMeanValue",
+ "InsertMenuXErrorBars", "InsertXErrorBars",
+ "InsertMenuYErrorBars", "InsertYErrorBars",
+ "InsertDataLabels", "InsertDataLabel",
+ "DeleteTrendline", "DeleteMeanValue", "DeleteTrendlineEquation",
+ "DeleteXErrorBars", "DeleteYErrorBars",
+ "DeleteDataLabels", "DeleteDataLabel",
+ "InsertMenuDataTable",
+ "InsertDataTable", "DeleteDataTable",
+ //format objects
+ "FormatSelection", "TransformDialog",
+ "DiagramType", "View3D",
+ "Forward", "Backward",
+ "MainTitle", "SubTitle",
+ "XTitle", "YTitle", "ZTitle",
+ "SecondaryXTitle", "SecondaryYTitle",
+ "AllTitles", "Legend",
+ "DiagramAxisX", "DiagramAxisY", "DiagramAxisZ",
+ "DiagramAxisA", "DiagramAxisB", "DiagramAxisAll",
+ "DiagramGridXMain", "DiagramGridYMain", "DiagramGridZMain",
+ "DiagramGridXHelp", "DiagramGridYHelp", "DiagramGridZHelp",
+ "DiagramGridAll",
+ "DiagramWall", "DiagramFloor", "DiagramArea",
+
+ //context menu - format objects entries
+ "FormatWall", "FormatFloor", "FormatChartArea",
+ "FormatLegend",
+
+ "FormatAxis", "FormatTitle",
+ "FormatDataSeries", "FormatDataPoint",
+ "ResetAllDataPoints", "ResetDataPoint",
+ "FormatDataLabels", "FormatDataLabel",
+ "FormatMeanValue", "FormatTrendline", "FormatTrendlineEquation",
+ "FormatXErrorBars", "FormatYErrorBars",
+ "FormatStockLoss", "FormatStockGain",
+
+ "FormatMajorGrid", "InsertMajorGrid", "DeleteMajorGrid",
+ "FormatMinorGrid", "InsertMinorGrid", "DeleteMinorGrid",
+ "InsertAxis", "DeleteAxis", "InsertAxisTitle",
+
+ // toolbar commands
+ "ToggleGridHorizontal", "ToggleGridVertical", "ToggleLegend", "ScaleText",
+ "NewArrangement", "Update",
+ "DefaultColors", "BarWidth", "NumberOfLines",
+ "ArrangeRow",
+ "StatusBarVisible",
+ "ChartElementSelector"};
+ return s_AvailableCommands;
+}
+
+ViewElementListProvider ChartController::getViewElementListProvider()
+{
+ return ViewElementListProvider(m_pDrawModelWrapper.get());
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartController_EditData.cxx b/chart2/source/controller/main/ChartController_EditData.cxx
new file mode 100644
index 0000000000..63577edf39
--- /dev/null
+++ b/chart2/source/controller/main/ChartController_EditData.cxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+
+#include <dlg_DataEditor.hxx>
+#include "UndoGuard.hxx"
+#include <ResId.hxx>
+#include <strings.hrc>
+
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+void ChartController::executeDispatch_EditData()
+{
+ rtl::Reference<::chart::ChartModel> xChartDoc( getChartModel(), uno::UNO_QUERY );
+ if (xChartDoc.is())
+ {
+ SolarMutexGuard aSolarGuard;
+ UndoLiveUpdateGuardWithData aUndoGuard(
+ SchResId( STR_ACTION_EDIT_CHART_DATA ),
+ m_xUndoManager );
+ DataEditor aDataEditorDialog(GetChartFrame(), xChartDoc, m_xCC);
+ aDataEditorDialog.run();
+ aUndoGuard.commit();
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartController_Insert.cxx b/chart2/source/controller/main/ChartController_Insert.cxx
new file mode 100644
index 0000000000..60b059ceff
--- /dev/null
+++ b/chart2/source/controller/main/ChartController_Insert.cxx
@@ -0,0 +1,987 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <ChartController.hxx>
+#include <ChartView.hxx>
+
+#include <dlg_InsertAxis_Grid.hxx>
+#include <dlg_InsertDataLabel.hxx>
+#include <dlg_InsertLegend.hxx>
+#include <dlg_InsertErrorBars.hxx>
+#include <dlg_InsertTitle.hxx>
+#include <dlg_InsertDataTable.hxx>
+#include <dlg_ObjectProperties.hxx>
+
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <TitleHelper.hxx>
+#include <DataSeries.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <GridProperties.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <chartview/ChartSfxItemIds.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <ViewElementListProvider.hxx>
+#include <MultipleChartConverters.hxx>
+#include <ControllerLockGuard.hxx>
+#include "UndoGuard.hxx"
+#include <ResId.hxx>
+#include <strings.hrc>
+#include <ReferenceSizeProvider.hxx>
+#include <ObjectIdentifier.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveItemConverter.hxx>
+#include <StatisticsHelper.hxx>
+#include <ErrorBarItemConverter.hxx>
+#include <DataSeriesHelper.hxx>
+#include <ObjectNameProvider.hxx>
+#include <Legend.hxx>
+#include <LegendHelper.hxx>
+#include <DataTable.hxx>
+#include <RegressionCurveModel.hxx>
+
+#include <com/sun/star/chart2/XRegressionCurve.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <svx/ActionDescriptionProvider.hxx>
+
+#include <comphelper/diagnose_ex.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+
+void lcl_InsertMeanValueLine( const rtl::Reference< ::chart::DataSeries > & xSeries )
+{
+ if( xSeries.is())
+ {
+ ::chart::RegressionCurveHelper::addMeanValueLine(
+ xSeries, xSeries);
+ }
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+void ChartController::executeDispatch_InsertAxes()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_AXES )),
+ m_xUndoManager );
+
+ try
+ {
+ InsertAxisOrGridDialogData aDialogInput;
+ rtl::Reference< Diagram > xDiagram = getFirstDiagram();
+ AxisHelper::getAxisOrGridExistence( aDialogInput.aExistenceList, xDiagram );
+ AxisHelper::getAxisOrGridPossibilities( aDialogInput.aPossibilityList, xDiagram );
+
+ SolarMutexGuard aGuard;
+ SchAxisDlg aDlg(GetChartFrame(), aDialogInput);
+ if (aDlg.run() == RET_OK)
+ {
+ // lock controllers till end of block
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+
+ InsertAxisOrGridDialogData aDialogOutput;
+ aDlg.getResult(aDialogOutput);
+ std::unique_ptr< ReferenceSizeProvider > pRefSizeProvider(
+ impl_createReferenceSizeProvider());
+ bool bChanged = AxisHelper::changeVisibilityOfAxes( xDiagram
+ , aDialogInput.aExistenceList, aDialogOutput.aExistenceList, m_xCC
+ , pRefSizeProvider.get() );
+ if( bChanged )
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_InsertGrid()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_GRIDS )),
+ m_xUndoManager );
+
+ try
+ {
+ InsertAxisOrGridDialogData aDialogInput;
+ rtl::Reference< Diagram > xDiagram = getFirstDiagram();
+ AxisHelper::getAxisOrGridExistence( aDialogInput.aExistenceList, xDiagram, false );
+ AxisHelper::getAxisOrGridPossibilities( aDialogInput.aPossibilityList, xDiagram, false );
+
+ SolarMutexGuard aGuard;
+ SchGridDlg aDlg(GetChartFrame(), aDialogInput);//aItemSet, b3D, bNet, bSecondaryX, bSecondaryY );
+ if (aDlg.run() == RET_OK)
+ {
+ // lock controllers till end of block
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+ InsertAxisOrGridDialogData aDialogOutput;
+ aDlg.getResult( aDialogOutput );
+ bool bChanged = AxisHelper::changeVisibilityOfGrids( xDiagram
+ , aDialogInput.aExistenceList, aDialogOutput.aExistenceList );
+ if( bChanged )
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_OpenInsertDataTableDialog()
+{
+ SolarMutexGuard aGuard;
+
+ auto aUndoDescription = ActionDescriptionProvider::createDescription(ActionDescriptionProvider::ActionType::Insert, SchResId(STR_DATA_TABLE));
+ UndoGuard aUndoGuard(aUndoDescription, m_xUndoManager);
+
+ rtl::Reference<Diagram> xDiagram = getFirstDiagram();
+
+ InsertDataTableDialog aDialog(GetChartFrame());
+ {
+ // init values
+ DataTableDialogData aData;
+ auto xDataTable = xDiagram->getDataTable();
+ aData.mbShow = xDataTable.is();
+ if (xDataTable.is())
+ {
+ uno::Reference<beans::XPropertySet> xProperties(xDataTable, uno::UNO_QUERY);
+
+ uno::Any aAny = xProperties->getPropertyValue("HBorder");
+ if (aAny.has<bool>())
+ aData.mbHorizontalBorders = aAny.get<bool>();
+
+ aAny = xProperties->getPropertyValue("VBorder");
+ if (aAny.has<bool>())
+ aData.mbVerticalBorders = aAny.get<bool>();
+
+ aAny = xProperties->getPropertyValue("Outline");
+ if (aAny.has<bool>())
+ aData.mbOutline = aAny.get<bool>();
+
+ aAny = xProperties->getPropertyValue("Keys");
+ if (aAny.has<bool>())
+ aData.mbKeys = aAny.get<bool>();
+ }
+ aDialog.init(aData);
+ }
+
+ // show the dialog
+ if (aDialog.run() == RET_OK)
+ {
+ bool bChanged = false;
+
+ auto& rDialogData = aDialog.getDataTableDialogData();
+ auto xDataTable = xDiagram->getDataTable();
+ if (!rDialogData.mbShow && xDataTable.is())
+ {
+ xDiagram->setDataTable(uno::Reference<chart2::XDataTable>());
+ bChanged = true;
+ }
+ else if (rDialogData.mbShow && !xDataTable.is())
+ {
+ uno::Reference<chart2::XDataTable> xNewDataTable(new DataTable);
+ if (xNewDataTable.is())
+ {
+ xDiagram->setDataTable(xNewDataTable);
+ bChanged = true;
+ }
+ }
+
+ // Set the properties
+ xDataTable = xDiagram->getDataTable();
+ if (rDialogData.mbShow && xDataTable.is())
+ {
+ uno::Reference<beans::XPropertySet> xProperties(xDataTable, uno::UNO_QUERY);
+ xProperties->setPropertyValue("HBorder" , uno::Any(rDialogData.mbHorizontalBorders));
+ xProperties->setPropertyValue("VBorder" , uno::Any(rDialogData.mbVerticalBorders));
+ xProperties->setPropertyValue("Outline" , uno::Any(rDialogData.mbOutline));
+ xProperties->setPropertyValue("Keys" , uno::Any(rDialogData.mbKeys));
+ bChanged = true;
+ }
+
+ if (bChanged)
+ aUndoGuard.commit();
+ }
+}
+
+/** Create and insert a data table to the chart */
+void ChartController::executeDispatch_InsertDataTable()
+{
+ auto aUndoDescription = ActionDescriptionProvider::createDescription(ActionDescriptionProvider::ActionType::Insert, SchResId(STR_DATA_TABLE));
+ UndoGuard aUndoGuard(aUndoDescription, m_xUndoManager);
+
+
+ rtl::Reference<Diagram> xDiagram = getFirstDiagram();
+ auto xDataTable = xDiagram->getDataTable();
+ if (!xDataTable.is())
+ {
+ uno::Reference<chart2::XDataTable> xNewDataTable(new DataTable);
+ if (xNewDataTable.is())
+ {
+ xDiagram->setDataTable(xNewDataTable);
+ aUndoGuard.commit();
+ }
+ }
+}
+
+/** Delete a data table from the chart */
+void ChartController::executeDispatch_DeleteDataTable()
+{
+ auto aUndoDescription = ActionDescriptionProvider::createDescription(ActionDescriptionProvider::ActionType::Delete, SchResId(STR_DATA_TABLE));
+ UndoGuard aUndoGuard(aUndoDescription, m_xUndoManager);
+
+ rtl::Reference<Diagram> xDiagram = getFirstDiagram();
+ auto xDataTable = xDiagram->getDataTable();
+ if (xDataTable.is())
+ {
+ // insert a empty data table reference
+ xDiagram->setDataTable(uno::Reference<chart2::XDataTable>());
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_InsertTitles()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_TITLES )),
+ m_xUndoManager );
+
+ try
+ {
+ TitleDialogData aDialogInput;
+ aDialogInput.readFromModel( getChartModel() );
+
+ SolarMutexGuard aGuard;
+ SchTitleDlg aDlg(GetChartFrame(), aDialogInput);
+ if (aDlg.run() == RET_OK)
+ {
+ // lock controllers till end of block
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+ TitleDialogData aDialogOutput(impl_createReferenceSizeProvider());
+ aDlg.getResult(aDialogOutput);
+ bool bChanged = aDialogOutput.writeDifferenceToModel( getChartModel(), m_xCC, &aDialogInput );
+ if( bChanged )
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_DeleteLegend()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_LEGEND )),
+ m_xUndoManager );
+
+ LegendHelper::hideLegend(*getChartModel());
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_InsertLegend()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_LEGEND )),
+ m_xUndoManager );
+
+ LegendHelper::showLegend(*getChartModel(), m_xCC);
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_OpenLegendDialog()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_LEGEND )),
+ m_xUndoManager );
+
+ try
+ {
+ //prepare and open dialog
+ SolarMutexGuard aGuard;
+ SchLegendDlg aDlg(GetChartFrame(), m_xCC);
+ aDlg.init( getChartModel() );
+ if (aDlg.run() == RET_OK)
+ {
+ // lock controllers till end of block
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+ aDlg.writeToModel( getChartModel() );
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_InsertMenu_DataLabels()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_DATALABELS )),
+ m_xUndoManager );
+
+ //if a series is selected insert labels for that series only:
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel());
+ if( xSeries.is() )
+ {
+ // add labels
+ DataSeriesHelper::insertDataLabelsToSeriesAndAllPoints( xSeries );
+
+ OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) + "=" );
+ OUString aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticles(
+ ObjectIdentifier::getSeriesParticleFromCID(m_aSelection.getSelectedCID()), aChildParticle );
+
+ bool bSuccess = ChartController::executeDlg_ObjectProperties_withoutUndoGuard( aObjectCID, true );
+ if( bSuccess )
+ aUndoGuard.commit();
+ return;
+ }
+
+ try
+ {
+ wrapper::AllDataLabelItemConverter aItemConverter(
+ getChartModel(),
+ m_pDrawModelWrapper->GetItemPool(),
+ m_pDrawModelWrapper->getSdrModel(),
+ getChartModel() );
+ SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet();
+ aItemConverter.FillItemSet( aItemSet );
+
+ //prepare and open dialog
+ SolarMutexGuard aGuard;
+
+ //get number formatter
+ NumberFormatterWrapper aNumberFormatterWrapper( getChartModel() );
+ SvNumberFormatter* pNumberFormatter = aNumberFormatterWrapper.getSvNumberFormatter();
+
+ DataLabelsDialog aDlg(GetChartFrame(), aItemSet, pNumberFormatter);
+
+ if (aDlg.run() == RET_OK)
+ {
+ SfxItemSet aOutItemSet = aItemConverter.CreateEmptyItemSet();
+ aDlg.FillItemSet(aOutItemSet);
+ // lock controllers till end of block
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+ bool bChanged = aItemConverter.ApplyItemSet( aOutItemSet );//model should be changed now
+ if( bChanged )
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_InsertMeanValue()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_AVERAGE_LINE )),
+ m_xUndoManager );
+ lcl_InsertMeanValueLine( ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(),
+ getChartModel() ) );
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_InsertMenu_MeanValues()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_AVERAGE_LINE )),
+ m_xUndoManager );
+
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xSeries.is() )
+ {
+ //if a series is selected insert mean value only for that series:
+ lcl_InsertMeanValueLine( xSeries );
+ }
+ else if (rtl::Reference<Diagram> xDiagram = getFirstDiagram())
+ {
+ std::vector< rtl::Reference< DataSeries > > aSeries =
+ xDiagram->getDataSeries();
+
+ for( const auto& xSrs : aSeries )
+ lcl_InsertMeanValueLine( xSrs );
+ }
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_InsertMenu_Trendlines()
+{
+ OUString aCID = m_aSelection.getSelectedCID();
+
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID( aCID, getChartModel() );
+
+ if( !xSeries.is() )
+ return;
+
+ executeDispatch_InsertTrendline();
+}
+
+void ChartController::executeDispatch_InsertTrendline()
+{
+ rtl::Reference< DataSeries > xRegressionCurveContainer =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel());
+
+ if( !xRegressionCurveContainer.is() )
+ return;
+
+ UndoLiveUpdateGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_CURVE )),
+ m_xUndoManager );
+
+ rtl::Reference< RegressionCurveModel > xCurve =
+ RegressionCurveHelper::addRegressionCurve(
+ SvxChartRegress::Linear,
+ xRegressionCurveContainer );
+
+ if( !xCurve.is())
+ return;
+
+ wrapper::RegressionCurveItemConverter aItemConverter(
+ xCurve, xRegressionCurveContainer, m_pDrawModelWrapper->getSdrModel().GetItemPool(),
+ m_pDrawModelWrapper->getSdrModel(),
+ getChartModel() );
+
+ // open dialog
+ SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet();
+ aItemConverter.FillItemSet( aItemSet );
+ ObjectPropertiesDialogParameter aDialogParameter(
+ ObjectIdentifier::createDataCurveCID(
+ ObjectIdentifier::getSeriesParticleFromCID( m_aSelection.getSelectedCID()),
+ RegressionCurveHelper::getRegressionCurveIndex( xRegressionCurveContainer, xCurve ), false ));
+ aDialogParameter.init( getChartModel() );
+ ViewElementListProvider aViewElementListProvider( m_pDrawModelWrapper.get());
+ SolarMutexGuard aGuard;
+ SchAttribTabDlg aDialog(
+ GetChartFrame(), &aItemSet, &aDialogParameter,
+ &aViewElementListProvider,
+ getChartModel() );
+
+ // note: when a user pressed "OK" but didn't change any settings in the
+ // dialog, the SfxTabDialog returns "Cancel"
+ if( aDialog.run() == RET_OK || aDialog.DialogWasClosedWithOK())
+ {
+ const SfxItemSet* pOutItemSet = aDialog.GetOutputItemSet();
+ if( pOutItemSet )
+ {
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+ aItemConverter.ApplyItemSet( *pOutItemSet );
+ }
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_InsertErrorBars( bool bYError )
+{
+ ObjectType objType = bYError ? OBJECTTYPE_DATA_ERRORS_Y : OBJECTTYPE_DATA_ERRORS_X;
+
+ //if a series is selected insert error bars for that series only:
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+
+ if( xSeries.is())
+ {
+ UndoLiveUpdateGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert,
+ SchResId( bYError ? STR_OBJECT_ERROR_BARS_Y : STR_OBJECT_ERROR_BARS_X )),
+ m_xUndoManager );
+
+ // add error bars with standard deviation
+ uno::Reference< beans::XPropertySet > xErrorBarProp(
+ StatisticsHelper::addErrorBars( xSeries,
+ css::chart::ErrorBarStyle::STANDARD_DEVIATION,
+ bYError));
+
+ // get an appropriate item converter
+ wrapper::ErrorBarItemConverter aItemConverter(
+ getChartModel(), xErrorBarProp, m_pDrawModelWrapper->getSdrModel().GetItemPool(),
+ m_pDrawModelWrapper->getSdrModel(),
+ getChartModel() );
+
+ // open dialog
+ SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet();
+ aItemSet.Put(SfxBoolItem(SCHATTR_STAT_ERRORBAR_TYPE,bYError));
+ aItemConverter.FillItemSet( aItemSet );
+ ObjectPropertiesDialogParameter aDialogParameter(
+ ObjectIdentifier::createClassifiedIdentifierWithParent(
+ objType, u"", m_aSelection.getSelectedCID()));
+ aDialogParameter.init( getChartModel() );
+ ViewElementListProvider aViewElementListProvider( m_pDrawModelWrapper.get());
+ SolarMutexGuard aGuard;
+ SchAttribTabDlg aDlg(
+ GetChartFrame(), &aItemSet, &aDialogParameter,
+ &aViewElementListProvider,
+ getChartModel() );
+ aDlg.SetAxisMinorStepWidthForErrorBarDecimals(
+ InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals( getChartModel(),
+ m_xChartView, m_aSelection.getSelectedCID()));
+
+ // note: when a user pressed "OK" but didn't change any settings in the
+ // dialog, the SfxTabDialog returns "Cancel"
+ if (aDlg.run() == RET_OK || aDlg.DialogWasClosedWithOK())
+ {
+ const SfxItemSet* pOutItemSet = aDlg.GetOutputItemSet();
+ if( pOutItemSet )
+ {
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+ aItemConverter.ApplyItemSet( *pOutItemSet );
+ }
+ aUndoGuard.commit();
+ }
+ }
+ else
+ {
+ //if no series is selected insert error bars for all series
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert,
+ ObjectNameProvider::getName_ObjectForAllSeries( objType ) ),
+ m_xUndoManager );
+
+ try
+ {
+ wrapper::AllSeriesStatisticsConverter aItemConverter(
+ getChartModel(), m_pDrawModelWrapper->GetItemPool() );
+ SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet();
+ aItemConverter.FillItemSet( aItemSet );
+
+ //prepare and open dialog
+ SolarMutexGuard aGuard;
+ InsertErrorBarsDialog aDlg(
+ GetChartFrame(), aItemSet,
+ getChartModel(),
+ bYError ? ErrorBarResources::ERROR_BAR_Y : ErrorBarResources::ERROR_BAR_X);
+
+ aDlg.SetAxisMinorStepWidthForErrorBarDecimals(
+ InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals( getChartModel(), m_xChartView, u"" ) );
+
+ if (aDlg.run() == RET_OK)
+ {
+ SfxItemSet aOutItemSet = aItemConverter.CreateEmptyItemSet();
+ aDlg.FillItemSet( aOutItemSet );
+
+ // lock controllers till end of block
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+ bool bChanged = aItemConverter.ApplyItemSet( aOutItemSet );//model should be changed now
+ if( bChanged )
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+}
+
+void ChartController::executeDispatch_InsertTrendlineEquation( bool bInsertR2 )
+{
+ uno::Reference< chart2::XRegressionCurve > xRegCurve(
+ ObjectIdentifier::getObjectPropertySet( m_aSelection.getSelectedCID(), getChartModel() ), uno::UNO_QUERY );
+ if( !xRegCurve.is() )
+ {
+ rtl::Reference< DataSeries > xRegCurveCnt =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ xRegCurve.set( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCurveCnt ) );
+ }
+ if( !xRegCurve.is())
+ return;
+
+ uno::Reference< beans::XPropertySet > xEqProp( xRegCurve->getEquationProperties());
+ if( xEqProp.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_CURVE_EQUATION )),
+ m_xUndoManager );
+ xEqProp->setPropertyValue( "ShowEquation", uno::Any( true ));
+ xEqProp->setPropertyValue( "XName", uno::Any( OUString("x") ));
+ xEqProp->setPropertyValue( "YName", uno::Any( OUString("f(x)") ));
+ xEqProp->setPropertyValue( "ShowCorrelationCoefficient", uno::Any( bInsertR2 ));
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_InsertR2Value()
+{
+ uno::Reference< beans::XPropertySet > xEqProp =
+ ObjectIdentifier::getObjectPropertySet( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xEqProp.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_CURVE_EQUATION )),
+ m_xUndoManager );
+ xEqProp->setPropertyValue( "ShowCorrelationCoefficient", uno::Any( true ));
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_DeleteR2Value()
+{
+ uno::Reference< beans::XPropertySet > xEqProp =
+ ObjectIdentifier::getObjectPropertySet( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xEqProp.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_CURVE_EQUATION )),
+ m_xUndoManager );
+ xEqProp->setPropertyValue( "ShowCorrelationCoefficient", uno::Any( false ));
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_DeleteMeanValue()
+{
+ rtl::Reference< DataSeries > xRegCurveCnt =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xRegCurveCnt.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_AVERAGE_LINE )),
+ m_xUndoManager );
+ RegressionCurveHelper::removeMeanValueLine( xRegCurveCnt );
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_DeleteTrendline()
+{
+ rtl::Reference< DataSeries > xRegCurveCnt =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xRegCurveCnt.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_CURVE )),
+ m_xUndoManager );
+ RegressionCurveHelper::removeAllExceptMeanValueLine( xRegCurveCnt );
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_DeleteTrendlineEquation()
+{
+ rtl::Reference< DataSeries > xRegCurveCnt =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xRegCurveCnt.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_CURVE_EQUATION )),
+ m_xUndoManager );
+ RegressionCurveHelper::removeEquations( xRegCurveCnt );
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_DeleteErrorBars( bool bYError )
+{
+ rtl::Reference< DataSeries > xDataSeries =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xDataSeries.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_CURVE )),
+ m_xUndoManager );
+ StatisticsHelper::removeErrorBars( xDataSeries, bYError );
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_InsertDataLabels()
+{
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xSeries.is() )
+ {
+ UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::ActionType::Insert,
+ SchResId( STR_OBJECT_DATALABELS )),
+ m_xUndoManager );
+ DataSeriesHelper::insertDataLabelsToSeriesAndAllPoints( xSeries );
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_InsertDataLabel()
+{
+ UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::ActionType::Insert,
+ SchResId( STR_OBJECT_LABEL )),
+ m_xUndoManager );
+ DataSeriesHelper::insertDataLabelToPoint( ObjectIdentifier::getObjectPropertySet( m_aSelection.getSelectedCID(), getChartModel() ) );
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_DeleteDataLabels()
+{
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xSeries.is() )
+ {
+ UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::ActionType::Delete,
+ SchResId( STR_OBJECT_DATALABELS )),
+ m_xUndoManager );
+ DataSeriesHelper::deleteDataLabelsFromSeriesAndAllPoints( xSeries );
+ aUndoGuard.commit();
+ }
+}
+
+void ChartController::executeDispatch_DeleteDataLabel()
+{
+ UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::ActionType::Delete,
+ SchResId( STR_OBJECT_LABEL )),
+ m_xUndoManager );
+ DataSeriesHelper::deleteDataLabelsFromPoint( ObjectIdentifier::getObjectPropertySet( m_aSelection.getSelectedCID(), getChartModel() ) );
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_ResetAllDataPoints()
+{
+ UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::ActionType::Format,
+ SchResId( STR_OBJECT_DATAPOINTS )),
+ m_xUndoManager );
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xSeries.is() )
+ xSeries->resetAllDataPoints();
+ aUndoGuard.commit();
+}
+void ChartController::executeDispatch_ResetDataPoint()
+{
+ UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::ActionType::Format,
+ SchResId( STR_OBJECT_DATAPOINT )),
+ m_xUndoManager );
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xSeries.is() )
+ {
+ sal_Int32 nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection.getSelectedCID() );
+ xSeries->resetDataPoint( nPointIndex );
+ }
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_InsertAxisTitle()
+{
+ try
+ {
+ rtl::Reference< Title > xTitle;
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_TITLE )),
+ m_xUndoManager );
+
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ sal_Int32 nDimensionIndex = -1;
+ sal_Int32 nCooSysIndex = -1;
+ sal_Int32 nAxisIndex = -1;
+ AxisHelper::getIndicesForAxis( xAxis, getFirstDiagram(), nCooSysIndex, nDimensionIndex, nAxisIndex );
+
+ TitleHelper::eTitleType eTitleType = TitleHelper::X_AXIS_TITLE;
+ if( nDimensionIndex==0 )
+ eTitleType = nAxisIndex==0 ? TitleHelper::X_AXIS_TITLE : TitleHelper::SECONDARY_X_AXIS_TITLE;
+ else if( nDimensionIndex==1 )
+ eTitleType = nAxisIndex==0 ? TitleHelper::Y_AXIS_TITLE : TitleHelper::SECONDARY_Y_AXIS_TITLE;
+ else
+ eTitleType = TitleHelper::Z_AXIS_TITLE;
+
+ std::unique_ptr< ReferenceSizeProvider > apRefSizeProvider( impl_createReferenceSizeProvider());
+ xTitle = TitleHelper::createTitle( eTitleType, ObjectNameProvider::getTitleNameByType(eTitleType), getChartModel(), m_xCC, apRefSizeProvider.get() );
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_InsertAxis()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_AXIS )),
+ m_xUndoManager );
+
+ try
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xAxis.is() )
+ {
+ AxisHelper::makeAxisVisible( xAxis );
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_DeleteAxis()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_AXIS )),
+ m_xUndoManager );
+
+ try
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xAxis.is() )
+ {
+ AxisHelper::makeAxisInvisible( xAxis );
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_InsertMajorGrid()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_GRID )),
+ m_xUndoManager );
+
+ try
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xAxis.is() )
+ {
+ AxisHelper::makeGridVisible( xAxis->getGridProperties2() );
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_DeleteMajorGrid()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_GRID )),
+ m_xUndoManager );
+
+ try
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xAxis.is() )
+ {
+ AxisHelper::makeGridInvisible( xAxis->getGridProperties2() );
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_InsertMinorGrid()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Insert, SchResId( STR_OBJECT_GRID )),
+ m_xUndoManager );
+
+ try
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xAxis.is() )
+ {
+ std::vector< rtl::Reference< ::chart::GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
+ for( rtl::Reference< GridProperties > const & props : aSubGrids)
+ AxisHelper::makeGridVisible( props );
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_DeleteMinorGrid()
+{
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId(STR_OBJECT_GRID)),
+ m_xUndoManager );
+
+ try
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xAxis.is() )
+ {
+ std::vector< rtl::Reference< ::chart::GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
+ for( rtl::Reference< ::chart::GridProperties > const & props : aSubGrids)
+ AxisHelper::makeGridInvisible( props );
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartController_Position.cxx b/chart2/source/controller/main/ChartController_Position.cxx
new file mode 100644
index 0000000000..9e7194eca8
--- /dev/null
+++ b/chart2/source/controller/main/ChartController_Position.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartController.hxx>
+
+#include <DrawViewWrapper.hxx>
+#include <PositionAndSizeHelper.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartView.hxx>
+#include "UndoGuard.hxx"
+#include <ObjectNameProvider.hxx>
+#include <DiagramHelper.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <CommonConverters.hxx>
+#include <svx/ActionDescriptionProvider.hxx>
+
+#include <comphelper/servicehelper.hxx>
+#include <svx/svxids.hrc>
+#include <svx/rectenum.hxx>
+#include <svl/intitem.hxx>
+#include <svx/svxdlg.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <vcl/svapp.hxx>
+#include <memory>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+static void lcl_getPositionAndSizeFromItemSet( const SfxItemSet& rItemSet, awt::Rectangle& rPosAndSize, const awt::Size& rOriginalSize )
+{
+ tools::Long nPosX(0);
+ tools::Long nPosY(0);
+ tools::Long nSizX(0);
+ tools::Long nSizY(0);
+
+ RectPoint eRP = RectPoint::LT;
+
+ //read position
+ if (const SfxInt32Item* pPosXItem = rItemSet.GetItemIfSet(SID_ATTR_TRANSFORM_POS_X))
+ nPosX = pPosXItem->GetValue();
+ if (const SfxInt32Item* pPosYItem = rItemSet.GetItemIfSet(SID_ATTR_TRANSFORM_POS_Y))
+ nPosY = pPosYItem->GetValue();
+ //read size
+ if (const SfxUInt32Item* pWidthItem = rItemSet.GetItemIfSet(SID_ATTR_TRANSFORM_WIDTH))
+ nSizX = pWidthItem->GetValue();
+ if (const SfxUInt32Item* pHeightItem = rItemSet.GetItemIfSet(SID_ATTR_TRANSFORM_HEIGHT))
+ nSizY = pHeightItem->GetValue();
+ if (const SfxUInt16Item* pSizeItem = rItemSet.GetItemIfSet(SID_ATTR_TRANSFORM_SIZE_POINT))
+ eRP=static_cast<RectPoint>(pSizeItem->GetValue());
+
+ switch( eRP )
+ {
+ case RectPoint::LT:
+ break;
+ case RectPoint::MT:
+ nPosX += ( rOriginalSize.Width - nSizX ) / 2;
+ break;
+ case RectPoint::RT:
+ nPosX += rOriginalSize.Width - nSizX;
+ break;
+ case RectPoint::LM:
+ nPosY += ( rOriginalSize.Height - nSizY ) / 2;
+ break;
+ case RectPoint::MM:
+ nPosX += ( rOriginalSize.Width - nSizX ) / 2;
+ nPosY += ( rOriginalSize.Height - nSizY ) / 2;
+ break;
+ case RectPoint::RM:
+ nPosX += rOriginalSize.Width - nSizX;
+ nPosY += ( rOriginalSize.Height - nSizY ) / 2;
+ break;
+ case RectPoint::LB:
+ nPosY += rOriginalSize.Height - nSizY;
+ break;
+ case RectPoint::MB:
+ nPosX += ( rOriginalSize.Width - nSizX ) / 2;
+ nPosY += rOriginalSize.Height - nSizY;
+ break;
+ case RectPoint::RB:
+ nPosX += rOriginalSize.Width - nSizX;
+ nPosY += rOriginalSize.Height - nSizY;
+ break;
+ default:
+ break;
+ }
+
+ rPosAndSize = awt::Rectangle(nPosX,nPosY,nSizX,nSizY);
+}
+
+void ChartController::executeDispatch_PositionAndSize(const ::css::uno::Sequence< ::css::beans::PropertyValue >* pArgs)
+{
+ const OUString aCID( m_aSelection.getSelectedCID() );
+
+ if( aCID.isEmpty() )
+ return;
+
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID );
+
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::PosSize,
+ ObjectNameProvider::getName( eObjectType)),
+ m_xUndoManager );
+
+ try
+ {
+ SfxItemSet aItemSet = m_pDrawViewWrapper->getPositionAndSizeItemSetFromMarkedObject();
+ const SfxItemSet* pOutItemSet = nullptr;
+ if (!pArgs)
+ {
+ //prepare and open dialog
+ SdrView* pSdrView = m_pDrawViewWrapper.get();
+ bool bResizePossible = m_aSelection.isResizeableObjectSelected();
+
+ SolarMutexGuard aGuard;
+ SvxAbstractDialogFactory * pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSchTransformTabDialog(
+ GetChartFrame(), &aItemSet, pSdrView, bResizePossible));
+
+ if( pDlg->Execute() == RET_OK )
+ {
+ pOutItemSet = pDlg->GetOutputItemSet();
+ if (pOutItemSet)
+ aItemSet.Put(*pOutItemSet);//overwrite old values with new values (-> all items are set)
+ }
+ }
+ else
+ {
+ const SfxItemPool* pPool = aItemSet.GetPool();
+ if (!pPool)
+ return;
+
+ for (const auto& aProp: *pArgs)
+ {
+ sal_Int32 nValue = 0;
+ aProp.Value >>= nValue;
+ if (aProp.Name == "TransformPosX") {
+ aItemSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_X, nValue));
+ }
+ else if (aProp.Name == "TransformPosY") {
+ aItemSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_Y, nValue));
+ }
+ else if (aProp.Name == "TransformWidth") {
+ aItemSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_WIDTH, static_cast<sal_uInt32>(nValue)));
+ }
+ else if (aProp.Name == "TransformHeight") {
+ aItemSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_HEIGHT, static_cast<sal_uInt32>(nValue)));
+ }
+ }
+ }
+
+ if(pOutItemSet || pArgs)
+ {
+ awt::Rectangle aOldObjectRect;
+ if( m_xChartView )
+ aOldObjectRect = m_xChartView->getRectangleOfObject(aCID);
+
+ awt::Rectangle aNewObjectRect;
+ lcl_getPositionAndSizeFromItemSet( aItemSet, aNewObjectRect, ToSize(aOldObjectRect) );
+ awt::Size aPageSize( ChartModelHelper::getPageSize( getChartModel() ) );
+ awt::Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height );
+
+ bool bChanged = false;
+ if ( eObjectType == OBJECTTYPE_LEGEND )
+ {
+ bChanged = DiagramHelper::switchDiagramPositioningToExcludingPositioning(*getChartModel(), false , true);
+ }
+
+ bool bMoved = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID(), getChartModel()
+ , aNewObjectRect, aOldObjectRect, aPageRect );
+ if( bMoved || bChanged )
+ aUndoGuard.commit();
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartController_Properties.cxx b/chart2/source/controller/main/ChartController_Properties.cxx
new file mode 100644
index 0000000000..5f9e9a7d95
--- /dev/null
+++ b/chart2/source/controller/main/ChartController_Properties.cxx
@@ -0,0 +1,840 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartController.hxx>
+#include <ChartView.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <chartview/ChartSfxItemIds.hxx>
+#include <ObjectIdentifier.hxx>
+#include <chartview/ExplicitScaleValues.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <dlg_ObjectProperties.hxx>
+#include <dlg_View3D.hxx>
+#include <dlg_InsertErrorBars.hxx>
+#include <ViewElementListProvider.hxx>
+#include <DataPointItemConverter.hxx>
+#include <TextLabelItemConverter.hxx>
+#include <AxisItemConverter.hxx>
+#include <MultipleChartConverters.hxx>
+#include <TitleItemConverter.hxx>
+#include <LegendItemConverter.hxx>
+#include <DataTableItemConverter.hxx>
+#include <RegressionCurveItemConverter.hxx>
+#include <RegressionEquationItemConverter.hxx>
+#include <ErrorBarItemConverter.hxx>
+#include <ChartModelHelper.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <TitleHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartModel.hxx>
+#include <ColorPerPointHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesProperties.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ControllerLockGuard.hxx>
+#include "UndoGuard.hxx"
+#include <ObjectNameProvider.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+#include <ReferenceSizeProvider.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <memory>
+
+#include <vcl/svapp.hxx>
+#include <svx/ActionDescriptionProvider.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart::DataSeriesProperties;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+
+wrapper::ItemConverter* createItemConverter(
+ std::u16string_view aObjectCID, const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const uno::Reference<uno::XComponentContext>& xContext, SdrModel& rDrawModel,
+ ExplicitValueProvider* pExplicitValueProvider, ReferenceSizeProvider const * pRefSizeProvider )
+{
+ wrapper::ItemConverter* pItemConverter=nullptr;
+
+ //get type of selected object
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( aObjectCID );
+ if( eObjectType==OBJECTTYPE_UNKNOWN )
+ {
+ OSL_FAIL("unknown ObjectType");
+ return nullptr;
+ }
+
+ std::u16string_view aParticleID = ObjectIdentifier::getParticleID( aObjectCID );
+ bool bAffectsMultipleObjects = aParticleID == u"ALLELEMENTS";
+ if( !bAffectsMultipleObjects )
+ {
+ uno::Reference< beans::XPropertySet > xObjectProperties =
+ ObjectIdentifier::getObjectPropertySet( aObjectCID, xChartModel );
+ if(!xObjectProperties.is())
+ return nullptr;
+ //create itemconverter for a single object
+ switch(eObjectType)
+ {
+ case OBJECTTYPE_PAGE:
+ pItemConverter = new wrapper::GraphicPropertyItemConverter(
+ xObjectProperties, rDrawModel.GetItemPool(),
+ rDrawModel, xChartModel,
+ wrapper::GraphicObjectType::LineAndFillProperties );
+ break;
+ case OBJECTTYPE_TITLE:
+ {
+ std::unique_ptr<awt::Size> pRefSize;
+ if (pRefSizeProvider)
+ pRefSize.reset(new awt::Size(pRefSizeProvider->getPageSize()));
+
+ pItemConverter = new wrapper::TitleItemConverter(
+ xObjectProperties, rDrawModel.GetItemPool(), rDrawModel,
+ xChartModel,
+ pRefSize.get());
+ }
+ break;
+ case OBJECTTYPE_LEGEND:
+ {
+ std::unique_ptr<awt::Size> pRefSize;
+ if (pRefSizeProvider)
+ pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize()));
+
+ pItemConverter = new wrapper::LegendItemConverter(
+ xObjectProperties, rDrawModel.GetItemPool(), rDrawModel,
+ xChartModel,
+ pRefSize.get());
+ }
+ break;
+ case OBJECTTYPE_LEGEND_ENTRY:
+ break;
+ case OBJECTTYPE_DIAGRAM:
+ break;
+ case OBJECTTYPE_DIAGRAM_WALL:
+ case OBJECTTYPE_DIAGRAM_FLOOR:
+ pItemConverter = new wrapper::GraphicPropertyItemConverter(
+ xObjectProperties, rDrawModel.GetItemPool(),
+ rDrawModel, xChartModel,
+ wrapper::GraphicObjectType::LineAndFillProperties );
+ break;
+ case OBJECTTYPE_AXIS:
+ {
+ std::unique_ptr<awt::Size> pRefSize;
+ if (pRefSizeProvider)
+ pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize()));
+
+ // the second property set contains the property CoordinateOrigin
+ // nOriginIndex is the index of the corresponding index of the
+ // origin (x=0, y=1, z=2)
+
+ ExplicitScaleData aExplicitScale;
+ ExplicitIncrementData aExplicitIncrement;
+ if( pExplicitValueProvider )
+ pExplicitValueProvider->getExplicitValuesForAxis(
+ dynamic_cast< Axis* >( xObjectProperties.get() ),
+ aExplicitScale, aExplicitIncrement );
+
+ pItemConverter = new wrapper::AxisItemConverter(
+ xObjectProperties, rDrawModel.GetItemPool(),
+ rDrawModel,
+ xChartModel,
+ &aExplicitScale, &aExplicitIncrement,
+ pRefSize.get() );
+ }
+ break;
+ case OBJECTTYPE_AXIS_UNITLABEL:
+ break;
+ case OBJECTTYPE_DATA_LABELS:
+ case OBJECTTYPE_DATA_LABEL:
+ {
+ std::unique_ptr<awt::Size> pRefSize;
+ if (pRefSizeProvider)
+ pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize()));
+
+ rtl::Reference<DataSeries> xSeries = ObjectIdentifier::getDataSeriesForCID(aObjectCID, xChartModel);
+
+ bool bDataSeries = eObjectType == OBJECTTYPE_DATA_LABELS;
+
+ sal_Int32 nNumberFormat = ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( xObjectProperties );
+ sal_Int32 nPercentNumberFormat = ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
+ xObjectProperties, xChartModel);
+
+ pItemConverter = new wrapper::TextLabelItemConverter(
+ xChartModel, xObjectProperties, xSeries,
+ rDrawModel.GetItemPool(), pRefSize.get(), bDataSeries,
+ nNumberFormat, nPercentNumberFormat);
+ }
+ break;
+ case OBJECTTYPE_DATA_SERIES:
+ case OBJECTTYPE_DATA_POINT:
+ {
+ std::unique_ptr<awt::Size> pRefSize;
+ if (pRefSizeProvider)
+ pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize()));
+
+ wrapper::GraphicObjectType eMapTo =
+ wrapper::GraphicObjectType::FilledDataPoint;
+
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( aObjectCID, xChartModel );
+ rtl::Reference< ChartType > xChartType = ChartModelHelper::getChartTypeOfSeries( xChartModel, xSeries );
+
+ rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
+ sal_Int32 nDimensionCount = xDiagram->getDimension();
+ if( !ChartTypeHelper::isSupportingAreaProperties( xChartType, nDimensionCount ) )
+ eMapTo = wrapper::GraphicObjectType::LineDataPoint;
+
+ bool bDataSeries = eObjectType == OBJECTTYPE_DATA_SERIES;
+
+ //special color for pie chart:
+ bool bUseSpecialFillColor = false;
+ sal_Int32 nSpecialFillColor =0;
+ sal_Int32 nPointIndex = -1; /*-1 for whole series*/
+ if(!bDataSeries)
+ {
+ nPointIndex = o3tl::toInt32(aParticleID);
+ bool bVaryColorsByPoint = false;
+ if( xSeries.is() &&
+ // "VaryColorsByPoint"
+ (xSeries->getFastPropertyValue(PROP_DATASERIES_VARY_COLORS_BY_POINT) >>= bVaryColorsByPoint) &&
+ bVaryColorsByPoint )
+ {
+ if( !ColorPerPointHelper::hasPointOwnColor( xSeries, nPointIndex, xObjectProperties ) )
+ {
+ bUseSpecialFillColor = true;
+ OSL_ASSERT( xDiagram.is());
+ uno::Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme() );
+ if( xColorScheme.is())
+ nSpecialFillColor = xColorScheme->getColorByIndex( nPointIndex );
+ }
+ }
+ }
+ sal_Int32 nNumberFormat=ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( xObjectProperties );
+ sal_Int32 nPercentNumberFormat=ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
+ xObjectProperties, xChartModel);
+
+ pItemConverter = new wrapper::DataPointItemConverter( xChartModel, xContext,
+ xObjectProperties, xSeries, rDrawModel.GetItemPool(), rDrawModel,
+ xChartModel,
+ eMapTo, pRefSize.get(), bDataSeries, bUseSpecialFillColor, nSpecialFillColor, true,
+ nNumberFormat, nPercentNumberFormat, nPointIndex );
+ break;
+ }
+ case OBJECTTYPE_GRID:
+ case OBJECTTYPE_SUBGRID:
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ pItemConverter = new wrapper::GraphicPropertyItemConverter(
+ xObjectProperties, rDrawModel.GetItemPool(),
+ rDrawModel, xChartModel,
+ wrapper::GraphicObjectType::LineProperties );
+ break;
+
+ case OBJECTTYPE_DATA_ERRORS_X:
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ pItemConverter = new wrapper::ErrorBarItemConverter(
+ xChartModel, xObjectProperties, rDrawModel.GetItemPool(),
+ rDrawModel, xChartModel);
+ break;
+
+ case OBJECTTYPE_DATA_CURVE:
+ pItemConverter = new wrapper::RegressionCurveItemConverter(
+ xObjectProperties,
+ ObjectIdentifier::getDataSeriesForCID( aObjectCID, xChartModel ),
+ rDrawModel.GetItemPool(), rDrawModel,
+ xChartModel);
+ break;
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ {
+ std::unique_ptr<awt::Size> pRefSize;
+ if (pRefSizeProvider)
+ pRefSize.reset(new awt::Size(pRefSizeProvider->getPageSize()));
+
+ pItemConverter = new wrapper::RegressionEquationItemConverter(
+ xObjectProperties, rDrawModel.GetItemPool(), rDrawModel,
+ xChartModel,
+ pRefSize.get());
+ break;
+ }
+ case OBJECTTYPE_DATA_STOCK_RANGE:
+ break;
+ case OBJECTTYPE_DATA_STOCK_LOSS:
+ case OBJECTTYPE_DATA_STOCK_GAIN:
+ pItemConverter = new wrapper::GraphicPropertyItemConverter(
+ xObjectProperties, rDrawModel.GetItemPool(),
+ rDrawModel, xChartModel,
+ wrapper::GraphicObjectType::LineAndFillProperties );
+ break;
+ case OBJECTTYPE_DATA_TABLE:
+ {
+ pItemConverter = new wrapper::DataTableItemConverter(
+ xObjectProperties, rDrawModel.GetItemPool(),
+ rDrawModel, xChartModel);
+ }
+ break;
+ default: //OBJECTTYPE_UNKNOWN
+ break;
+ }
+ }
+ else
+ {
+ //create itemconverter for all objects of given type
+ switch(eObjectType)
+ {
+ case OBJECTTYPE_TITLE:
+ pItemConverter = new wrapper::AllTitleItemConverter( xChartModel, rDrawModel.GetItemPool(),
+ rDrawModel, xChartModel);
+ break;
+ case OBJECTTYPE_AXIS:
+ {
+ std::unique_ptr<awt::Size> pRefSize;
+ if (pRefSizeProvider)
+ pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize()));
+
+ pItemConverter = new wrapper::AllAxisItemConverter(
+ xChartModel, rDrawModel.GetItemPool(),
+ rDrawModel, pRefSize.get());
+ }
+ break;
+ case OBJECTTYPE_GRID:
+ case OBJECTTYPE_SUBGRID:
+ pItemConverter = new wrapper::AllGridItemConverter( xChartModel, rDrawModel.GetItemPool(),
+ rDrawModel, xChartModel);
+ break;
+ default: //for this type it is not supported to change all elements at once
+ break;
+ }
+
+ }
+ return pItemConverter;
+}
+
+OUString lcl_getTitleCIDForCommand( std::string_view rDispatchCommand, const rtl::Reference<::chart::ChartModel> & xChartModel )
+{
+ if( rDispatchCommand == "AllTitles")
+ return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_TITLE, u"ALLELEMENTS" );
+
+ TitleHelper::eTitleType nTitleType( TitleHelper::MAIN_TITLE );
+ if( rDispatchCommand == "SubTitle" )
+ nTitleType = TitleHelper::SUB_TITLE;
+ else if( rDispatchCommand == "XTitle" )
+ nTitleType = TitleHelper::X_AXIS_TITLE;
+ else if( rDispatchCommand == "YTitle" )
+ nTitleType = TitleHelper::Y_AXIS_TITLE;
+ else if( rDispatchCommand == "ZTitle" )
+ nTitleType = TitleHelper::Z_AXIS_TITLE;
+ else if( rDispatchCommand == "SecondaryXTitle" )
+ nTitleType = TitleHelper::SECONDARY_X_AXIS_TITLE;
+ else if( rDispatchCommand == "SecondaryYTitle" )
+ nTitleType = TitleHelper::SECONDARY_Y_AXIS_TITLE;
+
+ rtl::Reference< Title > xTitle( TitleHelper::getTitle( nTitleType, xChartModel ) );
+ return ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, xChartModel );
+}
+
+OUString lcl_getAxisCIDForCommand( std::string_view rDispatchCommand, const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ if( rDispatchCommand == "DiagramAxisAll")
+ return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_AXIS, u"ALLELEMENTS" );
+
+ sal_Int32 nDimensionIndex=0;
+ bool bMainAxis=true;
+ if( rDispatchCommand == "DiagramAxisX")
+ {
+ nDimensionIndex=0; bMainAxis=true;
+ }
+ else if( rDispatchCommand == "DiagramAxisY")
+ {
+ nDimensionIndex=1; bMainAxis=true;
+ }
+ else if( rDispatchCommand == "DiagramAxisZ")
+ {
+ nDimensionIndex=2; bMainAxis=true;
+ }
+ else if( rDispatchCommand == "DiagramAxisA")
+ {
+ nDimensionIndex=0; bMainAxis=false;
+ }
+ else if( rDispatchCommand == "DiagramAxisB")
+ {
+ nDimensionIndex=1; bMainAxis=false;
+ }
+
+ rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram );
+ return ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartModel );
+}
+
+OUString lcl_getGridCIDForCommand( std::string_view rDispatchCommand, const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
+
+ if( rDispatchCommand == "DiagramGridAll")
+ return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_GRID, u"ALLELEMENTS" );
+
+ sal_Int32 nDimensionIndex=0;
+ bool bMainGrid=true;
+
+ //x and y is swapped in the commands
+
+ if( rDispatchCommand == "DiagramGridYMain")
+ {
+ nDimensionIndex=0; bMainGrid=true;
+ }
+ else if( rDispatchCommand == "DiagramGridXMain")
+ {
+ nDimensionIndex=1; bMainGrid=true;
+ }
+ else if( rDispatchCommand == "DiagramGridZMain")
+ {
+ nDimensionIndex=2; bMainGrid=true;
+ }
+ else if( rDispatchCommand == "DiagramGridYHelp")
+ {
+ nDimensionIndex=0; bMainGrid=false;
+ }
+ else if( rDispatchCommand == "DiagramGridXHelp")
+ {
+ nDimensionIndex=1; bMainGrid=false;
+ }
+ else if( rDispatchCommand == "DiagramGridZHelp")
+ {
+ nDimensionIndex=2; bMainGrid=false;
+ }
+
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, true/*bMainAxis*/, xDiagram );
+
+ sal_Int32 nSubGridIndex= bMainGrid ? -1 : 0;
+ OUString aCID( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGridIndex ) );
+ return aCID;
+}
+
+OUString lcl_getErrorCIDForCommand( const ObjectType eDispatchType, const ObjectType &eSelectedType, const OUString &rSelectedCID)
+{
+ if( eSelectedType == eDispatchType )
+ return rSelectedCID;
+
+ return ObjectIdentifier::createClassifiedIdentifierWithParent( eDispatchType, u"", rSelectedCID );
+}
+
+OUString lcl_getObjectCIDForCommand( std::string_view rDispatchCommand, const rtl::Reference<::chart::ChartModel> & xChartDocument, const OUString& rSelectedCID )
+{
+ ObjectType eObjectType = OBJECTTYPE_UNKNOWN;
+
+ const ObjectType eSelectedType = ObjectIdentifier::getObjectType( rSelectedCID );
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rSelectedCID, xChartDocument );
+
+ //legend
+ if( rDispatchCommand == "Legend" || rDispatchCommand == "FormatLegend" )
+ {
+ eObjectType = OBJECTTYPE_LEGEND;
+ //@todo set particular aParticleID if we have more than one legend
+ }
+ //wall floor area
+ else if( rDispatchCommand == "DiagramWall" || rDispatchCommand == "FormatWall" )
+ {
+ //OBJECTTYPE_DIAGRAM;
+ eObjectType = OBJECTTYPE_DIAGRAM_WALL;
+ //@todo set particular aParticleID if we have more than one diagram
+ }
+ else if( rDispatchCommand == "DiagramFloor" || rDispatchCommand == "FormatFloor" )
+ {
+ eObjectType = OBJECTTYPE_DIAGRAM_FLOOR;
+ //@todo set particular aParticleID if we have more than one diagram
+ }
+ else if( rDispatchCommand == "DiagramArea" || rDispatchCommand == "FormatChartArea" )
+ {
+ eObjectType = OBJECTTYPE_PAGE;
+ }
+ //title
+ else if( rDispatchCommand == "MainTitle"
+ || rDispatchCommand == "SubTitle"
+ || rDispatchCommand == "XTitle"
+ || rDispatchCommand == "YTitle"
+ || rDispatchCommand == "ZTitle"
+ || rDispatchCommand == "SecondaryXTitle"
+ || rDispatchCommand == "SecondaryYTitle"
+ || rDispatchCommand == "AllTitles"
+ )
+ {
+ return lcl_getTitleCIDForCommand( rDispatchCommand, xChartDocument );
+ }
+ //axis
+ else if( rDispatchCommand == "DiagramAxisX"
+ || rDispatchCommand == "DiagramAxisY"
+ || rDispatchCommand == "DiagramAxisZ"
+ || rDispatchCommand == "DiagramAxisA"
+ || rDispatchCommand == "DiagramAxisB"
+ || rDispatchCommand == "DiagramAxisAll"
+ )
+ {
+ return lcl_getAxisCIDForCommand( rDispatchCommand, xChartDocument );
+ }
+ //grid
+ else if( rDispatchCommand == "DiagramGridYMain"
+ || rDispatchCommand == "DiagramGridXMain"
+ || rDispatchCommand == "DiagramGridZMain"
+ || rDispatchCommand == "DiagramGridYHelp"
+ || rDispatchCommand == "DiagramGridXHelp"
+ || rDispatchCommand == "DiagramGridZHelp"
+ || rDispatchCommand == "DiagramGridAll"
+ )
+ {
+ return lcl_getGridCIDForCommand( rDispatchCommand, xChartDocument );
+ }
+ //data series
+ else if( rDispatchCommand == "FormatDataSeries" )
+ {
+ if( eSelectedType == OBJECTTYPE_DATA_SERIES )
+ return rSelectedCID;
+ else
+ return ObjectIdentifier::createClassifiedIdentifier(
+ OBJECTTYPE_DATA_SERIES, ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID ) );
+ }
+ //data point
+ else if( rDispatchCommand == "FormatDataPoint" )
+ {
+ return rSelectedCID;
+ }
+ //data labels
+ else if( rDispatchCommand == "FormatDataLabels" )
+ {
+ if( eSelectedType == OBJECTTYPE_DATA_LABELS )
+ return rSelectedCID;
+ else
+ return ObjectIdentifier::createClassifiedIdentifierWithParent(
+ OBJECTTYPE_DATA_LABELS, u"", rSelectedCID );
+ }
+ //data labels
+ else if( rDispatchCommand == "FormatDataLabel" )
+ {
+ if( eSelectedType == OBJECTTYPE_DATA_LABEL )
+ return rSelectedCID;
+ else
+ {
+ sal_Int32 nPointIndex = o3tl::toInt32(ObjectIdentifier::getParticleID( rSelectedCID ));
+ if( nPointIndex>=0 )
+ {
+ OUString aSeriesParticle = ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID );
+ OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) + "=" );
+ OUString aLabelsCID = ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle, aChildParticle );
+ OUString aLabelCID_Stub = ObjectIdentifier::createClassifiedIdentifierWithParent(
+ OBJECTTYPE_DATA_LABEL, u"", aLabelsCID );
+
+ return ObjectIdentifier::createPointCID( aLabelCID_Stub, nPointIndex );
+ }
+ }
+ }
+ //mean value line
+ else if( rDispatchCommand == "FormatMeanValue" )
+ {
+ if( eSelectedType == OBJECTTYPE_DATA_AVERAGE_LINE )
+ return rSelectedCID;
+ else
+ return ObjectIdentifier::createDataCurveCID(
+ ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID ),
+ RegressionCurveHelper::getRegressionCurveIndex( xSeries,
+ RegressionCurveHelper::getMeanValueLine( xSeries ) ), true );
+ }
+ //trend line
+ else if( rDispatchCommand == "FormatTrendline" )
+ {
+ if( eSelectedType == OBJECTTYPE_DATA_CURVE )
+ return rSelectedCID;
+ else
+ return ObjectIdentifier::createDataCurveCID(
+ ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID ),
+ RegressionCurveHelper::getRegressionCurveIndex( xSeries,
+ RegressionCurveHelper::getFirstCurveNotMeanValueLine( xSeries ) ), false );
+ }
+ //trend line equation
+ else if( rDispatchCommand == "FormatTrendlineEquation" )
+ {
+ if( eSelectedType == OBJECTTYPE_DATA_CURVE_EQUATION )
+ return rSelectedCID;
+ else
+ return ObjectIdentifier::createDataCurveEquationCID(
+ ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID ),
+ RegressionCurveHelper::getRegressionCurveIndex( xSeries,
+ RegressionCurveHelper::getFirstCurveNotMeanValueLine( xSeries ) ) );
+ }
+ // y error bars
+ else if( rDispatchCommand == "FormatXErrorBars" )
+ {
+ return lcl_getErrorCIDForCommand(OBJECTTYPE_DATA_ERRORS_X, eSelectedType, rSelectedCID );
+ }
+ // y error bars
+ else if( rDispatchCommand == "FormatYErrorBars" )
+ {
+ return lcl_getErrorCIDForCommand(OBJECTTYPE_DATA_ERRORS_Y, eSelectedType, rSelectedCID );
+ }
+ // axis
+ else if( rDispatchCommand == "FormatAxis" )
+ {
+ if( eSelectedType == OBJECTTYPE_AXIS )
+ return rSelectedCID;
+ else
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( rSelectedCID, xChartDocument );
+ return ObjectIdentifier::createClassifiedIdentifierForObject( xAxis , xChartDocument );
+ }
+ }
+ // major grid
+ else if( rDispatchCommand == "FormatMajorGrid" )
+ {
+ if( eSelectedType == OBJECTTYPE_GRID )
+ return rSelectedCID;
+ else
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( rSelectedCID, xChartDocument );
+ return ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartDocument );
+ }
+
+ }
+ // minor grid
+ else if( rDispatchCommand == "FormatMinorGrid" )
+ {
+ if( eSelectedType == OBJECTTYPE_SUBGRID )
+ return rSelectedCID;
+ else
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( rSelectedCID, xChartDocument );
+ return ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartDocument, 0 /*sub grid index*/ );
+ }
+ }
+ // title
+ else if( rDispatchCommand == "FormatTitle" )
+ {
+ if( eSelectedType == OBJECTTYPE_TITLE )
+ return rSelectedCID;
+ }
+ // stock loss
+ else if( rDispatchCommand == "FormatStockLoss" )
+ {
+ if( eSelectedType == OBJECTTYPE_DATA_STOCK_LOSS )
+ return rSelectedCID;
+ else
+ return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DATA_STOCK_LOSS, u"");
+ }
+ // stock gain
+ else if( rDispatchCommand == "FormatStockGain" )
+ {
+ if( eSelectedType == OBJECTTYPE_DATA_STOCK_GAIN )
+ return rSelectedCID;
+ else
+ return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DATA_STOCK_GAIN, u"" );
+ }
+
+ return ObjectIdentifier::createClassifiedIdentifier(
+ eObjectType,
+ u"" ); // aParticleID
+}
+
+}
+// anonymous namespace
+
+void ChartController::executeDispatch_FormatObject(std::u16string_view rDispatchCommand)
+{
+ rtl::Reference<::chart::ChartModel> xChartDocument( getChartModel() );
+ OString aCommand( OUStringToOString( rDispatchCommand, RTL_TEXTENCODING_ASCII_US ) );
+ OUString rObjectCID = lcl_getObjectCIDForCommand( aCommand, xChartDocument, m_aSelection.getSelectedCID() );
+ executeDlg_ObjectProperties( rObjectCID );
+}
+
+void ChartController::executeDispatch_ObjectProperties()
+{
+ executeDlg_ObjectProperties( m_aSelection.getSelectedCID() );
+}
+
+namespace
+{
+
+OUString lcl_getFormatCIDforSelectedCID( const OUString& rSelectedCID )
+{
+ OUString aFormatCID(rSelectedCID);
+
+ //get type of selected object
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( aFormatCID );
+
+ // some legend entries are handled as if they were data series
+ if( eObjectType==OBJECTTYPE_LEGEND_ENTRY )
+ {
+ std::u16string_view aParentParticle( ObjectIdentifier::getFullParentParticle( rSelectedCID ) );
+ aFormatCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle );
+ }
+
+ // treat diagram as wall
+ if( eObjectType==OBJECTTYPE_DIAGRAM )
+ aFormatCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" );
+
+ return aFormatCID;
+}
+
+}//end anonymous namespace
+
+void ChartController::executeDlg_ObjectProperties( const OUString& rSelectedObjectCID )
+{
+ OUString aObjectCID = lcl_getFormatCIDforSelectedCID( rSelectedObjectCID );
+
+ UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Format,
+ ObjectNameProvider::getName( ObjectIdentifier::getObjectType( aObjectCID ))),
+ m_xUndoManager );
+
+ bool bSuccess = ChartController::executeDlg_ObjectProperties_withoutUndoGuard( aObjectCID, false );
+ if( bSuccess )
+ aUndoGuard.commit();
+}
+
+bool ChartController::executeDlg_ObjectProperties_withoutUndoGuard(
+ const OUString& rObjectCID, bool bSuccessOnUnchanged )
+{
+ //return true if the properties were changed successfully
+ bool bRet = false;
+ if( rObjectCID.isEmpty() )
+ {
+ return bRet;
+ }
+ try
+ {
+ //get type of object
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( rObjectCID );
+ if( eObjectType==OBJECTTYPE_UNKNOWN )
+ {
+ return bRet;
+ }
+ if( eObjectType==OBJECTTYPE_DIAGRAM_WALL || eObjectType==OBJECTTYPE_DIAGRAM_FLOOR )
+ {
+ if( !getFirstDiagram()->isSupportingFloorAndWall() )
+ return bRet;
+ }
+
+ //convert properties to ItemSet
+
+ std::unique_ptr<ReferenceSizeProvider> pRefSizeProv(impl_createReferenceSizeProvider());
+
+ rtl::Reference<::chart::ChartModel> xChartDoc(getChartModel());
+
+ std::unique_ptr<wrapper::ItemConverter> pItemConverter(
+ createItemConverter( rObjectCID, xChartDoc, m_xCC,
+ m_pDrawModelWrapper->getSdrModel(),
+ m_xChartView.get(),
+ pRefSizeProv.get()));
+
+ if (!pItemConverter)
+ return bRet;
+
+ SfxItemSet aItemSet = pItemConverter->CreateEmptyItemSet();
+
+ if ( eObjectType == OBJECTTYPE_DATA_ERRORS_X || eObjectType == OBJECTTYPE_DATA_ERRORS_Y )
+ aItemSet.Put(SfxBoolItem(SCHATTR_STAT_ERRORBAR_TYPE, eObjectType == OBJECTTYPE_DATA_ERRORS_Y ));
+
+ pItemConverter->FillItemSet(aItemSet);
+
+ //prepare dialog
+ ObjectPropertiesDialogParameter aDialogParameter( rObjectCID );
+ aDialogParameter.init(xChartDoc);
+ ViewElementListProvider aViewElementListProvider( m_pDrawModelWrapper.get() );
+
+ SolarMutexGuard aGuard;
+ SchAttribTabDlg aDlg(
+ GetChartFrame(), &aItemSet, &aDialogParameter,
+ &aViewElementListProvider,
+ xChartDoc );
+
+ if(aDialogParameter.HasSymbolProperties())
+ {
+ uno::Reference< beans::XPropertySet > xObjectProperties =
+ ObjectIdentifier::getObjectPropertySet( rObjectCID, xChartDoc );
+ wrapper::DataPointItemConverter aSymbolItemConverter( xChartDoc, m_xCC
+ , xObjectProperties, ObjectIdentifier::getDataSeriesForCID( rObjectCID, xChartDoc )
+ , m_pDrawModelWrapper->getSdrModel().GetItemPool()
+ , m_pDrawModelWrapper->getSdrModel()
+ , xChartDoc
+ , wrapper::GraphicObjectType::FilledDataPoint );
+
+ SfxItemSet aSymbolShapeProperties(aSymbolItemConverter.CreateEmptyItemSet() );
+ aSymbolItemConverter.FillItemSet( aSymbolShapeProperties );
+
+ sal_Int32 const nStandardSymbol=0;//@todo get from somewhere
+ std::optional<Graphic> oAutoSymbolGraphic(std::in_place, aViewElementListProvider.GetSymbolGraphic( nStandardSymbol, &aSymbolShapeProperties ) );
+ // note: the dialog takes the ownership of pSymbolShapeProperties and pAutoSymbolGraphic
+ aDlg.setSymbolInformation( std::move(aSymbolShapeProperties), std::move(oAutoSymbolGraphic) );
+ }
+ if( aDialogParameter.HasStatisticProperties() )
+ {
+ aDlg.SetAxisMinorStepWidthForErrorBarDecimals(
+ InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals( xChartDoc, m_xChartView, rObjectCID ) );
+ }
+
+ //open the dialog
+ if (aDlg.run() == RET_OK || (bSuccessOnUnchanged && aDlg.DialogWasClosedWithOK()))
+ {
+ const SfxItemSet* pOutItemSet = aDlg.GetOutputItemSet();
+ if(pOutItemSet)
+ {
+ ControllerLockGuardUNO aCLGuard(xChartDoc);
+ (void)pItemConverter->ApplyItemSet(*pOutItemSet); //model should be changed now
+ bRet = true;
+ }
+ }
+ }
+ catch( const util::CloseVetoException& )
+ {
+ }
+ catch( const uno::RuntimeException& )
+ {
+ }
+ return bRet;
+}
+
+void ChartController::executeDispatch_View3D()
+{
+ try
+ {
+ UndoLiveUpdateGuard aUndoGuard(
+ SchResId( STR_ACTION_EDIT_3D_VIEW ),
+ m_xUndoManager );
+
+ //open dialog
+ SolarMutexGuard aSolarGuard;
+ View3DDialog aDlg(GetChartFrame(), getChartModel());
+ if (aDlg.run() == RET_OK)
+ aUndoGuard.commit();
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartController_TextEdit.cxx b/chart2/source/controller/main/ChartController_TextEdit.cxx
new file mode 100644
index 0000000000..f2d21779ba
--- /dev/null
+++ b/chart2/source/controller/main/ChartController_TextEdit.cxx
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_wasm_strip.h>
+
+#include <ChartController.hxx>
+
+#include <ResId.hxx>
+#include "UndoGuard.hxx"
+#include <DrawViewWrapper.hxx>
+#include <ChartWindow.hxx>
+#include <ChartModel.hxx>
+#include <ChartView.hxx>
+#include <TitleHelper.hxx>
+#include <ObjectIdentifier.hxx>
+#include <ControllerLockGuard.hxx>
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+#include <AccessibleTextHelper.hxx>
+#endif
+#include <strings.hrc>
+#include <chartview/DrawModelWrapper.hxx>
+#include <osl/diagnose.h>
+
+#include <svx/svdoutl.hxx>
+#include <svx/svxdlg.hxx>
+#include <svx/svxids.hrc>
+#include <editeng/editids.hrc>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/chart2/XTitle.hpp>
+#include <svl/stritem.hxx>
+#include <editeng/fontitem.hxx>
+#include <memory>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+void ChartController::executeDispatch_EditText( const Point* pMousePixel )
+{
+ StartTextEdit( pMousePixel );
+}
+
+void ChartController::StartTextEdit( const Point* pMousePixel )
+{
+ //the first marked object will be edited
+
+ SolarMutexGuard aGuard;
+ SdrObject* pTextObj = m_pDrawViewWrapper->getTextEditObject();
+ if(!pTextObj)
+ return;
+
+ OSL_PRECOND(!m_pTextActionUndoGuard,
+ "ChartController::StartTextEdit: already have a TextUndoGuard!?");
+ m_pTextActionUndoGuard.reset( new UndoGuard(
+ SchResId( STR_ACTION_EDIT_TEXT ), m_xUndoManager ) );
+ SdrOutliner* pOutliner = m_pDrawViewWrapper->getOutliner();
+
+ //#i77362 change notification for changes on additional shapes are missing
+ if( m_xChartView.is() )
+ m_xChartView->setPropertyValue( "SdrViewIsInEditMode", uno::Any(true) );
+
+ auto pChartWindow(GetChartWindow());
+
+ bool bEdit = m_pDrawViewWrapper->SdrBeginTextEdit( pTextObj
+ , m_pDrawViewWrapper->GetPageView()
+ , pChartWindow
+ , false //bIsNewObj
+ , pOutliner
+ , nullptr //pOutlinerView
+ , true //bDontDeleteOutliner
+ , true //bOnlyOneView
+ );
+ if(!bEdit)
+ return;
+
+ m_pDrawViewWrapper->SetEditMode();
+
+ // #i12587# support for shapes in chart
+ if ( pMousePixel )
+ {
+ OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
+ if ( pOutlinerView )
+ {
+ MouseEvent aEditEvt( *pMousePixel, 1, MouseEventModifiers::SYNTHETIC, MOUSE_LEFT, 0 );
+ pOutlinerView->MouseButtonDown( aEditEvt );
+ pOutlinerView->MouseButtonUp( aEditEvt );
+ }
+ }
+
+ if (pChartWindow)
+ {
+ //we invalidate the outliner region because the outliner has some
+ //paint problems (some characters are painted twice a little bit shifted)
+ pChartWindow->Invalidate( m_pDrawViewWrapper->GetMarkedObjBoundRect() );
+ }
+}
+
+bool ChartController::EndTextEdit()
+{
+ m_pDrawViewWrapper->SdrEndTextEdit();
+
+ //#i77362 change notification for changes on additional shapes are missing
+ if( m_xChartView.is() )
+ m_xChartView->setPropertyValue( "SdrViewIsInEditMode", uno::Any(false) );
+
+ SdrObject* pTextObject = m_pDrawViewWrapper->getTextEditObject();
+ if(!pTextObject)
+ return false;
+
+ SdrOutliner* pOutliner = m_pDrawViewWrapper->getOutliner();
+ OutlinerParaObject* pParaObj = pTextObject->GetOutlinerParaObject();
+ if( !pParaObj || !pOutliner )
+ return true;
+
+ pOutliner->SetText( *pParaObj );
+
+ OUString aString = pOutliner->GetText(
+ pOutliner->GetParagraph( 0 ),
+ pOutliner->GetParagraphCount() );
+
+ OUString aObjectCID = m_aSelection.getSelectedCID();
+ if ( !aObjectCID.isEmpty() )
+ {
+ uno::Reference< beans::XPropertySet > xPropSet =
+ ObjectIdentifier::getObjectPropertySet( aObjectCID, getChartModel() );
+
+ // lock controllers till end of block
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+
+ Title* pTitle = dynamic_cast<Title*>(xPropSet.get());
+ TitleHelper::setCompleteString( aString, pTitle, m_xCC );
+
+ OSL_ENSURE(m_pTextActionUndoGuard, "ChartController::EndTextEdit: no TextUndoGuard!");
+ if (m_pTextActionUndoGuard)
+ m_pTextActionUndoGuard->commit();
+ }
+ m_pTextActionUndoGuard.reset();
+ return true;
+}
+
+void ChartController::executeDispatch_InsertSpecialCharacter()
+{
+ SolarMutexGuard aGuard;
+ if( !m_pDrawViewWrapper)
+ {
+ OSL_ENSURE( m_pDrawViewWrapper, "No DrawViewWrapper for ChartController" );
+ return;
+ }
+ if( !m_pDrawViewWrapper->IsTextEdit() )
+ StartTextEdit();
+
+ SvxAbstractDialogFactory * pFact = SvxAbstractDialogFactory::Create();
+
+ SfxAllItemSet aSet( m_pDrawModelWrapper->GetItemPool() );
+ aSet.Put( SfxBoolItem( FN_PARAM_1, false ) );
+
+ //set fixed current font
+ aSet.Put( SfxBoolItem( FN_PARAM_2, true ) ); //maybe not necessary in future
+
+ vcl::Font aCurFont = m_pDrawViewWrapper->getOutliner()->GetRefDevice()->GetFont();
+ aSet.Put( SvxFontItem( aCurFont.GetFamilyType(), aCurFont.GetFamilyName(), aCurFont.GetStyleName(), aCurFont.GetPitch(), aCurFont.GetCharSet(), SID_ATTR_CHAR_FONT ) );
+
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateCharMapDialog(GetChartFrame(), aSet, nullptr));
+ if( pDlg->Execute() != RET_OK )
+ return;
+
+ const SfxItemSet* pSet = pDlg->GetOutputItemSet();
+ OUString aString;
+ if (pSet)
+ if (const SfxStringItem* pCharMapItem = pSet->GetItemIfSet(SID_CHARMAP))
+ aString = pCharMapItem->GetValue();
+
+ OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
+ SdrOutliner* pOutliner = m_pDrawViewWrapper->getOutliner();
+
+ if(!pOutliner || !pOutlinerView)
+ return;
+
+ // insert string to outliner
+
+ // prevent flicker
+ pOutlinerView->HideCursor();
+ pOutliner->SetUpdateLayout(false);
+
+ // delete current selection by inserting empty String, so current
+ // attributes become unique (sel. has to be erased anyway)
+ pOutlinerView->InsertText(OUString());
+
+ pOutlinerView->InsertText(aString, true);
+
+ ESelection aSel = pOutlinerView->GetSelection();
+ aSel.nStartPara = aSel.nEndPara;
+ aSel.nStartPos = aSel.nEndPos;
+ pOutlinerView->SetSelection(aSel);
+
+ // show changes
+ pOutliner->SetUpdateLayout(true);
+ pOutlinerView->ShowCursor();
+}
+
+rtl::Reference< ::chart::AccessibleTextHelper >
+ ChartController::createAccessibleTextContext()
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ return new AccessibleTextHelper( m_pDrawViewWrapper.get() );
+#else
+ return {};
+#endif
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartController_Tools.cxx b/chart2/source/controller/main/ChartController_Tools.cxx
new file mode 100644
index 0000000000..48dbfaf7f6
--- /dev/null
+++ b/chart2/source/controller/main/ChartController_Tools.cxx
@@ -0,0 +1,1127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartController.hxx>
+#include <ChartWindow.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <TitleHelper.hxx>
+#include <ThreeDHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include "UndoGuard.hxx"
+#include <ControllerLockGuard.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+#include <ObjectIdentifier.hxx>
+#include <ReferenceSizeProvider.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include "ChartTransferable.hxx"
+#include <DrawViewWrapper.hxx>
+#include <Legend.hxx>
+#include <LegendHelper.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <RegressionCurveHelper.hxx>
+#include "ShapeController.hxx"
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ObjectNameProvider.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+
+#include <docmodel/uno/UnoGradientTools.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/outliner.hxx>
+#include <svx/ActionDescriptionProvider.hxx>
+#include <vcl/transfer.hxx>
+#include <sot/storage.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/TypeSerializer.hxx>
+#include <svx/unomodel.hxx>
+#include <svx/svdmodel.hxx>
+#include <unotools/streamwrap.hxx>
+#include <vcl/svapp.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/strings.hrc>
+#include <svx/svditer.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdundo.hxx>
+#include <svx/unoapi.hxx>
+#include <svx/unopage.hxx>
+#include <svx/unoshape.hxx>
+#include <PropertyHelper.hxx>
+
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <tools/debug.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/UnitConversion.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+namespace
+{
+
+bool lcl_deleteDataSeries(
+ std::u16string_view rCID,
+ const rtl::Reference<::chart::ChartModel> & xModel,
+ const Reference< document::XUndoManager > & xUndoManager )
+{
+ bool bResult = false;
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rCID, xModel );
+ if( xSeries.is() && xModel.is())
+ {
+ rtl::Reference< ::chart::ChartType > xChartType =
+ DataSeriesHelper::getChartTypeOfSeries( xSeries, xModel->getFirstChartDiagram());
+ if( xChartType.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_DATASERIES )),
+ xUndoManager );
+
+ rtl::Reference< Diagram > xDiagram = xModel->getFirstChartDiagram();
+ rtl::Reference< Axis > xAxis = xDiagram->getAttachedAxis( xSeries );
+
+ DataSeriesHelper::deleteSeries( xSeries, xChartType );
+
+ AxisHelper::hideAxisIfNoDataIsAttached( xAxis, xDiagram );
+
+ bResult = true;
+ aUndoGuard.commit();
+ }
+ }
+ return bResult;
+}
+
+bool lcl_deleteDataCurve(
+ std::u16string_view rCID,
+ const rtl::Reference<::chart::ChartModel> & xModel,
+ const Reference< document::XUndoManager > & xUndoManager )
+{
+ bool bResult = false;
+
+ uno::Reference< beans::XPropertySet > xProperties(
+ ObjectIdentifier::getObjectPropertySet( rCID, xModel));
+
+ uno::Reference< chart2::XRegressionCurve > xRegressionCurve( xProperties, uno::UNO_QUERY );
+
+ if( xRegressionCurve.is())
+ {
+ uno::Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer(
+ ObjectIdentifier::getObjectPropertySet(
+ ObjectIdentifier::getFullParentParticle( rCID ), xModel), uno::UNO_QUERY );
+
+ if( xRegressionCurveContainer.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_CURVE )),
+ xUndoManager );
+
+ xRegressionCurveContainer->removeRegressionCurve( xRegressionCurve );
+
+ bResult = true;
+ aUndoGuard.commit();
+ }
+ }
+ return bResult;
+}
+
+} // anonymous namespace
+
+std::unique_ptr<ReferenceSizeProvider> ChartController::impl_createReferenceSizeProvider()
+{
+ awt::Size aPageSize( ChartModelHelper::getPageSize( getChartModel() ) );
+
+ return std::make_unique<ReferenceSizeProvider>(aPageSize, getChartModel());
+}
+
+void ChartController::impl_adaptDataSeriesAutoResize()
+{
+ std::unique_ptr<ReferenceSizeProvider> pRefSizeProvider(impl_createReferenceSizeProvider());
+ if (pRefSizeProvider)
+ pRefSizeProvider->setValuesAtAllDataSeries();
+}
+
+void ChartController::executeDispatch_NewArrangement()
+{
+ // remove manual positions at titles, legend and the diagram, remove manual
+ // size at the diagram
+
+ try
+ {
+ rtl::Reference<::chart::ChartModel> xModel( getChartModel() );
+ rtl::Reference< Diagram > xDiagram = xModel->getFirstChartDiagram();
+ if( xDiagram.is())
+ {
+ UndoGuard aUndoGuard(
+ SchResId( STR_ACTION_REARRANGE_CHART ),
+ m_xUndoManager );
+ ControllerLockGuardUNO aCtlLockGuard( xModel );
+
+ // diagram
+ xDiagram->setPropertyToDefault( "RelativeSize");
+ xDiagram->setPropertyToDefault( "RelativePosition");
+ xDiagram->setPropertyToDefault( "PosSizeExcludeAxes");
+
+ // 3d rotation
+ xDiagram->set3DSettingsToDefault();
+
+ // legend
+ rtl::Reference< Legend > xLegend = xDiagram->getLegend2();
+ if( xLegend.is())
+ {
+ xLegend->setPropertyToDefault( "RelativePosition");
+ xLegend->setPropertyToDefault( "RelativeSize");
+ xLegend->setPropertyToDefault( "AnchorPosition");
+ }
+
+ // titles
+ for( sal_Int32 eType = TitleHelper::TITLE_BEGIN;
+ eType < TitleHelper::NORMAL_TITLE_END;
+ ++eType )
+ {
+ rtl::Reference< Title > xTitleState =
+ TitleHelper::getTitle(
+ static_cast< TitleHelper::eTitleType >( eType ), xModel );
+ if( xTitleState.is())
+ xTitleState->setPropertyToDefault( "RelativePosition");
+ }
+
+ // regression curve equations
+ std::vector< rtl::Reference< RegressionCurveModel > > aRegressionCurves =
+ xDiagram->getAllRegressionCurvesNotMeanValueLine();
+
+ // reset equation position
+ for( const auto& xCurve : aRegressionCurves )
+ RegressionCurveHelper::resetEquationPosition( xCurve );
+
+ aUndoGuard.commit();
+ }
+ }
+ catch( const uno::RuntimeException & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ChartController::executeDispatch_ScaleText()
+{
+ SolarMutexGuard aSolarGuard;
+ UndoGuard aUndoGuard(
+ SchResId( STR_ACTION_SCALE_TEXT ),
+ m_xUndoManager );
+ ControllerLockGuardUNO aCtlLockGuard( getChartModel() );
+
+ std::unique_ptr<ReferenceSizeProvider> pRefSizeProv(impl_createReferenceSizeProvider());
+ OSL_ASSERT(pRefSizeProv);
+ if (pRefSizeProv)
+ pRefSizeProv->toggleAutoResizeState();
+
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_Paste()
+{
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+ if( !pChartWindow )
+ return;
+
+ Graphic aGraphic;
+ // paste location: center of window
+ Point aPos = pChartWindow->PixelToLogic( tools::Rectangle(Point{}, pChartWindow->GetSizePixel()).Center());
+
+ // handle different formats
+ TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pChartWindow ));
+ if( aDataHelper.GetTransferable().is())
+ {
+ if ( aDataHelper.HasFormat( SotClipboardFormatId::DRAWING ) )
+ {
+ tools::SvRef<SotTempStream> xStm;
+ if ( aDataHelper.GetSotStorageStream( SotClipboardFormatId::DRAWING, xStm ) )
+ {
+ xStm->Seek( 0 );
+ Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( *xStm ) );
+
+ std::unique_ptr< SdrModel > spModel(
+ new SdrModel());
+
+ if ( SvxDrawingLayerImport( spModel.get(), xInputStream ) )
+ {
+ impl_PasteShapes( spModel.get() );
+ }
+ }
+ }
+ else if ( aDataHelper.HasFormat( SotClipboardFormatId::SVXB ) )
+ {
+ // graphic exchange format (graphic manager bitmap format?)
+ tools::SvRef<SotTempStream> xStm;
+ if( aDataHelper.GetSotStorageStream( SotClipboardFormatId::SVXB, xStm ))
+ {
+ TypeSerializer aSerializer(*xStm);
+ aSerializer.readGraphic(aGraphic);
+ }
+ }
+ else if( aDataHelper.HasFormat( SotClipboardFormatId::GDIMETAFILE ))
+ {
+ // meta file
+ GDIMetaFile aMetafile;
+ if( aDataHelper.GetGDIMetaFile( SotClipboardFormatId::GDIMETAFILE, aMetafile ))
+ aGraphic = Graphic( aMetafile );
+ }
+ else if( aDataHelper.HasFormat( SotClipboardFormatId::BITMAP ))
+ {
+ // bitmap (non-graphic-manager)
+ BitmapEx aBmpEx;
+ if( aDataHelper.GetBitmapEx( SotClipboardFormatId::BITMAP, aBmpEx ))
+ aGraphic = Graphic( aBmpEx );
+ }
+ else if( aDataHelper.HasFormat( SotClipboardFormatId::STRING ))
+ {
+ OUString aString;
+ if( aDataHelper.GetString( SotClipboardFormatId::STRING, aString ) && m_pDrawModelWrapper )
+ {
+ if( m_pDrawViewWrapper )
+ {
+ OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
+ if( pOutlinerView )//in case of edit mode insert into edited string
+ pOutlinerView->InsertText( aString );
+ else
+ {
+ impl_PasteStringAsTextShape( aString, awt::Point( 0, 0 ) );
+ }
+ }
+ }
+ }
+ }
+
+ if( aGraphic.GetType() != GraphicType::NONE )
+ {
+ Reference< graphic::XGraphic > xGraphic( aGraphic.GetXGraphic());
+ if( xGraphic.is())
+ impl_PasteGraphic( xGraphic, aPos );
+ }
+}
+
+// note: aPosition is ignored for now. The object is always pasted centered to
+// the page
+void ChartController::impl_PasteGraphic(
+ uno::Reference< graphic::XGraphic > const & xGraphic,
+ const ::Point & /* aPosition */ )
+{
+ DBG_TESTSOLARMUTEX();
+ // note: the XPropertySet of the model is the old API. Also the property
+ // "AdditionalShapes" that is used there.
+ rtl::Reference< ChartModel > xModel = getChartModel();
+ DrawModelWrapper * pDrawModelWrapper( GetDrawModelWrapper());
+ if( ! (xGraphic.is() && xModel.is()))
+ return;
+ rtl::Reference<SvxGraphicObject> xGraphicShape = new SvxGraphicObject(nullptr);
+ xGraphicShape->setShapeKind(SdrObjKind::Graphic);
+
+ uno::Reference< drawing::XShapes > xPage = pDrawModelWrapper->getMainDrawPage();
+ if( xPage.is())
+ {
+ xPage->add( xGraphicShape );
+ //need to change the model state manually
+ xModel->setModified( true );
+ //select new shape
+ m_aSelection.setSelection( xGraphicShape );
+ m_aSelection.applySelection( m_pDrawViewWrapper.get() );
+ }
+ xGraphicShape->SvxShape::setPropertyValue( "Graphic", uno::Any( xGraphic ));
+
+ awt::Size aGraphicSize( 1000, 1000 );
+ bool bGotGraphicSize = false;
+ try
+ {
+ bGotGraphicSize = xGraphicShape->SvxShape::getPropertyValue( "Size100thMM") >>= aGraphicSize;
+ }
+ catch (css::beans::UnknownPropertyException& )
+ {}
+ auto pChartWindow(GetChartWindow());
+ // first try size in 100th mm, then pixel size
+ if( !bGotGraphicSize )
+ {
+ bool bGotSizePixel = false;
+ try
+ {
+ bGotSizePixel = xGraphicShape->SvxShape::getPropertyValue( "SizePixel") >>= aGraphicSize;
+ }
+ catch (css::beans::UnknownPropertyException& )
+ {}
+ if ( bGotSizePixel && pChartWindow )
+ {
+ ::Size aVCLSize( pChartWindow->PixelToLogic( Size( aGraphicSize.Width, aGraphicSize.Height )));
+ aGraphicSize.Width = aVCLSize.getWidth();
+ aGraphicSize.Height = aVCLSize.getHeight();
+ }
+ }
+ xGraphicShape->setSize( aGraphicSize );
+ xGraphicShape->setPosition( awt::Point( 0, 0 ) );
+}
+
+void ChartController::impl_PasteShapes( SdrModel* pModel )
+{
+ DrawModelWrapper* pDrawModelWrapper( GetDrawModelWrapper() );
+ if ( !(pDrawModelWrapper && m_pDrawViewWrapper) )
+ return;
+
+ Reference< drawing::XDrawPage > xDestPage( pDrawModelWrapper->getMainDrawPage() );
+ SdrPage* pDestPage = GetSdrPageFromXDrawPage( xDestPage );
+ if ( !pDestPage )
+ return;
+
+ Reference< drawing::XShape > xSelShape;
+ m_pDrawViewWrapper->BegUndo( SvxResId( RID_SVX_3D_UNDO_EXCHANGE_PASTE ) );
+ sal_uInt16 nCount = pModel->GetPageCount();
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ const SdrPage* pPage = pModel->GetPage( i );
+ SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups );
+ while ( aIter.IsMore() )
+ {
+ SdrObject* pObj(aIter.Next());
+ // Clone to new SdrModel
+ rtl::Reference<SdrObject> pNewObj;
+ if (pObj)
+ pNewObj = pObj->CloneSdrObject(pDrawModelWrapper->getSdrModel());
+
+ if ( pNewObj )
+ {
+ // set position
+ Reference< drawing::XShape > xShape( pNewObj->getUnoShape(), uno::UNO_QUERY );
+ if ( xShape.is() )
+ {
+ xShape->setPosition( awt::Point( 0, 0 ) );
+ }
+
+ pDestPage->InsertObject( pNewObj.get() );
+ m_pDrawViewWrapper->AddUndo( std::make_unique<SdrUndoInsertObj>( *pNewObj ) );
+ xSelShape = xShape;
+ }
+ }
+ }
+
+ rtl::Reference< ChartModel > xModifiable = getChartModel();
+ if ( xModifiable.is() )
+ {
+ xModifiable->setModified( true );
+ }
+
+ // select last inserted shape
+ m_aSelection.setSelection( xSelShape );
+ m_aSelection.applySelection( m_pDrawViewWrapper.get() );
+
+ m_pDrawViewWrapper->EndUndo();
+
+ impl_switchDiagramPositioningToExcludingPositioning();
+}
+
+void ChartController::impl_PasteStringAsTextShape( const OUString& rString, const awt::Point& rPosition )
+{
+ DrawModelWrapper* pDrawModelWrapper( GetDrawModelWrapper() );
+ if ( !(pDrawModelWrapper && m_pDrawViewWrapper) )
+ return;
+
+ const Reference< drawing::XDrawPage >& xDrawPage( pDrawModelWrapper->getMainDrawPage() );
+ OSL_ASSERT( xDrawPage.is() );
+
+ if ( !xDrawPage )
+ return;
+
+ try
+ {
+ rtl::Reference<SvxShapeText> xTextShape = new SvxShapeText(nullptr);
+ xTextShape->setShapeKind(SdrObjKind::Text);
+ xDrawPage->add( xTextShape );
+
+ xTextShape->setString( rString );
+
+ float fCharHeight = 10.0;
+ xTextShape->SvxShape::setPropertyValue( "TextAutoGrowHeight", uno::Any( true ) );
+ xTextShape->SvxShape::setPropertyValue( "TextAutoGrowWidth", uno::Any( true ) );
+ xTextShape->SvxShape::setPropertyValue( "CharHeight", uno::Any( fCharHeight ) );
+ xTextShape->SvxShape::setPropertyValue( "CharHeightAsian", uno::Any( fCharHeight ) );
+ xTextShape->SvxShape::setPropertyValue( "CharHeightComplex", uno::Any( fCharHeight ) );
+ xTextShape->SvxShape::setPropertyValue( "TextVerticalAdjust", uno::Any( drawing::TextVerticalAdjust_CENTER ) );
+ xTextShape->SvxShape::setPropertyValue( "TextHorizontalAdjust", uno::Any( drawing::TextHorizontalAdjust_CENTER ) );
+ xTextShape->SvxShape::setPropertyValue( "CharFontName", uno::Any( OUString("Albany") ) );
+
+ xTextShape->setPosition( rPosition );
+
+ m_aSelection.setSelection( xTextShape );
+ m_aSelection.applySelection( m_pDrawViewWrapper.get() );
+
+ SdrObject* pObj = DrawViewWrapper::getSdrObject( xTextShape );
+ if ( pObj )
+ {
+ m_pDrawViewWrapper->BegUndo( SvxResId( RID_SVX_3D_UNDO_EXCHANGE_PASTE ) );
+ m_pDrawViewWrapper->AddUndo( std::make_unique<SdrUndoInsertObj>( *pObj ) );
+ m_pDrawViewWrapper->EndUndo();
+
+ impl_switchDiagramPositioningToExcludingPositioning();
+ }
+ }
+ catch ( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ChartController::executeDispatch_Copy()
+{
+ SolarMutexGuard aSolarGuard;
+ if (!m_pDrawViewWrapper)
+ return;
+
+ OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
+ if (pOutlinerView)
+ pOutlinerView->Copy();
+ else
+ {
+ SdrObject* pSelectedObj = nullptr;
+ ObjectIdentifier aSelOID(m_aSelection.getSelectedOID());
+
+ if (aSelOID.isAutoGeneratedObject())
+ pSelectedObj = m_pDrawModelWrapper->getNamedSdrObject( aSelOID.getObjectCID() );
+ else if (aSelOID.isAdditionalShape())
+ pSelectedObj = DrawViewWrapper::getSdrObject( aSelOID.getAdditionalShape() );
+
+ if (pSelectedObj)
+ {
+ Reference<datatransfer::clipboard::XClipboard> xClipboard(GetChartWindow()->GetClipboard());
+ if (xClipboard.is())
+ {
+ Reference< datatransfer::XTransferable > xTransferable(
+ new ChartTransferable(m_pDrawModelWrapper->getSdrModel(),
+ pSelectedObj, aSelOID.isAdditionalShape()));
+ xClipboard->setContents(xTransferable, Reference< datatransfer::clipboard::XClipboardOwner >());
+ }
+ }
+ }
+}
+
+void ChartController::executeDispatch_Cut()
+{
+ executeDispatch_Copy();
+ executeDispatch_Delete();
+}
+
+bool ChartController::isObjectDeleteable( const uno::Any& rSelection )
+{
+ ObjectIdentifier aSelOID( rSelection );
+ if ( aSelOID.isAutoGeneratedObject() )
+ {
+ const OUString& aSelObjCID( aSelOID.getObjectCID() );
+ ObjectType aObjectType(ObjectIdentifier::getObjectType( aSelObjCID ));
+
+ switch(aObjectType)
+ {
+ case OBJECTTYPE_TITLE:
+ case OBJECTTYPE_LEGEND:
+ case OBJECTTYPE_DATA_SERIES:
+ case OBJECTTYPE_LEGEND_ENTRY:
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ case OBJECTTYPE_DATA_CURVE:
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ case OBJECTTYPE_DATA_ERRORS_X:
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ case OBJECTTYPE_DATA_LABELS:
+ case OBJECTTYPE_DATA_LABEL:
+ case OBJECTTYPE_AXIS:
+ case OBJECTTYPE_GRID:
+ case OBJECTTYPE_SUBGRID:
+ return true;
+ default:
+ break;
+ }
+ }
+ else if ( aSelOID.isAdditionalShape() )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool ChartController::isShapeContext() const
+{
+ return m_aSelection.isAdditionalShapeSelected() ||
+ ( m_pDrawViewWrapper && m_pDrawViewWrapper->AreObjectsMarked() &&
+ ( m_pDrawViewWrapper->GetCurrentObjIdentifier() == SdrObjKind::Text ) );
+}
+
+void ChartController::impl_ClearSelection()
+{
+ if( m_aSelection.hasSelection())
+ {
+ m_aSelection.clearSelection();
+ impl_notifySelectionChangeListeners();
+ }
+}
+
+bool ChartController::executeDispatch_Delete()
+{
+ bool bReturn = false;
+
+ // remove the selected object
+ OUString aCID( m_aSelection.getSelectedCID() );
+ if( !aCID.isEmpty() )
+ {
+ if( !isObjectDeleteable( uno::Any( aCID ) ) )
+ return false;
+
+ //remove chart object
+ rtl::Reference< ChartModel > xChartDoc = getChartModel();
+ if( !xChartDoc.is() )
+ return false;
+
+ ObjectType aObjectType( ObjectIdentifier::getObjectType( aCID ));
+ switch( aObjectType )
+ {
+ case OBJECTTYPE_TITLE:
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_TITLE )),
+ m_xUndoManager );
+ TitleHelper::removeTitle(
+ ObjectIdentifier::getTitleTypeForCID( aCID ), getChartModel() );
+ bReturn = true;
+ aUndoGuard.commit();
+ break;
+ }
+ case OBJECTTYPE_LEGEND:
+ {
+ rtl::Reference< Diagram > xDiagram( xChartDoc->getFirstChartDiagram());
+ if( xDiagram.is())
+ {
+ rtl::Reference< Legend > xLegend( xDiagram->getLegend2() );
+ if( xLegend.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_LEGEND )),
+ m_xUndoManager );
+ xLegend->setPropertyValue( "Show", uno::Any( false ));
+ bReturn = true;
+ aUndoGuard.commit();
+ }
+ }
+ break;
+ }
+
+ case OBJECTTYPE_DATA_SERIES:
+ bReturn = lcl_deleteDataSeries( aCID, getChartModel(), m_xUndoManager );
+ break;
+
+ case OBJECTTYPE_LEGEND_ENTRY:
+ {
+ ObjectType eParentObjectType = ObjectIdentifier::getObjectType(
+ ObjectIdentifier::getFullParentParticle( aCID ));
+ if( eParentObjectType == OBJECTTYPE_DATA_SERIES )
+ {
+ bReturn = lcl_deleteDataSeries( aCID, getChartModel(), m_xUndoManager );
+ }
+ else if( eParentObjectType == OBJECTTYPE_DATA_CURVE )
+ {
+ sal_Int32 nEndPos = aCID.lastIndexOf(':');
+ OUString aParentCID = aCID.copy(0, nEndPos);
+
+ bReturn = lcl_deleteDataCurve(aParentCID, getChartModel(), m_xUndoManager );
+ }
+ else if( eParentObjectType == OBJECTTYPE_DATA_AVERAGE_LINE )
+ {
+ executeDispatch_DeleteMeanValue();
+ bReturn = true;
+ }
+ break;
+ }
+
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ {
+ uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt(
+ ObjectIdentifier::getObjectPropertySet(
+ ObjectIdentifier::getFullParentParticle( aCID ), getChartModel()), uno::UNO_QUERY );
+ if( xRegCurveCnt.is())
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_AVERAGE_LINE )),
+ m_xUndoManager );
+ RegressionCurveHelper::removeMeanValueLine( xRegCurveCnt );
+ bReturn = true;
+ aUndoGuard.commit();
+ }
+ }
+ break;
+
+ case OBJECTTYPE_DATA_CURVE:
+ {
+ bReturn = lcl_deleteDataCurve( aCID, getChartModel(), m_xUndoManager );
+ }
+ break;
+
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ {
+ uno::Reference< beans::XPropertySet > xEqProp(
+ ObjectIdentifier::getObjectPropertySet( aCID, getChartModel()));
+
+ if( xEqProp.is())
+ {
+ rtl::Reference<::chart::ChartModel> xModel( getChartModel() );
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_CURVE_EQUATION )),
+ m_xUndoManager );
+ {
+ ControllerLockGuardUNO aCtlLockGuard( xModel );
+ xEqProp->setPropertyValue( "ShowEquation", uno::Any( false ));
+ xEqProp->setPropertyValue( "XName", uno::Any( OUString("x") ));
+ xEqProp->setPropertyValue( "YName", uno::Any( OUString("f(x)") ));
+ xEqProp->setPropertyValue( "ShowCorrelationCoefficient", uno::Any( false ));
+ }
+ bReturn = true;
+ aUndoGuard.commit();
+ }
+ }
+ break;
+
+ case OBJECTTYPE_DATA_ERRORS_X:
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ {
+ uno::Reference< beans::XPropertySet > xErrorBarProp(
+ ObjectIdentifier::getObjectPropertySet( aCID, getChartModel() ));
+ if( xErrorBarProp.is())
+ {
+ TranslateId pId;
+
+ if ( aObjectType == OBJECTTYPE_DATA_ERRORS_X )
+ pId = STR_OBJECT_ERROR_BARS_X;
+ else if ( aObjectType == OBJECTTYPE_DATA_ERRORS_Y )
+ pId = STR_OBJECT_ERROR_BARS_Y;
+ else
+ pId = STR_OBJECT_ERROR_BARS_Z;
+
+ rtl::Reference<::chart::ChartModel> xModel( getChartModel() );
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete, SchResId(pId)),
+ m_xUndoManager);
+ {
+ ControllerLockGuardUNO aCtlLockGuard( xModel );
+ xErrorBarProp->setPropertyValue(
+ "ErrorBarStyle",
+ uno::Any( css::chart::ErrorBarStyle::NONE ));
+ }
+ bReturn = true;
+ aUndoGuard.commit();
+ }
+ break;
+ }
+
+ case OBJECTTYPE_DATA_LABELS:
+ case OBJECTTYPE_DATA_LABEL:
+ {
+ uno::Reference< beans::XPropertySet > xObjectProperties =
+ ObjectIdentifier::getObjectPropertySet( aCID, getChartModel() );
+ if( xObjectProperties.is() )
+ {
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::Delete,
+ SchResId( aObjectType == OBJECTTYPE_DATA_LABEL ? STR_OBJECT_LABEL : STR_OBJECT_DATALABELS )),
+ m_xUndoManager );
+ chart2::DataPointLabel aLabel;
+ xObjectProperties->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel;
+ aLabel.ShowNumber = false;
+ aLabel.ShowNumberInPercent = false;
+ aLabel.ShowCategoryName = false;
+ aLabel.ShowLegendSymbol = false;
+ aLabel.ShowCustomLabel = false;
+ aLabel.ShowSeriesName = false;
+ if( aObjectType == OBJECTTYPE_DATA_LABELS )
+ {
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( aCID, getChartModel() );
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, CHART_UNONAME_LABEL, uno::Any(aLabel) );
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, CHART_UNONAME_CUSTOM_LABEL_FIELDS, uno::Any() );
+ }
+ else
+ {
+ xObjectProperties->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabel));
+ xObjectProperties->setPropertyValue(CHART_UNONAME_CUSTOM_LABEL_FIELDS, uno::Any());
+ }
+ bReturn = true;
+ aUndoGuard.commit();
+ }
+ break;
+ }
+ case OBJECTTYPE_AXIS:
+ {
+ executeDispatch_DeleteAxis();
+ bReturn = true;
+ break;
+ }
+ case OBJECTTYPE_GRID:
+ {
+ executeDispatch_DeleteMajorGrid();
+ bReturn = true;
+ break;
+ }
+ case OBJECTTYPE_SUBGRID:
+ {
+ executeDispatch_DeleteMinorGrid();
+ bReturn = true;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ //remove additional shape
+ impl_ClearSelection();
+ {
+ SolarMutexGuard aSolarGuard;
+ if ( m_pDrawViewWrapper )
+ {
+ m_pDrawViewWrapper->DeleteMarked();
+ bReturn = true;
+ }
+ }
+ }
+ return bReturn;
+}
+
+void ChartController::executeDispatch_ToggleLegend()
+{
+ rtl::Reference< ChartModel > xModel = getChartModel();
+ UndoGuard aUndoGuard(
+ SchResId( STR_ACTION_TOGGLE_LEGEND ), m_xUndoManager );
+ rtl::Reference< Legend > xLegendProp = LegendHelper::getLegend(*xModel);
+ bool bChanged = false;
+ if( xLegendProp.is())
+ {
+ try
+ {
+ bool bShow = false;
+ if( xLegendProp->getPropertyValue( "Show") >>= bShow )
+ {
+ xLegendProp->setPropertyValue( "Show", uno::Any( ! bShow ));
+ bChanged = true;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ else
+ {
+ xLegendProp = LegendHelper::getLegend(*xModel, m_xCC, true);
+ if( xLegendProp.is())
+ bChanged = true;
+ }
+
+ if( bChanged )
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_ToggleGridHorizontal()
+{
+ UndoGuard aUndoGuard(
+ SchResId( STR_ACTION_TOGGLE_GRID_HORZ ), m_xUndoManager );
+ rtl::Reference< Diagram > xDiagram( getFirstDiagram() );
+ if( !xDiagram.is())
+ return;
+
+ sal_Int32 nDimensionIndex = 1;
+ sal_Int32 nCooSysIndex = 0;
+
+ bool bHasMajorYGrid = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true, xDiagram );
+ bool bHasMinorYGrid = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false, xDiagram );
+
+ if( bHasMajorYGrid )
+ {
+ if ( bHasMinorYGrid )
+ {
+ AxisHelper::hideGrid( nDimensionIndex, nCooSysIndex, true, xDiagram );
+ AxisHelper::hideGrid( nDimensionIndex, nCooSysIndex, false, xDiagram );
+ }
+ else
+ {
+ AxisHelper::showGrid( nDimensionIndex, nCooSysIndex, false, xDiagram );
+ }
+ }
+ else
+ {
+ AxisHelper::showGrid( nDimensionIndex, nCooSysIndex, true, xDiagram );
+ }
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_ToggleGridVertical()
+{
+ UndoGuard aUndoGuard(
+ SchResId( STR_ACTION_TOGGLE_GRID_VERTICAL ), m_xUndoManager );
+ rtl::Reference< Diagram > xDiagram( getFirstDiagram() );
+ if( !xDiagram.is())
+ return;
+
+ sal_Int32 nDimensionIndex = 0;
+ sal_Int32 nCooSysIndex = 0;
+
+ bool bHasMajorXGrid = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true, xDiagram );
+ bool bHasMinorXGrid = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false, xDiagram );
+ if( bHasMajorXGrid )
+ {
+ if (bHasMinorXGrid)
+ {
+ AxisHelper::hideGrid( nDimensionIndex, nCooSysIndex, true, xDiagram );
+ AxisHelper::hideGrid( nDimensionIndex, nCooSysIndex, false, xDiagram );
+ }
+ else
+ {
+ AxisHelper::showGrid( nDimensionIndex, nCooSysIndex, false, xDiagram );
+ }
+ }
+ else
+ {
+ AxisHelper::showGrid( nDimensionIndex, nCooSysIndex, true, xDiagram );
+ }
+
+ aUndoGuard.commit();
+}
+
+void ChartController::executeDispatch_FillColor(sal_uInt32 nColor)
+{
+ try
+ {
+ OUString aCID( m_aSelection.getSelectedCID() );
+ rtl::Reference<::chart::ChartModel> xChartModel = getChartModel();
+ if( xChartModel.is() )
+ {
+ Reference< beans::XPropertySet > xPointProperties(
+ ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ) );
+ if( xPointProperties.is() )
+ xPointProperties->setPropertyValue( "FillColor", uno::Any( nColor ) );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION( "chart2" );
+ }
+}
+
+void ChartController::executeDispatch_FillGradient(std::u16string_view sJSONGradient)
+{
+ basegfx::BGradient aBGradient = basegfx::BGradient::fromJSON(sJSONGradient);
+ css::awt::Gradient aGradient = model::gradient::createUnoGradient2(aBGradient);
+
+ try
+ {
+ OUString aCID( m_aSelection.getSelectedCID() );
+ rtl::Reference<::chart::ChartModel> xChartModel = getChartModel();
+
+ if( xChartModel.is() )
+ {
+ Reference< beans::XPropertySet > xPropSet(
+ ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ) );
+
+ if( xPropSet.is() )
+ {
+ OUString aPrefferedName =
+ OUString::number(static_cast<sal_Int32>(Color(aBGradient.GetColorStops().front().getStopColor())))
+ + OUString::number(static_cast<sal_Int32>(Color(aBGradient.GetColorStops().back().getStopColor())))
+ + OUString::number(static_cast<sal_Int32>(aBGradient.GetAngle().get()));
+
+ OUString aNewName = PropertyHelper::addGradientUniqueNameToTable(css::uno::Any(aGradient),
+ xChartModel,
+ aPrefferedName);
+
+ xPropSet->setPropertyValue("FillGradientName", css::uno::Any(aNewName));
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::executeDispatch_LineColor(sal_uInt32 nColor)
+{
+ try
+ {
+ OUString aCID( m_aSelection.getSelectedCID() );
+ rtl::Reference<::chart::ChartModel> xChartModel = getChartModel();
+ if( xChartModel.is() )
+ {
+ Reference< beans::XPropertySet > xPropSet(
+ ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ) );
+
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType == OBJECTTYPE_DIAGRAM)
+ {
+ css::uno::Reference<css::chart2::XDiagram> xDiagram(
+ xPropSet, css::uno::UNO_QUERY);
+ if (xDiagram.is())
+ xPropSet.set(xDiagram->getWall());
+ }
+
+ if( xPropSet.is() )
+ xPropSet->setPropertyValue( "LineColor", css::uno::Any( Color(ColorTransparency, nColor) ) );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION( "chart2" );
+ }
+}
+
+void ChartController::executeDispatch_LineWidth(sal_uInt32 nWidth)
+{
+ try
+ {
+ OUString aCID( m_aSelection.getSelectedCID() );
+ rtl::Reference<::chart::ChartModel> xChartModel = getChartModel();
+ if( xChartModel.is() )
+ {
+ Reference< beans::XPropertySet > xPropSet(
+ ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ) );
+
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType == OBJECTTYPE_DIAGRAM)
+ {
+ css::uno::Reference<css::chart2::XDiagram> xDiagram(
+ xPropSet, css::uno::UNO_QUERY);
+ if (xDiagram.is())
+ xPropSet.set(xDiagram->getWall());
+ }
+
+ if( xPropSet.is() )
+ xPropSet->setPropertyValue( "LineWidth", css::uno::Any( nWidth ) );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION( "chart2" );
+ }
+}
+
+void ChartController::executeDispatch_LOKSetTextSelection(int nType, int nX, int nY)
+{
+ if (!m_pDrawViewWrapper)
+ return;
+
+ if (!m_pDrawViewWrapper->IsTextEdit())
+ return;
+
+ OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
+ if (!pOutlinerView)
+ return;
+
+ EditView& rEditView = pOutlinerView->GetEditView();
+ Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY));
+ switch (nType)
+ {
+ case LOK_SETTEXTSELECTION_START:
+ rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
+ break;
+ case LOK_SETTEXTSELECTION_END:
+ rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
+ break;
+ case LOK_SETTEXTSELECTION_RESET:
+ rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+}
+
+void ChartController::executeDispatch_LOKPieSegmentDragging( int nOffset )
+{
+ try
+ {
+ OUString aCID( m_aSelection.getSelectedCID() );
+ rtl::Reference<::chart::ChartModel> xChartModel = getChartModel();
+ if( xChartModel.is() )
+ {
+ Reference< beans::XPropertySet > xPointProperties(
+ ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ) );
+ if( xPointProperties.is() )
+ xPointProperties->setPropertyValue( "Offset", uno::Any( nOffset / 100.0 ) );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartController::impl_ShapeControllerDispatch( const util::URL& rURL, const Sequence< beans::PropertyValue >& rArgs )
+{
+ Reference< frame::XDispatch > xDispatch( m_aDispatchContainer.getShapeController() );
+ if ( xDispatch.is() )
+ {
+ xDispatch->dispatch( rURL, rArgs );
+ }
+}
+
+void ChartController::impl_switchDiagramPositioningToExcludingPositioning()
+{
+ UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription(
+ ActionDescriptionProvider::ActionType::PosSize,
+ ObjectNameProvider::getName( OBJECTTYPE_DIAGRAM)),
+ m_xUndoManager );
+ if (DiagramHelper::switchDiagramPositioningToExcludingPositioning(*getChartModel(), true, true))
+ aUndoGuard.commit();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartController_Window.cxx b/chart2/source/controller/main/ChartController_Window.cxx
new file mode 100644
index 0000000000..1bdb1f2ed4
--- /dev/null
+++ b/chart2/source/controller/main/ChartController_Window.cxx
@@ -0,0 +1,2103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <ChartController.hxx>
+#include <ChartView.hxx>
+#include <PositionAndSizeHelper.hxx>
+#include <ObjectIdentifier.hxx>
+#include <ChartWindow.hxx>
+#include <ResId.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <TitleHelper.hxx>
+#include "UndoGuard.hxx"
+#include <ControllerLockGuard.hxx>
+#include <ObjectNameProvider.hxx>
+#include <strings.hrc>
+#include "DragMethod_PieSegment.hxx"
+#include "DragMethod_RotateDiagram.hxx"
+#include <ObjectHierarchy.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <RelativePositionHelper.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <StatisticsHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DataSeriesProperties.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <LegendHelper.hxx>
+#include <servicenames_charttypes.hxx>
+#include "DrawCommandDispatch.hxx"
+#include <PopupRequest.hxx>
+#include "ControllerCommandDispatch.hxx"
+
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
+
+#include <com/sun/star/awt/PopupMenuDirection.hpp>
+#include <com/sun/star/frame/DispatchHelper.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/XPopupMenuController.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+
+#include <comphelper/lok.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <sfx2/viewsh.hxx>
+#include <svx/ActionDescriptionProvider.hxx>
+#include <svx/obj3d.hxx>
+#include <svx/scene3d.hxx>
+#include <svx/svddrgmt.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <svtools/acceleratorexecute.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <toolkit/awt/vclxmenu.hxx>
+#include <sal/log.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <boost/property_tree/json_parser.hpp>
+#include <sfx2/dispatch.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#define DRGPIX 2 // Drag MinMove in Pixel
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart::DataSeriesProperties;
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+namespace
+{
+bool lcl_GrowAndShiftLogic(
+ RelativePosition & rInOutRelPos,
+ RelativeSize & rInOutRelSize,
+ const awt::Size & rRefSize,
+ double fGrowLogicX,
+ double fGrowLogicY )
+{
+ if( rRefSize.Width == 0 ||
+ rRefSize.Height == 0 )
+ return false;
+
+ double fRelativeGrowX = fGrowLogicX / rRefSize.Width;
+ double fRelativeGrowY = fGrowLogicY / rRefSize.Height;
+
+ return ::chart::RelativePositionHelper::centerGrow(
+ rInOutRelPos, rInOutRelSize,
+ fRelativeGrowX, fRelativeGrowY );
+}
+
+bool lcl_MoveObjectLogic(
+ RelativePosition & rInOutRelPos,
+ RelativeSize const & rObjectSize,
+ const awt::Size & rRefSize,
+ double fShiftLogicX,
+ double fShiftLogicY )
+{
+ if( rRefSize.Width == 0 ||
+ rRefSize.Height == 0 )
+ return false;
+
+ double fRelativeShiftX = fShiftLogicX / rRefSize.Width;
+ double fRelativeShiftY = fShiftLogicY / rRefSize.Height;
+
+ return ::chart::RelativePositionHelper::moveObject(
+ rInOutRelPos, rObjectSize,
+ fRelativeShiftX, fRelativeShiftY );
+}
+
+void lcl_insertMenuCommand(
+ const uno::Reference< awt::XPopupMenu > & xMenu,
+ sal_Int16 nId, const OUString & rCommand )
+{
+ xMenu->insertItem( nId, "", 0, -1 );
+ xMenu->setCommand( nId, rCommand );
+}
+
+OUString lcl_getFormatCommandForObjectCID( std::u16string_view rCID )
+{
+ OUString aDispatchCommand( ".uno:FormatSelection" );
+
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID );
+
+ switch(eObjectType)
+ {
+ case OBJECTTYPE_DIAGRAM:
+ case OBJECTTYPE_DIAGRAM_WALL:
+ aDispatchCommand = ".uno:FormatWall";
+ break;
+ case OBJECTTYPE_DIAGRAM_FLOOR:
+ aDispatchCommand = ".uno:FormatFloor";
+ break;
+ case OBJECTTYPE_PAGE:
+ aDispatchCommand = ".uno:FormatChartArea";
+ break;
+ case OBJECTTYPE_LEGEND:
+ aDispatchCommand = ".uno:FormatLegend";
+ break;
+ case OBJECTTYPE_TITLE:
+ aDispatchCommand = ".uno:FormatTitle";
+ break;
+ case OBJECTTYPE_LEGEND_ENTRY:
+ aDispatchCommand = ".uno:FormatDataSeries";
+ break;
+ case OBJECTTYPE_AXIS:
+ case OBJECTTYPE_AXIS_UNITLABEL:
+ aDispatchCommand = ".uno:FormatAxis";
+ break;
+ case OBJECTTYPE_GRID:
+ aDispatchCommand = ".uno:FormatMajorGrid";
+ break;
+ case OBJECTTYPE_SUBGRID:
+ aDispatchCommand = ".uno:FormatMinorGrid";
+ break;
+ case OBJECTTYPE_DATA_LABELS:
+ aDispatchCommand = ".uno:FormatDataLabels";
+ break;
+ case OBJECTTYPE_DATA_SERIES:
+ aDispatchCommand = ".uno:FormatDataSeries";
+ break;
+ case OBJECTTYPE_DATA_LABEL:
+ aDispatchCommand = ".uno:FormatDataLabel";
+ break;
+ case OBJECTTYPE_DATA_POINT:
+ aDispatchCommand = ".uno:FormatDataPoint";
+ break;
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ aDispatchCommand = ".uno:FormatMeanValue";
+ break;
+ case OBJECTTYPE_DATA_ERRORS_X:
+ aDispatchCommand = ".uno:FormatXErrorBars";
+ break;
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ aDispatchCommand = ".uno:FormatYErrorBars";
+ break;
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ aDispatchCommand = ".uno:FormatZErrorBars";
+ break;
+ case OBJECTTYPE_DATA_CURVE:
+ aDispatchCommand = ".uno:FormatTrendline";
+ break;
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ aDispatchCommand = ".uno:FormatTrendlineEquation";
+ break;
+ case OBJECTTYPE_DATA_STOCK_RANGE:
+ aDispatchCommand = ".uno:FormatSelection";
+ break;
+ case OBJECTTYPE_DATA_STOCK_LOSS:
+ aDispatchCommand = ".uno:FormatStockLoss";
+ break;
+ case OBJECTTYPE_DATA_STOCK_GAIN:
+ aDispatchCommand = ".uno:FormatStockGain";
+ break;
+ default: //OBJECTTYPE_UNKNOWN
+ break;
+ }
+ return aDispatchCommand;
+}
+
+} // anonymous namespace
+
+// awt::XWindow
+void SAL_CALL ChartController::setPosSize(
+ sal_Int32 X,
+ sal_Int32 Y,
+ sal_Int32 Width,
+ sal_Int32 Height,
+ sal_Int16 Flags )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+ auto pChartWindow(GetChartWindow());
+
+ if(!(xWindow.is() && pChartWindow))
+ return;
+
+ Size aLogicSize = pChartWindow->PixelToLogic( Size( Width, Height ), MapMode( MapUnit::Map100thMM ) );
+
+ //todo: for standalone chart: detect whether we are standalone
+ //change map mode to fit new size
+ awt::Size aModelPageSize = ChartModelHelper::getPageSize( getChartModel() );
+ sal_Int32 nScaleXNumerator = aLogicSize.Width();
+ sal_Int32 nScaleXDenominator = aModelPageSize.Width;
+ sal_Int32 nScaleYNumerator = aLogicSize.Height();
+ sal_Int32 nScaleYDenominator = aModelPageSize.Height;
+ MapMode aNewMapMode(
+ MapUnit::Map100thMM,
+ Point(0,0),
+ Fraction(nScaleXNumerator, nScaleXDenominator),
+ Fraction(nScaleYNumerator, nScaleYDenominator) );
+ pChartWindow->SetMapMode(aNewMapMode);
+ pChartWindow->setPosSizePixel( X, Y, Width, Height, static_cast<PosSizeFlags>(Flags) );
+
+ //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
+ if( m_xChartView.is() )
+ {
+ auto aZoomFactors(::comphelper::InitPropertySequence({
+ { "ScaleXNumerator", uno::Any( nScaleXNumerator ) },
+ { "ScaleXDenominator", uno::Any( nScaleXDenominator ) },
+ { "ScaleYNumerator", uno::Any( nScaleYNumerator ) },
+ { "ScaleYDenominator", uno::Any( nScaleYDenominator ) }
+ }));
+ m_xChartView->setPropertyValue( "ZoomFactors", uno::Any( aZoomFactors ));
+ }
+
+ //a correct work area is at least necessary for correct values in the position and size dialog and for dragging area
+ if(m_pDrawViewWrapper)
+ {
+ tools::Rectangle aRect(Point(0,0), pChartWindow->GetOutDev()->GetOutputSize());
+ m_pDrawViewWrapper->SetWorkArea( aRect );
+ }
+ pChartWindow->Invalidate();
+}
+
+awt::Rectangle SAL_CALL ChartController::getPosSize()
+{
+ //@todo
+ awt::Rectangle aRet(0, 0, 0, 0);
+
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+ if(xWindow.is())
+ aRet = xWindow->getPosSize();
+
+ return aRet;
+}
+
+void SAL_CALL ChartController::setVisible( sal_Bool Visible )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->setVisible( Visible );
+}
+
+void SAL_CALL ChartController::setEnable( sal_Bool Enable )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->setEnable( Enable );
+}
+
+void SAL_CALL ChartController::setFocus()
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->setFocus();
+}
+
+void SAL_CALL ChartController::addWindowListener(
+ const uno::Reference< awt::XWindowListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->addWindowListener( xListener );
+}
+
+void SAL_CALL ChartController::removeWindowListener(
+ const uno::Reference< awt::XWindowListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->removeWindowListener( xListener );
+}
+
+void SAL_CALL ChartController::addFocusListener(
+ const uno::Reference< awt::XFocusListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->addFocusListener( xListener );
+}
+
+void SAL_CALL ChartController::removeFocusListener(
+ const uno::Reference< awt::XFocusListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->removeFocusListener( xListener );
+}
+
+void SAL_CALL ChartController::addKeyListener(
+ const uno::Reference< awt::XKeyListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->addKeyListener( xListener );
+}
+
+void SAL_CALL ChartController::removeKeyListener(
+ const uno::Reference< awt::XKeyListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->removeKeyListener( xListener );
+}
+
+void SAL_CALL ChartController::addMouseListener(
+ const uno::Reference< awt::XMouseListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->addMouseListener( xListener );
+}
+
+void SAL_CALL ChartController::removeMouseListener(
+ const uno::Reference< awt::XMouseListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->removeMouseListener( xListener );
+}
+
+void SAL_CALL ChartController::addMouseMotionListener(
+ const uno::Reference< awt::XMouseMotionListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->addMouseMotionListener( xListener );
+}
+
+void SAL_CALL ChartController::removeMouseMotionListener(
+ const uno::Reference< awt::XMouseMotionListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->removeMouseMotionListener( xListener );
+}
+
+void SAL_CALL ChartController::addPaintListener(
+ const uno::Reference< awt::XPaintListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->addPaintListener( xListener );
+}
+
+void SAL_CALL ChartController::removePaintListener(
+ const uno::Reference< awt::XPaintListener >& xListener )
+{
+ //@todo
+ uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
+
+ if(xWindow.is())
+ xWindow->removePaintListener( xListener );
+}
+
+// impl vcl window controller methods
+void ChartController::PrePaint()
+{
+ // forward VCLs PrePaint window event to DrawingLayer
+ DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
+
+ if (pDrawViewWrapper)
+ {
+ pDrawViewWrapper->PrePaint();
+ }
+}
+
+void ChartController::execute_Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ try
+ {
+ rtl::Reference<ChartModel> xModel(getChartModel());
+ //OSL_ENSURE( xModel.is(), "ChartController::execute_Paint: have no model to paint");
+ if (!xModel.is())
+ return;
+
+ //better performance for big data
+ if (m_xChartView.is())
+ {
+ awt::Size aResolution(1000, 1000);
+ {
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+ if (pChartWindow)
+ {
+ aResolution.Width = pChartWindow->GetSizePixel().Width();
+ aResolution.Height = pChartWindow->GetSizePixel().Height();
+ }
+ }
+ m_xChartView->setPropertyValue( "Resolution", uno::Any( aResolution ));
+ }
+
+ if (m_xChartView.is())
+ m_xChartView->update();
+
+ {
+ SolarMutexGuard aGuard;
+ DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
+ if (pDrawViewWrapper)
+ pDrawViewWrapper->CompleteRedraw(&rRenderContext, vcl::Region(rRect));
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ catch( ... )
+ {
+ }
+}
+
+static bool isDoubleClick( const MouseEvent& rMEvt )
+{
+ return rMEvt.GetClicks() == 2 && rMEvt.IsLeft() &&
+ !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsShift();
+}
+
+void ChartController::startDoubleClickWaiting()
+{
+ SolarMutexGuard aGuard;
+
+ m_bWaitingForDoubleClick = true;
+
+ sal_uInt64 nDblClkTime = 500;
+ auto pChartWindow(GetChartWindow());
+ if( pChartWindow )
+ {
+ const MouseSettings& rMSettings = pChartWindow->GetSettings().GetMouseSettings();
+ nDblClkTime = rMSettings.GetDoubleClickTime();
+ }
+ m_aDoubleClickTimer.SetTimeout( nDblClkTime );
+ m_aDoubleClickTimer.Start();
+}
+
+void ChartController::stopDoubleClickWaiting()
+{
+ m_aDoubleClickTimer.Stop();
+ m_bWaitingForDoubleClick = false;
+}
+
+IMPL_LINK_NOARG(ChartController, DoubleClickWaitingHdl, Timer *, void)
+{
+ m_bWaitingForDoubleClick = false;
+
+ if( m_bWaitingForMouseUp || !m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() )
+ return;
+
+ impl_selectObjectAndNotiy();
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+ if( pChartWindow )
+ {
+ vcl::Window::PointerState aPointerState( pChartWindow->GetPointerState() );
+ MouseEvent aMouseEvent(
+ aPointerState.maPos,
+ 1/*nClicks*/,
+ MouseEventModifiers::NONE,
+ static_cast< sal_uInt16 >( aPointerState.mnState )/*nButtons*/,
+ 0/*nModifier*/ );
+ impl_SetMousePointer( aMouseEvent );
+ }
+}
+
+void ChartController::execute_MouseButtonDown( const MouseEvent& rMEvt )
+{
+ SolarMutexGuard aGuard;
+
+ m_bWaitingForMouseUp = true;
+ m_bFieldButtonDown = false;
+
+ if( isDoubleClick(rMEvt) )
+ stopDoubleClickWaiting();
+ else
+ startDoubleClickWaiting();
+
+ m_aSelection.remindSelectionBeforeMouseDown();
+
+ DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
+ auto pChartWindow(GetChartWindow());
+ if(!pChartWindow || !pDrawViewWrapper )
+ return;
+
+ Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel());
+
+ // Check if button was clicked
+ SdrObject* pObject = pDrawViewWrapper->getHitObject(aMPos);
+ if (pObject)
+ {
+ OUString aCID = pObject->GetName();
+ if (aCID.startsWith("FieldButton"))
+ {
+ m_bFieldButtonDown = true;
+ return; // Don't take any action if button was clicked
+ }
+ }
+
+ if ( rMEvt.GetButtons() == MOUSE_LEFT )
+ {
+ pChartWindow->GrabFocus();
+ pChartWindow->CaptureMouse();
+ }
+
+ if( pDrawViewWrapper->IsTextEdit() )
+ {
+ SdrViewEvent aVEvt;
+ if ( pDrawViewWrapper->IsTextEditHit( aMPos ) ||
+ // #i12587# support for shapes in chart
+ ( rMEvt.IsRight() && pDrawViewWrapper->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt ) == SdrHitKind::MarkedObject ) )
+ {
+ pDrawViewWrapper->MouseButtonDown(rMEvt, pChartWindow->GetOutDev());
+ return;
+ }
+ else
+ {
+ EndTextEdit();
+ }
+ }
+
+ //abort running action
+ if( pDrawViewWrapper->IsAction() )
+ {
+ if( rMEvt.IsRight() )
+ pDrawViewWrapper->BckAction();
+ return;
+ }
+
+ if( isDoubleClick(rMEvt) ) //do not change selection if double click
+ return;//double click is handled further in mousebutton up
+
+ SdrHdl* pHitSelectionHdl = nullptr;
+ //switch from move to resize if handle is hit on a resizable object
+ if( m_aSelection.isResizeableObjectSelected() )
+ pHitSelectionHdl = pDrawViewWrapper->PickHandle( aMPos );
+ //only change selection if no selection handles are hit
+ if( !pHitSelectionHdl )
+ {
+ // #i12587# support for shapes in chart
+ if ( m_eDrawMode == CHARTDRAW_INSERT &&
+ ( !pDrawViewWrapper->IsMarkedHit( aMPos ) || !m_aSelection.isDragableObjectSelected() ) )
+ {
+ if ( m_aSelection.hasSelection() )
+ {
+ m_aSelection.clearSelection();
+ }
+ if ( !pDrawViewWrapper->IsAction() )
+ {
+ if ( pDrawViewWrapper->GetCurrentObjIdentifier() == SdrObjKind::Caption )
+ {
+ Size aCaptionSize( 2268, 1134 );
+ pDrawViewWrapper->BegCreateCaptionObj( aMPos, aCaptionSize );
+ }
+ else
+ {
+ pDrawViewWrapper->BegCreateObj( aMPos);
+ }
+ SdrObject* pObj = pDrawViewWrapper->GetCreateObj();
+ DrawCommandDispatch* pDrawCommandDispatch = m_aDispatchContainer.getDrawCommandDispatch();
+ if ( pObj && m_pDrawModelWrapper && pDrawCommandDispatch )
+ {
+ SfxItemSet aSet( m_pDrawModelWrapper->GetItemPool() );
+ pDrawCommandDispatch->setAttributes( pObj );
+ pDrawCommandDispatch->setLineEnds( aSet );
+ pObj->SetMergedItemSet( aSet );
+ }
+ }
+ impl_SetMousePointer( rMEvt );
+ return;
+ }
+
+ m_aSelection.adaptSelectionToNewPos(
+ aMPos,
+ pDrawViewWrapper,
+ rMEvt.IsRight(),
+ m_bWaitingForDoubleClick );
+
+ if( !m_aSelection.isRotateableObjectSelected( getChartModel() ) )
+ {
+ m_eDragMode = SdrDragMode::Move;
+ pDrawViewWrapper->SetDragMode(m_eDragMode);
+ }
+
+ m_aSelection.applySelection(pDrawViewWrapper);
+ }
+ if( m_aSelection.isDragableObjectSelected()
+ && !rMEvt.IsRight() )
+ {
+ //start drag
+ sal_uInt16 nDrgLog = static_cast<sal_uInt16>(pChartWindow->PixelToLogic(Size(DRGPIX,0)).Width());
+ SdrDragMethod* pDragMethod = nullptr;
+
+ //change selection to 3D scene if rotate mode
+ SdrDragMode eDragMode = pDrawViewWrapper->GetDragMode();
+ if( eDragMode==SdrDragMode::Rotate )
+ {
+ E3dScene* pScene = SelectionHelper::getSceneToRotate( pDrawViewWrapper->getNamedSdrObject( m_aSelection.getSelectedCID() ) );
+ if( pScene )
+ {
+ DragMethod_RotateDiagram::RotationDirection eRotationDirection(DragMethod_RotateDiagram::ROTATIONDIRECTION_FREE);
+ if(pHitSelectionHdl)
+ {
+ SdrHdlKind eKind = pHitSelectionHdl->GetKind();
+ if( eKind==SdrHdlKind::Upper || eKind==SdrHdlKind::Lower )
+ eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_X;
+ else if( eKind==SdrHdlKind::Left || eKind==SdrHdlKind::Right )
+ eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Y;
+ else if( eKind==SdrHdlKind::UpperLeft || eKind==SdrHdlKind::UpperRight || eKind==SdrHdlKind::LowerLeft || eKind==SdrHdlKind::LowerRight )
+ eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Z;
+ }
+ pDragMethod = new DragMethod_RotateDiagram( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getChartModel(), eRotationDirection );
+ }
+ }
+ else
+ {
+ std::u16string_view aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) );
+ if( aDragMethodServiceName == ObjectIdentifier::getPieSegmentDragMethodServiceName() )
+ pDragMethod = new DragMethod_PieSegment( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getChartModel() );
+ }
+ pDrawViewWrapper->SdrView::BegDragObj(aMPos, nullptr, pHitSelectionHdl, nDrgLog, pDragMethod);
+ }
+
+ impl_SetMousePointer( rMEvt );
+}
+
+void ChartController::execute_MouseMove( const MouseEvent& rMEvt )
+{
+ SolarMutexGuard aGuard;
+
+ DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
+ auto pChartWindow(GetChartWindow());
+ if(!pChartWindow || !pDrawViewWrapper)
+ return;
+
+ if( m_pDrawViewWrapper->IsTextEdit() )
+ {
+ if( m_pDrawViewWrapper->MouseMove(rMEvt,pChartWindow->GetOutDev()) )
+ return;
+ }
+
+ if(pDrawViewWrapper->IsAction())
+ {
+ pDrawViewWrapper->MovAction( pChartWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
+ }
+
+ impl_SetMousePointer( rMEvt );
+}
+
+void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt )
+{
+ ControllerLockGuardUNO aCLGuard( getChartModel() );
+ bool bMouseUpWithoutMouseDown = !m_bWaitingForMouseUp;
+ m_bWaitingForMouseUp = false;
+ bool bNotifySelectionChange = false;
+ {
+ SolarMutexGuard aGuard;
+
+ DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
+ auto pChartWindow(GetChartWindow());
+ if(!pChartWindow || !pDrawViewWrapper)
+ return;
+
+ Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel());
+
+ // Check if button was clicked
+ if (m_bFieldButtonDown)
+ {
+ m_bFieldButtonDown = false;
+ SdrObject* pObject = pDrawViewWrapper->getHitObject(aMPos);
+ if (pObject)
+ {
+ OUString aCID = pObject->GetName();
+ if (aCID.startsWith("FieldButton"))
+ {
+ sendPopupRequest(aCID, pObject->GetCurrentBoundRect());
+ return;
+ }
+ }
+ }
+
+ if(pDrawViewWrapper->IsTextEdit())
+ {
+ if( pDrawViewWrapper->MouseButtonUp(rMEvt,pChartWindow->GetOutDev()) )
+ return;
+ }
+
+ // #i12587# support for shapes in chart
+ if ( m_eDrawMode == CHARTDRAW_INSERT && pDrawViewWrapper->IsCreateObj() )
+ {
+ pDrawViewWrapper->EndCreateObj( SdrCreateCmd::ForceEnd );
+ {
+ HiddenUndoContext aUndoContext( m_xUndoManager );
+ // don't want the positioning Undo action to appear in the UI
+ impl_switchDiagramPositioningToExcludingPositioning();
+ }
+ if ( pDrawViewWrapper->AreObjectsMarked() )
+ {
+ if ( pDrawViewWrapper->GetCurrentObjIdentifier() == SdrObjKind::Text )
+ {
+ executeDispatch_EditText();
+ }
+ else
+ {
+ SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
+ if ( pObj )
+ {
+ uno::Reference< drawing::XShape > xShape( pObj->getUnoShape(), uno::UNO_QUERY );
+ if ( xShape.is() )
+ {
+ m_aSelection.setSelection( xShape );
+ m_aSelection.applySelection( pDrawViewWrapper );
+ }
+ }
+ }
+ }
+ else
+ {
+ m_aSelection.adaptSelectionToNewPos( aMPos, pDrawViewWrapper, rMEvt.IsRight(), m_bWaitingForDoubleClick );
+ m_aSelection.applySelection( pDrawViewWrapper );
+ setDrawMode( CHARTDRAW_SELECT );
+ }
+ }
+ else if ( pDrawViewWrapper->IsDragObj() )
+ {
+ bool bDraggingDone = false;
+ SdrDragMethod* pDragMethod = pDrawViewWrapper->SdrView::GetDragMethod();
+ bool bIsMoveOnly = pDragMethod && pDragMethod->getMoveOnly();
+ DragMethod_Base* pChartDragMethod = dynamic_cast< DragMethod_Base* >(pDragMethod);
+ if( pChartDragMethod )
+ {
+ UndoGuard aUndoGuard( pChartDragMethod->getUndoDescription(),
+ m_xUndoManager );
+
+ if( pDrawViewWrapper->EndDragObj() )
+ {
+ bDraggingDone = true;
+ aUndoGuard.commit();
+ }
+ }
+
+ if( !bDraggingDone && pDrawViewWrapper->EndDragObj() )
+ {
+ try
+ {
+ //end move or size
+ SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
+ if( pObj )
+ {
+ tools::Rectangle aObjectRect = pObj->GetSnapRect();
+ tools::Rectangle aOldObjectRect = pObj->GetLastBoundRect();
+ awt::Size aPageSize( ChartModelHelper::getPageSize( getChartModel() ) );
+ tools::Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height );
+
+ const E3dObject* pE3dObject(DynCastE3dObject(pObj));
+ if(nullptr != pE3dObject)
+ {
+ E3dScene* pScene(pE3dObject->getRootE3dSceneFromE3dObject());
+ if(nullptr != pScene)
+ {
+ aObjectRect = pScene->GetSnapRect();
+ }
+ }
+
+ ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::ActionType::Move);
+ if( !bIsMoveOnly && m_aSelection.isResizeableObjectSelected() )
+ eActionType = ActionDescriptionProvider::ActionType::Resize;
+
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
+
+ UndoGuard aUndoGuard(
+ ActionDescriptionProvider::createDescription( eActionType, ObjectNameProvider::getName( eObjectType)),
+ m_xUndoManager );
+
+ bool bChanged = false;
+ rtl::Reference< ChartModel > xModel = getChartModel();
+ if ( eObjectType == OBJECTTYPE_LEGEND )
+ bChanged = DiagramHelper::switchDiagramPositioningToExcludingPositioning( *xModel, false , true );
+
+ bool bMoved = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID()
+ , xModel
+ , awt::Rectangle(aObjectRect.Left(),aObjectRect.Top(),aObjectRect.getOpenWidth(),aObjectRect.getOpenHeight())
+ , awt::Rectangle(aOldObjectRect.Left(), aOldObjectRect.Top(), 0, 0)
+ , awt::Rectangle(aPageRect.Left(),aPageRect.Top(),aPageRect.getOpenWidth(),aPageRect.getOpenHeight()) );
+
+ if( bMoved || bChanged )
+ {
+ bDraggingDone = true;
+ aUndoGuard.commit();
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ //all wanted model changes will take effect
+ //and all unwanted view modifications are cleaned
+ }
+
+ if( !bDraggingDone ) //mouse wasn't moved while dragging
+ {
+ bool bClickedTwiceOnDragableObject = SelectionHelper::isDragableObjectHitTwice( aMPos, m_aSelection.getSelectedCID(), *pDrawViewWrapper );
+ bool bIsRotateable = m_aSelection.isRotateableObjectSelected( getChartModel() );
+
+ //toggle between move and rotate
+ if( bIsRotateable && bClickedTwiceOnDragableObject && m_eDragMode==SdrDragMode::Move )
+ m_eDragMode=SdrDragMode::Rotate;
+ else
+ m_eDragMode=SdrDragMode::Move;
+
+ pDrawViewWrapper->SetDragMode(m_eDragMode);
+
+ if( !m_bWaitingForDoubleClick && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() )
+ {
+ impl_selectObjectAndNotiy();
+ }
+ }
+ else
+ m_aSelection.resetPossibleSelectionAfterSingleClickWasEnsured();
+ }
+
+ //@todo ForcePointer(&rMEvt);
+ pChartWindow->ReleaseMouse();
+
+ // In tiled rendering drag mode could be not yet over on the call
+ // that should handle the double-click, so better to perform this check
+ // always.
+ if( isDoubleClick(rMEvt) && !bMouseUpWithoutMouseDown /*#i106966#*/ )
+ {
+ Point aMousePixel = rMEvt.GetPosPixel();
+ execute_DoubleClick( &aMousePixel );
+ }
+
+ if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() )
+ bNotifySelectionChange = true;
+ }
+
+ impl_SetMousePointer( rMEvt );
+
+ if(bNotifySelectionChange)
+ impl_notifySelectionChangeListeners();
+}
+
+void ChartController::execute_DoubleClick( const Point* pMousePixel )
+{
+ const SfxViewShell* pViewShell = SfxViewShell::Current();
+ bool isMobilePhone = pViewShell && pViewShell->isLOKMobilePhone();
+ if (isMobilePhone)
+ return;
+
+ bool bEditText = false;
+ if ( m_aSelection.hasSelection() )
+ {
+ OUString aCID( m_aSelection.getSelectedCID() );
+ if ( !aCID.isEmpty() )
+ {
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID );
+ if ( eObjectType == OBJECTTYPE_TITLE )
+ {
+ bEditText = true;
+ }
+ }
+ else
+ {
+ // #i12587# support for shapes in chart
+ SdrObject* pObj = DrawViewWrapper::getSdrObject( m_aSelection.getSelectedAdditionalShape() );
+ if ( DynCastSdrTextObj(pObj) != nullptr )
+ {
+ bEditText = true;
+ }
+ }
+ }
+
+ if ( bEditText )
+ {
+ executeDispatch_EditText( pMousePixel );
+ }
+ else
+ {
+ executeDispatch_ObjectProperties();
+ }
+}
+
+void ChartController::execute_Resize()
+{
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+ if(pChartWindow)
+ pChartWindow->Invalidate();
+}
+
+void ChartController::execute_Command( const CommandEvent& rCEvt )
+{
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+ bool bIsAction = false;
+ {
+ DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
+ if(!pChartWindow || !pDrawViewWrapper)
+ return;
+ bIsAction = m_pDrawViewWrapper->IsAction();
+ }
+
+ // pop-up menu
+ if(rCEvt.GetCommand() == CommandEventId::ContextMenu && !bIsAction)
+ {
+ {
+ if(pChartWindow)
+ pChartWindow->ReleaseMouse();
+ }
+
+ if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() )
+ impl_notifySelectionChangeListeners();
+
+ rtl::Reference< VCLXPopupMenu > xPopupMenu = new VCLXPopupMenu();
+
+ Point aPos( rCEvt.GetMousePosPixel() );
+ if( !rCEvt.IsMouseEvent() )
+ {
+ if(pChartWindow)
+ aPos = pChartWindow->GetPointerState().maPos;
+ }
+
+ OUString aMenuName;
+ if ( isShapeContext() )
+ // #i12587# support for shapes in chart
+ aMenuName = m_pDrawViewWrapper->IsTextEdit() ? std::u16string_view( u"drawtext" ) : std::u16string_view( u"draw" );
+ else
+ {
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
+
+ // todo: the context menu should be specified by an xml file in uiconfig
+ sal_Int16 nUniqueId = 1;
+ if (eObjectType != OBJECTTYPE_DATA_TABLE)
+ {
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Cut" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Copy" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Paste" );
+ xPopupMenu->insertSeparator( -1 );
+ }
+
+ rtl::Reference< Diagram > xDiagram = getFirstDiagram();
+
+ OUString aFormatCommand( lcl_getFormatCommandForObjectCID( m_aSelection.getSelectedCID() ) );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, aFormatCommand );
+
+ //some commands for dataseries and points:
+
+ if( eObjectType == OBJECTTYPE_DATA_SERIES || eObjectType == OBJECTTYPE_DATA_POINT )
+ {
+ bool bIsPoint = ( eObjectType == OBJECTTYPE_DATA_POINT );
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ rtl::Reference< RegressionCurveModel > xTrendline = RegressionCurveHelper::getFirstCurveNotMeanValueLine( xSeries );
+ bool bHasEquation = RegressionCurveHelper::hasEquation( xTrendline );
+ rtl::Reference< RegressionCurveModel > xMeanValue = RegressionCurveHelper::getMeanValueLine( xSeries );
+ bool bHasYErrorBars = StatisticsHelper::hasErrorBars( xSeries );
+ bool bHasXErrorBars = StatisticsHelper::hasErrorBars( xSeries, false );
+ bool bHasDataLabelsAtSeries = DataSeriesHelper::hasDataLabelsAtSeries( xSeries );
+ bool bHasDataLabelsAtPoints = DataSeriesHelper::hasDataLabelsAtPoints( xSeries );
+ bool bHasDataLabelAtPoint = false;
+ sal_Int32 nPointIndex = -1;
+ if( bIsPoint )
+ {
+ nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection.getSelectedCID() );
+ bHasDataLabelAtPoint = DataSeriesHelper::hasDataLabelAtPoint( xSeries, nPointIndex );
+ }
+ bool bSelectedPointIsFormatted = false;
+ bool bHasFormattedDataPointsOtherThanSelected = false;
+
+ if( xSeries.is() )
+ {
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ // "AttributedDataPoints"
+ if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
+ {
+ if( aAttributedDataPointIndexList.hasElements() )
+ {
+ if( bIsPoint )
+ {
+ auto aIt = std::find( std::as_const(aAttributedDataPointIndexList).begin(), std::as_const(aAttributedDataPointIndexList).end(), nPointIndex );
+ if( aIt != std::as_const(aAttributedDataPointIndexList).end())
+ bSelectedPointIsFormatted = true;
+ else
+ bHasFormattedDataPointsOtherThanSelected = true;
+ }
+ else
+ bHasFormattedDataPointsOtherThanSelected = true;
+ }
+ }
+ }
+
+ if( bIsPoint )
+ {
+ if( bHasDataLabelAtPoint )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatDataLabel" );
+ if( !bHasDataLabelAtPoint )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertDataLabel" );
+ else
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteDataLabel" );
+ if( bSelectedPointIsFormatted )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:ResetDataPoint" );
+
+ xPopupMenu->insertSeparator( -1 );
+
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatDataSeries" );
+ }
+
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeOfSeries( xSeries ) );
+ if( xChartType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK )
+ {
+ try
+ {
+ bool bJapaneseStyle = false;
+ xChartType->getPropertyValue( "Japanese" ) >>= bJapaneseStyle;
+
+ if( bJapaneseStyle )
+ {
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockLoss" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockGain" );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ if( bHasDataLabelsAtSeries )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatDataLabels" );
+ if( bHasEquation )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatTrendlineEquation" );
+ if( xMeanValue.is() )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatMeanValue" );
+ if( bHasXErrorBars )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatXErrorBars" );
+ if( bHasYErrorBars )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatYErrorBars" );
+
+ xPopupMenu->insertSeparator( -1 );
+
+ if( !bHasDataLabelsAtSeries )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertDataLabels" );
+
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTrendline" );
+
+ if( !xMeanValue.is() )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertMeanValue" );
+ if( !bHasXErrorBars )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertXErrorBars" );
+ if( !bHasYErrorBars )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertYErrorBars" );
+ if( bHasDataLabelsAtSeries || ( bHasDataLabelsAtPoints && bHasFormattedDataPointsOtherThanSelected ) )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteDataLabels" );
+ if( bHasEquation )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteTrendlineEquation" );
+ if( xMeanValue.is() )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteMeanValue" );
+ if( bHasXErrorBars )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteXErrorBars" );
+ if( bHasYErrorBars )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteYErrorBars" );
+
+ if( bHasFormattedDataPointsOtherThanSelected )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:ResetAllDataPoints" );
+
+ xPopupMenu->insertSeparator( -1 );
+
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId, ".uno:ArrangeRow" );
+ rtl::Reference< VCLXPopupMenu > xArrangePopupMenu = new VCLXPopupMenu();
+ sal_Int16 nSubId = nUniqueId + 1;
+ lcl_insertMenuCommand( xArrangePopupMenu, nSubId++, ".uno:Forward" );
+ lcl_insertMenuCommand( xArrangePopupMenu, nSubId, ".uno:Backward" );
+ xPopupMenu->setPopupMenu( nUniqueId, xArrangePopupMenu );
+ nUniqueId = nSubId;
+ ++nUniqueId;
+ }
+ else if( eObjectType == OBJECTTYPE_DATA_CURVE )
+ {
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteTrendline" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatTrendlineEquation" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTrendlineEquation" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTrendlineEquationAndR2" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertR2Value" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteTrendlineEquation" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteR2Value" );
+ }
+ else if( eObjectType == OBJECTTYPE_DATA_CURVE_EQUATION )
+ {
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertR2Value" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteR2Value" );
+ }
+
+ //some commands for axes: and grids
+
+ else if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_GRID || eObjectType == OBJECTTYPE_SUBGRID )
+ {
+ rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getChartModel() );
+ if( xAxis.is() && xDiagram.is() )
+ {
+ sal_Int32 nDimensionIndex = -1;
+ sal_Int32 nCooSysIndex = -1;
+ sal_Int32 nAxisIndex = -1;
+ AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
+ bool bIsSecondaryAxis = nAxisIndex!=0;
+ bool bIsAxisVisible = AxisHelper::isAxisVisible( xAxis );
+ bool bIsMajorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true /*bMainGrid*/, xDiagram );
+ bool bIsMinorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false /*bMainGrid*/, xDiagram );
+ bool bHasTitle = !TitleHelper::getCompleteString( xAxis->getTitleObject2() ).isEmpty();
+
+ if( eObjectType != OBJECTTYPE_AXIS && bIsAxisVisible )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatAxis" );
+ if( eObjectType != OBJECTTYPE_GRID && bIsMajorGridVisible && !bIsSecondaryAxis )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatMajorGrid" );
+ if( eObjectType != OBJECTTYPE_SUBGRID && bIsMinorGridVisible && !bIsSecondaryAxis )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatMinorGrid" );
+
+ xPopupMenu->insertSeparator( -1 );
+
+ if( eObjectType != OBJECTTYPE_AXIS && !bIsAxisVisible )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertAxis" );
+ if( eObjectType != OBJECTTYPE_GRID && !bIsMajorGridVisible && !bIsSecondaryAxis )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertMajorGrid" );
+ if( eObjectType != OBJECTTYPE_SUBGRID && !bIsMinorGridVisible && !bIsSecondaryAxis )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertMinorGrid" );
+ if( !bHasTitle )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertAxisTitle" );
+
+ if( bIsAxisVisible )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteAxis" );
+ if( bIsMajorGridVisible && !bIsSecondaryAxis )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteMajorGrid" );
+ if( bIsMinorGridVisible && !bIsSecondaryAxis )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteMinorGrid" );
+ if (bIsAxisVisible)
+ lcl_insertMenuCommand(xPopupMenu, nUniqueId++, ".uno:InsertDataTable");
+ }
+ }
+ else if (eObjectType == OBJECTTYPE_DATA_TABLE)
+ {
+ lcl_insertMenuCommand(xPopupMenu, nUniqueId++, ".uno:DeleteDataTable");
+ }
+
+ if( eObjectType == OBJECTTYPE_DATA_STOCK_LOSS )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockGain" );
+ else if( eObjectType == OBJECTTYPE_DATA_STOCK_GAIN )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockLoss" );
+
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:TransformDialog" );
+
+ if( eObjectType == OBJECTTYPE_PAGE || eObjectType == OBJECTTYPE_DIAGRAM
+ || eObjectType == OBJECTTYPE_DIAGRAM_WALL
+ || eObjectType == OBJECTTYPE_DIAGRAM_FLOOR
+ || eObjectType == OBJECTTYPE_UNKNOWN )
+ {
+ if( eObjectType != OBJECTTYPE_UNKNOWN )
+ xPopupMenu->insertSeparator( -1 );
+ bool bHasLegend = LegendHelper::hasLegend( xDiagram );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTitles" );
+ if( !bHasLegend )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertLegend" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertRemoveAxes" );
+ if( bHasLegend )
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteLegend" );
+ }
+
+ xPopupMenu->insertSeparator( -1 );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DiagramType" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DataRanges" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DiagramData" );
+ lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:View3D" );
+ }
+
+ css::uno::Sequence< css::uno::Any > aArgs{
+ css::uno::Any(comphelper::makePropertyValue( "IsContextMenu", true )),
+ css::uno::Any(comphelper::makePropertyValue( "Frame", m_xFrame )),
+ css::uno::Any(comphelper::makePropertyValue( "Value", aMenuName ))
+ };
+
+ css::uno::Reference< css::frame::XPopupMenuController > xPopupController(
+ m_xCC->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.comp.framework.ResourceMenuController", aArgs, m_xCC ), css::uno::UNO_QUERY );
+
+ if ( !xPopupController.is() || !xPopupMenu.is() )
+ return;
+
+ xPopupController->setPopupMenu( xPopupMenu );
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ if (SfxViewShell* pViewShell = SfxViewShell::Current())
+ {
+ ControllerCommandDispatch* pCommandDispatch = dynamic_cast<ControllerCommandDispatch*>(m_aDispatchContainer.getChartDispatcher().get());
+ if (pCommandDispatch)
+ {
+ for (int nPos = 0, nCount = xPopupMenu->getItemCount(); nPos < nCount; ++nPos)
+ {
+ auto nItemId = xPopupMenu->getItemId(nPos);
+ OUString aCommandURL = xPopupMenu->getCommand(nItemId);
+ if (!pCommandDispatch->commandAvailable(aCommandURL))
+ xPopupMenu->enableItem(nItemId, false);
+ }
+ }
+
+ boost::property_tree::ptree aMenu = SfxDispatcher::fillPopupMenu(xPopupMenu);
+ boost::property_tree::ptree aRoot;
+ aRoot.add_child("menu", aMenu);
+
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aRoot, true);
+ pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU, OString(aStream.str()));
+ }
+ }
+ else
+ {
+ xPopupMenu->execute( css::uno::Reference< css::awt::XWindowPeer >( m_xFrame->getContainerWindow(), css::uno::UNO_QUERY ),
+ css::awt::Rectangle( aPos.X(), aPos.Y(), 0, 0 ),
+ css::awt::PopupMenuDirection::EXECUTE_DEFAULT );
+ }
+
+ css::uno::Reference< css::lang::XComponent > xComponent( xPopupController, css::uno::UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ else if( ( rCEvt.GetCommand() == CommandEventId::StartExtTextInput ) ||
+ ( rCEvt.GetCommand() == CommandEventId::ExtTextInput ) ||
+ ( rCEvt.GetCommand() == CommandEventId::EndExtTextInput ) ||
+ ( rCEvt.GetCommand() == CommandEventId::InputContextChange ) )
+ {
+ //#i84417# enable editing with IME
+ m_pDrawViewWrapper->Command( rCEvt, pChartWindow );
+ }
+}
+
+bool ChartController::execute_KeyInput( const KeyEvent& rKEvt )
+{
+ SolarMutexGuard aGuard;
+ bool bReturn=false;
+
+ DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
+ auto pChartWindow(GetChartWindow());
+ if (!pChartWindow || !pDrawViewWrapper)
+ return bReturn;
+
+ // handle accelerators
+ if (!m_apAccelExecute && m_xFrame.is() && m_xCC.is())
+ {
+ m_apAccelExecute = ::svt::AcceleratorExecute::createAcceleratorHelper();
+ OSL_ASSERT(m_apAccelExecute);
+ if (m_apAccelExecute)
+ m_apAccelExecute->init( m_xCC, m_xFrame );
+ }
+
+ vcl::KeyCode aKeyCode( rKEvt.GetKeyCode());
+ sal_uInt16 nCode = aKeyCode.GetCode();
+ bool bAlternate = aKeyCode.IsMod2();
+ bool bCtrl = aKeyCode.IsMod1();
+
+ if (m_apAccelExecute)
+ bReturn = m_apAccelExecute->execute( aKeyCode );
+ if( bReturn )
+ return bReturn;
+
+ {
+ if( pDrawViewWrapper->IsTextEdit() )
+ {
+ if( pDrawViewWrapper->KeyInput(rKEvt, pChartWindow) )
+ {
+ bReturn = true;
+ if( nCode == KEY_ESCAPE )
+ {
+ EndTextEdit();
+ }
+ }
+ }
+ }
+
+ // keyboard accessibility
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
+ if( ! bReturn )
+ {
+ // Navigation (Tab/F3/Home/End)
+ rtl::Reference<::chart::ChartModel> xChartDoc( getChartModel() );
+ ObjectKeyNavigation aObjNav( m_aSelection.getSelectedOID(), xChartDoc, m_xChartView.get() );
+ awt::KeyEvent aKeyEvent( ::svt::AcceleratorExecute::st_VCLKey2AWTKey( aKeyCode ));
+ bReturn = aObjNav.handleKeyEvent( aKeyEvent );
+ if( bReturn )
+ {
+ const ObjectIdentifier& aNewOID = aObjNav.getCurrentSelection();
+ uno::Any aNewSelection;
+ if ( aNewOID.isValid() && !ObjectHierarchy::isRootNode( aNewOID ) )
+ {
+ aNewSelection = aNewOID.getAny();
+ }
+ if ( m_eDragMode == SdrDragMode::Rotate && !SelectionHelper::isRotateableObject( aNewOID.getObjectCID(), getChartModel() ) )
+ {
+ m_eDragMode = SdrDragMode::Move;
+ }
+ bReturn = select( aNewSelection );
+ }
+ }
+
+ // Position and Size (+/-/arrow-keys) or pie segment dragging
+ if( ! bReturn )
+ {
+ // pie segment dragging
+ // note: could also be done for data series
+ if( eObjectType == OBJECTTYPE_DATA_POINT &&
+ ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) ==
+ ObjectIdentifier::getPieSegmentDragMethodServiceName())
+ {
+ bool bDrag = false;
+ bool bDragInside = false;
+ if( nCode == KEY_ADD ||
+ nCode == KEY_SUBTRACT )
+ {
+ bDrag = true;
+ bDragInside = ( nCode == KEY_SUBTRACT );
+ }
+ else if(
+ nCode == KEY_LEFT ||
+ nCode == KEY_RIGHT ||
+ nCode == KEY_UP ||
+ nCode == KEY_DOWN )
+ {
+ bDrag = true;
+ std::u16string_view aParameter( ObjectIdentifier::getDragParameterString( m_aSelection.getSelectedCID() ));
+ sal_Int32 nOffsetPercentDummy( 0 );
+ awt::Point aMinimumPosition( 0, 0 );
+ awt::Point aMaximumPosition( 0, 0 );
+ ObjectIdentifier::parsePieSegmentDragParameterString(
+ aParameter, nOffsetPercentDummy, aMinimumPosition, aMaximumPosition );
+ aMaximumPosition.Y -= aMinimumPosition.Y;
+ aMaximumPosition.X -= aMinimumPosition.X;
+
+ bDragInside =
+ (nCode == KEY_RIGHT && (aMaximumPosition.X < 0)) ||
+ (nCode == KEY_LEFT && (aMaximumPosition.X > 0)) ||
+ (nCode == KEY_DOWN && (aMaximumPosition.Y < 0)) ||
+ (nCode == KEY_UP && (aMaximumPosition.Y > 0));
+ }
+
+ if( bDrag )
+ {
+ double fAmount = bAlternate ? 0.01 : 0.05;
+ if( bDragInside )
+ fAmount *= -1.0;
+
+ bReturn = impl_DragDataPoint( m_aSelection.getSelectedCID(), fAmount );
+ }
+ }
+ else
+ {
+ // size
+ if( nCode == KEY_ADD ||
+ nCode == KEY_SUBTRACT )
+ {
+ if( eObjectType == OBJECTTYPE_DIAGRAM )
+ {
+ // default 1 mm in each direction
+ double fGrowAmountX = 200.0;
+ double fGrowAmountY = 200.0;
+ if (bAlternate)
+ {
+ // together with Alt-key: 1 px in each direction
+ Size aPixelSize = pChartWindow->PixelToLogic( Size( 2, 2 ));
+ fGrowAmountX = static_cast< double >( aPixelSize.Width());
+ fGrowAmountY = static_cast< double >( aPixelSize.Height());
+ }
+ if( nCode == KEY_SUBTRACT )
+ {
+ fGrowAmountX = -fGrowAmountX;
+ fGrowAmountY = -fGrowAmountY;
+ }
+ bReturn = impl_moveOrResizeObject(
+ m_aSelection.getSelectedCID(), CENTERED_RESIZE_OBJECT, fGrowAmountX, fGrowAmountY );
+ }
+ }
+ // position
+ else if( nCode == KEY_LEFT ||
+ nCode == KEY_RIGHT ||
+ nCode == KEY_UP ||
+ nCode == KEY_DOWN )
+ {
+ if( m_aSelection.isDragableObjectSelected() )
+ {
+ // default 1 mm
+ double fShiftAmountX = 100.0;
+ double fShiftAmountY = 100.0;
+ if (bAlternate)
+ {
+ // together with Alt-key: 1 px
+ Size aPixelSize = pChartWindow->PixelToLogic( Size( 1, 1 ));
+ fShiftAmountX = static_cast< double >( aPixelSize.Width());
+ fShiftAmountY = static_cast< double >( aPixelSize.Height());
+ }
+ switch( nCode )
+ {
+ case KEY_LEFT:
+ fShiftAmountX = -fShiftAmountX;
+ fShiftAmountY = 0.0;
+ break;
+ case KEY_RIGHT:
+ fShiftAmountY = 0.0;
+ break;
+ case KEY_UP:
+ fShiftAmountX = 0.0;
+ fShiftAmountY = -fShiftAmountY;
+ break;
+ case KEY_DOWN:
+ fShiftAmountX = 0.0;
+ break;
+ }
+ if( !m_aSelection.getSelectedCID().isEmpty() )
+ {
+ //move chart objects
+ if (eObjectType == OBJECTTYPE_DATA_LABEL)
+ {
+ SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
+ if (pObj)
+ {
+ tools::Rectangle aRect = pObj->GetSnapRect();
+ awt::Size aPageSize(ChartModelHelper::getPageSize(getChartModel()));
+ if ((fShiftAmountX > 0.0 && (aRect.Right() + fShiftAmountX > aPageSize.Width)) ||
+ (fShiftAmountX < 0.0 && (aRect.Left() + fShiftAmountX < 0)) ||
+ (fShiftAmountY > 0.0 && (aRect.Bottom() + fShiftAmountY > aPageSize.Height)) ||
+ (fShiftAmountY < 0.0 && (aRect.Top() + fShiftAmountY < 0)))
+ bReturn = false;
+ else
+ bReturn = PositionAndSizeHelper::moveObject(
+ m_aSelection.getSelectedCID(), getChartModel(),
+ awt::Rectangle(aRect.Left() + fShiftAmountX, aRect.Top() + fShiftAmountY, aRect.getOpenWidth(), aRect.getOpenHeight()),
+ awt::Rectangle(aRect.Left(), aRect.Top(), 0, 0),
+ awt::Rectangle(0, 0, aPageSize.Width, aPageSize.Height));
+ }
+ }
+ else
+ bReturn = impl_moveOrResizeObject(
+ m_aSelection.getSelectedCID(), MOVE_OBJECT, fShiftAmountX, fShiftAmountY );
+ }
+ else
+ {
+ //move additional shapes
+ uno::Reference< drawing::XShape > xShape( m_aSelection.getSelectedAdditionalShape() );
+ if( xShape.is() )
+ {
+ awt::Point aPos( xShape->getPosition() );
+ awt::Size aSize( xShape->getSize() );
+ awt::Size aPageSize( ChartModelHelper::getPageSize( getChartModel() ) );
+ aPos.X = static_cast< tools::Long >( static_cast< double >( aPos.X ) + fShiftAmountX );
+ aPos.Y = static_cast< tools::Long >( static_cast< double >( aPos.Y ) + fShiftAmountY );
+ if( aPos.X + aSize.Width > aPageSize.Width )
+ aPos.X = aPageSize.Width - aSize.Width;
+ if( aPos.X < 0 )
+ aPos.X = 0;
+ if( aPos.Y + aSize.Height > aPageSize.Height )
+ aPos.Y = aPageSize.Height - aSize.Height;
+ if( aPos.Y < 0 )
+ aPos.Y = 0;
+
+ xShape->setPosition( aPos );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // dumping the shape
+ if( !bReturn && bCtrl && nCode == KEY_F12)
+ {
+ rtl::Reference< ChartModel > xChartModel = getChartModel();
+ if(xChartModel.is())
+ {
+ OUString aDump = xChartModel->dump("shapes");
+ SAL_WARN("chart2", aDump);
+ }
+ }
+
+ // text edit
+ if( ! bReturn &&
+ nCode == KEY_F2 )
+ {
+ if( eObjectType == OBJECTTYPE_TITLE )
+ {
+ executeDispatch_EditText();
+ bReturn = true;
+ }
+ }
+
+ // deactivate inplace mode (this code should be unnecessary, but
+ // unfortunately is not)
+ if( ! bReturn &&
+ nCode == KEY_ESCAPE )
+ {
+ uno::Reference< frame::XDispatchHelper > xDispatchHelper( frame::DispatchHelper::create(m_xCC) );
+ uno::Sequence< beans::PropertyValue > aArgs;
+ xDispatchHelper->executeDispatch(
+ uno::Reference< frame::XDispatchProvider >( m_xFrame, uno::UNO_QUERY ),
+ ".uno:TerminateInplaceActivation",
+ "_parent",
+ frame::FrameSearchFlag::PARENT,
+ aArgs );
+ bReturn = true;
+ }
+
+ if( ! bReturn &&
+ (nCode == KEY_DELETE || nCode == KEY_BACKSPACE ))
+ {
+ bReturn = executeDispatch_Delete();
+ if( ! bReturn )
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pChartWindow->GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SchResId(STR_ACTION_NOTPOSSIBLE)));
+ xInfoBox->run();
+ }
+ }
+
+ return bReturn;
+}
+
+bool ChartController::requestQuickHelp(
+ ::Point aAtLogicPosition,
+ bool bIsBalloonHelp,
+ OUString & rOutQuickHelpText,
+ awt::Rectangle & rOutEqualRect )
+{
+ rtl::Reference<::chart::ChartModel> xChartModel;
+ if( m_aModel.is())
+ xChartModel = getChartModel();
+ if( !xChartModel.is())
+ return false;
+
+ // help text
+ OUString aCID;
+ if( m_pDrawViewWrapper )
+ {
+ aCID = SelectionHelper::getHitObjectCID(
+ aAtLogicPosition, *m_pDrawViewWrapper );
+ }
+ bool bResult( !aCID.isEmpty());
+
+ if( bResult )
+ {
+ // get help text
+ rOutQuickHelpText = ObjectNameProvider::getHelpText( aCID, xChartModel, bIsBalloonHelp /* bVerbose */ );
+
+ // set rectangle
+ if( m_xChartView )
+ rOutEqualRect = m_xChartView->getRectangleOfObject( aCID, true );
+ }
+
+ return bResult;
+}
+
+// XSelectionSupplier (optional interface)
+sal_Bool SAL_CALL ChartController::select( const uno::Any& rSelection )
+{
+ bool bSuccess = false;
+
+ if ( rSelection.hasValue() )
+ {
+ const uno::Type& rType = rSelection.getValueType();
+ if ( rType == cppu::UnoType< OUString >::get() )
+ {
+ OUString aNewCID;
+ if ( ( rSelection >>= aNewCID ) && m_aSelection.setSelection( aNewCID ) )
+ {
+ bSuccess = true;
+ }
+ }
+ else if ( rType == cppu::UnoType<drawing::XShape>::get() )
+ {
+ uno::Reference< drawing::XShape > xShape;
+ if ( ( rSelection >>= xShape ) && m_aSelection.setSelection( xShape ) )
+ {
+ bSuccess = true;
+ }
+ }
+ }
+ else
+ {
+ if ( m_aSelection.hasSelection() )
+ {
+ m_aSelection.clearSelection();
+ bSuccess = true;
+ }
+ }
+
+ if ( bSuccess )
+ {
+ SolarMutexGuard aGuard;
+ if ( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() )
+ {
+ EndTextEdit();
+ }
+ impl_selectObjectAndNotiy();
+ auto pChartWindow(GetChartWindow());
+ if ( pChartWindow )
+ {
+ pChartWindow->Invalidate();
+ }
+ return true;
+ }
+
+ return false;
+}
+
+uno::Any SAL_CALL ChartController::getSelection()
+{
+ uno::Any aReturn;
+ if ( m_aSelection.hasSelection() )
+ {
+ OUString aCID( m_aSelection.getSelectedCID() );
+ if ( !aCID.isEmpty() )
+ {
+ aReturn <<= aCID;
+ }
+ else
+ {
+ // #i12587# support for shapes in chart
+ aReturn <<= m_aSelection.getSelectedAdditionalShape();
+ }
+ }
+ return aReturn;
+}
+
+void SAL_CALL ChartController::addSelectionChangeListener( const uno::Reference<view::XSelectionChangeListener> & xListener )
+{
+ SolarMutexGuard aGuard;
+ if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode?
+ return; //behave passive if already disposed or suspended
+
+ //--add listener
+ std::unique_lock aGuard2(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aSelectionChangeListeners.addInterface( aGuard2, xListener );
+}
+
+void SAL_CALL ChartController::removeSelectionChangeListener( const uno::Reference<view::XSelectionChangeListener> & xListener )
+{
+ SolarMutexGuard aGuard;
+ if( impl_isDisposedOrSuspended() ) //@todo? allow removing of listeners in suspend mode?
+ return; //behave passive if already disposed or suspended
+
+ //--remove listener
+ std::unique_lock aGuard2(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aSelectionChangeListeners.removeInterface( aGuard2, xListener );
+}
+
+void ChartController::impl_notifySelectionChangeListeners()
+{
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ if( m_aLifeTimeManager.m_aSelectionChangeListeners.getLength(aGuard) )
+ {
+ uno::Reference< view::XSelectionSupplier > xSelectionSupplier(this);
+ lang::EventObject aEvent( xSelectionSupplier );
+ m_aLifeTimeManager.m_aSelectionChangeListeners.notifyEach(aGuard, &view::XSelectionChangeListener::selectionChanged, aEvent);
+ }
+}
+
+void ChartController::impl_selectObjectAndNotiy()
+{
+ {
+ SolarMutexGuard aGuard;
+ DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
+ if( pDrawViewWrapper )
+ {
+ pDrawViewWrapper->SetDragMode( m_eDragMode );
+ m_aSelection.applySelection( m_pDrawViewWrapper.get() );
+ }
+ }
+ impl_notifySelectionChangeListeners();
+}
+
+bool ChartController::impl_moveOrResizeObject(
+ const OUString & rCID,
+ eMoveOrResizeType eType,
+ double fAmountLogicX,
+ double fAmountLogicY )
+{
+ bool bResult = false;
+ bool bNeedResize = ( eType == CENTERED_RESIZE_OBJECT );
+
+ rtl::Reference<::chart::ChartModel> xChartModel( getChartModel() );
+ uno::Reference< beans::XPropertySet > xObjProp(
+ ObjectIdentifier::getObjectPropertySet( rCID, xChartModel ));
+ if( xObjProp.is())
+ {
+ awt::Size aRefSize = ChartModelHelper::getPageSize( xChartModel );
+
+ chart2::RelativePosition aRelPos;
+ chart2::RelativeSize aRelSize;
+ bool bDeterminePos = !(xObjProp->getPropertyValue( "RelativePosition") >>= aRelPos);
+ bool bDetermineSize = !bNeedResize || !(xObjProp->getPropertyValue( "RelativeSize") >>= aRelSize);
+
+ if( ( bDeterminePos || bDetermineSize ) &&
+ ( aRefSize.Width > 0 && aRefSize.Height > 0 ) )
+ {
+ ExplicitValueProvider * pValueProvider( m_xChartView.get() );
+ if( pValueProvider )
+ {
+ awt::Rectangle aRect( pValueProvider->getRectangleOfObject( rCID ));
+ double fWidth = static_cast< double >( aRefSize.Width );
+ double fHeight = static_cast< double >( aRefSize.Height );
+ if( bDetermineSize )
+ {
+ aRelSize.Primary = static_cast< double >( aRect.Width ) / fWidth;
+ aRelSize.Secondary = static_cast< double >( aRect.Height ) / fHeight;
+ }
+ if( bDeterminePos )
+ {
+ if( bNeedResize && aRelSize.Primary > 0.0 && aRelSize.Secondary > 0.0 )
+ {
+ aRelPos.Primary = (static_cast< double >( aRect.X ) / fWidth) +
+ (aRelSize.Primary / 2.0);
+ aRelPos.Secondary = (static_cast< double >( aRect.Y ) / fHeight) +
+ (aRelSize.Secondary / 2.0);
+ aRelPos.Anchor = drawing::Alignment_CENTER;
+ }
+ else
+ {
+ aRelPos.Primary = static_cast< double >( aRect.X ) / fWidth;
+ aRelPos.Secondary = static_cast< double >( aRect.Y ) / fHeight;
+ aRelPos.Anchor = drawing::Alignment_TOP_LEFT;
+ }
+ }
+ }
+ }
+
+ if( eType == CENTERED_RESIZE_OBJECT )
+ bResult = lcl_GrowAndShiftLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY );
+ else if( eType == MOVE_OBJECT )
+ bResult = lcl_MoveObjectLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY );
+
+ if( bResult )
+ {
+ ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::ActionType::Move);
+ if( bNeedResize )
+ eActionType = ActionDescriptionProvider::ActionType::Resize;
+
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID );
+ UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription(
+ eActionType, ObjectNameProvider::getName( eObjectType )), m_xUndoManager );
+ {
+ ControllerLockGuardUNO aCLGuard( xChartModel );
+ xObjProp->setPropertyValue( "RelativePosition", uno::Any( aRelPos ));
+ if( bNeedResize || (eObjectType == OBJECTTYPE_DIAGRAM) )//Also set an explicit size at the diagram when an explicit position is set
+ xObjProp->setPropertyValue( "RelativeSize", uno::Any( aRelSize ));
+ }
+ aUndoGuard.commit();
+ }
+ }
+ return bResult;
+}
+
+bool ChartController::impl_DragDataPoint( std::u16string_view rCID, double fAdditionalOffset )
+{
+ bool bResult = false;
+ if( fAdditionalOffset < -1.0 || fAdditionalOffset > 1.0 || fAdditionalOffset == 0.0 )
+ return bResult;
+
+ sal_Int32 nDataPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rCID );
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID( rCID, getChartModel() );
+ if( xSeries.is())
+ {
+ try
+ {
+ uno::Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex( nDataPointIndex ));
+ double fOffset = 0.0;
+ if( xPointProp.is() &&
+ (xPointProp->getPropertyValue( "Offset" ) >>= fOffset ) &&
+ (( fAdditionalOffset > 0.0 && fOffset < 1.0 ) || (fOffset > 0.0)) )
+ {
+ fOffset += fAdditionalOffset;
+ if( fOffset > 1.0 )
+ fOffset = 1.0;
+ else if( fOffset < 0.0 )
+ fOffset = 0.0;
+ xPointProp->setPropertyValue( "Offset", uno::Any( fOffset ));
+ bResult = true;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return bResult;
+}
+
+void ChartController::impl_SetMousePointer( const MouseEvent & rEvent )
+{
+ SolarMutexGuard aGuard;
+ auto pChartWindow(GetChartWindow());
+
+ if (!m_pDrawViewWrapper || !pChartWindow)
+ return;
+
+ Point aMousePos( pChartWindow->PixelToLogic( rEvent.GetPosPixel()));
+ sal_uInt16 nModifier = rEvent.GetModifier();
+ bool bLeftDown = rEvent.IsLeft();
+
+ // Check if object is for field button and set the normal arrow pointer in this case
+ SdrObject* pObject = m_pDrawViewWrapper->getHitObject(aMousePos);
+ if (pObject && pObject->GetName().startsWith("FieldButton"))
+ {
+ pChartWindow->SetPointer(PointerStyle::Arrow);
+ return;
+ }
+
+ if ( m_pDrawViewWrapper->IsTextEdit() )
+ {
+ if( m_pDrawViewWrapper->IsTextEditHit( aMousePos ) )
+ {
+ pChartWindow->SetPointer( m_pDrawViewWrapper->GetPreferredPointer(
+ aMousePos, pChartWindow->GetOutDev(), nModifier, bLeftDown ) );
+ return;
+ }
+ }
+ else if( m_pDrawViewWrapper->IsAction() )
+ {
+ return;//don't change pointer during running action
+ }
+
+ SdrHdl* pHitSelectionHdl = nullptr;
+ if( m_aSelection.isResizeableObjectSelected() )
+ pHitSelectionHdl = m_pDrawViewWrapper->PickHandle( aMousePos );
+
+ if( pHitSelectionHdl )
+ {
+ PointerStyle aPointer = m_pDrawViewWrapper->GetPreferredPointer(
+ aMousePos, pChartWindow->GetOutDev(), nModifier, bLeftDown );
+ bool bForceArrowPointer = false;
+
+ ObjectIdentifier aOID( m_aSelection.getSelectedOID() );
+
+ switch( aPointer)
+ {
+ case PointerStyle::NSize:
+ case PointerStyle::SSize:
+ case PointerStyle::WSize:
+ case PointerStyle::ESize:
+ case PointerStyle::NWSize:
+ case PointerStyle::NESize:
+ case PointerStyle::SWSize:
+ case PointerStyle::SESize:
+ if( ! m_aSelection.isResizeableObjectSelected() )
+ bForceArrowPointer = true;
+ break;
+ case PointerStyle::Move:
+ if ( !aOID.isDragableObject() )
+ bForceArrowPointer = true;
+ break;
+ case PointerStyle::MovePoint:
+ case PointerStyle::MoveBezierWeight:
+ // there is no point-editing in a chart
+ // the PointerStyle::MoveBezierWeight appears in 3d data points
+ bForceArrowPointer = true;
+ break;
+ default:
+ break;
+ }
+
+ if( bForceArrowPointer )
+ pChartWindow->SetPointer( PointerStyle::Arrow );
+ else
+ pChartWindow->SetPointer( aPointer );
+
+ return;
+ }
+
+ // #i12587# support for shapes in chart
+ if ( m_eDrawMode == CHARTDRAW_INSERT &&
+ ( !m_pDrawViewWrapper->IsMarkedHit( aMousePos ) || !m_aSelection.isDragableObjectSelected() ) )
+ {
+ PointerStyle ePointerStyle = PointerStyle::DrawRect;
+ SdrObjKind eKind = m_pDrawViewWrapper->GetCurrentObjIdentifier();
+ switch ( eKind )
+ {
+ case SdrObjKind::Line:
+ {
+ ePointerStyle = PointerStyle::DrawLine;
+ }
+ break;
+ case SdrObjKind::Rectangle:
+ case SdrObjKind::CustomShape:
+ {
+ ePointerStyle = PointerStyle::DrawRect;
+ }
+ break;
+ case SdrObjKind::CircleOrEllipse:
+ {
+ ePointerStyle = PointerStyle::DrawEllipse;
+ }
+ break;
+ case SdrObjKind::FreehandLine:
+ {
+ ePointerStyle = PointerStyle::DrawPolygon;
+ }
+ break;
+ case SdrObjKind::Text:
+ {
+ ePointerStyle = PointerStyle::DrawText;
+ }
+ break;
+ case SdrObjKind::Caption:
+ {
+ ePointerStyle = PointerStyle::DrawCaption;
+ }
+ break;
+ default:
+ {
+ ePointerStyle = PointerStyle::DrawRect;
+ }
+ break;
+ }
+ pChartWindow->SetPointer( ePointerStyle );
+ return;
+ }
+
+ OUString aHitObjectCID(
+ SelectionHelper::getHitObjectCID(
+ aMousePos, *m_pDrawViewWrapper, true /*bGetDiagramInsteadOf_Wall*/ ));
+
+ if( m_pDrawViewWrapper->IsTextEdit() )
+ {
+ if( aHitObjectCID == m_aSelection.getSelectedCID() )
+ {
+ pChartWindow->SetPointer( PointerStyle::Arrow );
+ return;
+ }
+ }
+
+ if( aHitObjectCID.isEmpty() )
+ {
+ //additional shape was hit
+ pChartWindow->SetPointer( PointerStyle::Move );
+ }
+ else if( ObjectIdentifier::isDragableObject( aHitObjectCID ) )
+ {
+ if( (m_eDragMode == SdrDragMode::Rotate)
+ && SelectionHelper::isRotateableObject( aHitObjectCID
+ , getChartModel() ) )
+ pChartWindow->SetPointer( PointerStyle::Rotate );
+ else
+ {
+ ObjectType eHitObjectType = ObjectIdentifier::getObjectType( aHitObjectCID );
+ if( eHitObjectType == OBJECTTYPE_DATA_POINT )
+ {
+ if( !ObjectIdentifier::areSiblings(aHitObjectCID,m_aSelection.getSelectedCID())
+ && !ObjectIdentifier::areIdenticalObjects(aHitObjectCID,m_aSelection.getSelectedCID()) )
+ {
+ pChartWindow->SetPointer( PointerStyle::Arrow );
+ return;
+ }
+ }
+ pChartWindow->SetPointer( PointerStyle::Move );
+ }
+ }
+ else
+ pChartWindow->SetPointer( PointerStyle::Arrow );
+}
+
+void ChartController::sendPopupRequest(std::u16string_view rCID, tools::Rectangle aRectangle)
+{
+ ChartModel* pChartModel = m_aModel->getModel().get();
+ if (!pChartModel)
+ return;
+
+ uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider;
+ xPivotTableDataProvider.set(pChartModel->getDataProvider(), uno::UNO_QUERY);
+ if (!xPivotTableDataProvider.is())
+ return;
+
+ OUString sPivotTableName = xPivotTableDataProvider->getPivotTableName();
+
+ css::uno::Reference<css::awt::XRequestCallback> xPopupRequest = pChartModel->getPopupRequest();
+ PopupRequest* pPopupRequest = dynamic_cast<PopupRequest*>(xPopupRequest.get());
+ if (!pPopupRequest)
+ return;
+
+ // Get dimension index from CID
+ size_t nStartPos = rCID.rfind('.');
+ nStartPos++;
+ sal_Int32 nEndPos = rCID.size();
+ std::u16string_view sDimensionIndex = rCID.substr(nStartPos, nEndPos - nStartPos);
+ sal_Int32 nDimensionIndex = o3tl::toInt32(sDimensionIndex);
+
+ awt::Rectangle xRectangle {
+ sal_Int32(aRectangle.Left()),
+ sal_Int32(aRectangle.Top()),
+ sal_Int32(aRectangle.GetWidth()),
+ sal_Int32(aRectangle.GetHeight())
+ };
+
+ uno::Sequence<beans::PropertyValue> aCallbackData = comphelper::InitPropertySequence(
+ {
+ {"Rectangle", uno::Any(xRectangle)},
+ {"DimensionIndex", uno::Any(sal_Int32(nDimensionIndex))},
+ {"PivotTableName", uno::Any(sPivotTableName)},
+ });
+
+ pPopupRequest->getCallback()->notify(uno::Any(aCallbackData));
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartDropTargetHelper.cxx b/chart2/source/controller/main/ChartDropTargetHelper.cxx
new file mode 100644
index 0000000000..fc6762598a
--- /dev/null
+++ b/chart2/source/controller/main/ChartDropTargetHelper.cxx
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ChartDropTargetHelper.hxx"
+#include <DataSource.hxx>
+#include <DataSourceHelper.hxx>
+#include <ChartModel.hxx>
+#include <Diagram.hxx>
+
+#include <com/sun/star/chart2/data/XDataProvider.hpp>
+
+#include <sot/formats.hxx>
+#include <utility>
+#include <vector>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+
+std::vector< OUString > lcl_getStringsFromByteSequence(
+ const Sequence< sal_Int8 > & aByteSequence )
+{
+ std::vector< OUString > aResult;
+ const sal_Int32 nLength = aByteSequence.getLength();
+ const char * pBytes( reinterpret_cast< const char* >( aByteSequence.getConstArray()));
+ sal_Int32 nStartPos = 0;
+ for( sal_Int32 nPos=0; nPos<nLength; ++nPos )
+ {
+ if( pBytes[nPos] == '\0' )
+ {
+ aResult.emplace_back( pBytes + nStartPos, (nPos - nStartPos), RTL_TEXTENCODING_ASCII_US );
+ nStartPos = nPos + 1;
+ }
+ }
+ return aResult;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+ChartDropTargetHelper::ChartDropTargetHelper(
+ const Reference< datatransfer::dnd::XDropTarget >& rxDropTarget,
+ rtl::Reference<::chart::ChartModel> xChartDocument ) :
+ DropTargetHelper( rxDropTarget ),
+ m_xChartDocument(std::move( xChartDocument ))
+{}
+
+ChartDropTargetHelper::~ChartDropTargetHelper()
+{}
+
+bool ChartDropTargetHelper::satisfiesPrerequisites() const
+{
+ return ( m_xChartDocument.is() &&
+ ! m_xChartDocument->hasInternalDataProvider());
+}
+
+sal_Int8 ChartDropTargetHelper::AcceptDrop( const AcceptDropEvent& rEvt )
+{
+ sal_Int8 nResult = DND_ACTION_NONE;
+
+ if( ( rEvt.mnAction == DND_ACTION_COPY ||
+ rEvt.mnAction == DND_ACTION_MOVE ) &&
+ satisfiesPrerequisites() &&
+ IsDropFormatSupported( SotClipboardFormatId::LINK ) )
+ {
+ // @todo: check if the data is suitable. Is this possible without XTransferable?
+ nResult = rEvt.mnAction;
+ }
+
+ return nResult;
+}
+
+sal_Int8 ChartDropTargetHelper::ExecuteDrop( const ExecuteDropEvent& rEvt )
+{
+ sal_Int8 nResult = DND_ACTION_NONE;
+
+ if( ( rEvt.mnAction == DND_ACTION_COPY ||
+ rEvt.mnAction == DND_ACTION_MOVE ) &&
+ rEvt.maDropEvent.Transferable.is() &&
+ satisfiesPrerequisites())
+ {
+ TransferableDataHelper aDataHelper( rEvt.maDropEvent.Transferable );
+ if( aDataHelper.HasFormat( SotClipboardFormatId::LINK ))
+ {
+ Sequence<sal_Int8> aBytes = aDataHelper.GetSequence(SotClipboardFormatId::LINK, OUString());
+ if (aBytes.hasElements())
+ {
+ std::vector< OUString > aStrings( lcl_getStringsFromByteSequence( aBytes ));
+ if( aStrings.size() >= 3 && aStrings[0] == "soffice" )
+ {
+ OUString aRangeString( aStrings[2] );
+ if( m_xChartDocument.is())
+ {
+ Reference< frame::XModel > xParentModel( m_xChartDocument->getParent(), uno::UNO_QUERY );
+ if( xParentModel.is() &&
+ m_xChartDocument.is())
+ {
+ // @todo: get the title somehow and compare it to
+ // aDocName if successful (the document is the
+ // parent)
+ rtl::Reference< Diagram > xDiagram = m_xChartDocument->getFirstChartDiagram();
+ Reference< chart2::data::XDataProvider > xDataProvider( m_xChartDocument->getDataProvider());
+ if( xDataProvider.is() && xDiagram.is() &&
+ DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument ))
+ {
+ rtl::Reference< DataSource > xDataSource1 =
+ DataSourceHelper::pressUsedDataIntoRectangularFormat( m_xChartDocument );
+ Sequence< beans::PropertyValue > aArguments(
+ xDataProvider->detectArguments( xDataSource1 ));
+
+ OUString aOldRange;
+ beans::PropertyValue * pCellRange = nullptr;
+ for( sal_Int32 i=0; i<aArguments.getLength(); ++i )
+ {
+ if ( aArguments[i].Name == "CellRangeRepresentation" )
+ {
+ pCellRange = (aArguments.getArray() + i);
+ aArguments[i].Value >>= aOldRange;
+ break;
+ }
+ }
+ if( pCellRange )
+ {
+ // copy means add ranges, move means replace
+ if( rEvt.mnAction == DND_ACTION_COPY )
+ {
+ // @todo: using implicit knowledge that ranges can be
+ // merged with ";". This should be done more general
+ pCellRange->Value <<= aOldRange + ";" + aRangeString;
+ }
+ // move means replace range
+ else
+ {
+ pCellRange->Value <<= aRangeString;
+ }
+
+ Reference< chart2::data::XDataSource > xDataSource2 =
+ xDataProvider->createDataSource( aArguments );
+ xDiagram->setDiagramData( xDataSource2, aArguments );
+
+ // always return copy state to avoid deletion of the dragged range
+ nResult = DND_ACTION_COPY;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return nResult;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartDropTargetHelper.hxx b/chart2/source/controller/main/ChartDropTargetHelper.hxx
new file mode 100644
index 0000000000..ab573f1cd6
--- /dev/null
+++ b/chart2/source/controller/main/ChartDropTargetHelper.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/transfer.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star {
+ namespace chart2 {
+ class XChartDocument;
+ }
+}
+
+namespace chart
+{
+class ChartModel;
+
+class ChartDropTargetHelper : public DropTargetHelper
+{
+public:
+ ChartDropTargetHelper() = delete;
+ explicit ChartDropTargetHelper(
+ const css::uno::Reference< css::datatransfer::dnd::XDropTarget >& rxDropTarget,
+ rtl::Reference<::chart::ChartModel> xChartDocument );
+ virtual ~ChartDropTargetHelper() override;
+
+protected:
+
+ virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override;
+ virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override;
+
+private:
+ bool satisfiesPrerequisites() const;
+
+ rtl::Reference<::chart::ChartModel> m_xChartDocument;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartFrameloader.cxx b/chart2/source/controller/main/ChartFrameloader.cxx
new file mode 100644
index 0000000000..2ff4558800
--- /dev/null
+++ b/chart2/source/controller/main/ChartFrameloader.cxx
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ChartFrameloader.hxx"
+#include <servicenames.hxx>
+#include <MediaDescriptorHelper.hxx>
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+#include <unotools/fcm.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/frame/XLoadable.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+
+ChartFrameLoader::ChartFrameLoader(
+ uno::Reference<uno::XComponentContext> const & xContext)
+ : m_bCancelRequired( false )
+{
+ m_xCC = xContext;
+ m_oCancelFinished.reset();
+}
+
+ChartFrameLoader::~ChartFrameLoader()
+{
+}
+
+bool ChartFrameLoader::impl_checkCancel()
+{
+ if(m_bCancelRequired)
+ {
+ m_oCancelFinished.set();
+ return true;
+ }
+ return false;
+}
+
+// lang::XServiceInfo
+
+OUString SAL_CALL ChartFrameLoader::getImplementationName()
+{
+ return CHART_FRAMELOADER_SERVICE_IMPLEMENTATION_NAME;
+}
+
+sal_Bool SAL_CALL ChartFrameLoader::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ChartFrameLoader::getSupportedServiceNames()
+{
+ return { CHART_FRAMELOADER_SERVICE_NAME };
+}
+
+// frame::XFrameLoader
+
+sal_Bool SAL_CALL ChartFrameLoader::load( const uno::Sequence< beans::PropertyValue >& rMediaDescriptor, const uno::Reference<frame::XFrame >& xFrame )
+{
+ //@todo ? need to add as terminate listener to desktop?
+
+ uno::Reference< frame::XModel > xModel;
+ bool bHaveLoadedModel = false;
+
+ utl::MediaDescriptor aMediaDescriptor(rMediaDescriptor);
+ {
+ utl::MediaDescriptor::const_iterator aIt( aMediaDescriptor.find( utl::MediaDescriptor::PROP_MODEL));
+ if( aIt != aMediaDescriptor.end())
+ {
+ xModel.set( (*aIt).second.get< uno::Reference< frame::XModel > >());
+ bHaveLoadedModel = true;
+ }
+ }
+
+ //create and initialize the model
+ if( ! xModel.is())
+ {
+ //@todo?? load mechanism to cancel during loading of document
+ xModel = new ChartModel(m_xCC);
+
+ if( impl_checkCancel() )
+ return false;
+ }
+
+ //create the controller(+XWindow)
+ rtl::Reference< ChartController > xController = new ChartController(m_xCC);
+
+ if( impl_checkCancel() )
+ return false;
+
+ //connect frame, controller and model one to each other:
+ if(xModel.is())
+ {
+ utl::ConnectFrameControllerModel(xFrame, xController, xModel);
+ }
+
+ // call initNew() or load() at XLoadable
+ if(bHaveLoadedModel)
+ return true;
+
+ try
+ {
+ utl::MediaDescriptor::const_iterator aIt( aMediaDescriptor.find( utl::MediaDescriptor::PROP_URL));
+ if( aIt != aMediaDescriptor.end())
+ {
+ OUString aURL( (*aIt).second.get< OUString >());
+ if( aURL.startsWith( "private:factory/schart" ) )
+ {
+ // create new file
+ uno::Reference< frame::XLoadable > xLoadable( xModel, uno::UNO_QUERY_THROW );
+ xLoadable->initNew();
+ }
+ else
+ {
+ // use the URL as BaseURL, similar to what SfxBaseModel effectively does
+ if (!aURL.isEmpty())
+ {
+ aMediaDescriptor[utl::MediaDescriptor::PROP_DOCUMENTBASEURL] <<= aURL;
+ }
+ aMediaDescriptor.addInputStream();
+ uno::Sequence< beans::PropertyValue > aCompleteMediaDescriptor;
+ aMediaDescriptor >> aCompleteMediaDescriptor;
+ apphelper::MediaDescriptorHelper aMDHelper( aCompleteMediaDescriptor );
+
+ // load file
+ // @todo: replace: aMediaDescriptorHelper.getReducedForModel()
+ uno::Reference< frame::XLoadable > xLoadable( xModel, uno::UNO_QUERY_THROW );
+ xLoadable->load( aCompleteMediaDescriptor );
+
+ //resize standalone files to get correct size:
+ if( aMDHelper.ISSET_FilterName && aMDHelper.FilterName == "StarChart 5.0" )
+ {
+ uno::Reference<awt::XWindow> xComponentWindow = xController->getComponentWindow();
+ awt::Rectangle aRect( xComponentWindow->getPosSize() );
+ xComponentWindow->setPosSize( aRect.X, aRect.Y, aRect.Width, aRect.Height, 0 );
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return true;
+}
+
+void SAL_CALL ChartFrameLoader::cancel()
+{
+ m_oCancelFinished.reset();
+ m_bCancelRequired = true;
+ m_oCancelFinished.wait();
+ m_bCancelRequired = false;
+}
+
+} //namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_ChartFrameLoader_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new chart::ChartFrameLoader(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartFrameloader.hxx b/chart2/source/controller/main/ChartFrameloader.hxx
new file mode 100644
index 0000000000..99f0ffd069
--- /dev/null
+++ b/chart2/source/controller/main/ChartFrameloader.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <osl/conditn.hxx>
+#include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+
+class ChartFrameLoader : public ::cppu::WeakImplHelper<
+ css::frame::XSynchronousFrameLoader
+ , css::lang::XServiceInfo
+ >
+{
+private:
+ css::uno::Reference< css::uno::XComponentContext> m_xCC;
+ bool m_bCancelRequired;
+ ::osl::Condition m_oCancelFinished;
+
+private:
+ bool impl_checkCancel();
+
+public:
+ ChartFrameLoader() = delete;
+
+ explicit ChartFrameLoader(css::uno::Reference< css::uno::XComponentContext > const & xContext);
+ virtual ~ChartFrameLoader() override;
+
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // css::frame::XFrameLoader
+
+ virtual sal_Bool SAL_CALL
+ load( const css::uno::Sequence< css::beans::PropertyValue >& rMediaDescriptor
+ ,const css::uno::Reference< css::frame::XFrame >& xFrame ) override;
+
+ virtual void SAL_CALL
+ cancel() override;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartModelClone.cxx b/chart2/source/controller/main/ChartModelClone.cxx
new file mode 100644
index 0000000000..6e620a32da
--- /dev/null
+++ b/chart2/source/controller/main/ChartModelClone.cxx
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ChartModelClone.hxx"
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <DataSource.hxx>
+#include <DataSourceHelper.hxx>
+
+#include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/chart2/XTitled.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
+
+#include <comphelper/property.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::frame::XModel;
+ using ::com::sun::star::util::XCloneable;
+ using ::com::sun::star::chart2::XChartDocument;
+ using ::com::sun::star::chart2::XInternalDataProvider;
+ using ::com::sun::star::chart2::XAnyDescriptionAccess;
+ using ::com::sun::star::view::XSelectionSupplier;
+ using ::com::sun::star::chart2::data::XLabeledDataSequence;
+
+ // = helper
+ namespace
+ {
+ rtl::Reference<::chart::ChartModel> lcl_cloneModel( const rtl::Reference<::chart::ChartModel> & xModel )
+ {
+ try
+ {
+ return new ChartModel(*xModel);
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return nullptr;
+ }
+
+ }
+
+ // = ChartModelClone
+ ChartModelClone::ChartModelClone( const rtl::Reference<::chart::ChartModel>& i_model, const ModelFacet i_facet )
+ {
+ m_xModelClone = lcl_cloneModel( i_model );
+
+ try
+ {
+ if ( i_facet == E_MODEL_WITH_DATA )
+ {
+ ENSURE_OR_THROW( m_xModelClone && m_xModelClone->hasInternalDataProvider(), "invalid chart model" );
+
+ const Reference< XCloneable > xCloneable( m_xModelClone->getDataProvider(), UNO_QUERY_THROW );
+ m_xDataClone.set( xCloneable->createClone(), UNO_QUERY_THROW );
+ }
+
+ if ( i_facet == E_MODEL_WITH_SELECTION )
+ {
+ const Reference< XSelectionSupplier > xSelSupp( m_xModelClone->getCurrentController(), UNO_QUERY_THROW );
+ m_aSelection = xSelSupp->getSelection();
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ ChartModelClone::~ChartModelClone()
+ {
+ if ( !impl_isDisposed() )
+ dispose();
+ }
+
+ void ChartModelClone::dispose()
+ {
+ if ( impl_isDisposed() )
+ return;
+
+ m_xModelClone.clear();
+ m_xDataClone.clear();
+ m_aSelection.clear();
+ }
+
+ ModelFacet ChartModelClone::getFacet() const
+ {
+ if ( m_aSelection.hasValue() )
+ return E_MODEL_WITH_SELECTION;
+ if ( m_xDataClone.is() )
+ return E_MODEL_WITH_DATA;
+ return E_MODEL;
+ }
+
+ void ChartModelClone::applyToModel( const rtl::Reference<::chart::ChartModel>& i_model ) const
+ {
+ applyModelContentToModel( i_model, m_xModelClone, m_xDataClone );
+
+ if ( m_aSelection.hasValue() )
+ {
+ try
+ {
+ Reference< XSelectionSupplier > xCurrentSelectionSuppl( i_model->getCurrentController(), UNO_QUERY_THROW );
+ xCurrentSelectionSuppl->select( m_aSelection );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+
+ namespace
+ {
+ void ImplApplyDataToModel( const Reference< XModel >& i_model, const Reference< XInternalDataProvider > & i_data )
+ {
+ Reference< XChartDocument > xDoc( i_model, UNO_QUERY );
+ OSL_ASSERT( xDoc.is() && xDoc->hasInternalDataProvider() );
+
+ // copy data from stored internal data provider
+ if( xDoc.is() && xDoc->hasInternalDataProvider())
+ {
+ Reference< XAnyDescriptionAccess > xCurrentData( xDoc->getDataProvider(), UNO_QUERY );
+ Reference< XAnyDescriptionAccess > xSavedData( i_data, UNO_QUERY );
+ if ( xCurrentData.is() && xSavedData.is() )
+ {
+ xCurrentData->setData( xSavedData->getData() );
+ xCurrentData->setAnyRowDescriptions( xSavedData->getAnyRowDescriptions());
+ xCurrentData->setAnyColumnDescriptions( xSavedData->getAnyColumnDescriptions());
+ }
+ }
+ }
+ }
+
+ void ChartModelClone::applyModelContentToModel( const rtl::Reference<::chart::ChartModel>& i_model,
+ const rtl::Reference<::chart::ChartModel>& i_modelToCopyFrom,
+ const Reference< XInternalDataProvider >& i_data )
+ {
+ ENSURE_OR_RETURN_VOID( i_model.is(), "ChartModelElement::applyModelContentToModel: invalid source model!" );
+ ENSURE_OR_RETURN_VOID( i_modelToCopyFrom.is(), "ChartModelElement::applyModelContentToModel: invalid source model!" );
+ try
+ {
+ // locked controllers of destination
+ ControllerLockGuardUNO aLockedControllers( i_model );
+
+ // propagate the correct flag for plotting of hidden values to the data provider and all used sequences
+ ChartModelHelper::setIncludeHiddenCells(ChartModelHelper::isIncludeHiddenCells( i_modelToCopyFrom ), *i_model);
+
+ // diagram
+ i_model->setFirstDiagram( i_modelToCopyFrom->getFirstDiagram() );
+
+ // main title
+ i_model->setTitleObject( i_modelToCopyFrom->getTitleObject() );
+
+ // page background
+ ::comphelper::copyProperties(
+ i_modelToCopyFrom->getPageBackground(),
+ i_model->getPageBackground() );
+
+ // apply data (not applied in standard Undo)
+ if ( i_data.is() )
+ ImplApplyDataToModel( i_model, i_data );
+
+ // register all sequences at the internal data provider to get adapted
+ // indexes when columns are added/removed
+ if ( i_model->hasInternalDataProvider() )
+ {
+ Reference< XInternalDataProvider > xNewDataProvider( i_model->getDataProvider(), UNO_QUERY );
+ rtl::Reference< DataSource > xUsedData = DataSourceHelper::getUsedData( *i_model );
+ if ( xUsedData.is() && xNewDataProvider.is() )
+ {
+ const Sequence< Reference< XLabeledDataSequence > > aData( xUsedData->getDataSequences() );
+ for( Reference< XLabeledDataSequence > const & labeledDataSeq : aData )
+ {
+ xNewDataProvider->registerDataSequenceForChanges( labeledDataSeq->getValues() );
+ xNewDataProvider->registerDataSequenceForChanges( labeledDataSeq->getLabel() );
+ }
+ }
+ }
+
+ // restore modify status
+ if ( !i_modelToCopyFrom->isModified() )
+ {
+ i_model->setModified( false );
+ }
+ // \-- locked controllers of destination
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartModelClone.hxx b/chart2/source/controller/main/ChartModelClone.hxx
new file mode 100644
index 0000000000..41cf7fc109
--- /dev/null
+++ b/chart2/source/controller/main/ChartModelClone.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::chart2 { class XInternalDataProvider; }
+namespace com::sun::star::frame { class XModel; }
+
+namespace chart
+{
+class ChartModel;
+
+ enum ModelFacet
+ {
+ E_MODEL,
+ E_MODEL_WITH_DATA,
+ E_MODEL_WITH_SELECTION
+ };
+
+ class ChartModelClone
+ {
+ public:
+ ChartModelClone(
+ const rtl::Reference<::chart::ChartModel>& i_model,
+ const ModelFacet i_facet
+ );
+
+ ~ChartModelClone();
+
+ ChartModelClone(const ChartModelClone&) = delete;
+ const ChartModelClone& operator=(const ChartModelClone&) = delete;
+
+ ModelFacet getFacet() const;
+
+ void applyToModel( const rtl::Reference<::chart::ChartModel>& i_model ) const;
+
+ static void applyModelContentToModel(
+ const rtl::Reference<::chart::ChartModel> & i_model,
+ const rtl::Reference<::chart::ChartModel> & i_modelToCopyFrom,
+ const css::uno::Reference< css::chart2::XInternalDataProvider > & i_data );
+
+ void dispose();
+
+ private:
+ bool impl_isDisposed() const { return !m_xModelClone.is(); }
+
+ private:
+ rtl::Reference<::chart::ChartModel> m_xModelClone;
+ css::uno::Reference< css::chart2::XInternalDataProvider > m_xDataClone;
+ css::uno::Any m_aSelection;
+ };
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartTransferable.cxx b/chart2/source/controller/main/ChartTransferable.cxx
new file mode 100644
index 0000000000..2f27902ba1
--- /dev/null
+++ b/chart2/source/controller/main/ChartTransferable.cxx
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include "ChartTransferable.hxx"
+
+#include <sot/exchange.hxx>
+#include <sot/storage.hxx>
+#include <unotools/streamwrap.hxx>
+#include <vcl/graph.hxx>
+#include <svl/itempool.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/unomodel.hxx>
+#include <svx/svdview.hxx>
+#include <osl/diagnose.h>
+
+constexpr sal_uInt32 CHARTTRANSFER_OBJECTTYPE_DRAWMODEL = 1;
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+ChartTransferable::ChartTransferable(
+ SdrModel& rSdrModel,
+ SdrObject* pSelectedObj,
+ bool bDrawing)
+ : m_bDrawing(bDrawing)
+{
+ std::unique_ptr<SdrExchangeView> pExchgView(std::make_unique<SdrView>( rSdrModel ));
+ SdrPageView* pPv = pExchgView->ShowSdrPage( rSdrModel.GetPage( 0 ));
+ if( pSelectedObj )
+ pExchgView->MarkObj( pSelectedObj, pPv );
+ else
+ pExchgView->MarkAllObj( pPv );
+ Graphic aGraphic( pExchgView->GetMarkedObjMetaFile(true));
+ m_xMetaFileGraphic.set( aGraphic.GetXGraphic());
+ if ( m_bDrawing )
+ {
+ m_xMarkedObjModel = pExchgView->CreateMarkedObjModel();
+ }
+}
+
+ChartTransferable::~ChartTransferable()
+{}
+
+void ChartTransferable::AddSupportedFormats()
+{
+ if ( m_bDrawing )
+ {
+ AddFormat( SotClipboardFormatId::DRAWING );
+ }
+ AddFormat( SotClipboardFormatId::GDIMETAFILE );
+ AddFormat( SotClipboardFormatId::PNG );
+ AddFormat( SotClipboardFormatId::BITMAP );
+}
+
+bool ChartTransferable::GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
+{
+ SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
+ bool bResult = false;
+
+ if( HasFormat( nFormat ))
+ {
+ if ( nFormat == SotClipboardFormatId::DRAWING )
+ {
+ bResult = SetObject(m_xMarkedObjModel.get(), CHARTTRANSFER_OBJECTTYPE_DRAWMODEL, rFlavor);
+ }
+ else if ( nFormat == SotClipboardFormatId::GDIMETAFILE )
+ {
+ Graphic aGraphic( m_xMetaFileGraphic );
+ bResult = SetGDIMetaFile( aGraphic.GetGDIMetaFile() );
+ }
+ else if( nFormat == SotClipboardFormatId::BITMAP )
+ {
+ Graphic aGraphic( m_xMetaFileGraphic );
+ bResult = SetBitmapEx( aGraphic.GetBitmapEx(), rFlavor );
+ }
+ }
+
+ return bResult;
+}
+
+bool ChartTransferable::WriteObject( tools::SvRef<SotTempStream>& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId,
+ const datatransfer::DataFlavor& /* rFlavor */ )
+{
+ // called from SetObject, put data into stream
+
+ bool bRet = false;
+ switch ( nUserObjectId )
+ {
+ case CHARTTRANSFER_OBJECTTYPE_DRAWMODEL:
+ {
+ SdrModel* pMarkedObjModel = static_cast< SdrModel* >( pUserObject );
+ if ( pMarkedObjModel )
+ {
+ rxOStm->SetBufferSize( 0xff00 );
+
+ // for the changed pool defaults from drawing layer pool set those
+ // attributes as hard attributes to preserve them for saving
+ const SfxItemPool& rItemPool = pMarkedObjModel->GetItemPool();
+ const SvxFontHeightItem& rDefaultFontHeight = rItemPool.GetDefaultItem( EE_CHAR_FONTHEIGHT );
+ sal_uInt16 nCount = pMarkedObjModel->GetPageCount();
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ const SdrPage* pPage = pMarkedObjModel->GetPage( i );
+ SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups );
+ while ( aIter.IsMore() )
+ {
+ SdrObject* pObj = aIter.Next();
+ const SvxFontHeightItem& rItem = pObj->GetMergedItem( EE_CHAR_FONTHEIGHT );
+ if ( rItem.GetHeight() == rDefaultFontHeight.GetHeight() )
+ {
+ pObj->SetMergedItem( rDefaultFontHeight );
+ }
+ }
+ }
+
+ Reference< io::XOutputStream > xDocOut( new utl::OOutputStreamWrapper( *rxOStm ) );
+ SvxDrawingLayerExport( pMarkedObjModel, xDocOut );
+
+ bRet = ( rxOStm->GetError() == ERRCODE_NONE );
+ }
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "ChartTransferable::WriteObject: unknown object id" );
+ }
+ break;
+ }
+ return bRet;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartTransferable.hxx b/chart2/source/controller/main/ChartTransferable.hxx
new file mode 100644
index 0000000000..fd782864bf
--- /dev/null
+++ b/chart2/source/controller/main/ChartTransferable.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/transfer.hxx>
+
+namespace com::sun::star {
+ namespace graphic {
+ class XGraphic;
+ }
+}
+
+class SdrModel;
+class SdrObject;
+
+namespace chart
+{
+
+class ChartTransferable : public TransferableHelper
+{
+public:
+ explicit ChartTransferable(
+ SdrModel& rSdrModel,
+ SdrObject* pSelectedObj,
+ bool bDrawing );
+ virtual ~ChartTransferable() override;
+
+protected:
+
+ // implementation of TransferableHelper methods
+ virtual void AddSupportedFormats() override;
+ virtual bool GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc ) override;
+ virtual bool WriteObject( tools::SvRef<SotTempStream>& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId,
+ const css::datatransfer::DataFlavor& rFlavor ) override;
+
+private:
+ css::uno::Reference< css::graphic::XGraphic > m_xMetaFileGraphic;
+ std::unique_ptr<SdrModel> m_xMarkedObjModel;
+ bool m_bDrawing;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ChartWindow.cxx b/chart2/source/controller/main/ChartWindow.cxx
new file mode 100644
index 0000000000..60ab7eb0ed
--- /dev/null
+++ b/chart2/source/controller/main/ChartWindow.cxx
@@ -0,0 +1,376 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_wasm_strip.h>
+#include <ChartWindow.hxx>
+#include <ChartController.hxx>
+#include <helpids.h>
+#include <uiobject.hxx>
+
+#include <vcl/help.hxx>
+#include <vcl/settings.hxx>
+
+#include <sfx2/ipclient.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <comphelper/lok.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+::tools::Rectangle lcl_AWTRectToVCLRect( const css::awt::Rectangle & rAWTRect )
+{
+ ::tools::Rectangle aResult(rAWTRect.X, rAWTRect.Y);
+ aResult.setWidth( rAWTRect.Width );
+ aResult.setHeight( rAWTRect.Height );
+ return aResult;
+}
+} // anonymous namespace
+
+namespace chart
+{
+
+ChartWindow::ChartWindow( ChartController* pController, vcl::Window* pParent, WinBits nStyle )
+ : Window(pParent, nStyle)
+ , m_pWindowController( pController )
+ , m_bInPaint(false)
+ , m_pViewShellWindow( nullptr )
+{
+ set_id("chart_window");
+ SetHelpId( HID_SCH_WIN_DOCUMENT );
+ SetMapMode( MapMode(MapUnit::Map100thMM) );
+ adjustHighContrastMode();
+ // chart does not depend on exact pixel painting => enable antialiased drawing
+ GetOutDev()->SetAntialiasing( AntialiasingFlags::Enable | GetOutDev()->GetAntialiasing() );
+ EnableRTL( false );
+ if( pParent )
+ pParent->EnableRTL( false );// #i96215# necessary for a correct position of the context menu in rtl mode
+}
+
+ChartWindow::~ChartWindow()
+{
+ disposeOnce();
+}
+
+void ChartWindow::dispose()
+{
+ m_pWindowController = nullptr;
+ m_pViewShellWindow.clear();
+ vcl::Window::dispose();
+}
+
+void ChartWindow::PrePaint(vcl::RenderContext& )
+{
+ // forward VCLs PrePaint window event to DrawingLayer
+ if (m_pWindowController)
+ {
+ m_pWindowController->PrePaint();
+ }
+}
+
+void ChartWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ if (comphelper::LibreOfficeKit::isActive() && !rRenderContext.IsVirtual())
+ return;
+
+ m_bInPaint = true;
+ if (m_pWindowController)
+ {
+ m_pWindowController->execute_Paint(rRenderContext, rRect);
+ }
+ else
+ {
+ Window::Paint(rRenderContext, rRect);
+ }
+ m_bInPaint = false;
+}
+
+void ChartWindow::MouseButtonDown(const MouseEvent& rMEvt)
+{
+ if( m_pWindowController )
+ m_pWindowController->execute_MouseButtonDown(rMEvt);
+ else
+ Window::MouseButtonDown(rMEvt);
+}
+
+void ChartWindow::MouseMove( const MouseEvent& rMEvt )
+{
+ if( m_pWindowController )
+ m_pWindowController->execute_MouseMove( rMEvt );
+ else
+ Window::MouseMove( rMEvt );
+}
+
+void ChartWindow::Tracking( const TrackingEvent& rTEvt )
+{
+ if( !m_pWindowController )
+ Window::Tracking( rTEvt );
+}
+
+void ChartWindow::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if( m_pWindowController )
+ m_pWindowController->execute_MouseButtonUp( rMEvt );
+ else
+ Window::MouseButtonUp( rMEvt );
+}
+
+void ChartWindow::Resize()
+{
+ if( m_pWindowController )
+ m_pWindowController->execute_Resize();
+ else
+ Window::Resize();
+}
+
+void ChartWindow::Activate()
+{
+ if( !m_pWindowController )
+ Window::Activate();
+}
+void ChartWindow::Deactivate()
+{
+ if( !m_pWindowController )
+ Window::Deactivate();
+}
+void ChartWindow::GetFocus()
+{
+ if( !m_pWindowController )
+ Window::GetFocus();
+}
+void ChartWindow::LoseFocus()
+{
+ if( !m_pWindowController )
+ Window::LoseFocus();
+}
+
+void ChartWindow::Command( const CommandEvent& rCEvt )
+{
+ if( m_pWindowController )
+ m_pWindowController->execute_Command( rCEvt );
+ else
+ Window::Command( rCEvt );
+}
+
+void ChartWindow::KeyInput( const KeyEvent& rKEvt )
+{
+ if( m_pWindowController )
+ {
+ if( !m_pWindowController->execute_KeyInput(rKEvt) )
+ Window::KeyInput(rKEvt);
+ }
+ else
+ Window::KeyInput( rKEvt );
+}
+
+uno::Reference< css::accessibility::XAccessible > ChartWindow::CreateAccessible()
+{
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ if( m_pWindowController )
+ return m_pWindowController->CreateAccessible();
+ else
+ return Window::CreateAccessible();
+#else
+ return uno::Reference< css::accessibility::XAccessible >();
+#endif
+}
+
+void ChartWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ vcl::Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
+ (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
+ {
+ adjustHighContrastMode();
+ }
+}
+
+void ChartWindow::RequestHelp( const HelpEvent& rHEvt )
+{
+ bool bHelpHandled = false;
+ if( ( rHEvt.GetMode() & HelpEventMode::QUICK ) &&
+ m_pWindowController )
+ {
+ Point aLogicHitPos = PixelToLogic( GetPointerPosPixel());
+ OUString aQuickHelpText;
+ awt::Rectangle aHelpRect;
+ bool bIsBalloonHelp( Help::IsBalloonHelpEnabled() );
+ bHelpHandled = m_pWindowController->requestQuickHelp( aLogicHitPos, bIsBalloonHelp, aQuickHelpText, aHelpRect );
+
+ if( bHelpHandled )
+ {
+ tools::Rectangle aPixelRect(LogicToPixel(lcl_AWTRectToVCLRect(aHelpRect)));
+ tools::Rectangle aScreenRect(OutputToScreenPixel(aPixelRect.TopLeft()),
+ OutputToScreenPixel(aPixelRect.BottomRight()));
+
+ if( bIsBalloonHelp )
+ Help::ShowBalloon(this, rHEvt.GetMousePosPixel(), aScreenRect, aQuickHelpText);
+ else
+ Help::ShowQuickHelp(this, aScreenRect, aQuickHelpText);
+ }
+ }
+
+ if( !bHelpHandled )
+ vcl::Window::RequestHelp( rHEvt );
+}
+
+void ChartWindow::adjustHighContrastMode()
+{
+ static const DrawModeFlags nContrastMode =
+ DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill |
+ DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient;
+
+ bool bUseContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
+ GetOutDev()->SetDrawMode( bUseContrast ? nContrastMode : DrawModeFlags::Default );
+}
+
+void ChartWindow::ForceInvalidate()
+{
+ vcl::Window::Invalidate();
+}
+void ChartWindow::ImplInvalidate( const vcl::Region* rRegion, InvalidateFlags nFlags )
+{
+ if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts"
+ return;
+ vcl::Window::ImplInvalidate( rRegion, nFlags );
+}
+
+void ChartWindow::LogicInvalidate(const tools::Rectangle* pRectangle)
+{
+ SfxViewShell* pCurrentShell = SfxViewShell::Current();
+ if ( nullptr == pCurrentShell )
+ return;
+ tools::Rectangle aResultRectangle;
+ if (!pRectangle)
+ {
+ // we have to invalidate the whole chart area not the whole document
+ aResultRectangle = GetBoundingBox();
+ }
+ else
+ {
+ tools::Rectangle aRectangle(*pRectangle);
+ // When dragging shapes the map mode is disabled.
+ if (IsMapModeEnabled())
+ {
+ if (GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
+ {
+ aRectangle = o3tl::convert(aRectangle, o3tl::Length::mm100, o3tl::Length::twip);
+ }
+ }
+ else
+ {
+ aRectangle = PixelToLogic(aRectangle, MapMode(MapUnit::MapTwip));
+ }
+
+ vcl::Window* pEditWin = GetParentEditWin();
+ if (pEditWin)
+ {
+ MapMode aCWMapMode = GetMapMode();
+ constexpr auto p = o3tl::getConversionMulDiv(o3tl::Length::px, o3tl::Length::twip);
+ const auto& scaleX = aCWMapMode.GetScaleX();
+ const auto& scaleY = aCWMapMode.GetScaleY();
+ const auto nXNum = p.first * scaleX.GetDenominator();
+ const auto nXDen = p.second * scaleX.GetNumerator();
+ const auto nYNum = p.first * scaleY.GetDenominator();
+ const auto nYDen = p.second * scaleY.GetNumerator();
+
+ if (!IsMapModeEnabled())
+ {
+ aRectangle = aRectangle.scale(scaleX.GetDenominator(), scaleX.GetNumerator(),
+ scaleY.GetDenominator(), scaleY.GetNumerator());
+ }
+
+ Point aOffset = this->GetOffsetPixelFrom(*pEditWin).scale(nXNum, nXDen, nYNum, nYDen);
+
+ aRectangle = tools::Rectangle(aRectangle.TopLeft() + aOffset, aRectangle.GetSize());
+ }
+
+ aResultRectangle = aRectangle;
+ }
+ SfxLokHelper::notifyInvalidation(pCurrentShell, &aResultRectangle);
+}
+
+FactoryFunction ChartWindow::GetUITestFactory() const
+{
+ return ChartWindowUIObject::create;
+}
+
+ChartController* ChartWindow::GetController()
+{
+ return m_pWindowController;
+}
+
+vcl::Window* ChartWindow::GetParentEditWin()
+{
+ if (m_pViewShellWindow)
+ return m_pViewShellWindow.get();
+
+ // So, you are thinking, why do not invoke pCurrentShell->GetWindow() ?
+ // Because in Impress the parent edit win is not view shell window.
+ SfxViewShell* pCurrentShell = SfxViewShell::Current();
+ if( pCurrentShell )
+ {
+ SfxInPlaceClient* pIPClient = pCurrentShell->GetIPClient();
+ if (pIPClient)
+ {
+ vcl::Window* pRootWin = pIPClient->GetEditWin();
+ if(pRootWin && pRootWin->IsAncestorOf(*this))
+ {
+ m_pViewShellWindow = pRootWin;
+ return m_pViewShellWindow.get();
+ }
+ }
+ }
+ return nullptr;
+}
+
+tools::Rectangle ChartWindow::GetBoundingBox()
+{
+ tools::Rectangle aBBox;
+
+ vcl::Window* pRootWin = GetParentEditWin();
+ if (pRootWin)
+ {
+ // In all cases, the following code fragment
+ // returns the chart bounding box in twips.
+ MapMode aCWMapMode = GetMapMode();
+ constexpr auto p = o3tl::getConversionMulDiv(o3tl::Length::px, o3tl::Length::twip);
+ const auto& scaleX = aCWMapMode.GetScaleX();
+ const auto& scaleY = aCWMapMode.GetScaleY();
+ const auto nXNum = p.first * scaleX.GetDenominator();
+ const auto nXDen = p.second * scaleX.GetNumerator();
+ const auto nYNum = p.first * scaleY.GetDenominator();
+ const auto nYDen = p.second * scaleY.GetNumerator();
+
+ Point aOffset = GetOffsetPixelFrom(*pRootWin);
+ aOffset.setX( o3tl::convert(aOffset.X(), nXNum, nXDen) );
+ aOffset.setY( o3tl::convert(aOffset.Y(), nYNum, nYDen) );
+ Size aSize = GetSizePixel();
+ aSize.setWidth( o3tl::convert(aSize.Width(), nXNum, nXDen) );
+ aSize.setHeight( o3tl::convert(aSize.Height(), nYNum, nYDen) );
+ aBBox = tools::Rectangle(aOffset, aSize);
+ }
+ return aBBox;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/CommandDispatch.cxx b/chart2/source/controller/main/CommandDispatch.cxx
new file mode 100644
index 0000000000..37a56e1512
--- /dev/null
+++ b/chart2/source/controller/main/CommandDispatch.cxx
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "CommandDispatch.hxx"
+#include <com/sun/star/util/URLTransformer.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+CommandDispatch::CommandDispatch(
+ const Reference< uno::XComponentContext > & xContext ) :
+ m_xContext( xContext )
+{
+}
+
+CommandDispatch::~CommandDispatch()
+{}
+
+void CommandDispatch::initialize()
+{}
+
+// ____ WeakComponentImplHelperBase ____
+/// is called when this is disposed
+void CommandDispatch::disposing(std::unique_lock<std::mutex>& rGuard)
+{
+ Reference< uno::XInterface > xEventSource(static_cast< cppu::OWeakObject* >( this ));
+ for( auto& rElement : m_aListeners )
+ rElement.second.disposeAndClear( rGuard, xEventSource );
+ m_aListeners.clear();
+}
+
+// ____ XDispatch ____
+void SAL_CALL CommandDispatch::dispatch( const util::URL& /* URL */, const Sequence< beans::PropertyValue >& /* Arguments */ )
+{}
+
+void SAL_CALL CommandDispatch::addStatusListener( const Reference< frame::XStatusListener >& Control, const util::URL& URL )
+{
+ {
+ std::unique_lock g(m_aMutex);
+ tListenerMap::iterator aIt( m_aListeners.find( URL.Complete ));
+ if( aIt == m_aListeners.end())
+ {
+ aIt = m_aListeners.emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(URL.Complete),
+ std::forward_as_tuple()).first;
+ }
+ assert( aIt != m_aListeners.end());
+
+ aIt->second.addInterface( g, Control );
+ }
+ fireStatusEvent( URL.Complete, Control );
+}
+
+void SAL_CALL CommandDispatch::removeStatusListener( const Reference< frame::XStatusListener >& Control, const util::URL& URL )
+{
+ std::unique_lock g(m_aMutex);
+ tListenerMap::iterator aIt( m_aListeners.find( URL.Complete ));
+ if( aIt != m_aListeners.end())
+ (*aIt).second.removeInterface( g, Control );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL CommandDispatch::modified( const lang::EventObject& /* aEvent */ )
+{
+ fireAllStatusEvents( nullptr );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL CommandDispatch::disposing( const lang::EventObject& /* Source */ )
+{}
+
+void CommandDispatch::fireAllStatusEvents(
+ const css::uno::Reference< css::frame::XStatusListener > & xSingleListener )
+{
+ fireStatusEvent( OUString(), xSingleListener );
+}
+
+void CommandDispatch::fireStatusEventForURL(
+ const OUString & rURL,
+ const uno::Any & rState,
+ bool bEnabled,
+ const Reference< frame::XStatusListener > & xSingleListener /* = 0 */)
+{
+ // prepare event to send
+ util::URL aURL;
+ aURL.Complete = rURL;
+ if( !m_xURLTransformer.is())
+ {
+ m_xURLTransformer.set( util::URLTransformer::create(m_xContext) );
+ }
+ m_xURLTransformer->parseStrict( aURL );
+
+ frame::FeatureStateEvent aEventToSend(
+ static_cast< cppu::OWeakObject* >( this ), // Source
+ aURL, // FeatureURL
+ OUString(), // FeatureDescriptor
+ bEnabled, // IsEnabled
+ false, // Requery
+ rState // State
+ );
+
+ // send event either to single listener or all registered ones
+ if( xSingleListener.is())
+ xSingleListener->statusChanged( aEventToSend );
+ else
+ {
+ tListenerMap::iterator aIt( m_aListeners.find( aURL.Complete ));
+ if( aIt != m_aListeners.end())
+ {
+ std::unique_lock g(m_aMutex);
+ aIt->second.notifyEach(g, &css::frame::XStatusListener::statusChanged, aEventToSend);
+ }
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/CommandDispatch.hxx b/chart2/source/controller/main/CommandDispatch.hxx
new file mode 100644
index 0000000000..41171926b6
--- /dev/null
+++ b/chart2/source/controller/main/CommandDispatch.hxx
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <comphelper/compbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+
+#include <map>
+#include <memory>
+
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::util { class XURLTransformer; }
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::comphelper::WeakComponentImplHelper<
+ css::frame::XDispatch,
+ css::util::XModifyListener >
+ CommandDispatch_Base;
+}
+
+/** This is the base class for an XDispatch.
+ */
+class CommandDispatch : public impl::CommandDispatch_Base
+{
+public:
+ explicit CommandDispatch( const css::uno::Reference< css::uno::XComponentContext > & xContext );
+ virtual ~CommandDispatch() override;
+
+ // late initialisation, especially for adding as listener
+ virtual void initialize();
+
+protected:
+ /** sends a status event for a specific command to all registered listeners
+ or only the one given when set.
+
+ This method should be overridden. The implementation should call
+ fireStatusEventForURL and pass the xSingleListener argument to this
+ method unchanged.
+
+ @param rURL
+ If empty, all available status events must be fired, otherwise only
+ the one for the given command.
+
+ @param xSingleListener
+ If set, the event is only sent to this listener rather than to all
+ registered ones. Whenever a listener adds itself, this method is
+ called with this parameter set to give an initial state.
+ */
+ virtual void fireStatusEvent(
+ const OUString & rURL,
+ const css::uno::Reference< css::frame::XStatusListener > & xSingleListener ) = 0;
+
+ /** calls fireStatusEvent( OUString, xSingleListener )
+ */
+ void fireAllStatusEvents(
+ const css::uno::Reference< css::frame::XStatusListener > & xSingleListener );
+
+ /** sends a status event for a specific command to all registered listeners
+ or only the one given when set.
+
+ @param xSingleListener
+ If set, the event is only sent to this listener rather than to all
+ registered ones. Whenever a listener adds itself, this method is
+ called with this parameter set to give an initial state.
+ */
+ void fireStatusEventForURL(
+ const OUString & rURL,
+ const css::uno::Any & rState,
+ bool bEnabled,
+ const css::uno::Reference< css::frame::XStatusListener > & xSingleListener );
+
+ // ____ XDispatch ____
+ virtual void SAL_CALL dispatch(
+ const css::util::URL& URL,
+ const css::uno::Sequence< css::beans::PropertyValue >& Arguments ) override;
+ virtual void SAL_CALL addStatusListener(
+ const css::uno::Reference< css::frame::XStatusListener >& Control,
+ const css::util::URL& URL ) override;
+ virtual void SAL_CALL removeStatusListener(
+ const css::uno::Reference< css::frame::XStatusListener >& Control,
+ const css::util::URL& URL ) override;
+
+ // ____ WeakComponentImplHelperBase ____
+ /// is called when this is disposed
+ virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+private:
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ css::uno::Reference< css::util::XURLTransformer > m_xURLTransformer;
+
+ typedef std::map< OUString, ::comphelper::OInterfaceContainerHelper4<css::frame::XStatusListener> >
+ tListenerMap;
+
+ tListenerMap m_aListeners;
+
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/CommandDispatchContainer.cxx b/chart2/source/controller/main/CommandDispatchContainer.cxx
new file mode 100644
index 0000000000..c16a0e45be
--- /dev/null
+++ b/chart2/source/controller/main/CommandDispatchContainer.cxx
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <CommandDispatchContainer.hxx>
+#include "UndoCommandDispatch.hxx"
+#include "StatusBarCommandDispatch.hxx"
+#include <DisposeHelper.hxx>
+#include "DrawCommandDispatch.hxx"
+#include "ShapeController.hxx"
+#include <ChartModel.hxx>
+
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+
+#include <o3tl/sorted_vector.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+CommandDispatchContainer::CommandDispatchContainer(
+ const Reference< uno::XComponentContext > & xContext )
+ :m_xContext( xContext )
+ ,m_pDrawCommandDispatch( nullptr )
+ ,m_pShapeController( nullptr )
+{
+}
+
+void CommandDispatchContainer::setModel(
+ const rtl::Reference<::chart::ChartModel> & xModel )
+{
+ // remove all existing dispatcher that base on the old model
+ m_aCachedDispatches.clear();
+ DisposeHelper::DisposeAllElements( m_aToBeDisposedDispatches );
+ m_aToBeDisposedDispatches.clear();
+ m_xModel = xModel.get();
+}
+
+void CommandDispatchContainer::setChartDispatch(
+ const Reference< frame::XDispatch >& rChartDispatch,
+ o3tl::sorted_vector< OUString > && rChartCommands )
+{
+ OSL_ENSURE(rChartDispatch.is(),"Invalid fall back dispatcher!");
+ m_xChartDispatcher.set( rChartDispatch );
+ m_aChartCommands = std::move(rChartCommands);
+ m_aToBeDisposedDispatches.push_back( m_xChartDispatcher );
+}
+
+Reference< frame::XDispatch > CommandDispatchContainer::getDispatchForURL(
+ const util::URL & rURL )
+{
+ static const o3tl::sorted_vector< OUString > s_aContainerDocumentCommands {
+ "AddDirect", "NewDoc", "Open",
+ "Save", "SaveAs", "SendMail",
+ "EditDoc", "ExportDirectToPDF", "PrintDefault"};
+
+ Reference< frame::XDispatch > xResult;
+ tDispatchMap::const_iterator aIt( m_aCachedDispatches.find( rURL.Complete ));
+ if( aIt != m_aCachedDispatches.end())
+ {
+ xResult.set( (*aIt).second );
+ }
+ else
+ {
+ rtl::Reference< ::chart::ChartModel > xModel( m_xModel );
+
+ if( xModel.is() && ( rURL.Path == "Undo" || rURL.Path == "Redo" ||
+ rURL.Path == "GetUndoStrings" || rURL.Path == "GetRedoStrings" ) )
+ {
+ rtl::Reference<CommandDispatch> pDispatch = new UndoCommandDispatch( m_xContext, xModel );
+ xResult.set( pDispatch );
+ pDispatch->initialize();
+ m_aCachedDispatches[ ".uno:Undo" ].set( xResult );
+ m_aCachedDispatches[ ".uno:Redo" ].set( xResult );
+ m_aCachedDispatches[ ".uno:GetUndoStrings" ].set( xResult );
+ m_aCachedDispatches[ ".uno:GetRedoStrings" ].set( xResult );
+ m_aToBeDisposedDispatches.push_back( xResult );
+ }
+ else if( xModel.is() && ( rURL.Path == "Context" || rURL.Path == "ModifiedStatus" ) )
+ {
+ Reference< view::XSelectionSupplier > xSelSupp( xModel->getCurrentController(), uno::UNO_QUERY );
+ rtl::Reference<CommandDispatch> pDispatch = new StatusBarCommandDispatch( m_xContext, xModel, xSelSupp );
+ xResult.set( pDispatch );
+ pDispatch->initialize();
+ m_aCachedDispatches[ ".uno:Context" ].set( xResult );
+ m_aCachedDispatches[ ".uno:ModifiedStatus" ].set( xResult );
+ m_aToBeDisposedDispatches.push_back( xResult );
+ }
+ else if( xModel.is() &&
+ (s_aContainerDocumentCommands.find( rURL.Path ) != s_aContainerDocumentCommands.end()) )
+ {
+ xResult.set( getContainerDispatchForURL( xModel->getCurrentController(), rURL ));
+ // ToDo: can those dispatches be cached?
+ m_aCachedDispatches[ rURL.Complete ].set( xResult );
+ }
+ else if( m_xChartDispatcher.is() &&
+ (m_aChartCommands.find( rURL.Path ) != m_aChartCommands.end()) )
+ {
+ xResult.set( m_xChartDispatcher );
+ m_aCachedDispatches[ rURL.Complete ].set( xResult );
+ }
+ // #i12587# support for shapes in chart
+ // Note, that the chart dispatcher must be queried first, because
+ // the chart dispatcher is the default dispatcher for all context
+ // sensitive commands.
+ else if ( m_pDrawCommandDispatch && m_pDrawCommandDispatch->isFeatureSupported( rURL.Complete ) )
+ {
+ xResult.set( m_pDrawCommandDispatch );
+ m_aCachedDispatches[ rURL.Complete ].set( xResult );
+ }
+ else if ( m_pShapeController && m_pShapeController->isFeatureSupported( rURL.Complete ) )
+ {
+ xResult.set( m_pShapeController );
+ m_aCachedDispatches[ rURL.Complete ].set( xResult );
+ }
+ }
+
+ return xResult;
+}
+
+Sequence< Reference< frame::XDispatch > > CommandDispatchContainer::getDispatchesForURLs(
+ const Sequence< frame::DispatchDescriptor > & aDescriptors )
+{
+ sal_Int32 nCount = aDescriptors.getLength();
+ uno::Sequence< uno::Reference< frame::XDispatch > > aRet( nCount );
+ auto aRetRange = asNonConstRange(aRet);
+
+ for( sal_Int32 nPos = 0; nPos < nCount; ++nPos )
+ {
+ if ( aDescriptors[ nPos ].FrameName == "_self" )
+ aRetRange[ nPos ] = getDispatchForURL( aDescriptors[ nPos ].FeatureURL );
+ }
+ return aRet;
+}
+
+void CommandDispatchContainer::DisposeAndClear()
+{
+ m_aCachedDispatches.clear();
+ DisposeHelper::DisposeAllElements( m_aToBeDisposedDispatches );
+ m_aToBeDisposedDispatches.clear();
+ m_xChartDispatcher.clear();
+ m_aChartCommands.clear();
+ m_pDrawCommandDispatch = nullptr;
+ m_pShapeController = nullptr;
+}
+
+Reference< frame::XDispatch > CommandDispatchContainer::getContainerDispatchForURL(
+ const Reference< frame::XController > & xChartController,
+ const util::URL & rURL )
+{
+ Reference< frame::XDispatch > xResult;
+ if( xChartController.is())
+ {
+ Reference< frame::XFrame > xFrame( xChartController->getFrame());
+ if( xFrame.is())
+ {
+ Reference< frame::XDispatchProvider > xDispProv( xFrame->getCreator(), uno::UNO_QUERY );
+ if( xDispProv.is())
+ xResult.set( xDispProv->queryDispatch( rURL, "_self", 0 ));
+ }
+ }
+ return xResult;
+}
+
+void CommandDispatchContainer::setDrawCommandDispatch( DrawCommandDispatch* pDispatch )
+{
+ m_pDrawCommandDispatch = pDispatch;
+ m_aToBeDisposedDispatches.emplace_back( pDispatch );
+}
+
+void CommandDispatchContainer::setShapeController( ShapeController* pController )
+{
+ m_pShapeController = pController;
+ m_aToBeDisposedDispatches.emplace_back( pController );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ControllerCommandDispatch.cxx b/chart2/source/controller/main/ControllerCommandDispatch.cxx
new file mode 100644
index 0000000000..5317c1c47c
--- /dev/null
+++ b/chart2/source/controller/main/ControllerCommandDispatch.cxx
@@ -0,0 +1,844 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ControllerCommandDispatch.hxx"
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <TitleHelper.hxx>
+#include <LegendHelper.hxx>
+#include <ObjectIdentifier.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartController.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <StatisticsHelper.hxx>
+#include <ReferenceSizeProvider.hxx>
+#include "ShapeController.hxx"
+
+#include <vcl/svapp.hxx>
+#include <sal/log.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/lok.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/objsh.hxx>
+
+#include <com/sun/star/chart2/XRegressionCurve.hpp>
+#include <com/sun/star/chart2/XDataProviderAccess.hpp>
+
+// only needed until #i68864# is fixed
+#include <com/sun/star/frame/XLayoutManager.hpp>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+bool lcl_isStatusBarVisible( const Reference< frame::XController > & xController )
+{
+ bool bIsStatusBarVisible = false;
+ // Status-Bar visible, workaround: this should not be necessary. @todo:
+ // remove when Issue #i68864# is fixed
+ if( xController.is())
+ {
+ Reference< beans::XPropertySet > xPropSet( xController->getFrame(), uno::UNO_QUERY );
+ if( xPropSet.is() )
+ {
+ uno::Reference< css::frame::XLayoutManager > xLayoutManager;
+ xPropSet->getPropertyValue( "LayoutManager" ) >>= xLayoutManager;
+ if ( xLayoutManager.is() )
+ bIsStatusBarVisible = xLayoutManager->isElementVisible( "private:resource/statusbar/statusbar" );
+ }
+ }
+ return bIsStatusBarVisible;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+namespace impl
+{
+
+/// Constants for moving the series.
+namespace {
+ bool const MOVE_SERIES_FORWARD = true;
+ bool const MOVE_SERIES_BACKWARD = false;
+}
+
+/** Represents the current state of the controller (needed for issue 63017).
+
+ You can set the state by calling update(). After this call the state is
+ preserved in this class until the next call to update().
+
+ This is useful, not to say necessary, for enabling and disabling of menu
+ entries (e.g. format>arrangement). As the status requests are sent very
+ frequently it would be impossible, from a performance point of view, to
+ query the current status every time directly at the model. So this class
+ serves as a cache for the state.
+*/
+struct ControllerState
+{
+ ControllerState();
+
+ void update( const Reference< frame::XController > & xController,
+ const rtl::Reference<::chart::ChartModel> & xModel );
+
+ // -- State variables -------
+ bool bHasSelectedObject;
+ bool bIsPositionableObject;
+ bool bIsTextObject;
+ bool bIsDeleteableObjectSelected;
+ bool bIsFormateableObjectSelected;
+
+ // May the selected series be moved forward or backward (cf
+ // format>arrangement).
+ bool bMayMoveSeriesForward;
+ bool bMayMoveSeriesBackward;
+
+ // trendlines
+ bool bMayAddMenuTrendline;
+ bool bMayAddTrendline;
+ bool bMayAddTrendlineEquation;
+ bool bMayAddR2Value;
+ bool bMayAddMeanValue;
+ bool bMayAddXErrorBars;
+ bool bMayAddYErrorBars;
+
+ bool bMayDeleteTrendline;
+ bool bMayDeleteTrendlineEquation;
+ bool bMayDeleteR2Value;
+ bool bMayDeleteMeanValue;
+ bool bMayDeleteXErrorBars;
+ bool bMayDeleteYErrorBars;
+
+ bool bMayFormatTrendline;
+ bool bMayFormatTrendlineEquation;
+ bool bMayFormatMeanValue;
+ bool bMayFormatXErrorBars;
+ bool bMayFormatYErrorBars;
+};
+
+ControllerState::ControllerState() :
+ bHasSelectedObject( false ),
+ bIsPositionableObject( false ),
+ bIsTextObject(false),
+ bIsDeleteableObjectSelected(false),
+ bIsFormateableObjectSelected(false),
+ bMayMoveSeriesForward( false ),
+ bMayMoveSeriesBackward( false ),
+ bMayAddMenuTrendline( false ),
+ bMayAddTrendline( false ),
+ bMayAddTrendlineEquation( false ),
+ bMayAddR2Value( false ),
+ bMayAddMeanValue( false ),
+ bMayAddXErrorBars( false ),
+ bMayAddYErrorBars( false ),
+ bMayDeleteTrendline( false ),
+ bMayDeleteTrendlineEquation( false ),
+ bMayDeleteR2Value( false ),
+ bMayDeleteMeanValue( false ),
+ bMayDeleteXErrorBars( false ),
+ bMayDeleteYErrorBars( false ),
+ bMayFormatTrendline( false ),
+ bMayFormatTrendlineEquation( false ),
+ bMayFormatMeanValue( false ),
+ bMayFormatXErrorBars( false ),
+ bMayFormatYErrorBars( false )
+{}
+
+void ControllerState::update(
+ const Reference< frame::XController > & xController,
+ const rtl::Reference<::chart::ChartModel> & xModel )
+{
+ Reference< view::XSelectionSupplier > xSelectionSupplier(
+ xController, uno::UNO_QUERY );
+
+ // Update ControllerState variables.
+ if( !xSelectionSupplier.is())
+ return;
+
+ uno::Any aSelObj( xSelectionSupplier->getSelection() );
+ ObjectIdentifier aSelOID( aSelObj );
+ OUString aSelObjCID( aSelOID.getObjectCID() );
+
+ bHasSelectedObject = aSelOID.isValid();
+
+ ObjectType aObjectType(ObjectIdentifier::getObjectType( aSelObjCID ));
+
+ bIsPositionableObject = (aObjectType != OBJECTTYPE_DATA_POINT) && aSelOID.isDragableObject();
+ bIsTextObject = aObjectType == OBJECTTYPE_TITLE;
+
+ rtl::Reference< Diagram > xDiagram = xModel->getFirstChartDiagram();
+ bIsFormateableObjectSelected = bHasSelectedObject && aSelOID.isAutoGeneratedObject();
+ if( aObjectType==OBJECTTYPE_DIAGRAM || aObjectType==OBJECTTYPE_DIAGRAM_WALL || aObjectType==OBJECTTYPE_DIAGRAM_FLOOR )
+ bIsFormateableObjectSelected = xDiagram->isSupportingFloorAndWall();
+
+ rtl::Reference< DataSeries > xGivenDataSeries =
+ ObjectIdentifier::getDataSeriesForCID(
+ aSelObjCID, xModel );
+
+ bIsDeleteableObjectSelected = ChartController::isObjectDeleteable( aSelObj );
+
+ bMayMoveSeriesForward = (aObjectType!=OBJECTTYPE_DATA_POINT) && xDiagram && xDiagram->isSeriesMoveable(
+ xGivenDataSeries,
+ MOVE_SERIES_FORWARD );
+
+ bMayMoveSeriesBackward = (aObjectType!=OBJECTTYPE_DATA_POINT) && xDiagram && xDiagram->isSeriesMoveable(
+ xGivenDataSeries,
+ MOVE_SERIES_BACKWARD );
+
+ bMayAddMenuTrendline = false;
+ bMayAddTrendline = false;
+ bMayAddTrendlineEquation = false;
+ bMayAddR2Value = false;
+ bMayAddMeanValue = false;
+ bMayAddXErrorBars = false;
+ bMayAddYErrorBars = false;
+ bMayDeleteTrendline = false;
+ bMayDeleteTrendlineEquation = false;
+ bMayDeleteR2Value = false;
+ bMayDeleteMeanValue = false;
+ bMayDeleteXErrorBars = false;
+ bMayDeleteYErrorBars = false;
+ bMayFormatTrendline = false;
+ bMayFormatTrendlineEquation = false;
+ bMayFormatMeanValue = false;
+ bMayFormatXErrorBars = false;
+ bMayFormatYErrorBars = false;
+ if( !bHasSelectedObject )
+ return;
+
+ if( xGivenDataSeries.is())
+ {
+ bMayAddMenuTrendline = true;
+ sal_Int32 nDimensionCount = xDiagram->getDimension();
+ rtl::Reference< ::chart::ChartType > xFirstChartType(
+ DataSeriesHelper::getChartTypeOfSeries( xGivenDataSeries, xDiagram ));
+
+ // trend lines/mean value line
+ if( (aObjectType == OBJECTTYPE_DATA_SERIES || aObjectType == OBJECTTYPE_DATA_POINT)
+ && ChartTypeHelper::isSupportingRegressionProperties( xFirstChartType, nDimensionCount ))
+ {
+ // Trendline
+ bMayAddTrendline = true;
+
+ // Mean Value
+ bMayFormatMeanValue = bMayDeleteMeanValue = RegressionCurveHelper::hasMeanValueLine( xGivenDataSeries );
+ bMayAddMeanValue = ! bMayDeleteMeanValue;
+ }
+
+ // error bars
+ if( (aObjectType == OBJECTTYPE_DATA_SERIES || aObjectType == OBJECTTYPE_DATA_POINT)
+ && ChartTypeHelper::isSupportingStatisticProperties( xFirstChartType, nDimensionCount ))
+ {
+ bMayFormatXErrorBars = bMayDeleteXErrorBars = StatisticsHelper::hasErrorBars( xGivenDataSeries, false );
+ bMayAddXErrorBars = ! bMayDeleteXErrorBars;
+
+ bMayFormatYErrorBars = bMayDeleteYErrorBars = StatisticsHelper::hasErrorBars( xGivenDataSeries );
+ bMayAddYErrorBars = ! bMayDeleteYErrorBars;
+ }
+ }
+
+ if( aObjectType == OBJECTTYPE_DATA_AVERAGE_LINE )
+ bMayFormatMeanValue = true;
+
+ if( aObjectType == OBJECTTYPE_DATA_ERRORS_X)
+ bMayFormatXErrorBars = true;
+
+ if( aObjectType == OBJECTTYPE_DATA_ERRORS_Y )
+ bMayFormatYErrorBars = true;
+
+ if( aObjectType == OBJECTTYPE_DATA_CURVE )
+ {
+ bMayFormatTrendline = true;
+ bMayDeleteTrendline = true;
+ uno::Reference< chart2::XRegressionCurve > xRegCurve(
+ ObjectIdentifier::getObjectPropertySet( aSelObjCID, xModel ), uno::UNO_QUERY );
+
+ // Trendline Equation
+ bMayFormatTrendlineEquation = bMayDeleteTrendlineEquation = RegressionCurveHelper::hasEquation( xRegCurve );
+ bMayAddTrendlineEquation = !bMayDeleteTrendlineEquation;
+ bMayAddR2Value = RegressionCurveHelper::MayHaveCorrelationCoefficient( xRegCurve ) && bMayAddTrendlineEquation;
+ }
+ else if( aObjectType == OBJECTTYPE_DATA_CURVE_EQUATION )
+ {
+ bMayFormatTrendlineEquation = true;
+ bool bHasR2Value = false;
+ bool bMayHaveR2 = true;
+ try
+ {
+ uno::Reference< beans::XPropertySet > xEquationProperties =
+ ObjectIdentifier::getObjectPropertySet( aSelObjCID, xModel );
+ if( xEquationProperties.is() )
+ {
+ xEquationProperties->getPropertyValue( "ShowCorrelationCoefficient" ) >>= bHasR2Value;
+ xEquationProperties->getPropertyValue( "MayHaveCorrelationCoefficient" ) >>= bMayHaveR2;
+ }
+ }
+ catch(const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ bMayAddR2Value = !bHasR2Value && bMayHaveR2;
+ bMayDeleteR2Value = bHasR2Value;
+ }
+}
+
+/** Represents the current state of the model.
+
+ You can set the state by calling update(). After this call the state is
+ preserved in this class until the next call to update().
+
+ This is useful, not to say necessary, for enabling and disabling of menu
+ entries and toolbar icons. As the status requests are sent very frequently
+ it would be impossible, from a performance point of view, to query the
+ current status every time directly at the model. So this class serves as a
+ cache for the state.
+ */
+struct ModelState
+{
+ ModelState();
+
+ void update( const rtl::Reference<::chart::ChartModel> & xModel );
+
+ bool HasAnyAxis() const;
+ bool HasAnyGrid() const;
+ bool HasAnyTitle() const;
+
+ bool bIsReadOnly;
+ bool bIsThreeD;
+ bool bHasOwnData;
+ bool bHasDataFromPivotTable;
+
+ bool bHasMainTitle;
+ bool bHasSubTitle;
+ bool bHasXAxisTitle;
+ bool bHasYAxisTitle;
+ bool bHasZAxisTitle;
+ bool bHasSecondaryXAxisTitle;
+ bool bHasSecondaryYAxisTitle;
+
+ bool bHasXAxis;
+ bool bHasYAxis;
+ bool bHasZAxis;
+ bool bHasAAxis;
+ bool bHasBAxis;
+
+ bool bHasMainXGrid;
+ bool bHasMainYGrid;
+ bool bHasMainZGrid;
+ bool bHasHelpXGrid;
+ bool bHasHelpYGrid;
+ bool bHasHelpZGrid;
+
+ bool bHasAutoScaledText;
+ bool bHasLegend;
+ bool bHasWall;
+ bool bHasFloor;
+
+ bool bSupportsStatistics;
+ bool bSupportsAxes;
+
+ bool bDataTable = false;
+};
+
+ModelState::ModelState() :
+ bIsReadOnly(true),
+ bIsThreeD(false),
+ bHasOwnData(false),
+ bHasDataFromPivotTable(false),
+ bHasMainTitle(false),
+ bHasSubTitle(false),
+ bHasXAxisTitle(false),
+ bHasYAxisTitle(false),
+ bHasZAxisTitle(false),
+ bHasSecondaryXAxisTitle(false),
+ bHasSecondaryYAxisTitle(false),
+ bHasXAxis(false),
+ bHasYAxis(false),
+ bHasZAxis(false),
+ bHasAAxis(false),
+ bHasBAxis(false),
+ bHasMainXGrid(false),
+ bHasMainYGrid(false),
+ bHasMainZGrid(false),
+ bHasHelpXGrid(false),
+ bHasHelpYGrid(false),
+ bHasHelpZGrid(false),
+ bHasAutoScaledText(false),
+ bHasLegend(false),
+ bHasWall(false),
+ bHasFloor(false),
+ bSupportsStatistics(false),
+ bSupportsAxes(false)
+{}
+
+void ModelState::update( const rtl::Reference<::chart::ChartModel> & xModel )
+{
+ rtl::Reference< Diagram > xDiagram = xModel->getFirstChartDiagram();
+
+ bIsReadOnly = xModel->isReadonly();
+
+ sal_Int32 nDimensionCount = 0;
+ if (xDiagram)
+ nDimensionCount = xDiagram->getDimension();
+
+ rtl::Reference< ChartType > xFirstChartType;
+ if (xDiagram)
+ xFirstChartType = xDiagram->getChartTypeByIndex( 0 );
+ bSupportsStatistics = ChartTypeHelper::isSupportingStatisticProperties( xFirstChartType, nDimensionCount );
+ bSupportsAxes = ChartTypeHelper::isSupportingMainAxis( xFirstChartType, nDimensionCount, 0 );
+
+ bIsThreeD = (nDimensionCount == 3);
+ if (xModel.is())
+ {
+ bHasOwnData = xModel->hasInternalDataProvider();
+ bHasDataFromPivotTable = !bHasOwnData && xModel->isDataFromPivotTable();
+ }
+
+ bHasMainTitle = TitleHelper::getTitle( TitleHelper::MAIN_TITLE, xModel ).is();
+ bHasSubTitle = TitleHelper::getTitle( TitleHelper::SUB_TITLE, xModel ).is();
+ bHasXAxisTitle = TitleHelper::getTitle( TitleHelper::X_AXIS_TITLE, xModel ).is();
+ bHasYAxisTitle = TitleHelper::getTitle( TitleHelper::Y_AXIS_TITLE, xModel ).is();
+ bHasZAxisTitle = TitleHelper::getTitle( TitleHelper::Z_AXIS_TITLE, xModel ).is();
+ bHasSecondaryXAxisTitle = TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xModel ).is();
+ bHasSecondaryYAxisTitle = TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xModel ).is();
+
+ bHasXAxis = bSupportsAxes && AxisHelper::getAxis( 0, true, xDiagram ).is();
+ bHasYAxis = bSupportsAxes && AxisHelper::getAxis( 1, true, xDiagram ).is();
+ bHasZAxis = bSupportsAxes && AxisHelper::getAxis( 2, true, xDiagram ).is();
+ bHasAAxis = bSupportsAxes && AxisHelper::getAxis( 0, false, xDiagram ).is();
+ bHasBAxis = bSupportsAxes && AxisHelper::getAxis( 1, false, xDiagram ).is();
+
+ bHasMainXGrid = bSupportsAxes && AxisHelper::isGridShown( 0, 0, true, xDiagram );
+ bHasMainYGrid = bSupportsAxes && AxisHelper::isGridShown( 1, 0, true, xDiagram );
+ bHasMainZGrid = bSupportsAxes && AxisHelper::isGridShown( 2, 0, true, xDiagram );
+ bHasHelpXGrid = bSupportsAxes && AxisHelper::isGridShown( 0, 0, false, xDiagram );
+ bHasHelpYGrid = bSupportsAxes && AxisHelper::isGridShown( 1, 0, false, xDiagram );
+ bHasHelpZGrid = bSupportsAxes && AxisHelper::isGridShown( 2, 0, false, xDiagram );
+
+ bHasAutoScaledText =
+ (ReferenceSizeProvider::getAutoResizeState( xModel ) ==
+ ReferenceSizeProvider::AUTO_RESIZE_YES);
+
+ bHasLegend = LegendHelper::hasLegend( xDiagram );
+ bHasWall = xDiagram && xDiagram->isSupportingFloorAndWall();
+ bHasFloor = bHasWall && bIsThreeD;
+
+ bDataTable = xDiagram.is() && xDiagram->getDataTable().is();
+}
+
+bool ModelState::HasAnyAxis() const
+{
+ return bHasXAxis || bHasYAxis || bHasZAxis || bHasAAxis || bHasBAxis;
+}
+
+bool ModelState::HasAnyGrid() const
+{
+ return bHasMainXGrid || bHasMainYGrid || bHasMainZGrid ||
+ bHasHelpXGrid || bHasHelpYGrid || bHasHelpZGrid;
+}
+
+bool ModelState::HasAnyTitle() const
+{
+ return bHasMainTitle || bHasSubTitle || bHasXAxisTitle || bHasYAxisTitle || bHasZAxisTitle || bHasSecondaryXAxisTitle || bHasSecondaryYAxisTitle;
+}
+
+} // namespace impl
+
+ControllerCommandDispatch::ControllerCommandDispatch(
+ const Reference< uno::XComponentContext > & xContext,
+ ChartController* pController, CommandDispatchContainer* pContainer ) :
+ impl::ControllerCommandDispatch_Base( xContext ),
+ m_xChartController( pController ),
+ m_xSelectionSupplier( Reference< view::XSelectionSupplier >( pController ) ),
+ m_xDispatch( Reference< frame::XDispatch >( pController ) ),
+ m_apModelState( new impl::ModelState() ),
+ m_apControllerState( new impl::ControllerState() ),
+ m_pDispatchContainer( pContainer )
+{
+}
+
+ControllerCommandDispatch::~ControllerCommandDispatch()
+{
+}
+
+void ControllerCommandDispatch::initialize()
+{
+ if( !m_xChartController.is())
+ return;
+
+ rtl::Reference<::chart::ChartModel> xModel( m_xChartController->getChartModel());
+ OSL_ASSERT( xModel.is());
+ if( xModel.is())
+ xModel->addModifyListener( this );
+
+ // Listen selection modifications (Arrangement feature - issue 63017).
+ if( m_xSelectionSupplier.is() )
+ m_xSelectionSupplier->addSelectionChangeListener( this );
+
+ if( m_apModelState && xModel.is())
+ m_apModelState->update( xModel );
+
+ if( m_apControllerState && xModel.is())
+ m_apControllerState->update( m_xChartController, xModel );
+
+ updateCommandAvailability();
+}
+
+void ControllerCommandDispatch::fireStatusEventForURLImpl(
+ const OUString & rURL,
+ const Reference< frame::XStatusListener > & xSingleListener )
+{
+ std::map< OUString, uno::Any >::const_iterator aArgIt( m_aCommandArguments.find( rURL ));
+ if( aArgIt != m_aCommandArguments.end())
+ fireStatusEventForURL( rURL, aArgIt->second, commandAvailable( rURL ), xSingleListener );
+ else
+ fireStatusEventForURL( rURL, uno::Any(), commandAvailable( rURL ), xSingleListener );
+}
+
+void ControllerCommandDispatch::updateCommandAvailability()
+{
+ bool bModelStateIsValid = (m_apModelState != nullptr);
+ bool bControllerStateIsValid = (m_apControllerState != nullptr);
+ // Model and controller states exist.
+ OSL_ASSERT( bModelStateIsValid );
+ OSL_ASSERT( bControllerStateIsValid );
+
+ // read-only
+ bool bIsWritable = bModelStateIsValid && (! m_apModelState->bIsReadOnly);
+ bool bShapeContext = m_xChartController.is() && m_xChartController->isShapeContext();
+
+ bool bEnableDataTableDialog = false;
+ bool bCanCreateDataProvider = false;
+
+ if ( m_xChartController.is() )
+ {
+ Reference< beans::XPropertySet > xProps( m_xChartController->getModel(), uno::UNO_QUERY );
+ if ( xProps.is() )
+ {
+ try
+ {
+ xProps->getPropertyValue("EnableDataTableDialog") >>= bEnableDataTableDialog;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+
+ rtl::Reference< ChartModel > xChartModel = m_xChartController->getChartModel();
+ OSL_ENSURE(xChartModel.is(), "Invalid XChartDocument");
+ if ( xChartModel.is() )
+ {
+ css::uno::Reference< com::sun::star::chart2::XDataProviderAccess > xCreatorDoc(xChartModel->getParent(), uno::UNO_QUERY);
+ bCanCreateDataProvider = xCreatorDoc.is();
+ }
+ }
+
+ // edit commands
+ m_aCommandAvailability[ ".uno:Cut" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bIsDeleteableObjectSelected;
+ m_aCommandAvailability[ ".uno:Copy" ] = bControllerStateIsValid && m_apControllerState->bHasSelectedObject;
+ m_aCommandAvailability[ ".uno:Paste" ] = bIsWritable;
+
+ // toolbar commands
+ m_aCommandAvailability[ ".uno:ToggleGridHorizontal" ] = bIsWritable;
+ m_aCommandArguments[ ".uno:ToggleGridHorizontal" ] <<= bModelStateIsValid && m_apModelState->bHasMainYGrid;
+ m_aCommandAvailability[ ".uno:ToggleGridVertical" ] = bIsWritable;
+ m_aCommandArguments[ ".uno:ToggleGridVertical" ] <<= bModelStateIsValid && m_apModelState->bHasMainXGrid;
+
+ m_aCommandAvailability[ ".uno:ToggleLegend" ] = bIsWritable;
+ m_aCommandArguments[ ".uno:ToggleLegend" ] <<= bModelStateIsValid && m_apModelState->bHasLegend;
+
+ m_aCommandAvailability[ ".uno:NewArrangement" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:Update" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:DefaultColors" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:BarWidth" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:NumberOfLines" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:ArrangeRow" ] =
+ bShapeContext || ( bIsWritable && bControllerStateIsValid && ( m_apControllerState->bMayMoveSeriesForward || m_apControllerState->bMayMoveSeriesBackward ) );
+
+ // insert objects
+ m_aCommandAvailability[ ".uno:InsertTitles" ] = m_aCommandAvailability[ ".uno:InsertMenuTitles" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:InsertLegend" ] = m_aCommandAvailability[ ".uno:InsertMenuLegend" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:DeleteLegend" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:InsertMenuDataLabels" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:InsertRemoveAxes" ] = m_aCommandAvailability[ ".uno:InsertMenuAxes" ] = bIsWritable && m_apModelState->bSupportsAxes;
+ m_aCommandAvailability[ ".uno:InsertMenuGrids" ] = bIsWritable && m_apModelState->bSupportsAxes;
+ m_aCommandAvailability[ ".uno:InsertMenuTrendlines" ] = bIsWritable && m_apModelState->bSupportsStatistics && bControllerStateIsValid && m_apControllerState->bMayAddMenuTrendline;
+ m_aCommandAvailability[ ".uno:InsertMenuMeanValues" ] = bIsWritable && m_apModelState->bSupportsStatistics;
+ m_aCommandAvailability[ ".uno:InsertMenuXErrorBars" ] = bIsWritable && m_apModelState->bSupportsStatistics;
+ m_aCommandAvailability[ ".uno:InsertMenuYErrorBars" ] = bIsWritable && m_apModelState->bSupportsStatistics;
+ m_aCommandAvailability[ ".uno:InsertSymbol" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bIsTextObject;
+ m_aCommandAvailability[ ".uno:InsertMenuDataTable" ] = bIsWritable;
+
+ // format objects
+ bool bFormatObjectAvailable = bIsWritable && bControllerStateIsValid && m_apControllerState->bIsFormateableObjectSelected;
+ m_aCommandAvailability[ ".uno:FormatSelection" ] = bFormatObjectAvailable;
+ m_aCommandAvailability[ ".uno:FormatAxis" ] = bFormatObjectAvailable;
+ m_aCommandAvailability[ ".uno:FormatTitle" ] = bFormatObjectAvailable;
+ m_aCommandAvailability[ ".uno:FormatDataSeries" ] = bFormatObjectAvailable;
+ m_aCommandAvailability[ ".uno:FormatDataPoint" ] = bFormatObjectAvailable;
+ m_aCommandAvailability[ ".uno:FormatDataLabels" ] = bFormatObjectAvailable;
+ m_aCommandAvailability[ ".uno:FormatDataLabel" ] = bFormatObjectAvailable;
+ m_aCommandAvailability[ ".uno:FormatXErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatXErrorBars;
+ m_aCommandAvailability[ ".uno:FormatYErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatYErrorBars;
+ m_aCommandAvailability[ ".uno:FormatMeanValue" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatMeanValue;
+ m_aCommandAvailability[ ".uno:FormatTrendline" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatTrendline;
+ m_aCommandAvailability[ ".uno:FormatTrendlineEquation" ] = bFormatObjectAvailable && bControllerStateIsValid && m_apControllerState->bMayFormatTrendlineEquation;
+ m_aCommandAvailability[ ".uno:FormatStockLoss" ] = bFormatObjectAvailable;
+ m_aCommandAvailability[ ".uno:FormatStockGain" ] = bFormatObjectAvailable;
+
+ m_aCommandAvailability[ ".uno:DiagramType" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:Legend" ] = bIsWritable && m_apModelState->bHasLegend;
+ m_aCommandAvailability[ ".uno:DiagramWall" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasWall;
+ m_aCommandAvailability[ ".uno:DiagramArea" ] = bIsWritable;
+
+ m_aCommandAvailability[ ".uno:TransformDialog" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bHasSelectedObject && m_apControllerState->bIsPositionableObject;
+
+ // 3d commands
+ m_aCommandAvailability[ ".uno:View3D" ] = bIsWritable && bModelStateIsValid && m_apModelState->bIsThreeD;
+ m_aCommandAvailability[ ".uno:DiagramFloor" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasFloor;
+
+ //some more format commands with different ui text
+ m_aCommandAvailability[ ".uno:FormatWall" ] = m_aCommandAvailability[ ".uno:DiagramWall" ];
+ m_aCommandAvailability[ ".uno:FormatFloor" ] = m_aCommandAvailability[ ".uno:DiagramFloor" ];
+ m_aCommandAvailability[ ".uno:FormatChartArea" ] = m_aCommandAvailability[ ".uno:DiagramArea" ];
+ m_aCommandAvailability[ ".uno:FormatLegend" ] = m_aCommandAvailability[ ".uno:Legend" ];
+
+ // depending on own data and ability to create new data provider
+ m_aCommandAvailability[".uno:DataRanges"] = bIsWritable && bModelStateIsValid && !m_apModelState->bHasDataFromPivotTable
+ && ((m_apModelState->bHasOwnData && bCanCreateDataProvider) || !m_apModelState->bHasOwnData);
+ m_aCommandAvailability[ ".uno:DiagramData" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasOwnData && bEnableDataTableDialog;
+
+ // titles
+ m_aCommandAvailability[ ".uno:MainTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainTitle;
+ m_aCommandAvailability[ ".uno:SubTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSubTitle;
+ m_aCommandAvailability[ ".uno:XTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasXAxisTitle;
+ m_aCommandAvailability[ ".uno:YTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasYAxisTitle;
+ m_aCommandAvailability[ ".uno:ZTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasZAxisTitle;
+ m_aCommandAvailability[ ".uno:SecondaryXTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSecondaryXAxisTitle;
+ m_aCommandAvailability[ ".uno:SecondaryYTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSecondaryYAxisTitle;
+ m_aCommandAvailability[ ".uno:AllTitles" ] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyTitle();
+
+ // text
+ m_aCommandAvailability[ ".uno:ScaleText" ] = bIsWritable && bModelStateIsValid ;
+ m_aCommandArguments[ ".uno:ScaleText" ] <<= bModelStateIsValid && m_apModelState->bHasAutoScaledText;
+
+ // axes
+ m_aCommandAvailability[ ".uno:DiagramAxisX" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasXAxis;
+ m_aCommandAvailability[ ".uno:DiagramAxisY" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasYAxis;
+ m_aCommandAvailability[ ".uno:DiagramAxisZ" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasZAxis;
+ m_aCommandAvailability[ ".uno:DiagramAxisA" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasAAxis;
+ m_aCommandAvailability[ ".uno:DiagramAxisB" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasBAxis;
+ m_aCommandAvailability[ ".uno:DiagramAxisAll" ] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyAxis();
+
+ // grids
+ // note: x and y are swapped in the commands!
+ m_aCommandAvailability[ ".uno:DiagramGridYMain" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainXGrid;
+ m_aCommandAvailability[ ".uno:DiagramGridXMain" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainYGrid;
+ m_aCommandAvailability[ ".uno:DiagramGridZMain" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainZGrid;
+ m_aCommandAvailability[ ".uno:DiagramGridYHelp" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpXGrid;
+ m_aCommandAvailability[ ".uno:DiagramGridXHelp" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpYGrid;
+ m_aCommandAvailability[ ".uno:DiagramGridZHelp" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpZGrid;
+ m_aCommandAvailability[ ".uno:DiagramGridAll" ] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyGrid();
+
+ // series arrangement
+ m_aCommandAvailability[ ".uno:Forward" ] = ( bShapeContext ? isShapeControllerCommandAvailable( ".uno:Forward" ) :
+ ( bIsWritable && bControllerStateIsValid && m_apControllerState->bMayMoveSeriesForward && bEnableDataTableDialog ) );
+ m_aCommandAvailability[ ".uno:Backward" ] = ( bShapeContext ? isShapeControllerCommandAvailable( ".uno:Backward" ) :
+ ( bIsWritable && bControllerStateIsValid && m_apControllerState->bMayMoveSeriesBackward && bEnableDataTableDialog ) );
+
+ m_aCommandAvailability[ ".uno:InsertDataLabels" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:InsertDataLabel" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:InsertMeanValue" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddMeanValue;
+ m_aCommandAvailability[ ".uno:InsertTrendline" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddTrendline;
+ const bool bInsertTrendlineEquation = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddTrendlineEquation;
+ m_aCommandAvailability[ ".uno:InsertTrendlineEquation" ] = bInsertTrendlineEquation;
+ m_aCommandAvailability[ ".uno:InsertTrendlineEquationAndR2" ] = bInsertTrendlineEquation && m_apControllerState->bMayAddR2Value;
+ m_aCommandAvailability[ ".uno:InsertR2Value" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddR2Value
+ && !m_apControllerState->bMayAddTrendlineEquation;
+ m_aCommandAvailability[ ".uno:DeleteR2Value" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteR2Value;
+
+ m_aCommandAvailability[ ".uno:InsertXErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddXErrorBars;
+ m_aCommandAvailability[ ".uno:InsertYErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddYErrorBars;
+
+ m_aCommandAvailability[ ".uno:DeleteDataLabels" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:DeleteDataLabel" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:DeleteTrendline" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteTrendline;
+ m_aCommandAvailability[ ".uno:DeleteTrendlineEquation" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteTrendlineEquation;
+ m_aCommandAvailability[ ".uno:DeleteMeanValue" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteMeanValue;
+ m_aCommandAvailability[ ".uno:DeleteXErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteXErrorBars;
+ m_aCommandAvailability[ ".uno:DeleteYErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteYErrorBars;
+
+ m_aCommandAvailability[ ".uno:ResetDataPoint" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:ResetAllDataPoints" ] = bIsWritable;
+
+ m_aCommandAvailability[ ".uno:InsertAxis" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:DeleteAxis" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:InsertAxisTitle" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:FormatMajorGrid" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:InsertMajorGrid" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:DeleteMajorGrid" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:FormatMinorGrid" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:InsertMinorGrid" ] = bIsWritable;
+ m_aCommandAvailability[ ".uno:DeleteMinorGrid" ] = bIsWritable;
+
+ // data table
+ m_aCommandAvailability[ ".uno:InsertDataTable" ] = bIsWritable && bModelStateIsValid && !m_apModelState->bDataTable;
+ m_aCommandAvailability[ ".uno:DeleteDataTable" ] = bIsWritable && bModelStateIsValid && m_apModelState->bDataTable;
+}
+
+bool ControllerCommandDispatch::commandAvailable( const OUString & rCommand )
+{
+ std::map< OUString, bool >::const_iterator aIt( m_aCommandAvailability.find( rCommand ));
+ if( aIt != m_aCommandAvailability.end())
+ return aIt->second;
+ SAL_WARN("chart2", "commandAvailable: command not in availability map:" << rCommand);
+ return false;
+}
+
+bool ControllerCommandDispatch::isShapeControllerCommandAvailable( const OUString& rCommand )
+{
+ ShapeController* pShapeController(nullptr);
+ {
+ SolarMutexGuard g;
+ if (m_pDispatchContainer)
+ pShapeController = m_pDispatchContainer->getShapeController();
+ }
+ if ( pShapeController )
+ {
+ FeatureState aState( pShapeController->getState( rCommand ) );
+ return aState.bEnabled;
+ }
+ return false;
+}
+
+void ControllerCommandDispatch::fireStatusEvent(
+ const OUString & rURL,
+ const Reference< frame::XStatusListener > & xSingleListener /* = 0 */ )
+{
+ bool bIsChartSelectorURL = rURL == ".uno:ChartElementSelector";
+ if( rURL.isEmpty() || bIsChartSelectorURL )
+ {
+ uno::Any aArg;
+ aArg <<= Reference< frame::XController >(m_xChartController);
+ fireStatusEventForURL( ".uno:ChartElementSelector", aArg, true, xSingleListener );
+ }
+
+ if( rURL.isEmpty() )
+ {
+ for (auto const& elem : m_aCommandAvailability)
+ fireStatusEventForURLImpl( elem.first, xSingleListener );
+ }
+ else if( !bIsChartSelectorURL )
+ fireStatusEventForURLImpl( rURL, xSingleListener );
+
+ // statusbar. Should be handled by base implementation
+ // @todo: remove if Issue 68864 is fixed
+ if( rURL.isEmpty() || rURL == ".uno:StatusBarVisible" )
+ {
+ bool bIsStatusBarVisible( lcl_isStatusBarVisible( m_xChartController ));
+ fireStatusEventForURL( ".uno:StatusBarVisible", uno::Any( bIsStatusBarVisible ), true, xSingleListener );
+ }
+}
+
+// ____ XDispatch ____
+void SAL_CALL ControllerCommandDispatch::dispatch(
+ const util::URL& URL,
+ const Sequence< beans::PropertyValue >& Arguments )
+{
+ if( commandAvailable( URL.Complete ))
+ m_xDispatch->dispatch( URL, Arguments );
+}
+
+// ____ WeakComponentImplHelperBase ____
+/// is called when this is disposed
+void ControllerCommandDispatch::disposing(std::unique_lock<std::mutex>& /*rGuard*/)
+{
+ m_xChartController.clear();
+ m_xDispatch.clear();
+ m_xSelectionSupplier.clear();
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL ControllerCommandDispatch::disposing( const lang::EventObject& /* Source */ )
+{
+ m_xChartController.clear();
+ m_xDispatch.clear();
+ m_xSelectionSupplier.clear();
+}
+
+// ____ XModifyListener ____
+void SAL_CALL ControllerCommandDispatch::modified( const lang::EventObject& aEvent )
+{
+ bool bUpdateCommandAvailability = false;
+
+ // Update the "ModelState" Struct.
+ if( m_apModelState && m_xChartController.is())
+ {
+ m_apModelState->update( m_xChartController->getChartModel());
+ bUpdateCommandAvailability = true;
+ }
+
+ // Update the "ControllerState" Struct.
+ if( m_apControllerState && m_xChartController.is())
+ {
+ m_apControllerState->update( m_xChartController, m_xChartController->getChartModel());
+ bUpdateCommandAvailability = true;
+ }
+
+ if( bUpdateCommandAvailability )
+ updateCommandAvailability();
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ if (SfxViewShell* pViewShell = SfxViewShell::Current())
+ if (SfxObjectShell* pObjSh = pViewShell->GetObjectShell())
+ pObjSh->SetModified();
+ }
+
+ CommandDispatch::modified( aEvent );
+}
+
+// ____ XSelectionChangeListener ____
+void SAL_CALL ControllerCommandDispatch::selectionChanged( const lang::EventObject& aEvent )
+{
+ // Update the "ControllerState" Struct.
+ if( m_apControllerState && m_xChartController.is())
+ {
+ m_apControllerState->update( m_xChartController, m_xChartController->getChartModel());
+ updateCommandAvailability();
+ }
+
+ CommandDispatch::modified( aEvent );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ControllerCommandDispatch.hxx b/chart2/source/controller/main/ControllerCommandDispatch.hxx
new file mode 100644
index 0000000000..6a5e441e8e
--- /dev/null
+++ b/chart2/source/controller/main/ControllerCommandDispatch.hxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "CommandDispatch.hxx"
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+
+#include <memory>
+
+namespace com::sun::star::view { class XSelectionSupplier; }
+
+namespace chart
+{
+
+class ChartController;
+class CommandDispatchContainer;
+
+namespace impl
+{
+struct ModelState;
+struct ControllerState;
+
+// #i63017# : need to implement the XSelectionChangeListener in order
+// to update the ControllerState when the selection changes.
+typedef ::cppu::ImplInheritanceHelper<
+ CommandDispatch,
+ css::view::XSelectionChangeListener >
+ ControllerCommandDispatch_Base;
+}
+
+/** This class is a CommandDispatch that is responsible for all commands that
+ the ChartController supports.
+
+ This class determines which commands are currently available (via the model
+ state) and if an available command is called forwards it to the
+ ChartController.
+ */
+class ControllerCommandDispatch : public impl::ControllerCommandDispatch_Base
+{
+public:
+ explicit ControllerCommandDispatch(
+ const css::uno::Reference< css::uno::XComponentContext > & xContext,
+ ChartController* pController, CommandDispatchContainer* pContainer );
+ virtual ~ControllerCommandDispatch() override;
+
+ // late initialisation, especially for adding as listener
+ virtual void initialize() override;
+
+ bool commandAvailable( const OUString & rCommand );
+
+protected:
+ // ____ XDispatch ____
+ virtual void SAL_CALL dispatch(
+ const css::util::URL& URL,
+ const css::uno::Sequence< css::beans::PropertyValue >& Arguments ) override;
+
+ // ____ WeakComponentImplHelperBase ____
+ /// is called when this is disposed
+ virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ virtual void fireStatusEvent(
+ const OUString & rURL,
+ const css::uno::Reference< css::frame::XStatusListener > & xSingleListener ) override;
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XSelectionChangeListener ____
+ virtual void SAL_CALL selectionChanged(
+ const css::lang::EventObject& aEvent ) override;
+
+private:
+ void fireStatusEventForURLImpl(
+ const OUString & rURL,
+ const css::uno::Reference< css::frame::XStatusListener > & xSingleListener );
+
+ void updateCommandAvailability();
+
+ bool isShapeControllerCommandAvailable( const OUString& rCommand );
+
+ rtl::Reference<ChartController> m_xChartController;
+ css::uno::Reference< css::view::XSelectionSupplier > m_xSelectionSupplier;
+ css::uno::Reference< css::frame::XDispatch > m_xDispatch;
+
+ std::unique_ptr< impl::ModelState > m_apModelState;
+ std::unique_ptr< impl::ControllerState > m_apControllerState;
+
+ mutable std::map< OUString, bool > m_aCommandAvailability;
+ mutable std::map< OUString, css::uno::Any > m_aCommandArguments;
+
+ CommandDispatchContainer* m_pDispatchContainer;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/DragMethod_Base.cxx b/chart2/source/controller/main/DragMethod_Base.cxx
new file mode 100644
index 0000000000..5e46dc327b
--- /dev/null
+++ b/chart2/source/controller/main/DragMethod_Base.cxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DragMethod_Base.hxx"
+#include <DrawViewWrapper.hxx>
+#include <ChartModel.hxx>
+#include <ObjectNameProvider.hxx>
+#include <ObjectIdentifier.hxx>
+
+#include <svx/ActionDescriptionProvider.hxx>
+#include <utility>
+#include <vcl/ptrstyle.hxx>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+
+DragMethod_Base::DragMethod_Base( DrawViewWrapper& rDrawViewWrapper
+ , OUString aObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel
+ , ActionDescriptionProvider::ActionType eActionType )
+ : SdrDragMethod( rDrawViewWrapper )
+ , m_rDrawViewWrapper(rDrawViewWrapper)
+ , m_aObjectCID(std::move(aObjectCID))
+ , m_eActionType( eActionType )
+ , m_xChartModel( xChartModel.get() )
+{
+ setMoveOnly(true);
+}
+DragMethod_Base::~DragMethod_Base()
+{
+}
+
+rtl::Reference<::chart::ChartModel> DragMethod_Base::getChartModel() const
+{
+ return m_xChartModel.get();
+}
+
+OUString DragMethod_Base::getUndoDescription() const
+{
+ return ActionDescriptionProvider::createDescription(
+ m_eActionType,
+ ObjectNameProvider::getName( ObjectIdentifier::getObjectType( m_aObjectCID )));
+}
+OUString DragMethod_Base::GetSdrDragComment() const
+{
+ return getUndoDescription();
+}
+PointerStyle DragMethod_Base::GetSdrDragPointer() const
+{
+ if( IsDraggingPoints() || IsDraggingGluePoints() )
+ return PointerStyle::MovePoint;
+ else
+ return PointerStyle::Move;
+}
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/DragMethod_Base.hxx b/chart2/source/controller/main/DragMethod_Base.hxx
new file mode 100644
index 0000000000..1a65938890
--- /dev/null
+++ b/chart2/source/controller/main/DragMethod_Base.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svx/ActionDescriptionProvider.hxx>
+#include <svx/svddrgmt.hxx>
+#include <unotools/weakref.hxx>
+
+namespace chart { class DrawViewWrapper; }
+namespace com::sun::star::frame { class XModel; }
+
+namespace chart
+{
+class ChartModel;
+
+class DragMethod_Base : public SdrDragMethod
+{
+public:
+ DragMethod_Base( DrawViewWrapper& rDrawViewWrapper, OUString aObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel
+ , ActionDescriptionProvider::ActionType eActionType = ActionDescriptionProvider::ActionType::Move );
+ virtual ~DragMethod_Base() override;
+
+ OUString getUndoDescription() const;
+
+ virtual OUString GetSdrDragComment() const override;
+ virtual PointerStyle GetSdrDragPointer() const override;
+
+protected:
+ rtl::Reference<::chart::ChartModel> getChartModel() const;
+
+protected:
+ DrawViewWrapper& m_rDrawViewWrapper;
+ OUString m_aObjectCID;
+ ActionDescriptionProvider::ActionType m_eActionType;
+
+private:
+ unotools::WeakReference<::chart::ChartModel> m_xChartModel;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/DragMethod_PieSegment.cxx b/chart2/source/controller/main/DragMethod_PieSegment.cxx
new file mode 100644
index 0000000000..5bd85faaf9
--- /dev/null
+++ b/chart2/source/controller/main/DragMethod_PieSegment.cxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DragMethod_PieSegment.hxx"
+#include <DrawViewWrapper.hxx>
+#include <ChartModel.hxx>
+#include <strings.hrc>
+#include <ResId.hxx>
+#include <ObjectIdentifier.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/awt/Point.hpp>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::basegfx::B2DVector;
+
+DragMethod_PieSegment::DragMethod_PieSegment( DrawViewWrapper& rDrawViewWrapper
+ , const OUString& rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+ : DragMethod_Base( rDrawViewWrapper, rObjectCID, xChartModel )
+ , m_aStartVector(100.0,100.0)
+ , m_fInitialOffset(0.0)
+ , m_fAdditionalOffset(0.0)
+ , m_aDragDirection(1000.0,1000.0)
+ , m_fDragRange( 1.0 )
+{
+ std::u16string_view aParameter( ObjectIdentifier::getDragParameterString( m_aObjectCID ) );
+
+ sal_Int32 nOffsetPercent(0);
+ awt::Point aMinimumPosition(0,0);
+ awt::Point aMaximumPosition(0,0);
+
+ ObjectIdentifier::parsePieSegmentDragParameterString(
+ aParameter, nOffsetPercent, aMinimumPosition, aMaximumPosition );
+
+ m_fInitialOffset = nOffsetPercent / 100.0;
+ if( m_fInitialOffset < 0.0 )
+ m_fInitialOffset = 0.0;
+ if( m_fInitialOffset > 1.0 )
+ m_fInitialOffset = 1.0;
+ B2DVector aMinVector( aMinimumPosition.X, aMinimumPosition.Y );
+ B2DVector aMaxVector( aMaximumPosition.X, aMaximumPosition.Y );
+ m_aDragDirection = aMaxVector - aMinVector;
+ m_fDragRange = m_aDragDirection.scalar( m_aDragDirection );
+ if( m_fDragRange == 0.0 )
+ m_fDragRange = 1.0;
+}
+DragMethod_PieSegment::~DragMethod_PieSegment()
+{
+}
+OUString DragMethod_PieSegment::GetSdrDragComment() const
+{
+ OUString aStr = SchResId(STR_STATUS_PIE_SEGMENT_EXPLODED);
+ aStr = aStr.replaceFirst( "%PERCENTVALUE", OUString::number( static_cast<sal_Int32>((m_fAdditionalOffset+m_fInitialOffset)*100.0) ));
+ return aStr;
+}
+bool DragMethod_PieSegment::BeginSdrDrag()
+{
+ Point aStart( DragStat().GetStart() );
+ m_aStartVector = B2DVector( aStart.X(), aStart.Y() );
+ Show();
+ return true;
+}
+void DragMethod_PieSegment::MoveSdrDrag(const Point& rPnt)
+{
+ if( !DragStat().CheckMinMoved(rPnt) )
+ return;
+
+ //calculate new offset
+ B2DVector aShiftVector( B2DVector( rPnt.X(), rPnt.Y() ) - m_aStartVector );
+ m_fAdditionalOffset = m_aDragDirection.scalar( aShiftVector )/m_fDragRange; // projection
+
+ if( m_fAdditionalOffset < -m_fInitialOffset )
+ m_fAdditionalOffset = -m_fInitialOffset;
+ else if( m_fAdditionalOffset > (1.0-m_fInitialOffset) )
+ m_fAdditionalOffset = 1.0 - m_fInitialOffset;
+
+ B2DVector aNewPosVector = m_aStartVector + (m_aDragDirection * m_fAdditionalOffset);
+ Point aNewPos( static_cast<tools::Long>(aNewPosVector.getX()), static_cast<tools::Long>(aNewPosVector.getY()) );
+ if( aNewPos != DragStat().GetNow() )
+ {
+ Hide();
+ DragStat().NextMove( aNewPos );
+ Show();
+ }
+}
+bool DragMethod_PieSegment::EndSdrDrag(bool /*bCopy*/)
+{
+ Hide();
+
+ try
+ {
+ rtl::Reference<::chart::ChartModel> xChartModel( getChartModel() );
+ if( xChartModel.is() )
+ {
+ Reference< beans::XPropertySet > xPointProperties(
+ ObjectIdentifier::getObjectPropertySet( m_aObjectCID, xChartModel ) );
+ if( xPointProperties.is() )
+ xPointProperties->setPropertyValue( "Offset", uno::Any( m_fAdditionalOffset+m_fInitialOffset ));
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return true;
+}
+basegfx::B2DHomMatrix DragMethod_PieSegment::getCurrentTransformation() const
+{
+ basegfx::B2DHomMatrix aRetval;
+
+ aRetval.translate(DragStat().GetDX(), DragStat().GetDY());
+
+ return aRetval;
+}
+void DragMethod_PieSegment::createSdrDragEntries()
+{
+ SdrObject* pObj = m_rDrawViewWrapper.getSelectedObject();
+ SdrPageView* pPV = m_rDrawViewWrapper.GetPageView();
+
+ if( pObj && pPV )
+ {
+ basegfx::B2DPolyPolygon aNewPolyPolygon(pObj->TakeXorPoly());
+ addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPolyPolygon(std::move(aNewPolyPolygon))));
+ }
+}
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/DragMethod_PieSegment.hxx b/chart2/source/controller/main/DragMethod_PieSegment.hxx
new file mode 100644
index 0000000000..8cb498373f
--- /dev/null
+++ b/chart2/source/controller/main/DragMethod_PieSegment.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "DragMethod_Base.hxx"
+#include <basegfx/vector/b2dvector.hxx>
+
+namespace chart
+{
+
+class DragMethod_PieSegment : public DragMethod_Base
+{
+public:
+ DragMethod_PieSegment( DrawViewWrapper& rDrawViewWrapper, const OUString& rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+ virtual ~DragMethod_PieSegment() override;
+
+ virtual OUString GetSdrDragComment() const override;
+ virtual bool BeginSdrDrag() override;
+ virtual void MoveSdrDrag(const Point& rPnt) override;
+ virtual bool EndSdrDrag(bool bCopy) override;
+
+ virtual basegfx::B2DHomMatrix getCurrentTransformation() const override;
+
+protected:
+ virtual void createSdrDragEntries() override;
+
+private:
+ ::basegfx::B2DVector m_aStartVector;
+ double m_fInitialOffset;
+ double m_fAdditionalOffset;
+ ::basegfx::B2DVector m_aDragDirection;
+ double m_fDragRange;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/DragMethod_RotateDiagram.cxx b/chart2/source/controller/main/DragMethod_RotateDiagram.cxx
new file mode 100644
index 0000000000..0ae2f2803c
--- /dev/null
+++ b/chart2/source/controller/main/DragMethod_RotateDiagram.cxx
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DragMethod_RotateDiagram.hxx"
+#include <DrawViewWrapper.hxx>
+
+#include <SelectionHelper.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ThreeDHelper.hxx>
+#include <defines.hxx>
+#include <svx/sdr/overlay/overlaypolypolygon.hxx>
+
+#include <svx/scene3d.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <svx/sdr/contact/viewcontactofe3dscene.hxx>
+#include <drawinglayer/geometry/viewinformation3d.hxx>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+
+DragMethod_RotateDiagram::DragMethod_RotateDiagram( DrawViewWrapper& rDrawViewWrapper
+ , const OUString& rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel
+ , RotationDirection eRotationDirection )
+ : DragMethod_Base( rDrawViewWrapper, rObjectCID, xChartModel, ActionDescriptionProvider::ActionType::Rotate )
+ , m_pScene(nullptr)
+ , m_aReferenceRect(100,100,100,100)
+ , m_aStartPos(0,0)
+ , m_fInitialXAngleRad(0.0)
+ , m_fInitialYAngleRad(0.0)
+ , m_fInitialZAngleRad(0.0)
+ , m_fAdditionalXAngleRad(0.0)
+ , m_fAdditionalYAngleRad(0.0)
+ , m_fAdditionalZAngleRad(0.0)
+ , m_nInitialHorizontalAngleDegree(0)
+ , m_nInitialVerticalAngleDegree(0)
+ , m_nAdditionalHorizontalAngleDegree(0)
+ , m_nAdditionalVerticalAngleDegree(0)
+ , m_eRotationDirection(eRotationDirection)
+ , m_bRightAngledAxes(false)
+{
+ m_pScene = SelectionHelper::getSceneToRotate( rDrawViewWrapper.getNamedSdrObject( rObjectCID ) );
+ SdrObject* pObj = rDrawViewWrapper.getSelectedObject();
+ if(!(pObj && m_pScene))
+ return;
+
+ m_aReferenceRect = pObj->GetLogicRect();
+
+ m_aWireframePolyPolygon = m_pScene->CreateWireframe();
+
+ rtl::Reference< Diagram > xDiagram = getChartModel()->getFirstChartDiagram();
+ if( !xDiagram.is() )
+ return;
+
+ xDiagram->getRotation(
+ m_nInitialHorizontalAngleDegree, m_nInitialVerticalAngleDegree );
+
+ xDiagram->getRotationAngle(
+ m_fInitialXAngleRad, m_fInitialYAngleRad, m_fInitialZAngleRad );
+
+ if( ChartTypeHelper::isSupportingRightAngledAxes(
+ xDiagram->getChartTypeByIndex( 0 ) ) )
+ xDiagram->getPropertyValue("RightAngledAxes") >>= m_bRightAngledAxes;
+ if(m_bRightAngledAxes)
+ {
+ if( m_eRotationDirection==ROTATIONDIRECTION_Z )
+ m_eRotationDirection=ROTATIONDIRECTION_FREE;
+ ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fInitialXAngleRad, m_fInitialYAngleRad );
+ }
+}
+DragMethod_RotateDiagram::~DragMethod_RotateDiagram()
+{
+}
+OUString DragMethod_RotateDiagram::GetSdrDragComment() const
+{
+ return OUString();
+}
+bool DragMethod_RotateDiagram::BeginSdrDrag()
+{
+ m_aStartPos = DragStat().GetStart();
+ Show();
+ return true;
+}
+void DragMethod_RotateDiagram::MoveSdrDrag(const Point& rPnt)
+{
+ if( !DragStat().CheckMinMoved(rPnt) )
+ return;
+
+ Hide();
+
+ //calculate new angle
+ double fX = M_PI_2 * static_cast<double>(rPnt.Y() - m_aStartPos.Y())
+ / (m_aReferenceRect.GetHeight() > 0 ? static_cast<double>(m_aReferenceRect.GetHeight()) : 1.0);
+ double fY = M_PI * static_cast<double>(rPnt.X() - m_aStartPos.X())
+ / (m_aReferenceRect.GetWidth() > 0 ? static_cast<double>(m_aReferenceRect.GetWidth()) : 1.0);
+
+ if( m_eRotationDirection != ROTATIONDIRECTION_Y )
+ m_fAdditionalYAngleRad = fY;
+ else
+ m_fAdditionalYAngleRad = 0.0;
+ if( m_eRotationDirection != ROTATIONDIRECTION_X )
+ m_fAdditionalXAngleRad = fX;
+ else
+ m_fAdditionalXAngleRad = 0.0;
+ m_fAdditionalZAngleRad = 0.0;
+
+ if( m_eRotationDirection == ROTATIONDIRECTION_Z )
+ {
+ m_fAdditionalXAngleRad = 0.0;
+ m_fAdditionalYAngleRad = 0.0;
+
+ double fCx = m_aReferenceRect.Center().X();
+ double fCy = m_aReferenceRect.Center().Y();
+
+ m_fAdditionalZAngleRad = atan((fCx - m_aStartPos.X())/(m_aStartPos.Y()-fCy))
+ + atan((fCx - rPnt.X())/(fCy-rPnt.Y()));
+ }
+
+ m_nAdditionalHorizontalAngleDegree = static_cast<sal_Int32>(basegfx::rad2deg(m_fAdditionalXAngleRad));
+ m_nAdditionalVerticalAngleDegree = -static_cast<sal_Int32>(basegfx::rad2deg(m_fAdditionalYAngleRad));
+
+ DragStat().NextMove(rPnt);
+ Show();
+}
+bool DragMethod_RotateDiagram::EndSdrDrag(bool /*bCopy*/)
+{
+ Hide();
+
+ if( m_bRightAngledAxes || m_eRotationDirection==ROTATIONDIRECTION_Z )
+ {
+ double fResultX = m_fInitialXAngleRad + m_fAdditionalXAngleRad;
+ double fResultY = m_fInitialYAngleRad + m_fAdditionalYAngleRad;
+ double fResultZ = m_fInitialZAngleRad + m_fAdditionalZAngleRad;
+
+ if(m_bRightAngledAxes)
+ ThreeDHelper::adaptRadAnglesForRightAngledAxes( fResultX, fResultY );
+
+ rtl::Reference<Diagram> xDiagram = getChartModel()->getFirstChartDiagram();
+ if (xDiagram)
+ xDiagram->setRotationAngle( fResultX, fResultY, fResultZ );
+ }
+ else
+ {
+ rtl::Reference<Diagram> xDiagram = getChartModel()->getFirstChartDiagram();
+ if (xDiagram)
+ xDiagram->setRotation(
+ m_nInitialHorizontalAngleDegree+m_nAdditionalHorizontalAngleDegree, m_nInitialVerticalAngleDegree+m_nAdditionalVerticalAngleDegree );
+ }
+
+ return true;
+}
+void DragMethod_RotateDiagram::CreateOverlayGeometry(
+ sdr::overlay::OverlayManager& rOverlayManager,
+ const sdr::contact::ObjectContact& rObjectContact)
+{
+ ::basegfx::B3DHomMatrix aCurrentTransform;
+ aCurrentTransform.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
+ -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
+ -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
+
+ double fResultX = m_fInitialXAngleRad + m_fAdditionalXAngleRad;
+ double fResultY = m_fInitialYAngleRad + m_fAdditionalYAngleRad;
+ double fResultZ = m_fInitialZAngleRad + m_fAdditionalZAngleRad;
+
+ if(!m_bRightAngledAxes)
+ {
+ if( m_eRotationDirection!=ROTATIONDIRECTION_Z )
+ {
+ ThreeDHelper::convertElevationRotationDegToXYZAngleRad(
+ m_nInitialHorizontalAngleDegree+m_nAdditionalHorizontalAngleDegree, -(m_nInitialVerticalAngleDegree+m_nAdditionalVerticalAngleDegree)
+ , fResultX, fResultY, fResultZ );
+ }
+ aCurrentTransform.rotate( fResultX, fResultY, fResultZ );
+ }
+ else
+ {
+ ThreeDHelper::adaptRadAnglesForRightAngledAxes( fResultX, fResultY );
+ aCurrentTransform.shearXY(fResultY,-fResultX);
+ }
+
+ if(!(m_aWireframePolyPolygon.count() && m_pScene))
+ return;
+
+ const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(m_pScene->GetViewContact());
+ const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
+ const basegfx::B3DHomMatrix aWorldToView(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection() * aViewInfo3D.getOrientation());
+ const basegfx::B3DHomMatrix aTransform(aWorldToView * aCurrentTransform);
+
+ // transform to relative scene coordinates
+ basegfx::B2DPolyPolygon aPolyPolygon(basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(m_aWireframePolyPolygon, aTransform));
+
+ // transform to 2D view coordinates
+ aPolyPolygon.transform(rVCScene.getObjectTransformation());
+
+ std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(
+ new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
+ std::move(aPolyPolygon)));
+
+ insertNewlyCreatedOverlayObjectForSdrDragMethod(
+ std::move(pNew),
+ rObjectContact,
+ rOverlayManager);
+}
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/DragMethod_RotateDiagram.hxx b/chart2/source/controller/main/DragMethod_RotateDiagram.hxx
new file mode 100644
index 0000000000..69e9050eeb
--- /dev/null
+++ b/chart2/source/controller/main/DragMethod_RotateDiagram.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "DragMethod_Base.hxx"
+
+#include <basegfx/polygon/b3dpolypolygon.hxx>
+
+class E3dScene;
+namespace chart { class DrawViewWrapper; }
+
+namespace chart
+{
+
+class DragMethod_RotateDiagram : public DragMethod_Base
+{
+public:
+ enum RotationDirection
+ {
+ ROTATIONDIRECTION_FREE,
+ ROTATIONDIRECTION_X,
+ ROTATIONDIRECTION_Y,
+ ROTATIONDIRECTION_Z
+ };
+
+ DragMethod_RotateDiagram( DrawViewWrapper& rDrawViewWrapper
+ , const OUString& rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel
+ , RotationDirection eRotationDirection
+ );
+ virtual ~DragMethod_RotateDiagram() override;
+
+ virtual OUString GetSdrDragComment() const override;
+
+ virtual bool BeginSdrDrag() override;
+ virtual void MoveSdrDrag(const Point& rPnt) override;
+ virtual bool EndSdrDrag(bool bCopy) override;
+
+ virtual void CreateOverlayGeometry(
+ sdr::overlay::OverlayManager& rOverlayManager,
+ const sdr::contact::ObjectContact& rObjectContact) override;
+
+private:
+ E3dScene* m_pScene;
+
+ tools::Rectangle m_aReferenceRect;
+ Point m_aStartPos;
+ basegfx::B3DPolyPolygon m_aWireframePolyPolygon;
+
+ double m_fInitialXAngleRad;
+ double m_fInitialYAngleRad;
+ double m_fInitialZAngleRad;
+
+ double m_fAdditionalXAngleRad;
+ double m_fAdditionalYAngleRad;
+ double m_fAdditionalZAngleRad;
+
+ sal_Int32 m_nInitialHorizontalAngleDegree;
+ sal_Int32 m_nInitialVerticalAngleDegree;
+
+ sal_Int32 m_nAdditionalHorizontalAngleDegree;
+ sal_Int32 m_nAdditionalVerticalAngleDegree;
+
+ RotationDirection m_eRotationDirection;
+ bool m_bRightAngledAxes;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/DrawCommandDispatch.cxx b/chart2/source/controller/main/DrawCommandDispatch.cxx
new file mode 100644
index 0000000000..1446059a02
--- /dev/null
+++ b/chart2/source/controller/main/DrawCommandDispatch.cxx
@@ -0,0 +1,613 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DrawCommandDispatch.hxx"
+#include <ChartController.hxx>
+#include <DrawViewWrapper.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+
+#include <com/sun/star/frame/CommandGroup.hpp>
+#include <o3tl/unsafe_downcast.hxx>
+#include <o3tl/string_view.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/itempool.hxx>
+#include <editeng/eeitem.hxx>
+#include <svx/strings.hrc>
+#include <svx/dialmgr.hxx>
+#include <svx/fmmodel.hxx>
+#include <svx/gallery.hxx>
+#include <svx/svdoashp.hxx>
+#include <svx/svdocapt.hxx>
+#include <svx/svdopath.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/unoapi.hxx>
+#include <svx/xlnedit.hxx>
+#include <svx/xlnedwit.hxx>
+#include <svx/xlnwtit.hxx>
+#include <svx/xtable.hxx>
+#include <svx/sdtagitm.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::frame;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+
+namespace chart
+{
+
+DrawCommandDispatch::DrawCommandDispatch( const Reference< uno::XComponentContext >& rxContext,
+ ChartController* pController )
+ :FeatureCommandDispatchBase( rxContext )
+ ,m_pChartController( pController )
+{
+}
+
+DrawCommandDispatch::~DrawCommandDispatch()
+{
+}
+
+bool DrawCommandDispatch::isFeatureSupported( const OUString& rCommandURL )
+{
+ ChartCommandID nFeatureId = ChartCommandID::NONE;
+ OUString aBaseCommand;
+ OUString aCustomShapeType;
+ return parseCommandURL( rCommandURL, &nFeatureId, &aBaseCommand, &aCustomShapeType );
+}
+
+static ::basegfx::B2DPolyPolygon getPolygon(TranslateId pResId, const SdrModel& rModel)
+{
+ ::basegfx::B2DPolyPolygon aReturn;
+ XLineEndListRef pLineEndList = rModel.GetLineEndList();
+ if ( pLineEndList.is() )
+ {
+ OUString aName(SvxResId(pResId));
+ tools::Long nCount = pLineEndList->Count();
+ for ( tools::Long nIndex = 0; nIndex < nCount; ++nIndex )
+ {
+ const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nIndex);
+ if ( pEntry->GetName() == aName )
+ {
+ aReturn = pEntry->GetLineEnd();
+ break;
+ }
+ }
+ }
+ return aReturn;
+}
+
+void DrawCommandDispatch::setAttributes( SdrObject* pObj )
+{
+ if ( !m_pChartController )
+ return;
+
+ DrawModelWrapper* pDrawModelWrapper = m_pChartController->GetDrawModelWrapper();
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( !(pDrawModelWrapper && pDrawViewWrapper && pDrawViewWrapper->GetCurrentObjIdentifier() == SdrObjKind::CustomShape) )
+ return;
+
+ bool bAttributesAppliedFromGallery = false;
+ if ( GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT ) )
+ {
+ std::vector< OUString > aObjList;
+ if ( GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT, aObjList ) )
+ {
+ for ( size_t i = 0; i < aObjList.size(); ++i )
+ {
+ if ( aObjList[ i ].equalsIgnoreAsciiCase( m_aCustomShapeType ) )
+ {
+ FmFormModel aModel;
+ SfxItemPool& rPool(aModel.GetItemPool());
+ rPool.FreezeIdRanges();
+
+ if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT, i, &aModel ) )
+ {
+ const SdrObject* pSourceObj = aModel.GetPage( 0 )->GetObj( 0 );
+ if ( pSourceObj )
+ {
+ const SfxItemSet& rSource = pSourceObj->GetMergedItemSet();
+ SfxItemSetFixed<
+ // Ranges from SdrAttrObj:
+ SDRATTR_START, SDRATTR_SHADOW_LAST,
+ SDRATTR_MISC_FIRST,
+ SDRATTR_MISC_LAST,
+ SDRATTR_TEXTDIRECTION,
+ SDRATTR_TEXTDIRECTION,
+ // Graphic attributes, 3D
+ // properties, CustomShape
+ // properties:
+ SDRATTR_GRAF_FIRST,
+ SDRATTR_CUSTOMSHAPE_LAST,
+ // Range from SdrTextObj:
+ EE_ITEMS_START, EE_ITEMS_END>
+ aDest(pObj->getSdrModelFromSdrObject().GetItemPool());
+ aDest.Set( rSource );
+ pObj->SetMergedItemSet( aDest );
+ Degree100 nAngle = pSourceObj->GetRotateAngle();
+ if ( nAngle )
+ pObj->NbcRotate( pObj->GetSnapRect().Center(), nAngle );
+ bAttributesAppliedFromGallery = true;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ if ( !bAttributesAppliedFromGallery )
+ {
+ pObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) );
+ pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) );
+ pObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
+
+ o3tl::unsafe_downcast< SdrObjCustomShape* >( pObj )->MergeDefaultAttributes( &m_aCustomShapeType );
+ }
+}
+
+void DrawCommandDispatch::setLineEnds( SfxItemSet& rAttr )
+{
+ if ( !(m_nFeatureId == ChartCommandID::DrawLineArrowEnd && m_pChartController) )
+ return;
+
+ DrawModelWrapper* pDrawModelWrapper = m_pChartController->GetDrawModelWrapper();
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( !(pDrawModelWrapper && pDrawViewWrapper) )
+ return;
+
+ ::basegfx::B2DPolyPolygon aArrow( getPolygon( RID_SVXSTR_ARROW, pDrawModelWrapper->getSdrModel() ) );
+ if ( !aArrow.count() )
+ {
+ ::basegfx::B2DPolygon aNewArrow;
+ aNewArrow.append( ::basegfx::B2DPoint( 10.0, 0.0 ) );
+ aNewArrow.append( ::basegfx::B2DPoint( 0.0, 30.0) );
+ aNewArrow.append( ::basegfx::B2DPoint( 20.0, 30.0 ) );
+ aNewArrow.setClosed( true );
+ aArrow.append( aNewArrow );
+ }
+
+ SfxItemSet aSet(pDrawViewWrapper->GetModel().GetItemPool());
+ pDrawViewWrapper->GetAttributes( aSet );
+
+ tools::Long nWidth = 300; // (1/100th mm)
+ if ( aSet.GetItemState( XATTR_LINEWIDTH ) != SfxItemState::DONTCARE )
+ {
+ tools::Long nValue = aSet.Get( XATTR_LINEWIDTH ).GetValue();
+ if ( nValue > 0 )
+ {
+ nWidth = nValue * 3;
+ }
+ }
+
+ rAttr.Put( XLineEndItem( SvxResId( RID_SVXSTR_ARROW ), aArrow ) );
+ rAttr.Put( XLineEndWidthItem( nWidth ) );
+}
+
+// WeakComponentImplHelperBase
+void DrawCommandDispatch::disposing(std::unique_lock<std::mutex>& /*rGuard*/)
+{
+}
+
+// XEventListener
+void DrawCommandDispatch::disposing( const lang::EventObject& /* Source */ )
+{
+}
+
+FeatureState DrawCommandDispatch::getState( const OUString& rCommand )
+{
+ FeatureState aReturn;
+ aReturn.bEnabled = false;
+ aReturn.aState <<= false;
+
+ ChartCommandID nFeatureId = ChartCommandID::NONE;
+ OUString aBaseCommand;
+ OUString aCustomShapeType;
+ if ( parseCommandURL( rCommand, &nFeatureId, &aBaseCommand, &aCustomShapeType ) )
+ {
+ switch ( nFeatureId )
+ {
+ case ChartCommandID::DrawObjectSelect:
+ case ChartCommandID::DrawLine:
+ case ChartCommandID::DrawLineArrowEnd:
+ case ChartCommandID::DrawRect:
+ case ChartCommandID::DrawEllipse:
+ case ChartCommandID::DrawFreelineNoFill:
+ case ChartCommandID::DrawText:
+ case ChartCommandID::DrawCaption:
+ case ChartCommandID::DrawToolboxCsBasic:
+ case ChartCommandID::DrawToolboxCsSymbol:
+ case ChartCommandID::DrawToolboxCsArrow:
+ case ChartCommandID::DrawToolboxCsFlowchart:
+ case ChartCommandID::DrawToolboxCsCallout:
+ case ChartCommandID::DrawToolboxCsStar:
+ {
+ aReturn.bEnabled = true;
+ aReturn.aState <<= false;
+ }
+ break;
+ default:
+ {
+ aReturn.bEnabled = false;
+ aReturn.aState <<= false;
+ }
+ break;
+ }
+ }
+
+ return aReturn;
+}
+
+void DrawCommandDispatch::execute( const OUString& rCommand, const Sequence< beans::PropertyValue>& rArgs )
+{
+ ChartDrawMode eDrawMode = CHARTDRAW_SELECT;
+ SdrObjKind eKind = SdrObjKind::NONE;
+
+ ChartCommandID nFeatureId = ChartCommandID::NONE;
+ OUString aBaseCommand;
+ OUString aCustomShapeType;
+ if ( !parseCommandURL( rCommand, &nFeatureId, &aBaseCommand, &aCustomShapeType ) )
+ return;
+
+ bool bCreate = false;
+ m_nFeatureId = nFeatureId;
+ m_aCustomShapeType = aCustomShapeType;
+
+ switch ( nFeatureId )
+ {
+ case ChartCommandID::DrawObjectSelect:
+ {
+ eDrawMode = CHARTDRAW_SELECT;
+ eKind = SdrObjKind::NONE;
+ }
+ break;
+ case ChartCommandID::DrawLine:
+ case ChartCommandID::DrawLineArrowEnd:
+ {
+ eDrawMode = CHARTDRAW_INSERT;
+ eKind = SdrObjKind::Line;
+ }
+ break;
+ case ChartCommandID::DrawRect:
+ {
+ eDrawMode = CHARTDRAW_INSERT;
+ eKind = SdrObjKind::Rectangle;
+ }
+ break;
+ case ChartCommandID::DrawEllipse:
+ {
+ eDrawMode = CHARTDRAW_INSERT;
+ eKind = SdrObjKind::CircleOrEllipse;
+ }
+ break;
+ case ChartCommandID::DrawFreelineNoFill:
+ {
+ eDrawMode = CHARTDRAW_INSERT;
+ eKind = SdrObjKind::FreehandLine;
+ }
+ break;
+ case ChartCommandID::DrawText:
+ {
+ eDrawMode = CHARTDRAW_INSERT;
+ eKind = SdrObjKind::Text;
+ bCreate = true;
+ }
+ break;
+ case ChartCommandID::DrawCaption:
+ {
+ eDrawMode = CHARTDRAW_INSERT;
+ eKind = SdrObjKind::Caption;
+ }
+ break;
+ case ChartCommandID::DrawToolboxCsBasic:
+ case ChartCommandID::DrawToolboxCsSymbol:
+ case ChartCommandID::DrawToolboxCsArrow:
+ case ChartCommandID::DrawToolboxCsFlowchart:
+ case ChartCommandID::DrawToolboxCsCallout:
+ case ChartCommandID::DrawToolboxCsStar:
+ {
+ eDrawMode = CHARTDRAW_INSERT;
+ eKind = SdrObjKind::CustomShape;
+ }
+ break;
+ default:
+ {
+ eDrawMode = CHARTDRAW_SELECT;
+ eKind = SdrObjKind::NONE;
+ }
+ break;
+ }
+
+ if ( !m_pChartController )
+ return;
+
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( !pDrawViewWrapper )
+ return;
+
+ SolarMutexGuard aGuard;
+ m_pChartController->setDrawMode( eDrawMode );
+ setInsertObj(eKind);
+ if ( bCreate )
+ {
+ pDrawViewWrapper->SetCreateMode();
+ }
+
+ const beans::PropertyValue* pIter = rArgs.getConstArray();
+ const beans::PropertyValue* pEnd = pIter + rArgs.getLength();
+ const beans::PropertyValue* pKeyModifier = std::find_if(pIter, pEnd,
+ [](const beans::PropertyValue& lhs)
+ {return lhs.Name == "KeyModifier";} );
+ sal_Int16 nKeyModifier = 0;
+ if ( !(pKeyModifier != pEnd && ( pKeyModifier->Value >>= nKeyModifier ) && nKeyModifier == KEY_MOD1) )
+ return;
+
+ if ( eDrawMode != CHARTDRAW_INSERT )
+ return;
+
+ rtl::Reference<SdrObject> pObj = createDefaultObject( nFeatureId );
+ if ( pObj )
+ {
+ SdrPageView* pPageView = pDrawViewWrapper->GetSdrPageView();
+ if (pDrawViewWrapper->InsertObjectAtView(pObj.get(), *pPageView))
+ m_pChartController->SetAndApplySelection(Reference<drawing::XShape>(pObj->getUnoShape(), uno::UNO_QUERY));
+ if ( nFeatureId == ChartCommandID::DrawText )
+ {
+ m_pChartController->StartTextEdit();
+ }
+ }
+}
+
+void DrawCommandDispatch::describeSupportedFeatures()
+{
+ implDescribeSupportedFeature( ".uno:SelectObject", ChartCommandID::DrawObjectSelect, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:Line", ChartCommandID::DrawLine, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:LineArrowEnd", ChartCommandID::DrawLineArrowEnd, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:Rect", ChartCommandID::DrawRect, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:Ellipse", ChartCommandID::DrawEllipse, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:Freeline_Unfilled", ChartCommandID::DrawFreelineNoFill, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DrawText", ChartCommandID::DrawText, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:DrawCaption", ChartCommandID::DrawCaption, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:BasicShapes", ChartCommandID::DrawToolboxCsBasic, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:SymbolShapes", ChartCommandID::DrawToolboxCsSymbol, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:ArrowShapes", ChartCommandID::DrawToolboxCsArrow, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:FlowChartShapes", ChartCommandID::DrawToolboxCsFlowchart, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:CalloutShapes", ChartCommandID::DrawToolboxCsCallout, CommandGroup::INSERT );
+ implDescribeSupportedFeature( ".uno:StarShapes", ChartCommandID::DrawToolboxCsStar, CommandGroup::INSERT );
+}
+
+void DrawCommandDispatch::setInsertObj(SdrObjKind eObj)
+{
+ DrawViewWrapper* pDrawViewWrapper = ( m_pChartController ? m_pChartController->GetDrawViewWrapper() : nullptr );
+ if ( pDrawViewWrapper )
+ {
+ pDrawViewWrapper->SetCurrentObj( eObj /*, Inventor */);
+ }
+}
+
+rtl::Reference<SdrObject> DrawCommandDispatch::createDefaultObject( const ChartCommandID nID )
+{
+ rtl::Reference<SdrObject> pObj;
+ DrawViewWrapper* pDrawViewWrapper = ( m_pChartController ? m_pChartController->GetDrawViewWrapper() : nullptr );
+ DrawModelWrapper* pDrawModelWrapper = ( m_pChartController ? m_pChartController->GetDrawModelWrapper() : nullptr );
+
+ if ( pDrawViewWrapper && pDrawModelWrapper )
+ {
+ Reference< drawing::XDrawPage > xDrawPage( pDrawModelWrapper->getMainDrawPage() );
+ SdrPage* pPage = GetSdrPageFromXDrawPage( xDrawPage );
+ if ( pPage )
+ {
+ SolarMutexGuard aGuard;
+
+ pObj = SdrObjFactory::MakeNewObject(
+ pDrawModelWrapper->getSdrModel(),
+ pDrawViewWrapper->GetCurrentObjInventor(),
+ pDrawViewWrapper->GetCurrentObjIdentifier());
+
+ if ( pObj )
+ {
+ Size aObjectSize( 4000, 2500 );
+ tools::Rectangle aPageRect( tools::Rectangle( Point( 0, 0 ), pPage->GetSize() ) );
+ Point aObjectPos = aPageRect.Center();
+ aObjectPos.AdjustX( -(aObjectSize.Width() / 2) );
+ aObjectPos.AdjustY( -(aObjectSize.Height() / 2) );
+ tools::Rectangle aRect( aObjectPos, aObjectSize );
+
+ switch ( nID )
+ {
+ case ChartCommandID::DrawLine:
+ case ChartCommandID::DrawLineArrowEnd:
+ {
+ if ( auto const pathObj = dynamic_cast<SdrPathObj*>( pObj.get()) )
+ {
+ Point aStart = aRect.TopLeft();
+ Point aEnd = aRect.BottomRight();
+ sal_Int32 nYMiddle( ( aRect.Top() + aRect.Bottom() ) / 2 );
+ basegfx::B2DPolygon aPoly;
+ aPoly.append( basegfx::B2DPoint( aStart.X(), nYMiddle ) );
+ aPoly.append( basegfx::B2DPoint( aEnd.X(), nYMiddle ) );
+ pathObj->SetPathPoly(basegfx::B2DPolyPolygon(aPoly));
+ SfxItemSet aSet( pDrawModelWrapper->GetItemPool() );
+ setLineEnds( aSet );
+ pObj->SetMergedItemSet( aSet );
+ }
+ }
+ break;
+ case ChartCommandID::DrawFreelineNoFill:
+ {
+ if ( auto const pathObj = dynamic_cast<SdrPathObj*>( pObj.get()) )
+ {
+ basegfx::B2DPolygon aInnerPoly;
+ aInnerPoly.append( basegfx::B2DPoint( aRect.Left(), aRect.Bottom() ) );
+ aInnerPoly.appendBezierSegment(
+ basegfx::B2DPoint( aRect.Left(), aRect.Top() ),
+ basegfx::B2DPoint( aRect.Center().X(), aRect.Top() ),
+ basegfx::B2DPoint( aRect.Center().X(), aRect.Center().Y() ) );
+ aInnerPoly.appendBezierSegment(
+ basegfx::B2DPoint( aRect.Center().X(), aRect.Bottom() ),
+ basegfx::B2DPoint( aRect.Right(), aRect.Bottom() ),
+ basegfx::B2DPoint( aRect.Right(), aRect.Top() ) );
+ basegfx::B2DPolyPolygon aPoly;
+ aPoly.append( aInnerPoly );
+ pathObj->SetPathPoly(aPoly);
+ }
+ }
+ break;
+ case ChartCommandID::DrawText:
+ case ChartCommandID::DrawTextVertical:
+ {
+ if ( SdrTextObj* pTextObj = DynCastSdrTextObj( pObj.get()) )
+ {
+ pTextObj->SetLogicRect( aRect );
+ bool bVertical = ( nID == ChartCommandID::DrawTextVertical );
+ pTextObj->SetVerticalWriting( bVertical );
+ if ( bVertical )
+ {
+ SfxItemSet aSet( pDrawModelWrapper->GetItemPool() );
+ aSet.Put( makeSdrTextAutoGrowWidthItem( true ) );
+ aSet.Put( makeSdrTextAutoGrowHeightItem( false ) );
+ aSet.Put( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_TOP ) );
+ aSet.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_RIGHT ) );
+ pTextObj->SetMergedItemSet( aSet );
+ }
+ }
+ }
+ break;
+ case ChartCommandID::DrawCaption:
+ case ChartCommandID::DrawCaptionVertical:
+ {
+ if ( SdrCaptionObj* pCaptionObj = dynamic_cast<SdrCaptionObj*>( pObj.get()) )
+ {
+ bool bIsVertical( nID == ChartCommandID::DrawCaptionVertical );
+ pCaptionObj->SetVerticalWriting( bIsVertical );
+ if ( bIsVertical )
+ {
+ SfxItemSet aSet( pObj->GetMergedItemSet() );
+ aSet.Put( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) );
+ aSet.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_RIGHT ) );
+ pObj->SetMergedItemSet( aSet );
+ }
+ pCaptionObj->SetLogicRect( aRect );
+ pCaptionObj->SetTailPos(
+ aRect.TopLeft() - Point( aRect.GetWidth() / 2, aRect.GetHeight() / 2 ) );
+ }
+ }
+ break;
+ default:
+ {
+ pObj->SetLogicRect( aRect );
+ SfxItemSet aSet( pDrawModelWrapper->GetItemPool() );
+ setAttributes( pObj.get() );
+ pObj->SetMergedItemSet( aSet );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return pObj;
+}
+
+bool DrawCommandDispatch::parseCommandURL( const OUString& rCommandURL, ChartCommandID* pnFeatureId,
+ OUString* pBaseCommand, OUString* pCustomShapeType )
+{
+ bool bFound = true;
+ ChartCommandID nFeatureId = ChartCommandID::NONE;
+ OUString aBaseCommand;
+ OUString aType;
+
+ sal_Int32 nIndex = std::min(sal_Int32(1), rCommandURL.getLength());
+ std::u16string_view aToken = o3tl::getToken(rCommandURL, 0, '.', nIndex );
+ if ( nIndex == -1 || aToken.empty() )
+ {
+ aBaseCommand = rCommandURL;
+ SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( aBaseCommand );
+ if ( aIter != m_aSupportedFeatures.end() )
+ {
+ nFeatureId = aIter->second.nFeatureId;
+
+ switch ( nFeatureId )
+ {
+ case ChartCommandID::DrawToolboxCsBasic:
+ {
+ aType = "diamond";
+ }
+ break;
+ case ChartCommandID::DrawToolboxCsSymbol:
+ {
+ aType = "smiley";
+ }
+ break;
+ case ChartCommandID::DrawToolboxCsArrow:
+ {
+ aType = "left-right-arrow";
+ }
+ break;
+ case ChartCommandID::DrawToolboxCsFlowchart:
+ {
+ aType = "flowchart-internal-storage";
+ }
+ break;
+ case ChartCommandID::DrawToolboxCsCallout:
+ {
+ aType = "round-rectangular-callout";
+ }
+ break;
+ case ChartCommandID::DrawToolboxCsStar:
+ {
+ aType = "star5";
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+ }
+ else
+ {
+ bFound = false;
+ }
+ }
+ else
+ {
+ aBaseCommand = rCommandURL.copy( 0, nIndex - 1 );
+ SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( aBaseCommand );
+ if ( aIter != m_aSupportedFeatures.end() )
+ {
+ nFeatureId = aIter->second.nFeatureId;
+ aType = rCommandURL.getToken( 0, '.', nIndex );
+ }
+ else
+ {
+ bFound = false;
+ }
+ }
+
+ *pnFeatureId = nFeatureId;
+ *pBaseCommand = aBaseCommand;
+ *pCustomShapeType = aType;
+
+ return bFound;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/DrawCommandDispatch.hxx b/chart2/source/controller/main/DrawCommandDispatch.hxx
new file mode 100644
index 0000000000..65200cca63
--- /dev/null
+++ b/chart2/source/controller/main/DrawCommandDispatch.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svx/svdobjkind.hxx>
+#include "FeatureCommandDispatchBase.hxx"
+#include <rtl/ref.hxx>
+
+class SfxItemSet;
+class SdrObject;
+
+namespace chart
+{
+
+class ChartController;
+
+/** This is a CommandDispatch implementation for drawing objects.
+ */
+class DrawCommandDispatch: public FeatureCommandDispatchBase
+{
+public:
+ DrawCommandDispatch( const css::uno::Reference< css::uno::XComponentContext >& rxContext, ChartController* pController );
+ virtual ~DrawCommandDispatch() override;
+
+ virtual bool isFeatureSupported( const OUString& rCommandURL ) override;
+
+ void setAttributes( SdrObject* pObj );
+ void setLineEnds( SfxItemSet& rAttr );
+
+protected:
+ // WeakComponentImplHelperBase
+ virtual void disposing( std::unique_lock<std::mutex>& rGuard ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // state of a feature
+ virtual FeatureState getState( const OUString& rCommand ) override;
+
+ // execute a feature
+ virtual void execute( const OUString& rCommand, const css::uno::Sequence< css::beans::PropertyValue>& rArgs ) override;
+
+ // all the features which should be handled by this class
+ virtual void describeSupportedFeatures() override;
+
+private:
+ void setInsertObj(SdrObjKind eObj);
+ rtl::Reference<SdrObject> createDefaultObject( const ChartCommandID nID );
+
+ bool parseCommandURL( const OUString& rCommandURL, ChartCommandID* pnFeatureId, OUString* pBaseCommand, OUString* pCustomShapeType );
+
+ ChartController* m_pChartController;
+ OUString m_aCustomShapeType;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ElementSelector.cxx b/chart2/source/controller/main/ElementSelector.cxx
new file mode 100644
index 0000000000..d538108ae8
--- /dev/null
+++ b/chart2/source/controller/main/ElementSelector.cxx
@@ -0,0 +1,319 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ElementSelector.hxx"
+#include <ObjectNameProvider.hxx>
+#include <ObjectHierarchy.hxx>
+#include <servicenames.hxx>
+#include <DrawViewWrapper.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+#include <ObjectIdentifier.hxx>
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/svapp.hxx>
+
+namespace chart { class ExplicitValueProvider; }
+
+namespace chart
+{
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+constexpr OUStringLiteral lcl_aServiceName
+ = u"com.sun.star.comp.chart.ElementSelectorToolbarController";
+}
+
+SelectorListBox::SelectorListBox(vcl::Window* pParent)
+ : InterimItemWindow(pParent, "modules/schart/ui/combobox.ui", "ComboBox")
+ , m_xWidget(m_xBuilder->weld_combo_box("combobox"))
+ , m_bReleaseFocus(true)
+{
+ InitControlBase(m_xWidget.get());
+
+ m_xWidget->connect_key_press(LINK(this, SelectorListBox, KeyInputHdl));
+ m_xWidget->connect_changed(LINK(this, SelectorListBox, SelectHdl));
+ m_xWidget->connect_focus_out(LINK(this, SelectorListBox, FocusOutHdl));
+
+ ::Size aLogicalSize(75, 0);
+ ::Size aPixelSize = LogicToPixel(aLogicalSize, MapMode(MapUnit::MapAppFont));
+ m_xWidget->set_size_request(aPixelSize.Width(), -1);
+ SetSizePixel(m_xContainer->get_preferred_size());
+}
+
+void SelectorListBox::dispose()
+{
+ m_xWidget.reset();
+ InterimItemWindow::dispose();
+}
+
+SelectorListBox::~SelectorListBox()
+{
+ disposeOnce();
+}
+
+static void lcl_addObjectsToList( const ObjectHierarchy& rHierarchy, const ObjectIdentifier & rParent, std::vector< ListBoxEntryData >& rEntries
+ , const sal_Int32 nHierarchyDepth, const rtl::Reference<::chart::ChartModel>& xChartDoc )
+{
+ ObjectHierarchy::tChildContainer aChildren( rHierarchy.getChildren(rParent) );
+ for (auto const& child : aChildren)
+ {
+ ListBoxEntryData aEntry;
+ aEntry.OID = child;
+ aEntry.UIName = ObjectNameProvider::getNameForCID( child.getObjectCID(), xChartDoc );
+ aEntry.nHierarchyDepth = nHierarchyDepth;
+ rEntries.push_back(aEntry);
+ lcl_addObjectsToList( rHierarchy, child, rEntries, nHierarchyDepth+1, xChartDoc );
+ }
+}
+
+void SelectorListBox::SetChartController( const rtl::Reference< ::chart::ChartController >& xChartController )
+{
+ m_xChartController = xChartController.get();
+}
+
+void SelectorListBox::UpdateChartElementsListAndSelection()
+{
+ m_xWidget->clear();
+ m_aEntries.clear();
+
+ rtl::Reference< ::chart::ChartController > xChartController = m_xChartController.get();
+ if( xChartController.is() )
+ {
+ ObjectIdentifier aSelectedOID( xChartController->getSelection() );
+ OUString aSelectedCID = aSelectedOID.getObjectCID();
+
+ rtl::Reference<::chart::ChartModel> xChartDoc = xChartController->getChartModel();
+ ObjectType eType( aSelectedOID.getObjectType() );
+ bool bAddSelectionToList = false;
+ if ( eType == OBJECTTYPE_DATA_POINT || eType == OBJECTTYPE_DATA_LABEL || eType == OBJECTTYPE_SHAPE )
+ bAddSelectionToList = true;
+
+ Reference< uno::XInterface > xChartView;
+ rtl::Reference< ChartModel > xFact = xChartController->getChartModel();
+ if( xFact.is() )
+ xChartView = xFact->createInstance( CHART_VIEW_SERVICE_NAME );
+ ExplicitValueProvider* pExplicitValueProvider = nullptr; //ExplicitValueProvider::getExplicitValueProvider(xChartView); this creates all visible data points, that's too much
+ ObjectHierarchy aHierarchy( xChartDoc, pExplicitValueProvider, true /*bFlattenDiagram*/, true /*bOrderingForElementSelector*/ );
+ lcl_addObjectsToList( aHierarchy, ::chart::ObjectHierarchy::getRootNodeOID(), m_aEntries, 0, xChartDoc );
+
+ if( bAddSelectionToList )
+ {
+ if ( aSelectedOID.isAutoGeneratedObject() )
+ {
+ OUString aSeriesCID = ObjectIdentifier::createClassifiedIdentifierForParticle( ObjectIdentifier::getSeriesParticleFromCID( aSelectedCID ) );
+ std::vector< ListBoxEntryData >::iterator aIt = std::find_if(m_aEntries.begin(), m_aEntries.end(),
+ [&aSeriesCID](const ListBoxEntryData& rEntry) { return rEntry.OID.getObjectCID().match(aSeriesCID); });
+ if (aIt != m_aEntries.end())
+ {
+ ListBoxEntryData aEntry;
+ aEntry.UIName = ObjectNameProvider::getNameForCID( aSelectedCID, xChartDoc );
+ aEntry.OID = aSelectedOID;
+ ++aIt;
+ if( aIt != m_aEntries.end() )
+ m_aEntries.insert(aIt, aEntry);
+ else
+ m_aEntries.push_back( aEntry );
+ }
+ }
+ else if ( aSelectedOID.isAdditionalShape() )
+ {
+ ListBoxEntryData aEntry;
+ SdrObject* pSelectedObj = DrawViewWrapper::getSdrObject( aSelectedOID.getAdditionalShape() );
+ OUString aName = pSelectedObj ? pSelectedObj->GetName() : OUString();
+ aEntry.UIName = ( aName.isEmpty() ? SchResId( STR_OBJECT_SHAPE ) : aName );
+ aEntry.OID = aSelectedOID;
+ m_aEntries.push_back( aEntry );
+ }
+ }
+
+ m_xWidget->freeze();
+ sal_uInt16 nEntryPosToSelect = 0; bool bSelectionFound = false;
+ sal_uInt16 nN=0;
+ for (auto const& entry : m_aEntries)
+ {
+ // tdf#152087 strip any newlines from the entry
+ m_xWidget->append_text(entry.UIName.replaceAll("\n", " "));
+ if ( !bSelectionFound && aSelectedOID == entry.OID )
+ {
+ nEntryPosToSelect = nN;
+ bSelectionFound = true;
+ }
+ ++nN;
+ }
+ m_xWidget->thaw();
+
+ if( bSelectionFound )
+ m_xWidget->set_active(nEntryPosToSelect);
+ }
+ m_xWidget->save_value(); //remind current selection pos
+}
+
+void SelectorListBox::ReleaseFocus_Impl()
+{
+ if ( !m_bReleaseFocus )
+ {
+ m_bReleaseFocus = true;
+ return;
+ }
+
+ rtl::Reference< ::chart::ChartController > xController = m_xChartController.get();
+ Reference< frame::XFrame > xFrame( xController->getFrame() );
+ if ( xFrame.is() && xFrame->getContainerWindow().is() )
+ xFrame->getContainerWindow()->setFocus();
+}
+
+IMPL_LINK(SelectorListBox, SelectHdl, weld::ComboBox&, rComboBox, void)
+{
+ if (rComboBox.changed_by_direct_pick())
+ {
+ const sal_Int32 nPos = rComboBox.get_active();
+ if (o3tl::make_unsigned(nPos) < m_aEntries.size())
+ {
+ ObjectIdentifier aOID = m_aEntries[nPos].OID;
+ rtl::Reference< ::chart::ChartController > xController = m_xChartController.get();
+ if( xController.is() )
+ xController->select( aOID.getAny() );
+ }
+ ReleaseFocus_Impl();
+ }
+}
+
+IMPL_LINK(SelectorListBox, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ bool bHandled = false;
+
+ sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
+
+ switch ( nCode )
+ {
+ case KEY_RETURN:
+ case KEY_TAB:
+ {
+ if ( nCode == KEY_TAB )
+ m_bReleaseFocus = false;
+ else
+ bHandled = true;
+ SelectHdl(*m_xWidget);
+ break;
+ }
+
+ case KEY_ESCAPE:
+ m_xWidget->set_active_text(m_xWidget->get_saved_value()); //restore saved selection
+ ReleaseFocus_Impl();
+ break;
+ }
+
+ return bHandled || ChildKeyInput(rKEvt);
+}
+
+IMPL_LINK_NOARG(SelectorListBox, FocusOutHdl, weld::Widget&, void)
+{
+ if (m_xWidget && !m_xWidget->has_focus()) // comboboxes can be comprised of multiple widgets, ensure all have lost focus
+ m_xWidget->set_active_text(m_xWidget->get_saved_value());
+}
+
+OUString SAL_CALL ElementSelectorToolbarController::getImplementationName()
+{
+ return lcl_aServiceName;
+}
+
+sal_Bool SAL_CALL ElementSelectorToolbarController::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ElementSelectorToolbarController::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.ToolbarController" };
+}
+ElementSelectorToolbarController::ElementSelectorToolbarController()
+{
+}
+ElementSelectorToolbarController::~ElementSelectorToolbarController()
+{
+}
+// XInterface
+Any SAL_CALL ElementSelectorToolbarController::queryInterface( const Type& _rType )
+{
+ Any aReturn = ToolboxController::queryInterface(_rType);
+ if (!aReturn.hasValue())
+ aReturn = ElementSelectorToolbarController_BASE::queryInterface(_rType);
+ return aReturn;
+}
+void SAL_CALL ElementSelectorToolbarController::acquire() noexcept
+{
+ ToolboxController::acquire();
+}
+void SAL_CALL ElementSelectorToolbarController::release() noexcept
+{
+ ToolboxController::release();
+}
+void SAL_CALL ElementSelectorToolbarController::statusChanged( const frame::FeatureStateEvent& rEvent )
+{
+ if( m_apSelectorListBox )
+ {
+ SolarMutexGuard aSolarMutexGuard;
+ if ( rEvent.FeatureURL.Path == "ChartElementSelector" )
+ {
+ Reference< frame::XController > xChartController;
+ rEvent.State >>= xChartController;
+ ::chart::ChartController* pController = dynamic_cast<::chart::ChartController*>(xChartController.get());
+ assert(!xChartController || pController);
+ m_apSelectorListBox->SetChartController( pController );
+ m_apSelectorListBox->UpdateChartElementsListAndSelection();
+ }
+ }
+}
+uno::Reference< awt::XWindow > SAL_CALL ElementSelectorToolbarController::createItemWindow( const uno::Reference< awt::XWindow >& xParent )
+{
+ uno::Reference< awt::XWindow > xItemWindow;
+ if( !m_apSelectorListBox )
+ {
+ VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent );
+ if( pParent )
+ {
+ m_apSelectorListBox.reset(VclPtr<SelectorListBox>::Create(pParent));
+ }
+ }
+ if( m_apSelectorListBox )
+ xItemWindow = VCLUnoHelper::GetInterface( m_apSelectorListBox.get() );
+ return xItemWindow;
+}
+
+} // chart2
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_ElementSelectorToolbarController_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new chart::ElementSelectorToolbarController );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ElementSelector.hxx b/chart2/source/controller/main/ElementSelector.hxx
new file mode 100644
index 0000000000..fb1e4e0527
--- /dev/null
+++ b/chart2/source/controller/main/ElementSelector.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ObjectIdentifier.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <svtools/toolboxcontroller.hxx>
+
+#include <vcl/InterimItemWindow.hxx>
+#include <unotools/weakref.hxx>
+
+namespace chart
+{
+class ChartController;
+
+struct ListBoxEntryData
+{
+ OUString UIName;
+ ObjectIdentifier OID;
+ sal_Int32 nHierarchyDepth;
+
+ ListBoxEntryData() : nHierarchyDepth(0)
+ {
+ }
+};
+
+class SelectorListBox final : public InterimItemWindow
+{
+public:
+ SelectorListBox(vcl::Window* pParent);
+ virtual void dispose() override;
+ virtual ~SelectorListBox() override;
+
+ void ReleaseFocus_Impl();
+
+ void SetChartController( const rtl::Reference< ::chart::ChartController >& xChartController );
+ void UpdateChartElementsListAndSelection();
+
+private:
+ unotools::WeakReference<::chart::ChartController> m_xChartController;
+ std::unique_ptr<weld::ComboBox> m_xWidget;
+
+ std::vector<ListBoxEntryData> m_aEntries;
+
+ bool m_bReleaseFocus;
+
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+ DECL_LINK(SelectHdl, weld::ComboBox&, void);
+ DECL_LINK(FocusOutHdl, weld::Widget&, void);
+};
+
+typedef ::cppu::ImplHelper1 < css::lang::XServiceInfo> ElementSelectorToolbarController_BASE;
+
+class ElementSelectorToolbarController : public ::svt::ToolboxController
+ , public ElementSelectorToolbarController_BASE
+{
+public:
+ explicit ElementSelectorToolbarController();
+ virtual ~ElementSelectorToolbarController() override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // XStatusListener
+ virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override;
+ // XToolbarController
+ virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override;
+
+private:
+ VclPtr< SelectorListBox > m_apSelectorListBox;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/FeatureCommandDispatchBase.cxx b/chart2/source/controller/main/FeatureCommandDispatchBase.cxx
new file mode 100644
index 0000000000..b1c5f72d1d
--- /dev/null
+++ b/chart2/source/controller/main/FeatureCommandDispatchBase.cxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "FeatureCommandDispatchBase.hxx"
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+FeatureCommandDispatchBase::FeatureCommandDispatchBase( const Reference< uno::XComponentContext >& rxContext )
+ :CommandDispatch( rxContext )
+ ,m_nFeatureId( ChartCommandID::NONE )
+{
+}
+
+FeatureCommandDispatchBase::~FeatureCommandDispatchBase()
+{
+}
+
+void FeatureCommandDispatchBase::initialize()
+{
+ CommandDispatch::initialize();
+ describeSupportedFeatures();
+}
+
+bool FeatureCommandDispatchBase::isFeatureSupported( const OUString& rCommandURL )
+{
+ SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( rCommandURL );
+ return aIter != m_aSupportedFeatures.end();
+}
+
+void FeatureCommandDispatchBase::fireStatusEvent( const OUString& rURL,
+ const Reference< frame::XStatusListener >& xSingleListener /* = 0 */ )
+{
+ if ( rURL.isEmpty() )
+ {
+ for (auto const& elem : m_aSupportedFeatures)
+ {
+ FeatureState aFeatureState( getState(elem.first) );
+ fireStatusEventForURL( elem.first, aFeatureState.aState, aFeatureState.bEnabled, xSingleListener );
+ }
+ }
+ else
+ {
+ FeatureState aFeatureState( getState( rURL ) );
+ fireStatusEventForURL( rURL, aFeatureState.aState, aFeatureState.bEnabled, xSingleListener );
+ }
+}
+
+// XDispatch
+void FeatureCommandDispatchBase::dispatch( const util::URL& URL,
+ const Sequence< beans::PropertyValue >& Arguments )
+{
+ OUString aCommand( URL.Complete );
+ if ( getState( aCommand ).bEnabled )
+ {
+ execute( aCommand, Arguments );
+ }
+}
+
+void FeatureCommandDispatchBase::implDescribeSupportedFeature( const char* pAsciiCommandURL,
+ ChartCommandID nId, sal_Int16 nGroup )
+{
+ ControllerFeature aFeature;
+ aFeature.Command = OUString::createFromAscii( pAsciiCommandURL );
+ aFeature.nFeatureId = nId;
+ aFeature.GroupId = nGroup;
+
+ m_aSupportedFeatures[ aFeature.Command ] = aFeature;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/FeatureCommandDispatchBase.hxx b/chart2/source/controller/main/FeatureCommandDispatchBase.hxx
new file mode 100644
index 0000000000..3ceb35ad12
--- /dev/null
+++ b/chart2/source/controller/main/FeatureCommandDispatchBase.hxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "CommandDispatch.hxx"
+
+#include <com/sun/star/frame/DispatchInformation.hpp>
+
+enum class ChartCommandID
+{
+ NONE = 0,
+
+ //Draw Command Ids:
+ DrawObjectSelect = 1,
+ DrawLine = 2,
+ DrawLineArrowEnd = 3,
+ DrawRect = 4,
+ DrawEllipse = 5,
+ DrawFreelineNoFill = 6,
+ DrawText = 7,
+ DrawTextVertical = 8,
+ DrawCaption = 9,
+ DrawCaptionVertical = 10,
+ DrawToolboxCsBasic = 11,
+ DrawToolboxCsSymbol = 12,
+ DrawToolboxCsArrow = 13,
+ DrawToolboxCsFlowchart = 14,
+ DrawToolboxCsCallout = 15,
+ DrawToolboxCsStar = 16,
+
+ //Shape Controller Command Ids:
+ ShapeFormatLine = 21,
+ ShapeFormatArea = 22,
+ ShapeTextAttributes = 23,
+ ShapeTransformDialog = 24,
+ ShapeObjectTitleDescription = 25,
+ ShapeRenameObject = 26,
+ ShapeBringToFront = 28,
+ ShapeForward = 29,
+ ShapeBackward = 30,
+ ShapeSendToBack = 31,
+ ShapeFontDialog = 35,
+ ShapeParagraphDialog = 36
+};
+
+
+namespace chart
+{
+
+struct ControllerFeature: public css::frame::DispatchInformation
+{
+ ChartCommandID nFeatureId;
+};
+
+typedef std::map< OUString,
+ ControllerFeature > SupportedFeatures;
+
+struct FeatureState
+{
+ bool bEnabled;
+ css::uno::Any aState;
+
+ FeatureState() : bEnabled( false ) { }
+};
+
+/** This is a base class for CommandDispatch implementations with feature support.
+ */
+class FeatureCommandDispatchBase: public CommandDispatch
+{
+public:
+ explicit FeatureCommandDispatchBase( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ virtual ~FeatureCommandDispatchBase() override;
+
+ // late initialisation, especially for adding as listener
+ virtual void initialize() override;
+
+ virtual bool isFeatureSupported( const OUString& rCommandURL );
+
+protected:
+ // XDispatch
+ virtual void SAL_CALL dispatch( const css::util::URL& URL,
+ const css::uno::Sequence< css::beans::PropertyValue >& Arguments ) override;
+
+ virtual void fireStatusEvent( const OUString& rURL,
+ const css::uno::Reference< css::frame::XStatusListener >& xSingleListener ) override;
+
+ // state of a feature
+ virtual FeatureState getState( const OUString& rCommand ) = 0;
+
+ // execute a feature
+ virtual void execute( const OUString& rCommand, const css::uno::Sequence< css::beans::PropertyValue>& rArgs ) = 0;
+
+ // all the features which should be handled by this class
+ virtual void describeSupportedFeatures() = 0;
+
+ /** describes a feature supported by the controller
+
+ Must not be called outside <member>describeSupportedFeatures</member>.
+
+ @param pAsciiCommandURL
+ the URL of the feature command
+ @param nId
+ the id of the feature. Later references to this feature usually happen by id, not by
+ URL.
+ @param nGroup
+ the command group of the feature. This is important for configuring the controller UI
+ by the user, see also <type scope="css::frame">CommandGroup</type>.
+ */
+ void implDescribeSupportedFeature( const char* pAsciiCommandURL, ChartCommandID nId,
+ sal_Int16 nGroup );
+
+ mutable SupportedFeatures m_aSupportedFeatures;
+
+ ChartCommandID m_nFeatureId;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ObjectHierarchy.cxx b/chart2/source/controller/main/ObjectHierarchy.cxx
new file mode 100644
index 0000000000..44846850dc
--- /dev/null
+++ b/chart2/source/controller/main/ObjectHierarchy.cxx
@@ -0,0 +1,727 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ObjectHierarchy.hxx>
+#include <ObjectIdentifier.hxx>
+#include <ChartModelHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartModel.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <GridProperties.hxx>
+#include <LegendHelper.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <unonames.hxx>
+#include <BaseCoordinateSystem.hxx>
+
+#include <map>
+#include <algorithm>
+#include <cstddef>
+
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/awt/Key.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+
+void lcl_getChildOIDs(
+ ::chart::ObjectHierarchy::tChildContainer& rOutChildren,
+ const Reference< container::XIndexAccess >& xShapes )
+{
+ if( !xShapes.is())
+ return;
+
+ sal_Int32 nCount = xShapes->getCount();
+ for( sal_Int32 i=0; i<nCount; ++i)
+ {
+ Reference< beans::XPropertySet > xShapeProp( xShapes->getByIndex( i ), uno::UNO_QUERY );
+ if( xShapeProp.is())
+ {
+ Reference< beans::XPropertySetInfo > xInfo( xShapeProp->getPropertySetInfo());
+ OUString aName;
+ if( xInfo.is() &&
+ xInfo->hasPropertyByName( "Name") &&
+ (xShapeProp->getPropertyValue( "Name") >>= aName ) &&
+ !aName.isEmpty() &&
+ ::chart::ObjectIdentifier::isCID( aName ))
+ {
+ rOutChildren.emplace_back( aName );
+ }
+ Reference< container::XIndexAccess > xNewShapes( xShapeProp, uno::UNO_QUERY );
+ if( xNewShapes.is())
+ lcl_getChildOIDs( rOutChildren, xNewShapes );
+ }
+ }
+}
+
+void lcl_addAxisTitle( const rtl::Reference< ::chart::Axis >& xAxis, ::chart::ObjectHierarchy::tChildContainer& rContainer, const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ if( xAxis.is())
+ {
+ Reference< XTitle > xAxisTitle( xAxis->getTitleObject());
+ if( xAxisTitle.is())
+ rContainer.emplace_back( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xChartModel ) );
+ }
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+void ObjectHierarchy::createTree( const rtl::Reference<::chart::ChartModel>& xChartDocument )
+{
+ m_aChildMap.clear();
+
+ if( !xChartDocument.is() )
+ return;
+
+ //@todo: change ObjectIdentifier to take an XChartDocument rather than XModel
+ rtl::Reference< Diagram > xDiagram = xChartDocument->getFirstChartDiagram();
+ ObjectIdentifier aDiaOID;
+ if( xDiagram.is() )
+ aDiaOID = ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( static_cast<cppu::OWeakObject*>(xDiagram.get()), xChartDocument ) );
+ tChildContainer aTopLevelContainer;
+
+ // First Level
+
+ // Chart Area
+ if( m_bOrderingForElementSelector )
+ {
+ aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) );
+ if( xDiagram.is() )
+ {
+ aTopLevelContainer.push_back( aDiaOID );
+ createWallAndFloor( aTopLevelContainer, xDiagram );
+ createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
+ }
+ }
+
+ // Main Title
+ Reference< XTitle > xMainTitle( xChartDocument->getTitleObject());
+ if( xMainTitle.is())
+ aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle, xChartDocument ) );
+
+ if( xDiagram.is())
+ {
+ // Sub Title. Note: This is interpreted of being top level
+ Reference< XTitle > xSubTitle( xDiagram->getTitleObject());
+ if( xSubTitle.is())
+ aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xChartDocument ) );
+
+ if( !m_bOrderingForElementSelector )
+ {
+ // Axis Titles. Note: These are interpreted of being top level
+ const std::vector< rtl::Reference< Axis > > aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
+ for( rtl::Reference< Axis > const & axis : aAxes )
+ lcl_addAxisTitle( axis, aTopLevelContainer, xChartDocument );
+
+ // Diagram
+ aTopLevelContainer.push_back( aDiaOID );
+ }
+
+ if( m_bFlattenDiagram )
+ createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram );
+ else
+ {
+ tChildContainer aSubContainer;
+ createDiagramTree( aSubContainer, xChartDocument, xDiagram );
+ if( !aSubContainer.empty() )
+ m_aChildMap[ aDiaOID ] = aSubContainer;
+ }
+
+ if( !m_bOrderingForElementSelector )
+ createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
+ }
+
+ // #i12587# support for shapes in chart
+ if ( !m_bOrderingForElementSelector )
+ {
+ createAdditionalShapesTree( aTopLevelContainer );
+ }
+
+ // Chart Area
+ if( !m_bOrderingForElementSelector )
+ aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) );
+
+ if( ! aTopLevelContainer.empty())
+ m_aChildMap[ObjectHierarchy::getRootNodeOID()] = aTopLevelContainer;
+}
+
+void ObjectHierarchy::createLegendTree(
+ tChildContainer & rContainer,
+ const rtl::Reference<::chart::ChartModel> & xChartDoc,
+ const rtl::Reference< Diagram > & xDiagram )
+{
+ if( !(xDiagram.is() && LegendHelper::hasLegend( xDiagram )) )
+ return;
+
+ ObjectIdentifier aLegendOID( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram->getLegend(), xChartDoc ) ) );
+ rContainer.push_back( aLegendOID );
+
+ // iterate over child shapes of legend and search for matching CIDs
+ if( m_pExplicitValueProvider )
+ {
+ rtl::Reference< SvxShapeGroupAnyD > xLegendShapeContainer =
+ dynamic_cast<SvxShapeGroupAnyD*>(
+ m_pExplicitValueProvider->getShapeForCID( aLegendOID.getObjectCID() ).get() );
+ tChildContainer aLegendEntryOIDs;
+ lcl_getChildOIDs( aLegendEntryOIDs, xLegendShapeContainer );
+
+ m_aChildMap[ aLegendOID ] = aLegendEntryOIDs;
+ }
+}
+
+void ObjectHierarchy::createAxesTree(
+ tChildContainer & rContainer,
+ const rtl::Reference<::chart::ChartModel> & xChartDoc,
+ const rtl::Reference< Diagram > & xDiagram )
+{
+ sal_Int32 nDimensionCount = xDiagram->getDimension();
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeByIndex( 0 ) );
+ bool bSupportsAxesGrids = ChartTypeHelper::isSupportingMainAxis( xChartType, nDimensionCount, 0 );
+ if( !bSupportsAxesGrids )
+ return;
+
+ // Data Table
+ uno::Reference<chart2::XDataTable> xDataTable = xDiagram->getDataTable();
+ if (xDataTable.is())
+ {
+ rContainer.push_back(ObjectIdentifier::createClassifiedIdentifierForObject(xDataTable, xChartDoc));
+ }
+
+ // Axes
+ std::vector< rtl::Reference< Axis > > aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ true );
+ if( !m_bOrderingForElementSelector )
+ {
+ for (const auto & rAxis : std::as_const(aAxes))
+ rContainer.push_back( ObjectIdentifier::createClassifiedIdentifierForObject( rAxis, xChartDoc ) );
+ }
+
+ // get all axes, also invisible ones
+ aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
+ // Grids
+ for( rtl::Reference< Axis > const & xAxis : aAxes )
+ {
+ if(!xAxis.is())
+ continue;
+
+ sal_Int32 nCooSysIndex = 0;
+ sal_Int32 nDimensionIndex = 0;
+ sal_Int32 nAxisIndex = 0;
+ AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
+ if( nAxisIndex>0 && !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount ) )
+ continue;
+
+ if( m_bOrderingForElementSelector )
+ {
+ // axis
+ if( AxisHelper::isAxisVisible( xAxis ) )
+ rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartDoc ) );
+
+ // axis title
+ lcl_addAxisTitle( xAxis, rContainer, xChartDoc );
+ }
+
+ rtl::Reference< ::chart::GridProperties > xGridProperties( xAxis->getGridProperties2() );
+ if( AxisHelper::isGridVisible( xGridProperties ) )
+ {
+ //main grid
+ rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartDoc ) );
+ }
+
+ std::vector< rtl::Reference< ::chart::GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
+ for( size_t nSubGrid = 0; nSubGrid < aSubGrids.size(); ++nSubGrid )
+ {
+ if( AxisHelper::isGridVisible( aSubGrids[nSubGrid] ) )
+ {
+ //sub grid
+ rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartDoc, nSubGrid ) );
+ }
+ }
+ }
+}
+
+void ObjectHierarchy::createWallAndFloor(
+ tChildContainer & rContainer,
+ const rtl::Reference< Diagram > & xDiagram )
+{
+ sal_Int32 nDimensionCount = xDiagram->getDimension();
+ bool bIsThreeD = ( nDimensionCount == 3 );
+ bool bHasWall = xDiagram->isSupportingFloorAndWall();
+ if( bHasWall && bIsThreeD )
+ {
+ rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );
+
+ Reference< beans::XPropertySet > xFloor( xDiagram->getFloor());
+ if( xFloor.is())
+ rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, u"" ) );
+ }
+
+}
+
+void ObjectHierarchy::createDiagramTree(
+ tChildContainer & rContainer,
+ const rtl::Reference<::chart::ChartModel> & xChartDoc,
+ const rtl::Reference< Diagram > & xDiagram )
+{
+ if( !m_bOrderingForElementSelector )
+ {
+ createDataSeriesTree( rContainer, xDiagram );
+ createAxesTree( rContainer, xChartDoc, xDiagram );
+ createWallAndFloor( rContainer, xDiagram );
+ }
+ else
+ {
+ createAxesTree( rContainer, xChartDoc, xDiagram );
+ createDataSeriesTree( rContainer, xDiagram );
+ }
+}
+
+void ObjectHierarchy::createDataSeriesTree(
+ tChildContainer & rOutDiagramSubContainer,
+ const rtl::Reference< Diagram > & xDiagram )
+{
+ try
+ {
+ sal_Int32 nDimensionCount = xDiagram->getDimension();
+ std::vector< rtl::Reference< BaseCoordinateSystem > > aCooSysSeq(
+ xDiagram->getBaseCoordinateSystems());
+ for( std::size_t nCooSysIdx=0; nCooSysIdx<aCooSysSeq.size(); ++nCooSysIdx )
+ {
+ std::vector< rtl::Reference< ChartType > > aChartTypeSeq( aCooSysSeq[nCooSysIdx]->getChartTypes2());
+ for( std::size_t nCTIdx=0; nCTIdx<aChartTypeSeq.size(); ++nCTIdx )
+ {
+ rtl::Reference< ChartType > xChartType( aChartTypeSeq[nCTIdx] );
+ std::vector< rtl::Reference< DataSeries > > aSeriesSeq( xChartType->getDataSeries2() );
+ const sal_Int32 nNumberOfSeries =
+ ChartTypeHelper::getNumberOfDisplayedSeries( xChartType, aSeriesSeq.size());
+
+ for( sal_Int32 nSeriesIdx=0; nSeriesIdx<nNumberOfSeries; ++nSeriesIdx )
+ {
+ OUString aSeriesParticle(
+ ObjectIdentifier::createParticleForSeries(
+ 0, nCooSysIdx, nCTIdx, nSeriesIdx ));
+ ObjectIdentifier aSeriesOID(
+ ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticle( aSeriesParticle ) ) );
+ rOutDiagramSubContainer.push_back( aSeriesOID );
+
+ tChildContainer aSeriesSubContainer;
+
+ rtl::Reference< DataSeries > const & xSeries = aSeriesSeq[nSeriesIdx];
+
+ // data labels
+ if( DataSeriesHelper::hasDataLabelsAtSeries( xSeries ) )
+ {
+ OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) + "=" );
+ aSeriesSubContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle, aChildParticle ) );
+ }
+
+ // Statistics
+ if( ChartTypeHelper::isSupportingStatisticProperties( xChartType, nDimensionCount ) )
+ {
+ const std::vector< rtl::Reference< RegressionCurveModel > > & rCurves( xSeries->getRegressionCurves2());
+ for( size_t nCurveIdx=0; nCurveIdx<rCurves.size(); ++nCurveIdx )
+ {
+ bool bIsAverageLine = RegressionCurveHelper::isMeanValueLine( rCurves[nCurveIdx] );
+ aSeriesSubContainer.emplace_back( ObjectIdentifier::createDataCurveCID( aSeriesParticle, nCurveIdx, bIsAverageLine ) );
+ if( RegressionCurveHelper::hasEquation( rCurves[nCurveIdx] ) )
+ {
+ aSeriesSubContainer.emplace_back( ObjectIdentifier::createDataCurveEquationCID( aSeriesParticle, nCurveIdx ) );
+ }
+ }
+ Reference< beans::XPropertySet > xErrorBarProp;
+ if( (xSeries->getPropertyValue( CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarProp) &&
+ xErrorBarProp.is())
+ {
+ sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
+ if( ( xErrorBarProp->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
+ ( nStyle != css::chart::ErrorBarStyle::NONE ) )
+ {
+ aSeriesSubContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierWithParent(
+ OBJECTTYPE_DATA_ERRORS_Y, u"", aSeriesParticle ) );
+ }
+ }
+
+ if( (xSeries->getPropertyValue(CHART_UNONAME_ERRORBAR_X) >>= xErrorBarProp) &&
+ xErrorBarProp.is())
+ {
+ sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
+ if( ( xErrorBarProp->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
+ ( nStyle != css::chart::ErrorBarStyle::NONE ) )
+ {
+ aSeriesSubContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierWithParent(
+ OBJECTTYPE_DATA_ERRORS_X, u"", aSeriesParticle ) );
+ }
+ }
+ }
+
+ // Data Points
+ // iterate over child shapes of legend and search for matching CIDs
+ if( m_pExplicitValueProvider )
+ {
+ rtl::Reference< SvxShapeGroupAnyD > xSeriesShapeContainer =
+ dynamic_cast<SvxShapeGroupAnyD*>(
+ m_pExplicitValueProvider->getShapeForCID( aSeriesOID.getObjectCID() ).get() );
+ lcl_getChildOIDs( aSeriesSubContainer, xSeriesShapeContainer );
+ }
+
+ if( ! aSeriesSubContainer.empty())
+ m_aChildMap[ aSeriesOID ] = aSeriesSubContainer;
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ObjectHierarchy::createAdditionalShapesTree(tChildContainer& rContainer)
+{
+ try
+ {
+ if ( m_pExplicitValueProvider )
+ {
+ rtl::Reference<SvxDrawPage> xDrawPage( m_pExplicitValueProvider->getDrawModelWrapper()->getMainDrawPage() );
+ Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) );
+ sal_Int32 nCount = xDrawPage->getCount();
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ Reference< drawing::XShape > xShape;
+ if ( xDrawPage->getByIndex( i ) >>= xShape )
+ {
+ if ( xShape.is() && xShape != xChartRoot )
+ {
+ rContainer.emplace_back( xShape );
+ }
+ }
+ }
+ }
+ }
+ catch ( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+bool ObjectHierarchy::hasChildren( const ObjectIdentifier& rParent ) const
+{
+ if ( rParent.isValid() )
+ {
+ tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
+ if( aIt != m_aChildMap.end())
+ return ! (aIt->second.empty());
+ }
+ return false;
+}
+
+const ObjectHierarchy::tChildContainer & ObjectHierarchy::getChildren( const ObjectIdentifier& rParent ) const
+{
+ if ( rParent.isValid() )
+ {
+ tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
+ if( aIt != m_aChildMap.end())
+ return aIt->second;
+ }
+ static const tChildContainer EMPTY;
+ return EMPTY;
+}
+
+const ObjectHierarchy::tChildContainer & ObjectHierarchy::getSiblings( const ObjectIdentifier& rNode ) const
+{
+ if ( rNode.isValid() && !ObjectHierarchy::isRootNode( rNode ) )
+ {
+ for (auto const& child : m_aChildMap)
+ {
+ tChildContainer::const_iterator aElemIt(
+ std::find( child.second.begin(), child.second.end(), rNode ));
+ if( aElemIt != child.second.end())
+ return child.second;
+ }
+ }
+ static const tChildContainer EMPTY;
+ return EMPTY;
+}
+
+ObjectIdentifier ObjectHierarchy::getParentImpl(
+ const ObjectIdentifier & rParentOID,
+ const ObjectIdentifier & rOID ) const
+{
+ // search children
+ tChildContainer aChildren( getChildren( rParentOID ));
+ tChildContainer::const_iterator aIt(
+ std::find( aChildren.begin(), aChildren.end(), rOID ));
+ // recursion end
+ if( aIt != aChildren.end())
+ return rParentOID;
+
+ for (auto const& child : aChildren)
+ {
+ // recursion
+ ObjectIdentifier aTempParent( getParentImpl( child, rOID ));
+ if ( aTempParent.isValid() )
+ {
+ // exit on success
+ return aTempParent;
+ }
+ }
+
+ // exit on fail
+ return ObjectIdentifier();
+}
+
+ObjectIdentifier ObjectHierarchy::getParent(
+ const ObjectIdentifier & rOID ) const
+{
+ return getParentImpl( ObjectHierarchy::getRootNodeOID(), rOID );
+}
+
+ObjectHierarchy::ObjectHierarchy(
+ const rtl::Reference<::chart::ChartModel> & xChartDocument,
+ ExplicitValueProvider * pExplicitValueProvider /* = 0 */,
+ bool bFlattenDiagram /* = false */,
+ bool bOrderingForElementSelector /* = false */) :
+ m_pExplicitValueProvider( pExplicitValueProvider ),
+ m_bFlattenDiagram( bFlattenDiagram ),
+ m_bOrderingForElementSelector( bOrderingForElementSelector )
+{
+ createTree( xChartDocument );
+ // don't remember this helper to avoid access after lifetime
+ m_pExplicitValueProvider = nullptr;
+}
+
+ObjectHierarchy::~ObjectHierarchy()
+{}
+
+ObjectIdentifier ObjectHierarchy::getRootNodeOID()
+{
+ return ObjectIdentifier( "ROOT" );
+}
+
+bool ObjectHierarchy::isRootNode( const ObjectIdentifier& rOID )
+{
+ return ( rOID == ObjectHierarchy::getRootNodeOID() );
+}
+
+const ObjectHierarchy::tChildContainer & ObjectHierarchy::getTopLevelChildren() const
+{
+ return getChildren( ObjectHierarchy::getRootNodeOID());
+}
+
+sal_Int32 ObjectHierarchy::getIndexInParent(
+ const ObjectIdentifier& rNode ) const
+{
+ ObjectIdentifier aParentOID( getParent( rNode ));
+ const tChildContainer & aChildren( getChildren( aParentOID ) );
+ sal_Int32 nIndex = 0;
+ for (auto const& child : aChildren)
+ {
+ if ( child == rNode )
+ return nIndex;
+ ++nIndex;
+ }
+ return -1;
+}
+
+ObjectKeyNavigation::ObjectKeyNavigation(
+ ObjectIdentifier aCurrentOID,
+ rtl::Reference<::chart::ChartModel> xChartDocument,
+ ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) :
+ m_aCurrentOID(std::move( aCurrentOID )),
+ m_xChartDocument(std::move( xChartDocument )),
+ m_pExplicitValueProvider( pExplicitValueProvider )
+{
+ if ( !m_aCurrentOID.isValid() )
+ {
+ setCurrentSelection( ObjectHierarchy::getRootNodeOID() );
+ }
+}
+
+bool ObjectKeyNavigation::handleKeyEvent(
+ const awt::KeyEvent & rEvent )
+{
+ bool bResult = false;
+
+ switch( rEvent.KeyCode )
+ {
+ case awt::Key::TAB:
+ if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
+ bResult = previous();
+ else
+ bResult = next();
+ break;
+ case awt::Key::HOME:
+ bResult = first();
+ break;
+ case awt::Key::END:
+ bResult = last();
+ break;
+ case awt::Key::F3:
+ if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
+ bResult = up();
+ else
+ bResult = down();
+ break;
+ case awt::Key::ESCAPE:
+ setCurrentSelection( ObjectIdentifier() );
+ bResult = true;
+ break;
+ default:
+ bResult = false;
+ break;
+ }
+ return bResult;
+}
+
+void ObjectKeyNavigation::setCurrentSelection( const ObjectIdentifier& rOID )
+{
+ m_aCurrentOID = rOID;
+}
+
+bool ObjectKeyNavigation::first()
+{
+ ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
+ ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
+ bool bResult = !aSiblings.empty();
+ if( bResult )
+ setCurrentSelection( aSiblings.front());
+ else
+ bResult = veryFirst();
+ return bResult;
+}
+
+bool ObjectKeyNavigation::last()
+{
+ ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
+ ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
+ bool bResult = !aSiblings.empty();
+ if( bResult )
+ setCurrentSelection( aSiblings.back());
+ else
+ bResult = veryLast();
+ return bResult;
+}
+
+bool ObjectKeyNavigation::next()
+{
+ ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
+ ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
+ bool bResult = !aSiblings.empty();
+ if( bResult )
+ {
+ ObjectHierarchy::tChildContainer::const_iterator aIt(
+ std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
+ assert(aIt != aSiblings.end());
+ if( ++aIt == aSiblings.end())
+ aIt = aSiblings.begin();
+ setCurrentSelection( *aIt );
+ }
+ else
+ bResult = veryFirst();
+
+ return bResult;
+}
+
+bool ObjectKeyNavigation::previous()
+{
+ ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
+ ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection()));
+ bool bResult = !aSiblings.empty();
+ if( bResult )
+ {
+ ObjectHierarchy::tChildContainer::const_iterator aIt(
+ std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
+ OSL_ASSERT( aIt != aSiblings.end());
+ if( aIt == aSiblings.begin())
+ aIt = aSiblings.end();
+ --aIt;
+ setCurrentSelection( *aIt );
+ }
+ else
+ bResult = veryLast();
+ return bResult;
+}
+
+bool ObjectKeyNavigation::up()
+{
+ ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
+ bool bResult = !ObjectHierarchy::isRootNode( getCurrentSelection());
+ if( bResult )
+ setCurrentSelection( aHierarchy.getParent( getCurrentSelection()));
+ return bResult;
+}
+
+bool ObjectKeyNavigation::down()
+{
+ ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
+ bool bResult = aHierarchy.hasChildren( getCurrentSelection());
+ if( bResult )
+ {
+ ObjectHierarchy::tChildContainer aChildren = aHierarchy.getChildren( getCurrentSelection());
+ OSL_ASSERT( !aChildren.empty());
+ setCurrentSelection( aChildren.front());
+ }
+ return bResult;
+}
+
+bool ObjectKeyNavigation::veryFirst()
+{
+ ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
+ ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
+ bool bResult = !aChildren.empty();
+ if( bResult )
+ setCurrentSelection( aChildren.front());
+ return bResult;
+}
+
+bool ObjectKeyNavigation::veryLast()
+{
+ ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
+ ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
+ bool bResult = !aChildren.empty();
+ if( bResult )
+ setCurrentSelection( aChildren.back());
+ return bResult;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/PositionAndSizeHelper.cxx b/chart2/source/controller/main/PositionAndSizeHelper.cxx
new file mode 100644
index 0000000000..50678d145b
--- /dev/null
+++ b/chart2/source/controller/main/PositionAndSizeHelper.cxx
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PositionAndSizeHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <com/sun/star/chart/ChartLegendExpansion.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <tools/gen.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <ChartModel.hxx>
+#include <Diagram.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+bool PositionAndSizeHelper::moveObject( ObjectType eObjectType
+ , const uno::Reference< beans::XPropertySet >& xObjectProp
+ , const awt::Rectangle& rNewPositionAndSize
+ , const awt::Rectangle& rOldPositionAndSize
+ , const awt::Rectangle& rPageRectangle
+ )
+{
+ if(!xObjectProp.is())
+ return false;
+ tools::Rectangle aObjectRect( Point(rNewPositionAndSize.X,rNewPositionAndSize.Y), Size(rNewPositionAndSize.Width,rNewPositionAndSize.Height) );
+ tools::Rectangle aPageRect( Point(rPageRectangle.X,rPageRectangle.Y), Size(rPageRectangle.Width,rPageRectangle.Height) );
+
+ // every following branch divides by width and height
+ if (aPageRect.getOpenWidth() == 0 || aPageRect.getOpenHeight() == 0)
+ return false;
+
+ if( eObjectType==OBJECTTYPE_TITLE )
+ {
+ //@todo decide whether x is primary or secondary
+ chart2::RelativePosition aRelativePosition;
+ aRelativePosition.Anchor = drawing::Alignment_CENTER;
+ //the anchor point at the title object is top/middle
+ Point aPos = aObjectRect.TopLeft();
+ aRelativePosition.Primary = (double(aPos.X())+double(aObjectRect.getOpenWidth())/2.0)/double(aPageRect.getOpenWidth());
+ aRelativePosition.Secondary = (double(aPos.Y())+double(aObjectRect.getOpenHeight())/2.0)/double(aPageRect.getOpenHeight());
+ xObjectProp->setPropertyValue( "RelativePosition", uno::Any(aRelativePosition) );
+ }
+ else if( eObjectType == OBJECTTYPE_DATA_LABEL )
+ {
+ RelativePosition aAbsolutePosition;
+ RelativePosition aCustomLabelPosition;
+ aAbsolutePosition.Primary = double(rOldPositionAndSize.X) / double(aPageRect.getOpenWidth());
+ aAbsolutePosition.Secondary = double(rOldPositionAndSize.Y) / double(aPageRect.getOpenHeight());
+
+ if( xObjectProp->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition )
+ {
+ aAbsolutePosition.Primary -= aCustomLabelPosition.Primary;
+ aAbsolutePosition.Secondary -= aCustomLabelPosition.Secondary;
+ }
+
+ //the anchor point at the data label object is top/left
+ Point aPos = aObjectRect.TopLeft();
+ double fRotation = 0.0;
+ xObjectProp->getPropertyValue("TextRotation") >>= fRotation;
+ if( fRotation == 90.0 )
+ aPos = aObjectRect.BottomLeft();
+ else if( fRotation == 270.0 )
+ aPos = aObjectRect.TopRight();
+
+ aCustomLabelPosition.Primary = double(aPos.X()) / double(aPageRect.getOpenWidth()) - aAbsolutePosition.Primary;
+ aCustomLabelPosition.Secondary = double(aPos.Y()) / double(aPageRect.getOpenHeight()) - aAbsolutePosition.Secondary;
+ xObjectProp->setPropertyValue("CustomLabelPosition", uno::Any(aCustomLabelPosition));
+ }
+ else if( eObjectType==OBJECTTYPE_DATA_CURVE_EQUATION )
+ {
+ //@todo decide whether x is primary or secondary
+ chart2::RelativePosition aRelativePosition;
+ aRelativePosition.Anchor = drawing::Alignment_TOP_LEFT;
+ //the anchor point at the title object is top/middle
+ Point aPos = aObjectRect.TopLeft();
+ aRelativePosition.Primary = double(aPos.X())/double(aPageRect.getOpenWidth());
+ aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getOpenHeight());
+ xObjectProp->setPropertyValue( "RelativePosition", uno::Any(aRelativePosition) );
+ }
+ else if(eObjectType==OBJECTTYPE_LEGEND)
+ {
+ xObjectProp->setPropertyValue( "Expansion", uno::Any(css::chart::ChartLegendExpansion_CUSTOM));
+ chart2::RelativePosition aRelativePosition;
+ chart2::RelativeSize aRelativeSize;
+ Point aAnchor = aObjectRect.TopLeft();
+
+ aRelativePosition.Primary =
+ static_cast< double >( aAnchor.X()) /
+ static_cast< double >( aPageRect.getOpenWidth() );
+ aRelativePosition.Secondary =
+ static_cast< double >( aAnchor.Y()) /
+ static_cast< double >( aPageRect.getOpenHeight());
+
+ xObjectProp->setPropertyValue( "RelativePosition", uno::Any(aRelativePosition) );
+
+ aRelativeSize.Primary =
+ static_cast< double >( aObjectRect.getOpenWidth()) /
+ static_cast< double >( aPageRect.getOpenWidth() );
+ if (aRelativeSize.Primary > 1.0)
+ aRelativeSize.Primary = 1.0;
+ aRelativeSize.Secondary =
+ static_cast< double >( aObjectRect.getOpenHeight()) /
+ static_cast< double >( aPageRect.getOpenHeight());
+ if (aRelativeSize.Secondary > 1.0)
+ aRelativeSize.Secondary = 1.0;
+
+ xObjectProp->setPropertyValue( "RelativeSize", uno::Any(aRelativeSize) );
+ }
+ else if(eObjectType==OBJECTTYPE_DIAGRAM || eObjectType==OBJECTTYPE_DIAGRAM_WALL || eObjectType==OBJECTTYPE_DIAGRAM_FLOOR)
+ {
+ //@todo decide whether x is primary or secondary
+
+ //set position:
+ chart2::RelativePosition aRelativePosition;
+ aRelativePosition.Anchor = drawing::Alignment_CENTER;
+
+ Point aPos = aObjectRect.Center();
+ aRelativePosition.Primary = double(aPos.X())/double(aPageRect.getOpenWidth());
+ aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getOpenHeight());
+ xObjectProp->setPropertyValue( "RelativePosition", uno::Any(aRelativePosition) );
+
+ //set size:
+ RelativeSize aRelativeSize;
+ //the anchor points for the diagram are in the middle of the diagram
+ //and in the middle of the page
+ aRelativeSize.Primary = double(aObjectRect.getOpenWidth())/double(aPageRect.getOpenWidth());
+ aRelativeSize.Secondary = double(aObjectRect.getOpenHeight())/double(aPageRect.getOpenHeight());
+ xObjectProp->setPropertyValue( "RelativeSize", uno::Any(aRelativeSize) );
+ }
+ else
+ return false;
+ return true;
+}
+
+bool PositionAndSizeHelper::moveObject( std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel
+ , const awt::Rectangle& rNewPositionAndSize
+ , const awt::Rectangle& rOldPositionAndSize
+ , const awt::Rectangle& rPageRectangle
+ )
+{
+ ControllerLockGuardUNO aLockedControllers( xChartModel );
+
+ awt::Rectangle aNewPositionAndSize( rNewPositionAndSize );
+
+ uno::Reference< beans::XPropertySet > xObjectProp = ObjectIdentifier::getObjectPropertySet( rObjectCID, xChartModel );
+ ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) );
+ if(eObjectType==OBJECTTYPE_DIAGRAM || eObjectType==OBJECTTYPE_DIAGRAM_WALL || eObjectType==OBJECTTYPE_DIAGRAM_FLOOR)
+ {
+ xObjectProp = ObjectIdentifier::getDiagramForCID( rObjectCID, xChartModel );
+ if(!xObjectProp.is())
+ return false;
+ }
+ return moveObject( eObjectType, xObjectProp, aNewPositionAndSize, rOldPositionAndSize, rPageRectangle );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/SelectionHelper.cxx b/chart2/source/controller/main/SelectionHelper.cxx
new file mode 100644
index 0000000000..11fc5d9fae
--- /dev/null
+++ b/chart2/source/controller/main/SelectionHelper.cxx
@@ -0,0 +1,651 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <SelectionHelper.hxx>
+#include <ObjectIdentifier.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+
+#include <svx/svdpage.hxx>
+#include <svx/svditer.hxx>
+#include <svx/obj3d.hxx>
+#include <svx/svdopath.hxx>
+#include <vcl/svapp.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <osl/diagnose.h>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+namespace
+{
+
+OUString lcl_getObjectName( SdrObject const * pObj )
+{
+ if(pObj)
+ return pObj->GetName();
+ return OUString();
+}
+
+void impl_selectObject( SdrObject* pObjectToSelect, DrawViewWrapper& rDrawViewWrapper )
+{
+ SolarMutexGuard aSolarGuard;
+
+ if(pObjectToSelect)
+ {
+ SelectionHelper aSelectionHelper( pObjectToSelect );
+ SdrObject* pMarkObj = aSelectionHelper.getObjectToMark();
+ rDrawViewWrapper.setMarkHandleProvider(&aSelectionHelper);
+ rDrawViewWrapper.MarkObject(pMarkObj);
+ rDrawViewWrapper.setMarkHandleProvider(nullptr);
+ }
+}
+
+}//anonymous namespace
+
+bool Selection::hasSelection() const
+{
+ return m_aSelectedOID.isValid();
+}
+
+OUString const & Selection::getSelectedCID() const
+{
+ return m_aSelectedOID.getObjectCID();
+}
+
+uno::Reference< drawing::XShape > const & Selection::getSelectedAdditionalShape() const
+{
+ return m_aSelectedOID.getAdditionalShape();
+}
+
+bool Selection::setSelection( const OUString& rCID )
+{
+ if ( rCID != m_aSelectedOID.getObjectCID() )
+ {
+ m_aSelectedOID = ObjectIdentifier( rCID );
+ return true;
+ }
+ return false;
+}
+
+bool Selection::setSelection( const uno::Reference< drawing::XShape >& xShape )
+{
+ if ( !( xShape == m_aSelectedOID.getAdditionalShape() ) )
+ {
+ clearSelection();
+ m_aSelectedOID = ObjectIdentifier( xShape );
+ return true;
+ }
+ return false;
+}
+
+void Selection::clearSelection()
+{
+ m_aSelectedOID = ObjectIdentifier();
+ m_aSelectedOID_beforeMouseDown = ObjectIdentifier();
+ m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
+}
+
+bool Selection::maybeSwitchSelectionAfterSingleClickWasEnsured()
+{
+ if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid()
+ && m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing != m_aSelectedOID )
+ {
+ m_aSelectedOID = m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing;
+ m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
+ return true;
+ }
+ return false;
+}
+
+void Selection::resetPossibleSelectionAfterSingleClickWasEnsured()
+{
+ if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() )
+ {
+ m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
+ }
+}
+
+void Selection::remindSelectionBeforeMouseDown()
+{
+ m_aSelectedOID_beforeMouseDown = m_aSelectedOID;
+}
+
+bool Selection::isSelectionDifferentFromBeforeMouseDown() const
+{
+ return ( m_aSelectedOID != m_aSelectedOID_beforeMouseDown );
+}
+
+void Selection::applySelection( DrawViewWrapper* pDrawViewWrapper )
+{
+ if( !pDrawViewWrapper )
+ return;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ pDrawViewWrapper->UnmarkAll();
+ }
+ SdrObject* pObjectToSelect = nullptr;
+ if ( m_aSelectedOID.isAutoGeneratedObject() )
+ {
+ pObjectToSelect = pDrawViewWrapper->getNamedSdrObject( m_aSelectedOID.getObjectCID() );
+ }
+ else if( m_aSelectedOID.isAdditionalShape() )
+ {
+ pObjectToSelect = DrawViewWrapper::getSdrObject( m_aSelectedOID.getAdditionalShape() );
+ }
+
+ impl_selectObject( pObjectToSelect, *pDrawViewWrapper );
+}
+
+void Selection::adaptSelectionToNewPos( const Point& rMousePos, DrawViewWrapper const * pDrawViewWrapper
+ , bool bIsRightMouse, bool bWaitingForDoubleClick )
+{
+ if( !pDrawViewWrapper )
+ return;
+
+ //do not toggle multiclick selection if right clicked on the selected object or waiting for double click
+ bool bAllowMultiClickSelectionChange = !bIsRightMouse && !bWaitingForDoubleClick;
+
+ ObjectIdentifier aLastSelectedObject( m_aSelectedOID );
+
+ SolarMutexGuard aSolarGuard;
+
+ //bAllowMultiClickSelectionChange==true -> a second click on the same object can lead to a changed selection (e.g. series -> single data point)
+
+ //get object to select:
+ {
+ m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
+
+ //the search for the object to select starts with the hit object deepest in the grouping hierarchy (a leaf in the tree)
+ //further we travel along the grouping hierarchy from child to parent
+ SdrObject* pNewObj = pDrawViewWrapper->getHitObject(rMousePos);
+ m_aSelectedOID = ObjectIdentifier( lcl_getObjectName( pNewObj ) );//name of pNewObj
+
+ //ignore handle only objects for hit test
+ while( pNewObj && m_aSelectedOID.getObjectCID().match( "HandlesOnly" ) )
+ {
+ pNewObj->SetMarkProtect(true);
+ pNewObj = pDrawViewWrapper->getHitObject(rMousePos);
+ m_aSelectedOID = ObjectIdentifier( lcl_getObjectName( pNewObj ) );
+ }
+
+ //accept only named objects while searching for the object to select
+ //this call may change m_aSelectedOID
+ if ( SelectionHelper::findNamedParent( pNewObj, m_aSelectedOID, true ) )
+ {
+ //if the so far found object is a multi click object further steps are necessary
+ while( ObjectIdentifier::isMultiClickObject( m_aSelectedOID.getObjectCID() ) )
+ {
+ bool bSameObjectAsLastSelected = ( aLastSelectedObject == m_aSelectedOID );
+ if( bSameObjectAsLastSelected )
+ {
+ //if the same child is clicked again don't go up further
+ break;
+ }
+ if ( ObjectIdentifier::areSiblings( aLastSelectedObject.getObjectCID(), m_aSelectedOID.getObjectCID() ) )
+ {
+ //if a sibling of the last selected object is clicked don't go up further
+ break;
+ }
+ ObjectIdentifier aLastChild = m_aSelectedOID;
+ if ( !SelectionHelper::findNamedParent( pNewObj, m_aSelectedOID, false ) )
+ {
+ //take the one found so far
+ break;
+ }
+ //if the last selected object is found don't go up further
+ //but take the last child if selection change is allowed
+ if ( aLastSelectedObject == m_aSelectedOID )
+ {
+ if( bAllowMultiClickSelectionChange )
+ {
+ m_aSelectedOID = aLastChild;
+ }
+ else
+ m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = aLastChild;
+ break;
+ }
+ }
+
+ OSL_ENSURE(m_aSelectedOID.isValid(), "somehow lost selected object");
+ }
+ else
+ {
+ //maybe an additional shape was hit
+ if ( pNewObj )
+ {
+ m_aSelectedOID = ObjectIdentifier( uno::Reference< drawing::XShape >( pNewObj->getUnoShape(), uno::UNO_QUERY ) );
+ }
+ else
+ {
+ m_aSelectedOID = ObjectIdentifier();
+ }
+ }
+
+ if ( !m_aSelectedOID.isAdditionalShape() )
+ {
+ OUString aPageCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) );//@todo read CID from model
+
+ if ( !m_aSelectedOID.isAutoGeneratedObject() )
+ {
+ m_aSelectedOID = ObjectIdentifier( aPageCID );
+ }
+
+ //check whether the diagram was hit but not selected (e.g. because it has no filling):
+ OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) );
+ OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
+ bool bBackGroundHit = m_aSelectedOID.getObjectCID() == aPageCID || m_aSelectedOID.getObjectCID() == aWallCID || !m_aSelectedOID.isAutoGeneratedObject();
+ if( bBackGroundHit )
+ {
+ //todo: if more than one diagram is available in future do check the list of all diagrams here
+ SdrObject* pDiagram = pDrawViewWrapper->getNamedSdrObject( aDiagramCID );
+ if( pDiagram )
+ {
+ if( DrawViewWrapper::IsObjectHit( pDiagram, rMousePos ) )
+ {
+ m_aSelectedOID = ObjectIdentifier( aDiagramCID );
+ }
+ }
+ }
+ //check whether the legend was hit but not selected (e.g. because it has no filling):
+ if( bBackGroundHit || m_aSelectedOID.getObjectCID() == aDiagramCID )
+ {
+ OUString aLegendCID( ObjectIdentifier::createClassifiedIdentifierForParticle( ObjectIdentifier::createParticleForLegend(nullptr) ) );//@todo read CID from model
+ SdrObject* pLegend = pDrawViewWrapper->getNamedSdrObject( aLegendCID );
+ if( pLegend )
+ {
+ if( DrawViewWrapper::IsObjectHit( pLegend, rMousePos ) )
+ {
+ m_aSelectedOID = ObjectIdentifier( aLegendCID );
+ }
+ }
+ }
+ }
+ }
+
+ if ( bIsRightMouse && m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() )
+ {
+ m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
+ }
+}
+
+bool Selection::isResizeableObjectSelected() const
+{
+ ObjectType eObjectType = m_aSelectedOID.getObjectType();
+ switch( eObjectType )
+ {
+ case OBJECTTYPE_DIAGRAM:
+ case OBJECTTYPE_DIAGRAM_WALL:
+ case OBJECTTYPE_SHAPE:
+ case OBJECTTYPE_LEGEND:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Selection::isRotateableObjectSelected( const rtl::Reference<::chart::ChartModel>& xChartModel ) const
+{
+ return SelectionHelper::isRotateableObject( m_aSelectedOID.getObjectCID(), xChartModel );
+}
+
+bool Selection::isDragableObjectSelected() const
+{
+ return m_aSelectedOID.isDragableObject();
+}
+
+bool Selection::isAdditionalShapeSelected() const
+{
+ return m_aSelectedOID.isAdditionalShape();
+}
+
+bool SelectionHelper::findNamedParent( SdrObject*& pInOutObject
+ , OUString& rOutName
+ , bool bGivenObjectMayBeResult )
+{
+ SolarMutexGuard aSolarGuard;
+ //find the deepest named group
+ SdrObject* pObj = pInOutObject;
+ OUString aName;
+ if( bGivenObjectMayBeResult )
+ aName = lcl_getObjectName( pObj );
+
+ while( pObj && !ObjectIdentifier::isCID( aName ) )
+ {
+ SdrObjList* pObjList = pObj->getParentSdrObjListFromSdrObject();
+ if( !pObjList )
+ return false;
+ SdrObject* pOwner = pObjList->getSdrObjectFromSdrObjList();
+ if( !pOwner )
+ return false;
+ pObj = pOwner;
+ aName = lcl_getObjectName( pObj );
+ }
+
+ if(!pObj)
+ return false;
+ if(aName.isEmpty())
+ return false;
+
+ pInOutObject = pObj;
+ rOutName = aName;
+ return true;
+}
+
+bool SelectionHelper::findNamedParent( SdrObject*& pInOutObject
+ , ObjectIdentifier& rOutObject
+ , bool bGivenObjectMayBeResult )
+{
+ OUString aName;
+ if ( findNamedParent( pInOutObject, aName, bGivenObjectMayBeResult ) )
+ {
+ rOutObject = ObjectIdentifier( aName );
+ return true;
+ }
+ return false;
+}
+
+bool SelectionHelper::isDragableObjectHitTwice( const Point& rMPos
+ , const OUString& rNameOfSelectedObject
+ , const DrawViewWrapper& rDrawViewWrapper )
+{
+ if(rNameOfSelectedObject.isEmpty())
+ return false;
+ if( !ObjectIdentifier::isDragableObject(rNameOfSelectedObject) )
+ return false;
+ SolarMutexGuard aSolarGuard;
+ SdrObject* pObj = rDrawViewWrapper.getNamedSdrObject( rNameOfSelectedObject );
+ return DrawViewWrapper::IsObjectHit( pObj, rMPos );
+}
+
+OUString SelectionHelper::getHitObjectCID(
+ const Point& rMPos,
+ DrawViewWrapper const & rDrawViewWrapper,
+ bool bGetDiagramInsteadOf_Wall )
+{
+ SolarMutexGuard aSolarGuard;
+ OUString aRet;
+
+ SdrObject* pNewObj = rDrawViewWrapper.getHitObject(rMPos);
+ aRet = lcl_getObjectName( pNewObj );//name of pNewObj
+
+ //ignore handle only objects for hit test
+ while( pNewObj && aRet.match("HandlesOnly") )
+ {
+ pNewObj->SetMarkProtect(true);
+ pNewObj = rDrawViewWrapper.getHitObject(rMPos);
+ aRet = lcl_getObjectName( pNewObj );
+ }
+
+ //accept only named objects while searching for the object to select
+ if( !findNamedParent( pNewObj, aRet, true ) )
+ {
+ aRet.clear();
+ }
+
+ OUString aPageCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) );//@todo read CID from model
+ //get page when nothing was hit
+ if( aRet.isEmpty() && !pNewObj )
+ {
+ aRet = aPageCID;
+ }
+
+ //get diagram instead wall or page if hit inside diagram
+ if( !aRet.isEmpty() )
+ {
+ if( aRet == aPageCID )
+ {
+ OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) );
+ //todo: if more than one diagram is available in future do check the list of all diagrams here
+ SdrObject* pDiagram = rDrawViewWrapper.getNamedSdrObject( aDiagramCID );
+ if( pDiagram )
+ {
+ if( DrawViewWrapper::IsObjectHit( pDiagram, rMPos ) )
+ {
+ aRet = aDiagramCID;
+ }
+ }
+ }
+ else if( bGetDiagramInsteadOf_Wall )
+ {
+ OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
+
+ if( aRet == aWallCID )
+ {
+ OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) );
+ aRet = aDiagramCID;
+ }
+ }
+ }
+
+ return aRet;
+ // \\- solar mutex
+}
+
+bool SelectionHelper::isRotateableObject( std::u16string_view rCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ if( !ObjectIdentifier::isRotateableObject( rCID ) )
+ return false;
+
+ sal_Int32 nDimensionCount = xChartModel->getFirstChartDiagram()->getDimension();
+
+ return nDimensionCount == 3;
+}
+
+SelectionHelper::SelectionHelper( SdrObject* pSelectedObj )
+ : m_pSelectedObj( pSelectedObj ), m_pMarkObj(nullptr)
+{
+
+}
+SelectionHelper::~SelectionHelper()
+{
+}
+
+bool SelectionHelper::getFrameDragSingles()
+{
+ //true == green == surrounding handles
+ return DynCastE3dObject( m_pSelectedObj) == nullptr;
+}
+
+SdrObject* SelectionHelper::getMarkHandlesObject( SdrObject* pObj )
+{
+ if(!pObj)
+ return nullptr;
+ OUString aName( lcl_getObjectName( pObj ) );
+ if( aName.match("MarkHandles") || aName.match("HandlesOnly") )
+ return pObj;
+ if( !aName.isEmpty() )//don't get the markhandles of a different object
+ return nullptr;
+
+ //search for a child with name "MarkHandles" or "HandlesOnly"
+ SolarMutexGuard aSolarGuard;
+ SdrObjList* pSubList = pObj->GetSubList();
+ if(pSubList)
+ {
+ SdrObjListIter aIterator(pSubList, SdrIterMode::Flat);
+ while (aIterator.IsMore())
+ {
+ SdrObject* pMarkHandles = SelectionHelper::getMarkHandlesObject( aIterator.Next() );
+ if( pMarkHandles )
+ return pMarkHandles;
+ }
+ }
+ return nullptr;
+}
+
+SdrObject* SelectionHelper::getObjectToMark()
+{
+ //return the selected object itself
+ //or a specific other object if that exists
+ SdrObject* pObj = m_pSelectedObj;
+ m_pMarkObj = pObj;
+
+ //search for a child with name "MarkHandles" or "HandlesOnly"
+ if(pObj)
+ {
+ SolarMutexGuard aSolarGuard;
+ SdrObjList* pSubList = pObj->GetSubList();
+ if(pSubList)
+ {
+ SdrObjListIter aIterator(pSubList, SdrIterMode::Flat);
+ while (aIterator.IsMore())
+ {
+ SdrObject* pMarkHandles = SelectionHelper::getMarkHandlesObject( aIterator.Next() );
+ if( pMarkHandles )
+ {
+ m_pMarkObj = pMarkHandles;
+ break;
+ }
+ }
+ }
+ }
+ return m_pMarkObj;
+}
+
+E3dScene* SelectionHelper::getSceneToRotate( SdrObject* pObj )
+{
+ //search whether the object or one of its children is a 3D object
+ //if so, return the accessory 3DScene
+
+ E3dObject* pRotateable = nullptr;
+
+ if(pObj)
+ {
+ pRotateable = DynCastE3dObject(pObj);
+ if( !pRotateable )
+ {
+ SolarMutexGuard aSolarGuard;
+ SdrObjList* pSubList = pObj->GetSubList();
+ if(pSubList)
+ {
+ SdrObjListIter aIterator(pSubList, SdrIterMode::DeepWithGroups);
+ while( aIterator.IsMore() && !pRotateable )
+ {
+ pRotateable = DynCastE3dObject(aIterator.Next());
+ }
+ }
+ }
+ }
+
+ E3dScene* pScene(nullptr);
+
+ if(pRotateable)
+ {
+ SolarMutexGuard aSolarGuard;
+ pScene = pRotateable->getRootE3dSceneFromE3dObject();
+ }
+
+ return pScene;
+}
+
+bool SelectionHelper::getMarkHandles( SdrHdlList& rHdlList )
+{
+ SolarMutexGuard aSolarGuard;
+
+ //@todo -> more flexible handle creation
+ //2 scenarios possible:
+ //1. add an additional invisible shape as a child to the selected object
+ //this child needs to be named somehow and handles need to be generated there from...
+ //or 2. offer a central service per view where renderer and so can register for handle creation for a special shape
+ //.. or 3. feature from drawinglayer to create handles for each shape... (bad performance... ?) ?
+
+ //scenario 1 is now used:
+ //if a child with name MarkHandles exists
+ //this child is marked instead of the logical selected object
+
+/*
+ //if a special mark object was found
+ //that object should be used for marking only
+ if( m_pMarkObj != m_pSelectedObj)
+ return false;
+*/
+ //if a special mark object was found
+ //that object should be used to create handles from
+ if( m_pMarkObj && m_pMarkObj != m_pSelectedObj)
+ {
+ rHdlList.Clear();
+ if( auto pPathObj = dynamic_cast<const SdrPathObj*>( m_pMarkObj) )
+ {
+ //if th object is a polygon
+ //from each point a handle is generated
+ const ::basegfx::B2DPolyPolygon& rPolyPolygon = pPathObj->GetPathPoly();
+ for( sal_uInt32 nN = 0; nN < rPolyPolygon.count(); nN++)
+ {
+ const ::basegfx::B2DPolygon& aPolygon(rPolyPolygon.getB2DPolygon(nN));
+ for( sal_uInt32 nM = 0; nM < aPolygon.count(); nM++)
+ {
+ const ::basegfx::B2DPoint aPoint(aPolygon.getB2DPoint(nM));
+ rHdlList.AddHdl(std::make_unique<SdrHdl>(Point(basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY())), SdrHdlKind::Poly));
+ }
+ }
+ return true;
+ }
+ else
+ return false; //use the special MarkObject for marking
+ }
+
+ //@todo:
+ //add and document good marking defaults ...
+
+ rHdlList.Clear();
+
+ SdrObject* pObj = m_pSelectedObj;
+ if(!pObj)
+ return false;
+ SdrObjList* pSubList = pObj->GetSubList();
+ if( !pSubList )//no group object !pObj->IsGroupObject()
+ return false;
+
+ OUString aName( lcl_getObjectName( pObj ) );
+ ObjectType eObjectType( ObjectIdentifier::getObjectType( aName ) );
+ if( eObjectType == OBJECTTYPE_DATA_POINT
+ || eObjectType == OBJECTTYPE_DATA_LABEL
+ || eObjectType == OBJECTTYPE_LEGEND_ENTRY
+ || eObjectType == OBJECTTYPE_AXIS_UNITLABEL )
+ {
+ return false;
+ }
+
+ SdrObjListIter aIterator(pSubList, SdrIterMode::Flat);
+
+ while (aIterator.IsMore())
+ {
+ SdrObject* pSubObj = aIterator.Next();
+ if( eObjectType == OBJECTTYPE_DATA_SERIES )
+ {
+ OUString aSubName( lcl_getObjectName( pSubObj ) );
+ ObjectType eSubObjectType( ObjectIdentifier::getObjectType( aSubName ) );
+ if( eSubObjectType!=OBJECTTYPE_DATA_POINT )
+ return false;
+ }
+
+ Point aPos = pSubObj->GetCurrentBoundRect().Center();
+ rHdlList.AddHdl(std::make_unique<SdrHdl>(aPos,SdrHdlKind::Poly));
+ }
+ return true;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ShapeController.cxx b/chart2/source/controller/main/ShapeController.cxx
new file mode 100644
index 0000000000..97715b07c2
--- /dev/null
+++ b/chart2/source/controller/main/ShapeController.cxx
@@ -0,0 +1,673 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ShapeController.hxx"
+#include <ChartController.hxx>
+#include <ViewElementListProvider.hxx>
+#include <dlg_ShapeFont.hxx>
+#include <dlg_ShapeParagraph.hxx>
+#include <ChartModel.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/frame/CommandGroup.hpp>
+
+#include <vcl/svapp.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <editeng/editids.hrc>
+#include <editeng/eeitem.hxx>
+#include <editeng/hyphenzoneitem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <svx/svxdlg.hxx>
+#include <editeng/widwitem.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::frame;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+ShapeController::ShapeController( const Reference< uno::XComponentContext >& rxContext,
+ ChartController* pController )
+ :FeatureCommandDispatchBase( rxContext )
+ ,m_pChartController( pController )
+{
+}
+
+ShapeController::~ShapeController()
+{
+}
+
+// WeakComponentImplHelperBase
+void ShapeController::disposing(std::unique_lock<std::mutex>& /*rGuard*/)
+{
+}
+
+// XEventListener
+void ShapeController::disposing( const lang::EventObject& /* Source */ )
+{
+}
+
+FeatureState ShapeController::getState( const OUString& rCommand )
+{
+ FeatureState aReturn;
+ aReturn.bEnabled = false;
+ aReturn.aState <<= false;
+
+ bool bWritable = false;
+ if ( m_pChartController )
+ {
+ rtl::Reference< ChartModel > xStorable = m_pChartController->getChartModel();
+ if ( xStorable.is() )
+ {
+ bWritable = !xStorable->isReadonly();
+ }
+ }
+
+ SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( rCommand );
+ if ( aIter != m_aSupportedFeatures.end() )
+ {
+ ChartCommandID nFeatureId = aIter->second.nFeatureId;
+ switch ( nFeatureId )
+ {
+ case ChartCommandID::ShapeFormatLine:
+ case ChartCommandID::ShapeFormatArea:
+ case ChartCommandID::ShapeTextAttributes:
+ case ChartCommandID::ShapeTransformDialog:
+ case ChartCommandID::ShapeObjectTitleDescription:
+ case ChartCommandID::ShapeRenameObject:
+ {
+ aReturn.bEnabled = bWritable;
+ aReturn.aState <<= false;
+ }
+ break;
+ case ChartCommandID::ShapeBringToFront:
+ case ChartCommandID::ShapeForward:
+ {
+ aReturn.bEnabled = ( bWritable && isForwardPossible() );
+ aReturn.aState <<= false;
+ }
+ break;
+ case ChartCommandID::ShapeBackward:
+ case ChartCommandID::ShapeSendToBack:
+ {
+
+ aReturn.bEnabled = ( bWritable && isBackwardPossible() );
+ aReturn.aState <<= false;
+ }
+ break;
+ case ChartCommandID::ShapeFontDialog:
+ case ChartCommandID::ShapeParagraphDialog:
+ {
+ aReturn.bEnabled = bWritable;
+ aReturn.aState <<= false;
+ }
+ break;
+ default:
+ {
+ aReturn.bEnabled = false;
+ aReturn.aState <<= false;
+ }
+ break;
+ }
+ }
+
+ return aReturn;
+}
+
+void ShapeController::execute( const OUString& rCommand, const Sequence< beans::PropertyValue>& )
+{
+ SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( rCommand );
+ if ( aIter == m_aSupportedFeatures.end() )
+ return;
+
+ ChartCommandID nFeatureId = aIter->second.nFeatureId;
+ switch ( nFeatureId )
+ {
+ case ChartCommandID::ShapeFormatLine:
+ {
+ executeDispatch_FormatLine();
+ }
+ break;
+ case ChartCommandID::ShapeFormatArea:
+ {
+ executeDispatch_FormatArea();
+ }
+ break;
+ case ChartCommandID::ShapeTextAttributes:
+ {
+ executeDispatch_TextAttributes();
+ }
+ break;
+ case ChartCommandID::ShapeTransformDialog:
+ {
+ executeDispatch_TransformDialog();
+ }
+ break;
+ case ChartCommandID::ShapeObjectTitleDescription:
+ {
+ executeDispatch_ObjectTitleDescription();
+ }
+ break;
+ case ChartCommandID::ShapeRenameObject:
+ {
+ executeDispatch_RenameObject();
+ }
+ break;
+ case ChartCommandID::ShapeBringToFront:
+ case ChartCommandID::ShapeForward:
+ case ChartCommandID::ShapeBackward:
+ case ChartCommandID::ShapeSendToBack:
+ {
+ executeDispatch_ChangeZOrder( nFeatureId );
+ }
+ break;
+ case ChartCommandID::ShapeFontDialog:
+ {
+ executeDispatch_FontDialog();
+ }
+ break;
+ case ChartCommandID::ShapeParagraphDialog:
+ {
+ executeDispatch_ParagraphDialog();
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+}
+
+void ShapeController::describeSupportedFeatures()
+{
+ implDescribeSupportedFeature( ".uno:FormatLine", ChartCommandID::ShapeFormatLine, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:FormatArea", ChartCommandID::ShapeFormatArea, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:TextAttributes", ChartCommandID::ShapeTextAttributes, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:TransformDialog", ChartCommandID::ShapeTransformDialog, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:ObjectTitleDescription", ChartCommandID::ShapeObjectTitleDescription, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:RenameObject", ChartCommandID::ShapeRenameObject, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:BringToFront", ChartCommandID::ShapeBringToFront, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:Forward", ChartCommandID::ShapeForward, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:Backward", ChartCommandID::ShapeBackward, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:SendToBack", ChartCommandID::ShapeSendToBack, CommandGroup::FORMAT );
+ implDescribeSupportedFeature( ".uno:FontDialog", ChartCommandID::ShapeFontDialog, CommandGroup::EDIT );
+ implDescribeSupportedFeature( ".uno:ParagraphDialog", ChartCommandID::ShapeParagraphDialog, CommandGroup::EDIT );
+}
+
+IMPL_LINK( ShapeController, CheckNameHdl, AbstractSvxObjectNameDialog&, rDialog, bool )
+{
+ OUString aName;
+ rDialog.GetName( aName );
+
+ if ( !aName.isEmpty() )
+ {
+ DrawViewWrapper* pDrawViewWrapper = ( m_pChartController ? m_pChartController->GetDrawViewWrapper() : nullptr );
+ if ( pDrawViewWrapper && pDrawViewWrapper->getNamedSdrObject( aName ) )
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+void ShapeController::executeDispatch_FormatLine()
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pChartController )
+ return;
+
+ weld::Window* pChartWindow(m_pChartController->GetChartFrame());
+ DrawModelWrapper* pDrawModelWrapper = m_pChartController->GetDrawModelWrapper();
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( !(pChartWindow && pDrawModelWrapper && pDrawViewWrapper) )
+ return;
+
+ SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject();
+ SfxItemSet aAttr( pDrawViewWrapper->GetDefaultAttr() );
+ bool bHasMarked = pDrawViewWrapper->AreObjectsMarked();
+ if ( bHasMarked )
+ {
+ pDrawViewWrapper->MergeAttrFromMarked( aAttr, false );
+ }
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr< SfxAbstractTabDialog > pDlg(
+ pFact->CreateSvxLineTabDialog(pChartWindow, &aAttr, &pDrawModelWrapper->getSdrModel(),
+ pSelectedObj, bHasMarked));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet();
+ if ( bHasMarked )
+ {
+ pDrawViewWrapper->SetAttrToMarked( *pOutAttr, false );
+ }
+ else
+ {
+ pDrawViewWrapper->SetDefaultAttr( *pOutAttr, false );
+ }
+ }
+}
+
+void ShapeController::executeDispatch_FormatArea()
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pChartController )
+ return;
+
+ weld::Window* pChartWindow(m_pChartController->GetChartFrame());
+ DrawModelWrapper* pDrawModelWrapper = m_pChartController->GetDrawModelWrapper();
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( !(pChartWindow && pDrawModelWrapper && pDrawViewWrapper) )
+ return;
+
+ SfxItemSet aAttr( pDrawViewWrapper->GetDefaultAttr() );
+ bool bHasMarked = pDrawViewWrapper->AreObjectsMarked();
+ if ( bHasMarked )
+ {
+ pDrawViewWrapper->MergeAttrFromMarked( aAttr, false );
+ }
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr< AbstractSvxAreaTabDialog > pDlg(
+ pFact->CreateSvxAreaTabDialog(pChartWindow, &aAttr, &pDrawModelWrapper->getSdrModel(), true, false));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet();
+ if ( bHasMarked )
+ {
+ pDrawViewWrapper->SetAttrToMarked( *pOutAttr, false );
+ }
+ else
+ {
+ pDrawViewWrapper->SetDefaultAttr( *pOutAttr, false );
+ }
+ }
+}
+
+void ShapeController::executeDispatch_TextAttributes()
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pChartController )
+ return;
+
+ weld::Window* pChartWindow(m_pChartController->GetChartFrame());
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( !(pChartWindow && pDrawViewWrapper) )
+ return;
+
+ SfxItemSet aAttr( pDrawViewWrapper->GetDefaultAttr() );
+ bool bHasMarked = pDrawViewWrapper->AreObjectsMarked();
+ if ( bHasMarked )
+ {
+ pDrawViewWrapper->MergeAttrFromMarked( aAttr, false );
+ }
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr< SfxAbstractTabDialog > pDlg(
+ pFact->CreateTextTabDialog(pChartWindow, &aAttr, pDrawViewWrapper));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet();
+ if ( bHasMarked )
+ {
+ pDrawViewWrapper->SetAttributes( *pOutAttr );
+ }
+ else
+ {
+ pDrawViewWrapper->SetDefaultAttr( *pOutAttr, false );
+ }
+ }
+}
+
+void ShapeController::executeDispatch_TransformDialog()
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pChartController )
+ return;
+
+ weld::Window* pChartWindow(m_pChartController->GetChartFrame());
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( !(pChartWindow && pDrawViewWrapper) )
+ return;
+
+ SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject();
+ if ( pSelectedObj && pSelectedObj->GetObjIdentifier() == SdrObjKind::Caption )
+ {
+ // item set for caption
+ SfxItemSet aAttr(pDrawViewWrapper->GetModel().GetItemPool());
+ pDrawViewWrapper->GetAttributes( aAttr );
+ // item set for position and size
+ SfxItemSet aGeoAttr( pDrawViewWrapper->GetGeoAttrFromMarked() );
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr< SfxAbstractTabDialog > pDlg(
+ pFact->CreateCaptionDialog(pChartWindow, pDrawViewWrapper));
+ const WhichRangesContainer& pRange = pDlg->GetInputRanges( *aAttr.GetPool() );
+ SfxItemSet aCombAttr( *aAttr.GetPool(), pRange );
+ aCombAttr.Put( aAttr );
+ aCombAttr.Put( aGeoAttr );
+ pDlg->SetInputSet( &aCombAttr );
+ if ( pDlg->Execute() == RET_OK )
+ {
+ const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet();
+ pDrawViewWrapper->SetAttributes( *pOutAttr );
+ pDrawViewWrapper->SetGeoAttrToMarked( *pOutAttr );
+ }
+ }
+ else
+ {
+ SfxItemSet aGeoAttr( pDrawViewWrapper->GetGeoAttrFromMarked() );
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr< SfxAbstractTabDialog > pDlg(
+ pFact->CreateSvxTransformTabDialog(pChartWindow, &aGeoAttr, pDrawViewWrapper));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet();
+ pDrawViewWrapper->SetGeoAttrToMarked( *pOutAttr );
+ }
+ }
+}
+
+void ShapeController::executeDispatch_ObjectTitleDescription()
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pChartController )
+ return;
+
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( !(pDrawViewWrapper && pDrawViewWrapper->GetMarkedObjectCount() == 1) )
+ return;
+
+ SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject();
+ if ( !pSelectedObj )
+ return;
+
+ OUString aTitle( pSelectedObj->GetTitle() );
+ OUString aDescription( pSelectedObj->GetDescription() );
+ bool isDecorative(pSelectedObj->IsDecorative());
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ weld::Window* pChartWindow(m_pChartController->GetChartFrame());
+ ScopedVclPtr< AbstractSvxObjectTitleDescDialog > pDlg(
+ pFact->CreateSvxObjectTitleDescDialog(pChartWindow, aTitle, aDescription, isDecorative));
+ if ( pDlg->Execute() == RET_OK )
+ {
+ pDlg->GetTitle( aTitle );
+ pDlg->GetDescription( aDescription );
+ pDlg->IsDecorative(isDecorative);
+ pSelectedObj->SetTitle( aTitle );
+ pSelectedObj->SetDescription( aDescription );
+ pSelectedObj->SetDecorative(isDecorative);
+ }
+}
+
+void ShapeController::executeDispatch_RenameObject()
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pChartController )
+ return;
+
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( !(pDrawViewWrapper && pDrawViewWrapper->GetMarkedObjectCount() == 1) )
+ return;
+
+ SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject();
+ if ( !pSelectedObj )
+ return;
+
+ OUString aName = pSelectedObj->GetName();
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ weld::Window* pChartWindow(m_pChartController->GetChartFrame());
+ ScopedVclPtr< AbstractSvxObjectNameDialog > pDlg(
+ pFact->CreateSvxObjectNameDialog(pChartWindow, aName));
+ pDlg->SetCheckNameHdl( LINK( this, ShapeController, CheckNameHdl ) );
+ if ( pDlg->Execute() == RET_OK )
+ {
+ pDlg->GetName(aName);
+ if (pSelectedObj->GetName() == aName)
+ {
+ pSelectedObj->SetName( aName );
+ }
+ }
+}
+
+void ShapeController::executeDispatch_ChangeZOrder( ChartCommandID nId )
+{
+ SolarMutexGuard aGuard;
+ DrawViewWrapper* pDrawViewWrapper = ( m_pChartController ? m_pChartController->GetDrawViewWrapper() : nullptr );
+ if ( !pDrawViewWrapper )
+ return;
+
+ switch ( nId )
+ {
+ case ChartCommandID::ShapeBringToFront:
+ {
+ if ( isForwardPossible() )
+ {
+ pDrawViewWrapper->PutMarkedToTop();
+ }
+ }
+ break;
+ case ChartCommandID::ShapeForward:
+ {
+ if ( isForwardPossible() )
+ {
+ pDrawViewWrapper->MovMarkedToTop();
+ }
+ }
+ break;
+ case ChartCommandID::ShapeBackward:
+ {
+ if ( isBackwardPossible() )
+ {
+ pDrawViewWrapper->MovMarkedToBtm();
+ }
+ }
+ break;
+ case ChartCommandID::ShapeSendToBack:
+ {
+ if ( isBackwardPossible() )
+ {
+ SdrObject* pFirstObj = getFirstAdditionalShape();
+ pDrawViewWrapper->PutMarkedBehindObj( pFirstObj );
+ }
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+}
+
+void ShapeController::executeDispatch_FontDialog()
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pChartController )
+ return;
+
+ weld::Window* pChartWindow(m_pChartController->GetChartFrame());
+ DrawModelWrapper* pDrawModelWrapper = m_pChartController->GetDrawModelWrapper();
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( pChartWindow && pDrawModelWrapper && pDrawViewWrapper )
+ {
+ SfxItemSet aAttr(pDrawViewWrapper->GetModel().GetItemPool());
+ pDrawViewWrapper->GetAttributes( aAttr );
+ ViewElementListProvider aViewElementListProvider( pDrawModelWrapper );
+ ShapeFontDialog aDlg(pChartWindow, &aAttr, &aViewElementListProvider);
+ if (aDlg.run() == RET_OK)
+ {
+ const SfxItemSet* pOutAttr = aDlg.GetOutputItemSet();
+ pDrawViewWrapper->SetAttributes( *pOutAttr );
+ }
+ }
+}
+
+void ShapeController::executeDispatch_ParagraphDialog()
+{
+ SolarMutexGuard aGuard;
+ if ( !m_pChartController )
+ return;
+
+ weld::Window* pChartWindow(m_pChartController->GetChartFrame());
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( !(pChartWindow && pDrawViewWrapper) )
+ return;
+
+ SfxItemPool& rPool = pDrawViewWrapper->GetModel().GetItemPool();
+ SfxItemSet aAttr( rPool );
+ pDrawViewWrapper->GetAttributes( aAttr );
+
+ SfxItemSetFixed<
+ EE_ITEMS_START, EE_ITEMS_END,
+ SID_ATTR_PARA_PAGEBREAK, SID_ATTR_PARA_WIDOWS> aNewAttr(rPool);
+ aNewAttr.Put( aAttr );
+ aNewAttr.Put( SvxHyphenZoneItem( false, SID_ATTR_PARA_HYPHENZONE ) );
+ aNewAttr.Put( SvxFormatBreakItem( SvxBreak::NONE, SID_ATTR_PARA_PAGEBREAK ) );
+ aNewAttr.Put( SvxFormatSplitItem( true, SID_ATTR_PARA_SPLIT) );
+ aNewAttr.Put( SvxWidowsItem( 0, SID_ATTR_PARA_WIDOWS) );
+ aNewAttr.Put( SvxOrphansItem( 0, SID_ATTR_PARA_ORPHANS) );
+
+ ShapeParagraphDialog aDlg(pChartWindow, &aNewAttr);
+ if (aDlg.run() == RET_OK)
+ {
+ const SfxItemSet* pOutAttr = aDlg.GetOutputItemSet();
+ pDrawViewWrapper->SetAttributes( *pOutAttr );
+ }
+}
+
+SdrObject* ShapeController::getFirstAdditionalShape()
+{
+ SdrObject* pFirstObj = nullptr;
+
+ try
+ {
+ DrawModelWrapper* pDrawModelWrapper = ( m_pChartController ? m_pChartController->GetDrawModelWrapper() : nullptr );
+ if ( pDrawModelWrapper )
+ {
+ Reference< drawing::XShape > xFirstShape;
+ rtl::Reference<SvxDrawPage> xDrawPage( pDrawModelWrapper->getMainDrawPage() );
+ Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) );
+ sal_Int32 nCount = xDrawPage->getCount();
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ Reference< drawing::XShape > xShape;
+ if ( xDrawPage->getByIndex( i ) >>= xShape )
+ {
+ if ( xShape.is() && xShape != xChartRoot )
+ {
+ xFirstShape = xShape;
+ break;
+ }
+ }
+ }
+ if ( xFirstShape.is() )
+ {
+ pFirstObj = DrawViewWrapper::getSdrObject( xFirstShape );
+ }
+ }
+ }
+ catch ( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return pFirstObj;
+}
+
+SdrObject* ShapeController::getLastAdditionalShape()
+{
+ SdrObject* pLastObj = nullptr;
+
+ try
+ {
+ DrawModelWrapper* pDrawModelWrapper = ( m_pChartController ? m_pChartController->GetDrawModelWrapper() : nullptr );
+ if ( pDrawModelWrapper )
+ {
+ Reference< drawing::XShape > xLastShape;
+ rtl::Reference<SvxDrawPage> xDrawPage( pDrawModelWrapper->getMainDrawPage() );
+ Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) );
+ sal_Int32 nCount = xDrawPage->getCount();
+ for ( sal_Int32 i = nCount - 1; i >= 0; --i )
+ {
+ Reference< drawing::XShape > xShape;
+ if ( xDrawPage->getByIndex( i ) >>= xShape )
+ {
+ if ( xShape.is() && xShape != xChartRoot )
+ {
+ xLastShape = xShape;
+ break;
+ }
+ }
+ }
+ if ( xLastShape.is() )
+ {
+ pLastObj = DrawViewWrapper::getSdrObject( xLastShape );
+ }
+ }
+ }
+ catch ( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return pLastObj;
+}
+
+bool ShapeController::isBackwardPossible()
+{
+ if ( m_pChartController && m_pChartController->isAdditionalShapeSelected() )
+ {
+ SolarMutexGuard aGuard;
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( pDrawViewWrapper )
+ {
+ SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject();
+ SdrObject* pFirstObj = getFirstAdditionalShape();
+ if ( pSelectedObj && pFirstObj && pSelectedObj != pFirstObj )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool ShapeController::isForwardPossible()
+{
+ if ( m_pChartController && m_pChartController->isAdditionalShapeSelected() )
+ {
+ SolarMutexGuard aGuard;
+ DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper();
+ if ( pDrawViewWrapper )
+ {
+ SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject();
+ SdrObject* pLastObj = getLastAdditionalShape();
+ if ( pSelectedObj && pLastObj && pSelectedObj != pLastObj )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ShapeController.hxx b/chart2/source/controller/main/ShapeController.hxx
new file mode 100644
index 0000000000..cdd8002ce2
--- /dev/null
+++ b/chart2/source/controller/main/ShapeController.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "FeatureCommandDispatchBase.hxx"
+#include <tools/link.hxx>
+
+class AbstractSvxObjectNameDialog;
+class SdrObject;
+
+namespace chart
+{
+
+class ChartController;
+
+/** This is a CommandDispatch implementation for shapes.
+ */
+class ShapeController: public FeatureCommandDispatchBase
+{
+ friend class ControllerCommandDispatch;
+
+public:
+ ShapeController( const css::uno::Reference< css::uno::XComponentContext >& rxContext, ChartController* pController );
+ virtual ~ShapeController() override;
+
+protected:
+ // WeakComponentImplHelperBase
+ virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // state of a feature
+ virtual FeatureState getState( const OUString& rCommand ) override;
+
+ // execute a feature
+ virtual void execute( const OUString& rCommand, const css::uno::Sequence< css::beans::PropertyValue>& rArgs ) override;
+
+ // all the features which should be handled by this class
+ virtual void describeSupportedFeatures() override;
+
+private:
+ DECL_LINK( CheckNameHdl, AbstractSvxObjectNameDialog&, bool);
+
+ void executeDispatch_FormatLine();
+ void executeDispatch_FormatArea();
+ void executeDispatch_TextAttributes();
+ void executeDispatch_TransformDialog();
+ void executeDispatch_ObjectTitleDescription();
+ void executeDispatch_RenameObject();
+ void executeDispatch_ChangeZOrder( ChartCommandID nId );
+ void executeDispatch_FontDialog();
+ void executeDispatch_ParagraphDialog();
+
+ SdrObject* getFirstAdditionalShape();
+ SdrObject* getLastAdditionalShape();
+ bool isBackwardPossible();
+ bool isForwardPossible();
+
+ ChartController* m_pChartController;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/StatusBarCommandDispatch.cxx b/chart2/source/controller/main/StatusBarCommandDispatch.cxx
new file mode 100644
index 0000000000..e3c1f038b0
--- /dev/null
+++ b/chart2/source/controller/main/StatusBarCommandDispatch.cxx
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "StatusBarCommandDispatch.hxx"
+#include <ObjectNameProvider.hxx>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <ChartModel.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+StatusBarCommandDispatch::StatusBarCommandDispatch(
+ const Reference< uno::XComponentContext > & xContext,
+ rtl::Reference<::chart::ChartModel> xModel,
+ const Reference< view::XSelectionSupplier > & xSelSupp ) :
+ impl::StatusBarCommandDispatch_Base( xContext ),
+ m_xChartModel(std::move( xModel )),
+ m_xSelectionSupplier( xSelSupp ),
+ m_bIsModified( false )
+{}
+
+StatusBarCommandDispatch::~StatusBarCommandDispatch()
+{}
+
+void StatusBarCommandDispatch::initialize()
+{
+ if( m_xChartModel.is())
+ {
+ m_xChartModel->addModifyListener( this );
+ }
+
+ if( m_xSelectionSupplier.is())
+ {
+ m_xSelectionSupplier->addSelectionChangeListener( this );
+ }
+}
+
+void StatusBarCommandDispatch::fireStatusEvent(
+ const OUString & rURL,
+ const Reference< frame::XStatusListener > & xSingleListener /* = 0 */ )
+{
+ bool bFireAll( rURL.isEmpty() );
+ bool bFireContext( bFireAll || rURL == ".uno:Context" );
+ bool bFireModified( bFireAll || rURL == ".uno:ModifiedStatus" );
+
+ if( bFireContext && m_xChartModel.is())
+ {
+ uno::Any aArg;
+ aArg <<= ObjectNameProvider::getSelectedObjectText( m_aSelectedOID.getObjectCID(), m_xChartModel );
+ fireStatusEventForURL( ".uno:Context", aArg, true, xSingleListener );
+ }
+ if( bFireModified )
+ {
+ uno::Any aArg;
+ if( m_bIsModified )
+ aArg <<= OUString("*");
+ fireStatusEventForURL( ".uno:ModifiedStatus", aArg, true, xSingleListener );
+ }
+}
+
+// ____ XDispatch ____
+void SAL_CALL StatusBarCommandDispatch::dispatch(
+ const util::URL& /* URL */,
+ const Sequence< beans::PropertyValue >& /* Arguments */ )
+{
+ // nothing to do here
+}
+
+// ____ WeakComponentImplHelperBase ____
+/// is called when this is disposed
+void StatusBarCommandDispatch::disposing(std::unique_lock<std::mutex>& /*rGuard*/)
+{
+ m_xChartModel.clear();
+ m_xSelectionSupplier.clear();
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL StatusBarCommandDispatch::disposing( const lang::EventObject& /* Source */ )
+{
+ m_xChartModel.clear();
+ m_xSelectionSupplier.clear();
+}
+
+// ____ XModifyListener ____
+void SAL_CALL StatusBarCommandDispatch::modified( const lang::EventObject& aEvent )
+{
+ if( m_xChartModel.is())
+ m_bIsModified = m_xChartModel->isModified();
+
+ CommandDispatch::modified( aEvent );
+}
+
+// ____ XSelectionChangeListener ____
+void SAL_CALL StatusBarCommandDispatch::selectionChanged( const lang::EventObject& /* aEvent */ )
+{
+ if( m_xSelectionSupplier.is())
+ m_aSelectedOID = ObjectIdentifier( m_xSelectionSupplier->getSelection() );
+ else
+ m_aSelectedOID = ObjectIdentifier();
+ fireAllStatusEvents( nullptr );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/StatusBarCommandDispatch.hxx b/chart2/source/controller/main/StatusBarCommandDispatch.hxx
new file mode 100644
index 0000000000..ae9dcaf4f6
--- /dev/null
+++ b/chart2/source/controller/main/StatusBarCommandDispatch.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "CommandDispatch.hxx"
+#include <ObjectIdentifier.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::util { class XModifiable; }
+namespace com::sun::star::view { class XSelectionSupplier; }
+
+namespace chart
+{
+
+/** This is a CommandDispatch implementation for all commands the status bar offers
+
+ This class reads the information needed from the XModel passed here.
+ */
+
+namespace impl
+{
+typedef ::cppu::ImplInheritanceHelper<
+ CommandDispatch,
+ css::view::XSelectionChangeListener >
+ StatusBarCommandDispatch_Base;
+}
+
+class StatusBarCommandDispatch : public impl::StatusBarCommandDispatch_Base
+{
+public:
+ explicit StatusBarCommandDispatch(
+ const css::uno::Reference< css::uno::XComponentContext > & xContext,
+ rtl::Reference<::chart::ChartModel> xModel,
+ const css::uno::Reference< css::view::XSelectionSupplier > & xSelSupp );
+ virtual ~StatusBarCommandDispatch() override;
+
+ // late initialisation, especially for adding as listener
+ virtual void initialize() override;
+
+protected:
+ // ____ XDispatch ____
+ virtual void SAL_CALL dispatch(
+ const css::util::URL& URL,
+ const css::uno::Sequence< css::beans::PropertyValue >& Arguments ) override;
+
+ // ____ WeakComponentImplHelperBase ____
+ /// is called when this is disposed
+ virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
+
+ // ____ XModifyListener (override from CommandDispatch) ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ virtual void fireStatusEvent(
+ const OUString & rURL,
+ const css::uno::Reference< css::frame::XStatusListener > & xSingleListener ) override;
+
+ // ____ XSelectionChangeListener ____
+ virtual void SAL_CALL selectionChanged(
+ const css::lang::EventObject& aEvent ) override;
+
+private:
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+ css::uno::Reference< css::view::XSelectionSupplier > m_xSelectionSupplier;
+ bool m_bIsModified;
+ ObjectIdentifier m_aSelectedOID;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/ToolbarController.cxx b/chart2/source/controller/main/ToolbarController.cxx
new file mode 100644
index 0000000000..17df7c7c8b
--- /dev/null
+++ b/chart2/source/controller/main/ToolbarController.cxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <ChartToolbarController.hxx>
+
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XFramesSupplier.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <sal/log.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart {
+
+ChartToolbarController::ChartToolbarController(const css::uno::Sequence<css::uno::Any>& rProperties)
+{
+ for (const auto& rProperty : rProperties)
+ {
+ css::beans::PropertyValue aPropValue;
+ rProperty >>= aPropValue;
+ if (aPropValue.Name == "Frame")
+ {
+ mxFramesSupplier.set(aPropValue.Value, css::uno::UNO_QUERY);
+ break;
+ }
+ }
+}
+
+ChartToolbarController::~ChartToolbarController()
+{
+}
+
+void ChartToolbarController::execute(sal_Int16 /*nKeyModifier*/)
+{
+}
+
+void ChartToolbarController::click()
+{
+ css::uno::Reference<css::frame::XFrame> xActiveFrame = mxFramesSupplier->getActiveFrame();
+ if (!xActiveFrame.is())
+ return;
+
+ css::uno::Reference<css::frame::XController> xActiveController = xActiveFrame->getController();
+ if (!xActiveController.is())
+ return;
+
+ css::uno::Reference<css::frame::XDispatch> xDispatch(xActiveController, css::uno::UNO_QUERY);
+ if (!xDispatch.is())
+ return;
+
+ css::util::URL aURL;
+ aURL.Path = "FormatSelection";
+ xDispatch->dispatch(aURL, css::uno::Sequence<css::beans::PropertyValue>());
+}
+
+void ChartToolbarController::doubleClick()
+{
+ SAL_INFO("chart2", "double clicked");
+}
+
+
+css::uno::Reference<css::awt::XWindow> ChartToolbarController::createPopupWindow()
+{
+ return css::uno::Reference<css::awt::XWindow>();
+}
+
+css::uno::Reference<css::awt::XWindow> ChartToolbarController::createItemWindow(
+ const css::uno::Reference<css::awt::XWindow>& /*rParent*/)
+{
+ return css::uno::Reference<css::awt::XWindow>();
+}
+
+void ChartToolbarController::statusChanged(const css::frame::FeatureStateEvent& /*rEvent*/)
+{
+
+}
+
+void ChartToolbarController::disposing(const css::lang::EventObject& /*rSource*/)
+{
+}
+
+void ChartToolbarController::initialize(const css::uno::Sequence<css::uno::Any>& /*rAny*/)
+{
+}
+
+void ChartToolbarController::update()
+{
+}
+
+
+OUString ChartToolbarController::getImplementationName()
+{
+ return "org.libreoffice.chart2.Chart2ToolboxController";
+}
+
+sal_Bool ChartToolbarController::supportsService(OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> ChartToolbarController::getSupportedServiceNames()
+{
+ return { "com.sun.star.frame.ToolbarController" };
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_chart2_Chart2ToolboxController(css::uno::XComponentContext*, css::uno::Sequence<css::uno::Any> const & rProperties)
+{
+ return cppu::acquire(new ::chart::ChartToolbarController(rProperties));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/UndoActions.cxx b/chart2/source/controller/main/UndoActions.cxx
new file mode 100644
index 0000000000..cf2de5eb5a
--- /dev/null
+++ b/chart2/source/controller/main/UndoActions.cxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "UndoActions.hxx"
+#include "ChartModelClone.hxx"
+#include <ChartModel.hxx>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+
+#include <svx/svdundo.hxx>
+
+#include <memory>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+namespace chart::impl
+{
+ using ::com::sun::star::lang::DisposedException;
+
+UndoElement::UndoElement( OUString i_actionString, rtl::Reference<::chart::ChartModel> i_documentModel, std::shared_ptr< ChartModelClone > i_modelClone )
+ :m_sActionString(std::move( i_actionString ))
+ ,m_xDocumentModel(std::move( i_documentModel ))
+ ,m_pModelClone(std::move( i_modelClone ))
+{
+}
+
+UndoElement::~UndoElement()
+{
+}
+
+void UndoElement::disposing(std::unique_lock<std::mutex>&)
+{
+ if ( m_pModelClone )
+ m_pModelClone->dispose();
+ m_pModelClone.reset();
+ m_xDocumentModel.clear();
+}
+
+OUString SAL_CALL UndoElement::getTitle()
+{
+ return m_sActionString;
+}
+
+void UndoElement::impl_toggleModelState()
+{
+ // get a snapshot of the current state of our model
+ auto pNewClone = std::make_shared<ChartModelClone>( m_xDocumentModel, m_pModelClone->getFacet() );
+ // apply the previous snapshot to our model
+ m_pModelClone->applyToModel( m_xDocumentModel );
+ // remember the new snapshot, for the next toggle
+ m_pModelClone = pNewClone;
+}
+
+void SAL_CALL UndoElement::undo( )
+{
+ impl_toggleModelState();
+}
+
+void SAL_CALL UndoElement::redo( )
+{
+ impl_toggleModelState();
+}
+
+// = ShapeUndoElement
+
+ShapeUndoElement::ShapeUndoElement( std::unique_ptr<SdrUndoAction> xSdrUndoAction )
+ :m_xAction( std::move(xSdrUndoAction) )
+{
+}
+
+ShapeUndoElement::~ShapeUndoElement()
+{
+}
+
+OUString SAL_CALL ShapeUndoElement::getTitle()
+{
+ if ( !m_xAction )
+ throw DisposedException( OUString(), *this );
+ return m_xAction->GetComment();
+}
+
+void SAL_CALL ShapeUndoElement::undo( )
+{
+ if ( !m_xAction )
+ throw DisposedException( OUString(), *this );
+ m_xAction->Undo();
+}
+
+void SAL_CALL ShapeUndoElement::redo( )
+{
+ if ( !m_xAction )
+ throw DisposedException( OUString(), *this );
+ m_xAction->Redo();
+}
+
+} // namespace chart::impl
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/UndoActions.hxx b/chart2/source/controller/main/UndoActions.hxx
new file mode 100644
index 0000000000..a86479e167
--- /dev/null
+++ b/chart2/source/controller/main/UndoActions.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/document/XUndoAction.hpp>
+
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <comphelper/compbase.hxx>
+
+#include <memory>
+
+namespace com::sun::star::frame { class XModel; }
+
+class SdrUndoAction;
+
+namespace chart
+{
+class ChartModel;
+class ChartModelClone;
+
+namespace impl
+{
+
+typedef comphelper::WeakComponentImplHelper< css::document::XUndoAction > UndoElement_TBase;
+
+class UndoElement final : public UndoElement_TBase
+{
+public:
+ /** creates a new undo action
+
+ @param i_actionString
+ is the title of the Undo action
+ @param i_documentModel
+ is the actual document model which the undo actions operates on
+ @param i_modelClone
+ is the cloned model from before the changes, which the Undo action represents, have been applied.
+ Upon <member>invoking</member>, the clone model is applied to the document model.
+ */
+ UndoElement( OUString i_actionString,
+ rtl::Reference<::chart::ChartModel> i_documentModel,
+ std::shared_ptr< ChartModelClone > i_modelClone
+ );
+ virtual ~UndoElement() override;
+
+ UndoElement(const UndoElement&) = delete;
+ const UndoElement& operator=(const UndoElement&) = delete;
+
+ // XUndoAction
+ virtual OUString SAL_CALL getTitle() override;
+ virtual void SAL_CALL undo( ) override;
+ virtual void SAL_CALL redo( ) override;
+
+ // WeakComponentImplHelper
+ virtual void disposing(std::unique_lock<std::mutex>&) override;
+
+private:
+ void impl_toggleModelState();
+
+private:
+ OUString m_sActionString;
+ rtl::Reference<::chart::ChartModel> m_xDocumentModel;
+ std::shared_ptr< ChartModelClone > m_pModelClone;
+};
+
+typedef comphelper::WeakComponentImplHelper< css::document::XUndoAction > ShapeUndoElement_TBase;
+class ShapeUndoElement final : public ShapeUndoElement_TBase
+{
+public:
+ explicit ShapeUndoElement( std::unique_ptr<SdrUndoAction> xSdrUndoAction );
+ virtual ~ShapeUndoElement() override;
+
+ // XUndoAction
+ virtual OUString SAL_CALL getTitle() override;
+ virtual void SAL_CALL undo( ) override;
+ virtual void SAL_CALL redo( ) override;
+
+private:
+ std::unique_ptr<SdrUndoAction> m_xAction;
+};
+
+} // namespace impl
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/UndoCommandDispatch.cxx b/chart2/source/controller/main/UndoCommandDispatch.cxx
new file mode 100644
index 0000000000..c90fac3f40
--- /dev/null
+++ b/chart2/source/controller/main/UndoCommandDispatch.cxx
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "UndoCommandDispatch.hxx"
+#include <ChartModel.hxx>
+
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/document/UndoFailedException.hpp>
+
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <svtools/strings.hrc>
+#include <svtools/svtresid.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+UndoCommandDispatch::UndoCommandDispatch(
+ const Reference< uno::XComponentContext > & xContext,
+ rtl::Reference<::chart::ChartModel> xModel ) :
+ CommandDispatch( xContext ),
+ m_xModel(std::move( xModel ))
+{
+ m_xUndoManager.set( m_xModel->getUndoManager(), uno::UNO_SET_THROW );
+}
+
+UndoCommandDispatch::~UndoCommandDispatch()
+{}
+
+void UndoCommandDispatch::initialize()
+{
+ Reference< util::XModifyBroadcaster > xBroadcaster( m_xUndoManager, uno::UNO_QUERY );
+ ENSURE_OR_RETURN_VOID( xBroadcaster.is(), "UndoCommandDispatch::initialize: missing modification broadcaster interface!" );
+ xBroadcaster->addModifyListener( this );
+}
+
+void UndoCommandDispatch::fireStatusEvent(
+ const OUString & rURL,
+ const Reference< frame::XStatusListener > & xSingleListener /* = 0 */ )
+{
+ if( !m_xUndoManager.is() )
+ return;
+
+ const bool bFireAll = rURL.isEmpty();
+ uno::Any aUndoState, aRedoState, aUndoStrings, aRedoStrings;
+ if( m_xUndoManager->isUndoPossible())
+ aUndoState <<= SvtResId( STR_UNDO ) + m_xUndoManager->getCurrentUndoActionTitle();
+ if( m_xUndoManager->isRedoPossible())
+ aRedoState <<= SvtResId( STR_REDO ) + m_xUndoManager->getCurrentRedoActionTitle();
+
+ aUndoStrings <<= m_xUndoManager->getAllUndoActionTitles();
+ aRedoStrings <<= m_xUndoManager->getAllRedoActionTitles();
+
+ if( bFireAll || rURL == ".uno:Undo" )
+ fireStatusEventForURL( ".uno:Undo", aUndoState, m_xUndoManager->isUndoPossible(), xSingleListener );
+ if( bFireAll || rURL == ".uno:Redo" )
+ fireStatusEventForURL( ".uno:Redo", aRedoState, m_xUndoManager->isRedoPossible(), xSingleListener );
+ if( bFireAll || rURL == ".uno:GetUndoStrings" )
+ fireStatusEventForURL( ".uno:GetUndoStrings", aUndoStrings, true, xSingleListener );
+ if( bFireAll || rURL == ".uno:GetRedoStrings" )
+ fireStatusEventForURL( ".uno:GetRedoStrings", aRedoStrings, true, xSingleListener );
+}
+
+// ____ XDispatch ____
+void SAL_CALL UndoCommandDispatch::dispatch(
+ const util::URL& URL,
+ const Sequence< beans::PropertyValue >& Arguments )
+{
+ if( !m_xUndoManager.is() )
+ return;
+
+ // why is it necessary to lock the solar mutex here?
+ SolarMutexGuard aSolarGuard;
+ try
+ {
+ sal_Int16 nCount( 1 );
+ if ( Arguments.hasElements() && Arguments[0].Name == URL.Path )
+ Arguments[0].Value >>= nCount;
+
+ while ( nCount-- )
+ {
+ if ( URL.Path == "Undo" )
+ m_xUndoManager->undo();
+ else
+ m_xUndoManager->redo();
+ }
+ }
+ catch( const document::UndoFailedException& )
+ {
+ // silently ignore
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ // \--
+}
+
+// ____ WeakComponentImplHelperBase ____
+/// is called when this is disposed
+void UndoCommandDispatch::disposing(std::unique_lock<std::mutex>& /*rGuard*/)
+{
+ Reference< util::XModifyBroadcaster > xBroadcaster( m_xUndoManager, uno::UNO_QUERY );
+ OSL_ENSURE( xBroadcaster.is(), "UndoCommandDispatch::initialize: missing modification broadcaster interface!" );
+ if( xBroadcaster.is() )
+ {
+ xBroadcaster->removeModifyListener( this );
+ }
+
+ m_xUndoManager.clear();
+ m_xModel.clear();
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL UndoCommandDispatch::disposing( const lang::EventObject& /* Source */ )
+{
+ m_xUndoManager.clear();
+ m_xModel.clear();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/UndoCommandDispatch.hxx b/chart2/source/controller/main/UndoCommandDispatch.hxx
new file mode 100644
index 0000000000..f872387c76
--- /dev/null
+++ b/chart2/source/controller/main/UndoCommandDispatch.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "CommandDispatch.hxx"
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::document { class XUndoManager; }
+namespace com::sun::star::frame { class XModel; }
+
+namespace chart
+{
+class ChartModel;
+
+/** This is a CommandDispatch implementation for Undo and Redo.
+ */
+class UndoCommandDispatch : public CommandDispatch
+{
+public:
+ explicit UndoCommandDispatch(
+ const css::uno::Reference< css::uno::XComponentContext > & xContext,
+ rtl::Reference<::chart::ChartModel> xModel );
+ virtual ~UndoCommandDispatch() override;
+
+ // late initialisation, especially for adding as listener
+ virtual void initialize() override;
+
+protected:
+ // ____ XDispatch ____
+ virtual void SAL_CALL dispatch(
+ const css::util::URL& URL,
+ const css::uno::Sequence< css::beans::PropertyValue >& Arguments ) override;
+
+ // ____ WeakComponentImplHelperBase ____
+ /// is called when this is disposed
+ virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ virtual void fireStatusEvent(
+ const OUString & rURL,
+ const css::uno::Reference< css::frame::XStatusListener > & xSingleListener ) override;
+
+private:
+ rtl::Reference<::chart::ChartModel> m_xModel;
+ css::uno::Reference< css::document::XUndoManager > m_xUndoManager;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/UndoGuard.cxx b/chart2/source/controller/main/UndoGuard.cxx
new file mode 100644
index 0000000000..4e870c36d0
--- /dev/null
+++ b/chart2/source/controller/main/UndoGuard.cxx
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "UndoGuard.hxx"
+#include "ChartModelClone.hxx"
+#include "UndoActions.hxx"
+#include <ChartModel.hxx>
+
+#include <com/sun/star/document/XUndoManager.hpp>
+#include <utility>
+
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+UndoGuard::UndoGuard( OUString i_undoString, const uno::Reference< document::XUndoManager > & i_undoManager,
+ const ModelFacet i_facet )
+ :m_xUndoManager( i_undoManager )
+ ,m_aUndoString(std::move( i_undoString ))
+ ,m_bActionPosted( false )
+{
+ m_xChartModel = dynamic_cast<::chart::ChartModel*>(i_undoManager->getParent().get());
+ assert(m_xChartModel);
+ m_pDocumentSnapshot = std::make_shared<ChartModelClone>( m_xChartModel, i_facet );
+}
+
+UndoGuard::~UndoGuard()
+{
+ if ( m_pDocumentSnapshot )
+ discardSnapshot();
+}
+
+void UndoGuard::commit()
+{
+ if ( !m_bActionPosted && m_pDocumentSnapshot )
+ {
+ try
+ {
+ const Reference< document::XUndoAction > xAction( new impl::UndoElement( m_aUndoString, m_xChartModel, m_pDocumentSnapshot ) );
+ m_pDocumentSnapshot.reset(); // don't dispose, it's data went over to the UndoElement
+ m_xUndoManager->addUndoAction( xAction );
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ m_bActionPosted = true;
+}
+
+void UndoGuard::rollback()
+{
+ ENSURE_OR_RETURN_VOID( !!m_pDocumentSnapshot, "no snapshot!" );
+ m_pDocumentSnapshot->applyToModel( m_xChartModel );
+ discardSnapshot();
+}
+
+void UndoGuard::discardSnapshot()
+{
+ ENSURE_OR_RETURN_VOID( !!m_pDocumentSnapshot, "no snapshot!" );
+ m_pDocumentSnapshot->dispose();
+ m_pDocumentSnapshot.reset();
+}
+
+UndoLiveUpdateGuard::UndoLiveUpdateGuard( const OUString& i_undoString, const uno::Reference< document::XUndoManager >& i_undoManager )
+ :UndoGuard( i_undoString, i_undoManager, E_MODEL )
+{
+}
+
+UndoLiveUpdateGuard::~UndoLiveUpdateGuard()
+{
+ if ( !isActionPosted() )
+ rollback();
+}
+
+UndoLiveUpdateGuardWithData::UndoLiveUpdateGuardWithData(
+ const OUString& i_undoString, const uno::Reference< document::XUndoManager >& i_undoManager )
+ :UndoGuard( i_undoString, i_undoManager, E_MODEL_WITH_DATA )
+{
+}
+
+UndoLiveUpdateGuardWithData::~UndoLiveUpdateGuardWithData()
+{
+ if ( !isActionPosted() )
+ rollback();
+}
+
+UndoGuardWithSelection::UndoGuardWithSelection(
+ const OUString& i_undoString, const uno::Reference< document::XUndoManager >& i_undoManager )
+ :UndoGuard( i_undoString, i_undoManager, E_MODEL_WITH_SELECTION )
+{
+}
+
+UndoGuardWithSelection::~UndoGuardWithSelection()
+{
+ if ( !isActionPosted() )
+ rollback();
+}
+
+HiddenUndoContext::HiddenUndoContext( const Reference< document::XUndoManager > & i_undoManager )
+ :m_xUndoManager( i_undoManager )
+{
+ ENSURE_OR_THROW( m_xUndoManager.is(), "invalid undo manager!" );
+ try
+ {
+ m_xUndoManager->enterHiddenUndoContext();
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ m_xUndoManager.clear();
+ // prevents the leaveUndoContext in the dtor
+ }
+}
+
+HiddenUndoContext::~HiddenUndoContext()
+{
+ try
+ {
+ if ( m_xUndoManager.is() )
+ m_xUndoManager->leaveUndoContext();
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/main/UndoGuard.hxx b/chart2/source/controller/main/UndoGuard.hxx
new file mode 100644
index 0000000000..90443a247a
--- /dev/null
+++ b/chart2/source/controller/main/UndoGuard.hxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "ChartModelClone.hxx"
+
+#include <rtl/ustring.hxx>
+
+#include <memory>
+
+namespace com::sun::star::document { class XUndoManager; }
+namespace com::sun::star::frame { class XModel; }
+
+namespace chart
+{
+
+/** A guard which does nothing, unless you explicitly call commitAction. In particular, in its destructor, it
+ does neither auto-commit nor auto-rollback the model changes.
+ */
+class UndoGuard
+{
+public:
+ explicit UndoGuard(
+ OUString i_undoMessage,
+ const css::uno::Reference< css::document::XUndoManager > & i_undoManager,
+ const ModelFacet i_facet = E_MODEL
+ );
+ ~UndoGuard();
+
+ void commit();
+ void rollback();
+
+protected:
+ bool isActionPosted() const { return m_bActionPosted; }
+
+private:
+ void discardSnapshot();
+
+private:
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+ const css::uno::Reference< css::document::XUndoManager > m_xUndoManager;
+
+ std::shared_ptr< ChartModelClone > m_pDocumentSnapshot;
+ OUString m_aUndoString;
+ bool m_bActionPosted;
+};
+
+/** A guard which, in its destructor, restores the model state it found in the constructor. If
+ <member>commitAction</member> is called inbetween, the restoration is not performed.
+ */
+class UndoLiveUpdateGuard : public UndoGuard
+{
+public:
+ explicit UndoLiveUpdateGuard(
+ const OUString& i_undoMessage,
+ const css::uno::Reference< css::document::XUndoManager > & i_undoManager
+ );
+ ~UndoLiveUpdateGuard();
+};
+
+/** Same as UndoLiveUpdateGuard but with additional storage of the chart's data.
+ Only use this if the data has internal data.
+ */
+class UndoLiveUpdateGuardWithData :
+ public UndoGuard
+{
+public:
+ explicit UndoLiveUpdateGuardWithData(
+ const OUString& i_undoMessage,
+ const css::uno::Reference< css::document::XUndoManager > & i_undoManager
+ );
+ ~UndoLiveUpdateGuardWithData();
+};
+
+class UndoGuardWithSelection : public UndoGuard
+{
+public:
+ explicit UndoGuardWithSelection(
+ const OUString& i_undoMessage,
+ const css::uno::Reference< css::document::XUndoManager > & i_undoManager
+ );
+ virtual ~UndoGuardWithSelection();
+};
+
+class HiddenUndoContext
+{
+public:
+ explicit HiddenUndoContext(
+ const css::uno::Reference< css::document::XUndoManager > & i_undoManager
+ );
+ ~HiddenUndoContext();
+
+private:
+ css::uno::Reference< css::document::XUndoManager > m_xUndoManager;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/Chart2PanelFactory.cxx b/chart2/source/controller/sidebar/Chart2PanelFactory.cxx
new file mode 100644
index 0000000000..081322b094
--- /dev/null
+++ b/chart2/source/controller/sidebar/Chart2PanelFactory.cxx
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Chart2PanelFactory.hxx"
+
+#include <sfx2/sidebar/SidebarPanelBase.hxx>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <vcl/weldutils.hxx>
+
+#include "ChartElementsPanel.hxx"
+#include "ChartTypePanel.hxx"
+#include "ChartSeriesPanel.hxx"
+#include <ChartController.hxx>
+#include "ChartAxisPanel.hxx"
+#include "ChartErrorBarPanel.hxx"
+#include "ChartAreaPanel.hxx"
+#include "ChartLinePanel.hxx"
+
+using namespace css::uno;
+
+namespace chart::sidebar {
+
+ChartPanelFactory::ChartPanelFactory()
+{
+}
+
+ChartPanelFactory::~ChartPanelFactory()
+{
+}
+
+Reference<css::ui::XUIElement> SAL_CALL ChartPanelFactory::createUIElement (
+ const OUString& rsResourceURL,
+ const ::css::uno::Sequence<css::beans::PropertyValue>& rArguments)
+{
+ Reference<css::ui::XUIElement> xElement;
+
+ try
+ {
+ const ::comphelper::NamedValueCollection aArguments (rArguments);
+ Reference<css::frame::XFrame> xFrame (aArguments.getOrDefault("Frame", Reference<css::frame::XFrame>()));
+ Reference<css::awt::XWindow> xParentWindow (aArguments.getOrDefault("ParentWindow", Reference<css::awt::XWindow>()));
+ Reference<css::frame::XController> xController (aArguments.getOrDefault("Controller", Reference<css::frame::XController>()));
+
+ weld::Widget* pParent(nullptr);
+ if (weld::TransportAsXWindow* pTunnel = dynamic_cast<weld::TransportAsXWindow*>(xParentWindow.get()))
+ pParent = pTunnel->getWidget();
+
+ if (!pParent)
+ throw RuntimeException(
+ "PanelFactory::createUIElement called without ParentWindow",
+ nullptr);
+ if ( ! xFrame.is())
+ throw RuntimeException(
+ "PanelFactory::createUIElement called without Frame",
+ nullptr);
+ if (!xController.is())
+ throw RuntimeException(
+ "ChartPanelFactory::createUIElement called without Controller",
+ nullptr);
+
+ ChartController* pController = dynamic_cast<ChartController*>(xController.get());
+ if (!pController)
+ throw RuntimeException(
+ "ChartPanelFactory::createUIElement called without valid ChartController",
+ nullptr);
+
+ std::unique_ptr<PanelLayout> xPanel;
+ if (rsResourceURL.endsWith("/ElementsPanel"))
+ xPanel = ChartElementsPanel::Create( pParent, pController );
+ else if (rsResourceURL.endsWith("/TypePanel"))
+ xPanel = std::make_unique<ChartTypePanel>(pParent, pController);
+ else if (rsResourceURL.endsWith("/SeriesPanel"))
+ xPanel = ChartSeriesPanel::Create(pParent, pController);
+ else if (rsResourceURL.endsWith("/AxisPanel"))
+ xPanel = ChartAxisPanel::Create(pParent, pController);
+ else if (rsResourceURL.endsWith("/ErrorBarPanel"))
+ xPanel = ChartErrorBarPanel::Create(pParent, pController);
+ else if (rsResourceURL.endsWith("/AreaPanel"))
+ xPanel = ChartAreaPanel::Create(pParent, xFrame, pController);
+ else if (rsResourceURL.endsWith("/LinePanel"))
+ xPanel = ChartLinePanel::Create(pParent, xFrame, pController);
+
+ if (xPanel)
+ xElement = sfx2::sidebar::SidebarPanelBase::Create(
+ rsResourceURL,
+ xFrame,
+ std::move(xPanel),
+ css::ui::LayoutSize(-1,-1,-1));
+ }
+ catch (const css::uno::RuntimeException &)
+ {
+ throw;
+ }
+ catch (const css::uno::Exception&)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "ChartPanelFactory::createUIElement exception",
+ nullptr, anyEx );
+ }
+
+ return xElement;
+}
+
+OUString ChartPanelFactory::getImplementationName()
+{
+ return "org.libreoffice.comp.chart2.sidebar.ChartPanelFactory";
+}
+
+sal_Bool ChartPanelFactory::supportsService(OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> ChartPanelFactory::getSupportedServiceNames()
+{
+ return { "com.sun.star.ui.UIElementFactory" };
+}
+
+} // end of namespace chart::sidebar
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+org_libreoffice_comp_chart2_sidebar_ChartPanelFactory(css::uno::XComponentContext*, css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::sidebar::ChartPanelFactory());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/Chart2PanelFactory.hxx b/chart2/source/controller/sidebar/Chart2PanelFactory.hxx
new file mode 100644
index 0000000000..87619f647d
--- /dev/null
+++ b/chart2/source/controller/sidebar/Chart2PanelFactory.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <comphelper/compbase.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/ui/XUIElementFactory.hpp>
+
+
+namespace chart::sidebar {
+
+typedef comphelper::WeakComponentImplHelper <
+ css::ui::XUIElementFactory, css::lang::XServiceInfo
+ > PanelFactoryInterfaceBase;
+
+class ChartPanelFactory final
+ : public PanelFactoryInterfaceBase
+{
+public:
+ ChartPanelFactory();
+ virtual ~ChartPanelFactory() override;
+
+ ChartPanelFactory(const ChartPanelFactory&) = delete;
+ const ChartPanelFactory& operator=(const ChartPanelFactory&) = delete;
+
+ // XUIElementFactory
+ virtual css::uno::Reference<css::ui::XUIElement> SAL_CALL createUIElement(
+ const OUString& rsResourceURL,
+ const ::css::uno::Sequence<css::beans::PropertyValue>& rArguments) override;
+
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+} // end of namespace chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartAreaPanel.cxx b/chart2/source/controller/sidebar/ChartAreaPanel.cxx
new file mode 100644
index 0000000000..cb660661c1
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartAreaPanel.cxx
@@ -0,0 +1,551 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include "ChartAreaPanel.hxx"
+
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+#include <ViewElementListProvider.hxx>
+#include <PropertyHelper.hxx>
+
+#include <chartview/DrawModelWrapper.hxx>
+#include <com/sun/star/chart2/XDiagram.hpp>
+
+#include <sfx2/weldutils.hxx>
+#include <svx/xfltrit.hxx>
+#include <svx/xflftrit.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/unomid.hxx>
+#include <vcl/svapp.hxx>
+
+#include <svx/tbcontrl.hxx>
+
+namespace chart::sidebar {
+
+namespace {
+
+SvxColorToolBoxControl* getColorToolBoxControl(const ToolbarUnoDispatcher& rColorDispatch)
+{
+ css::uno::Reference<css::frame::XToolbarController> xController = rColorDispatch.GetControllerForCommand(".uno:FillColor");
+ SvxColorToolBoxControl* pToolBoxColorControl = dynamic_cast<SvxColorToolBoxControl*>(xController.get());
+ return pToolBoxColorControl;
+}
+
+OUString getCID(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ css::uno::Reference<css::frame::XController> xController(xModel->getCurrentController());
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(xController, css::uno::UNO_QUERY);
+ if (!xSelectionSupplier.is())
+ return OUString();
+
+ css::uno::Any aAny = xSelectionSupplier->getSelection();
+ if (!aAny.hasValue())
+ {
+ // if no selection, default to diagram wall so sidebar can show some editable properties
+ ChartController* pController = dynamic_cast<ChartController*>(xController.get());
+ if (pController)
+ {
+ pController->select( css::uno::Any( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) ) );
+ xSelectionSupplier = css::uno::Reference<css::view::XSelectionSupplier>(xController, css::uno::UNO_QUERY);
+ if (xSelectionSupplier.is())
+ aAny = xSelectionSupplier->getSelection();
+ }
+
+ if (!aAny.hasValue())
+ return OUString();
+ }
+
+ OUString aCID;
+ aAny >>= aCID;
+
+ return aCID;
+}
+
+css::uno::Reference<css::beans::XPropertySet> getPropSet(
+ const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ OUString aCID = getCID(xModel);
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ ObjectIdentifier::getObjectPropertySet(aCID, xModel);
+
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType == OBJECTTYPE_DIAGRAM)
+ {
+ css::uno::Reference<css::chart2::XDiagram> xDiagram(
+ xPropSet, css::uno::UNO_QUERY);
+ if (!xDiagram.is())
+ return xPropSet;
+
+ xPropSet.set(xDiagram->getWall());
+ }
+
+ return xPropSet;
+}
+
+ChartController* getController(const css::uno::Reference<css::frame::XModel>& xModel)
+{
+ css::uno::Reference<css::frame::XController>xController = xModel->getCurrentController();
+ if (!xController.is())
+ throw std::exception();
+
+ ChartController* pController = dynamic_cast<ChartController*>(xController.get());
+ if (!pController)
+ throw std::exception();
+
+ return pController;
+}
+
+ViewElementListProvider getViewElementListProvider( const css::uno::Reference<css::frame::XModel>& xModel)
+{
+ ChartController* pController = getController(xModel);
+ ViewElementListProvider aProvider = pController->getViewElementListProvider();
+ return aProvider;
+}
+
+DrawModelWrapper* getDrawModelWrapper(const css::uno::Reference<css::frame::XModel>& xModel)
+{
+ ChartController* pController = getController(xModel);
+ return pController->GetDrawModelWrapper();
+}
+
+XFillGradientItem getXGradientForName(const css::uno::Reference<css::frame::XModel>& xModel,
+ const OUString& rName)
+{
+ css::uno::Reference<css::lang::XMultiServiceFactory> xFact(xModel, css::uno::UNO_QUERY);
+ css::uno::Reference<css::container::XNameAccess> xNameAccess(
+ xFact->createInstance("com.sun.star.drawing.GradientTable"), css::uno::UNO_QUERY);
+ if (!xNameAccess.is())
+ return XFillGradientItem();
+
+ if (!xNameAccess->hasByName(rName))
+ return XFillGradientItem();
+
+ css::uno::Any aAny = xNameAccess->getByName(rName);
+
+ XFillGradientItem aItem;
+ aItem.SetName(rName);
+ aItem.PutValue(aAny, MID_FILLGRADIENT);
+
+ return aItem;
+
+}
+
+XFillFloatTransparenceItem getXTransparencyGradientForName(const css::uno::Reference<css::frame::XModel>& xModel,
+ const OUString& rName)
+{
+ css::uno::Reference<css::lang::XMultiServiceFactory> xFact(xModel, css::uno::UNO_QUERY);
+ css::uno::Reference<css::container::XNameAccess> xNameAccess(
+ xFact->createInstance("com.sun.star.drawing.TransparencyGradientTable"), css::uno::UNO_QUERY);
+ if (!xNameAccess.is())
+ return XFillFloatTransparenceItem();
+
+ if (!xNameAccess->hasByName(rName))
+ return XFillFloatTransparenceItem();
+
+ css::uno::Any aAny = xNameAccess->getByName(rName);
+
+ XFillFloatTransparenceItem aItem;
+ aItem.SetName(rName);
+ aItem.PutValue(aAny, MID_FILLGRADIENT);
+ aItem.SetEnabled(true);
+
+ return aItem;
+}
+
+XHatch getXHatchFromName(const css::uno::Reference<css::frame::XModel>& xModel,
+ OUString& rName)
+{
+ try
+ {
+ ViewElementListProvider aProvider = getViewElementListProvider(xModel);
+ XHatchListRef aRef = aProvider.GetHatchList();
+ size_t n = aRef->Count();
+ for (size_t i = 0; i < n; ++i)
+ {
+ const XHatchEntry* pHatch = aRef->GetHatch(i);
+ if (!pHatch)
+ continue;
+
+ if (pHatch->GetName().equalsIgnoreAsciiCase(rName))
+ {
+ // we need to update the hatch name
+ rName = pHatch->GetName();
+ return pHatch->GetHatch();
+ }
+ }
+ }
+ catch (...)
+ {
+ // ignore exception
+ }
+
+ return XHatch();
+}
+
+GraphicObject getXBitmapFromName(const css::uno::Reference<css::frame::XModel>& xModel,
+ std::u16string_view rName)
+{
+ try
+ {
+ ViewElementListProvider aProvider = getViewElementListProvider(xModel);
+ XBitmapListRef aBmpRef = aProvider.GetBitmapList();
+ XPatternListRef aPatRef = aProvider.GetPatternList();
+
+ size_t n = aBmpRef->Count();
+ for (size_t i = 0; i < n; ++i)
+ {
+ const XBitmapEntry* pBitmap = aBmpRef->GetBitmap(i);
+ if (!pBitmap)
+ continue;
+
+ if (pBitmap->GetName().equalsIgnoreAsciiCase(rName))
+ {
+ return pBitmap->GetGraphicObject();
+ }
+ }
+
+ // perhaps it's a pattern
+ size_t m = aPatRef->Count();
+ for (size_t i = 0; i < m; ++i)
+ {
+ const XBitmapEntry* pBitmap = aPatRef->GetBitmap(i);
+ if (!pBitmap)
+ continue;
+
+ if (pBitmap->GetName().equalsIgnoreAsciiCase(rName))
+ {
+ return pBitmap->GetGraphicObject();
+ }
+ }
+ }
+ catch (...)
+ {
+ // ignore exception
+ }
+
+ return GraphicObject();
+}
+
+class PreventUpdate
+{
+public:
+ explicit PreventUpdate(bool& bUpdate):
+ mbUpdate(bUpdate)
+ {
+ mbUpdate = false;
+ }
+
+ ~PreventUpdate()
+ {
+ mbUpdate = true;
+ }
+
+private:
+ bool& mbUpdate;
+};
+
+}
+
+std::unique_ptr<PanelLayout> ChartAreaPanel::Create(
+ weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ ChartController* pController)
+{
+ if (pParent == nullptr)
+ throw css::lang::IllegalArgumentException("no parent Window given to ChartAxisPanel::Create", nullptr, 0);
+ if (!rxFrame.is())
+ throw css::lang::IllegalArgumentException("no XFrame given to ChartAxisPanel::Create", nullptr, 1);
+
+ return std::make_unique<ChartAreaPanel>(pParent, rxFrame, pController);
+}
+
+ChartAreaPanel::ChartAreaPanel(weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ ChartController* pController):
+ svx::sidebar::AreaPropertyPanelBase(pParent, rxFrame),
+ mxModel(pController->getChartModel()),
+ mxListener(new ChartSidebarModifyListener(this)),
+ mxSelectionListener(new ChartSidebarSelectionListener(this)),
+ mbUpdate(true),
+ mbModelValid(true),
+ maFillColorWrapper(mxModel, getColorToolBoxControl(*mxColorDispatch), "FillColor")
+{
+ std::vector<ObjectType> aAcceptedTypes { OBJECTTYPE_PAGE, OBJECTTYPE_DIAGRAM,
+ OBJECTTYPE_DATA_SERIES, OBJECTTYPE_DATA_POINT,
+ OBJECTTYPE_TITLE, OBJECTTYPE_LEGEND};
+ mxSelectionListener->setAcceptedTypes(std::move(aAcceptedTypes));
+ Initialize();
+}
+
+ChartAreaPanel::~ChartAreaPanel()
+{
+ doUpdateModel(nullptr);
+}
+
+void ChartAreaPanel::Initialize()
+{
+ mxModel->addModifyListener(mxListener);
+
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (xSelectionSupplier.is())
+ xSelectionSupplier->addSelectionChangeListener(mxSelectionListener);
+
+ SvxColorToolBoxControl* pToolBoxColor = getColorToolBoxControl(*mxColorDispatch);
+ pToolBoxColor->setColorSelectFunction(maFillColorWrapper);
+
+ updateData();
+}
+
+void ChartAreaPanel::setFillTransparence(const XFillTransparenceItem& rItem)
+{
+ PreventUpdate aProtector(mbUpdate);
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ xPropSet->setPropertyValue("FillTransparence", css::uno::Any(rItem.GetValue()));
+}
+
+void ChartAreaPanel::setFillFloatTransparence(
+ const XFillFloatTransparenceItem& rItem)
+{
+ PreventUpdate aProtector(mbUpdate);
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ if (!rItem.IsEnabled())
+ {
+ xPropSet->setPropertyValue("FillTransparenceGradientName", css::uno::Any(OUString()));
+ return;
+ }
+
+ const OUString& aName = rItem.GetName();
+ css::uno::Any aGradientVal;
+ rItem.QueryValue(aGradientVal, MID_FILLGRADIENT);
+ OUString aNewName = PropertyHelper::addTransparencyGradientUniqueNameToTable(aGradientVal, mxModel, aName);
+ xPropSet->setPropertyValue("FillTransparenceGradientName", css::uno::Any(aNewName));
+}
+
+void ChartAreaPanel::setFillStyle(const XFillStyleItem& rItem)
+{
+ PreventUpdate aProtector(mbUpdate);
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ xPropSet->setPropertyValue("FillStyle", css::uno::Any(rItem.GetValue()));
+}
+
+void ChartAreaPanel::setFillStyleAndColor(const XFillStyleItem* pStyleItem,
+ const XFillColorItem& rColorItem)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ if (pStyleItem)
+ xPropSet->setPropertyValue("FillStyle", css::uno::Any(pStyleItem->GetValue()));
+ xPropSet->setPropertyValue("FillColor", css::uno::Any(rColorItem.GetValue()));
+}
+
+void ChartAreaPanel::setFillStyleAndGradient(const XFillStyleItem* pStyleItem,
+ const XFillGradientItem& rGradientItem)
+{
+ PreventUpdate aProtector(mbUpdate);
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ if (pStyleItem)
+ xPropSet->setPropertyValue("FillStyle", css::uno::Any(pStyleItem->GetValue()));
+
+ const OUString& aName = rGradientItem.GetName();
+ css::uno::Any aGradientVal;
+ rGradientItem.QueryValue(aGradientVal, MID_FILLGRADIENT);
+ OUString aNewName = PropertyHelper::addGradientUniqueNameToTable(aGradientVal, mxModel, aName);
+ xPropSet->setPropertyValue("FillGradientName", css::uno::Any(aNewName));
+}
+
+void ChartAreaPanel::setFillStyleAndHatch(const XFillStyleItem* pStyleItem,
+ const XFillHatchItem& rHatchItem)
+{
+ PreventUpdate aProtector(mbUpdate);
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ if (pStyleItem)
+ xPropSet->setPropertyValue("FillStyle", css::uno::Any(pStyleItem->GetValue()));
+ xPropSet->setPropertyValue("FillHatchName", css::uno::Any(rHatchItem.GetValue()));
+}
+
+void ChartAreaPanel::setFillStyleAndBitmap(const XFillStyleItem* pStyleItem,
+ const XFillBitmapItem& rBitmapItem)
+{
+ PreventUpdate aProtector(mbUpdate);
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ if (pStyleItem)
+ xPropSet->setPropertyValue("FillStyle", css::uno::Any(pStyleItem->GetValue()));
+
+ css::uno::Any aBitmap;
+ rBitmapItem.QueryValue(aBitmap, MID_BITMAP);
+ const OUString& aPreferredName = rBitmapItem.GetName();
+ aBitmap <<= PropertyHelper::addBitmapUniqueNameToTable(aBitmap, mxModel, aPreferredName);
+ xPropSet->setPropertyValue("FillBitmapName", aBitmap);
+}
+
+void ChartAreaPanel::setFillUseBackground(const XFillStyleItem* pStyleItem,
+ const XFillUseSlideBackgroundItem& /*rItem*/)
+{
+ setFillStyle(*pStyleItem);
+}
+
+void ChartAreaPanel::updateData()
+{
+ if (!mbUpdate || !mbModelValid)
+ return;
+
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ css::uno::Reference<css::beans::XPropertySetInfo> xInfo(xPropSet->getPropertySetInfo());
+ if (!xInfo.is())
+ return;
+
+ SolarMutexGuard aGuard;
+ if (xInfo->hasPropertyByName("FillStyle"))
+ {
+ css::drawing::FillStyle eFillStyle = css::drawing::FillStyle_SOLID;
+ xPropSet->getPropertyValue("FillStyle") >>= eFillStyle;
+ XFillStyleItem aFillStyleItem(eFillStyle);
+ updateFillStyle(false, true, &aFillStyleItem);
+ }
+
+ if (xInfo->hasPropertyByName("FillTransparence"))
+ {
+ sal_uInt16 nFillTransparence = 0;
+ xPropSet->getPropertyValue("FillTransparence") >>= nFillTransparence;
+ SfxUInt16Item aTransparenceItem(0, nFillTransparence);
+ updateFillTransparence(false, true, &aTransparenceItem);
+ }
+
+ if (xInfo->hasPropertyByName("FillGradientName"))
+ {
+ OUString aGradientName;
+ xPropSet->getPropertyValue("FillGradientName") >>= aGradientName;
+ XFillGradientItem aGradientItem = getXGradientForName(mxModel, aGradientName);
+ updateFillGradient(false, true, &aGradientItem);
+ }
+
+ if (xInfo->hasPropertyByName("FillHatchName"))
+ {
+ OUString aHatchName;
+ xPropSet->getPropertyValue("FillHatchName") >>= aHatchName;
+ XHatch aHatch = getXHatchFromName(mxModel, aHatchName);
+ XFillHatchItem aHatchItem(aHatchName, aHatch);
+ updateFillHatch(false, true, &aHatchItem);
+ }
+
+ if (xInfo->hasPropertyByName("FillBitmapName"))
+ {
+ OUString aBitmapName;
+ xPropSet->getPropertyValue("FillBitmapName") >>= aBitmapName;
+ GraphicObject aBitmap = getXBitmapFromName(mxModel, aBitmapName);
+ XFillBitmapItem aBitmapItem(aBitmapName, aBitmap);
+ std::unique_ptr<XFillBitmapItem> pBitmapItem;
+ try
+ {
+ DrawModelWrapper* pModelWrapper = getDrawModelWrapper(mxModel);
+ if (pModelWrapper)
+ {
+ pBitmapItem = aBitmapItem.checkForUniqueItem(&pModelWrapper->getSdrModel());
+ }
+ }
+ catch (...)
+ {
+ }
+ updateFillBitmap(false, true, pBitmapItem ? pBitmapItem.get() : &aBitmapItem);
+ }
+
+ if (xInfo->hasPropertyByName("FillTransparenceGradientName"))
+ {
+ OUString aFillFloatTransparenceName;
+ xPropSet->getPropertyValue("FillTransparenceGradientName") >>= aFillFloatTransparenceName;
+ XFillFloatTransparenceItem aFillFloatTransparenceItem = getXTransparencyGradientForName(mxModel, aFillFloatTransparenceName);
+ updateFillFloatTransparence(false, true, &aFillFloatTransparenceItem);
+
+ maFillColorWrapper.updateData();
+ }
+
+ if (xInfo->hasPropertyByName("FillColor"))
+ {
+ sal_uInt32 nFillColor = 0;
+ xPropSet->getPropertyValue("FillColor") >>= nFillColor;
+ XFillColorItem aFillColorItem("", Color(ColorTransparency, nFillColor));
+ updateFillColor(true, &aFillColorItem);
+ }
+}
+
+void ChartAreaPanel::modelInvalid()
+{
+ mbModelValid = false;
+}
+
+void ChartAreaPanel::selectionChanged(bool bCorrectType)
+{
+ if (bCorrectType)
+ updateData();
+}
+
+void ChartAreaPanel::doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ if (mbModelValid)
+ {
+ mxModel->removeModifyListener(mxListener);
+
+ css::uno::Reference<css::view::XSelectionSupplier> oldSelectionSupplier(
+ mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (oldSelectionSupplier.is()) {
+ oldSelectionSupplier->removeSelectionChangeListener(mxSelectionListener);
+ }
+ }
+
+ mxModel = xModel;
+ mbModelValid = mxModel.is();
+
+ if (!mbModelValid)
+ return;
+
+ mxModel->addModifyListener(mxListener);
+
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (xSelectionSupplier.is())
+ xSelectionSupplier->addSelectionChangeListener(mxSelectionListener);
+}
+
+void ChartAreaPanel::updateModel( css::uno::Reference<css::frame::XModel> xModel)
+{
+ ::chart::ChartModel* pModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
+ assert(!xModel || pModel);
+ doUpdateModel(pModel);
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartAreaPanel.hxx b/chart2/source/controller/sidebar/ChartAreaPanel.hxx
new file mode 100644
index 0000000000..e1edd3d832
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartAreaPanel.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sfx2/sidebar/SidebarModelUpdate.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/xbtmpit.hxx>
+
+#include <svx/sidebar/AreaPropertyPanelBase.hxx>
+
+#include "ChartSidebarModifyListener.hxx"
+#include "ChartSidebarSelectionListener.hxx"
+#include "ChartColorWrapper.hxx"
+
+class XFillFloatTransparenceItem;
+class XFillTransparenceItem;
+class XFillColorItem;
+
+namespace chart {
+
+class ChartController;
+
+namespace sidebar {
+
+class ChartAreaPanel : public svx::sidebar::AreaPropertyPanelBase,
+ public sfx2::sidebar::SidebarModelUpdate,
+ public ChartSidebarModifyListenerParent,
+ public ChartSidebarSelectionListenerParent
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ ChartController* pController);
+
+ // constructor/destructor
+ ChartAreaPanel(
+ weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ ChartController* pController);
+
+ virtual ~ChartAreaPanel() override;
+
+ virtual void setFillTransparence(const XFillTransparenceItem& rItem) override;
+ virtual void setFillFloatTransparence(const XFillFloatTransparenceItem& rItem) override;
+ virtual void setFillStyle(const XFillStyleItem& rItem) override;
+ virtual void setFillStyleAndColor(const XFillStyleItem* pStyleItem, const XFillColorItem& rColorItem) override;
+ virtual void setFillStyleAndGradient(const XFillStyleItem* pStyleItem, const XFillGradientItem& rGradientItem) override;
+ virtual void setFillStyleAndHatch(const XFillStyleItem* pStyleItem, const XFillHatchItem& rHatchItem) override;
+ virtual void setFillStyleAndBitmap(const XFillStyleItem* pStyleItem, const XFillBitmapItem& rBitmapItem) override;
+ virtual void setFillUseBackground(const XFillStyleItem* pStyleItem, const XFillUseSlideBackgroundItem& rItem) override;
+
+ virtual void updateData() override;
+ virtual void modelInvalid() override;
+
+ virtual void selectionChanged(bool bCorrectType) override;
+
+ virtual void updateModel(css::uno::Reference<css::frame::XModel> xModel) override;
+
+private:
+
+ rtl::Reference<::chart::ChartModel> mxModel;
+ css::uno::Reference<css::util::XModifyListener> mxListener;
+ rtl::Reference<ChartSidebarSelectionListener> mxSelectionListener;
+
+ void Initialize();
+ void doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel);
+
+ bool mbUpdate;
+ bool mbModelValid;
+
+ ChartColorWrapper maFillColorWrapper;
+};
+
+} } // end of namespace svx::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartAxisPanel.cxx b/chart2/source/controller/sidebar/ChartAxisPanel.cxx
new file mode 100644
index 0000000000..48a4620684
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartAxisPanel.cxx
@@ -0,0 +1,373 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
+#include <com/sun/star/chart2/AxisOrientation.hpp>
+
+#include <vcl/svapp.hxx>
+#include <sal/log.hxx>
+
+#include "ChartAxisPanel.hxx"
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+#include <Axis.hxx>
+
+using namespace css;
+using namespace css::uno;
+
+namespace chart::sidebar {
+
+namespace {
+
+bool isLabelShown(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID)
+{
+ rtl::Reference< ::chart::Axis > xAxis = ObjectIdentifier::getAxisForCID(rCID, xModel);
+
+ if (!xAxis.is())
+ return false;
+
+ uno::Any aAny = xAxis->getPropertyValue("DisplayLabels");
+ if (!aAny.hasValue())
+ return false;
+
+ bool bVisible = false;
+ aAny >>= bVisible;
+ return bVisible;
+}
+
+void setLabelShown(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, bool bVisible)
+{
+ rtl::Reference< ::chart::Axis > xAxis = ObjectIdentifier::getAxisForCID(rCID, xModel);
+
+ if (!xAxis.is())
+ return;
+
+ xAxis->setPropertyValue("DisplayLabels", css::uno::Any(bVisible));
+}
+
+struct AxisLabelPosMap
+{
+ sal_Int32 nPos;
+ css::chart::ChartAxisLabelPosition ePos;
+};
+
+AxisLabelPosMap const aLabelPosMap[] = {
+ { 0, css::chart::ChartAxisLabelPosition_NEAR_AXIS },
+ { 1, css::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE },
+ { 2, css::chart::ChartAxisLabelPosition_OUTSIDE_START },
+ { 3, css::chart::ChartAxisLabelPosition_OUTSIDE_END }
+};
+
+sal_Int32 getLabelPosition(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID)
+{
+ rtl::Reference< ::chart::Axis > xAxis = ObjectIdentifier::getAxisForCID(rCID, xModel);
+
+ if (!xAxis.is())
+ return 0;
+
+ uno::Any aAny = xAxis->getPropertyValue("LabelPosition");
+ if (!aAny.hasValue())
+ return 0;
+
+ css::chart::ChartAxisLabelPosition ePos;
+ aAny >>= ePos;
+ for (AxisLabelPosMap const & i : aLabelPosMap)
+ {
+ if (i.ePos == ePos)
+ return i.nPos;
+ }
+
+ return 0;
+}
+
+void setLabelPosition(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, sal_Int32 nPos)
+{
+ rtl::Reference< ::chart::Axis > xAxis = ObjectIdentifier::getAxisForCID(rCID, xModel);
+
+ if (!xAxis.is())
+ return;
+
+ css::chart::ChartAxisLabelPosition ePos;
+ for (AxisLabelPosMap const & i : aLabelPosMap)
+ {
+ if (i.nPos == nPos)
+ ePos = i.ePos;
+ }
+
+ xAxis->setPropertyValue("LabelPosition", css::uno::Any(ePos));
+}
+
+bool isReverse(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID)
+{
+ rtl::Reference< Axis > xAxis =
+ ObjectIdentifier::getAxisForCID(rCID, xModel);
+
+ if (!xAxis.is())
+ return false;
+
+ css::chart2::ScaleData aData = xAxis->getScaleData();
+
+ return aData.Orientation == css::chart2::AxisOrientation_REVERSE;
+}
+
+void setReverse(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, bool bReverse)
+{
+ rtl::Reference< Axis > xAxis =
+ ObjectIdentifier::getAxisForCID(rCID, xModel);
+
+ if (!xAxis.is())
+ return;
+
+ css::chart2::ScaleData aData = xAxis->getScaleData();
+ if (bReverse)
+ aData.Orientation = css::chart2::AxisOrientation_REVERSE;
+ else
+ aData.Orientation = css::chart2::AxisOrientation_MATHEMATICAL;
+
+ xAxis->setScaleData(aData);
+}
+
+OUString getCID(const css::uno::Reference<css::frame::XModel>& xModel)
+{
+ css::uno::Reference<css::frame::XController> xController(xModel->getCurrentController());
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(xController, css::uno::UNO_QUERY);
+ if (!xSelectionSupplier.is())
+ return OUString();
+
+ uno::Any aAny = xSelectionSupplier->getSelection();
+ assert(aAny.hasValue());
+ OUString aCID;
+ aAny >>= aCID;
+#if defined DBG_UTIL && !defined NDEBUG
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if(eType != OBJECTTYPE_AXIS)
+ SAL_WARN("chart2","Selected item is not an axis");
+#endif
+
+ return aCID;
+}
+
+void setAxisRotation(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, double nVal)
+{
+ rtl::Reference< ::chart::Axis > xAxis =
+ ObjectIdentifier::getAxisForCID(rCID, xModel);
+
+ if (!xAxis.is())
+ return;
+
+ xAxis->setPropertyValue("TextRotation", css::uno::Any(nVal));
+}
+
+double getAxisRotation(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID)
+{
+ rtl::Reference< ::chart::Axis > xAxis =
+ ObjectIdentifier::getAxisForCID(rCID, xModel);
+
+ if (!xAxis.is())
+ return 0;
+
+ css::uno::Any aAny = xAxis->getPropertyValue("TextRotation");
+ double nVal = 0;
+ aAny >>= nVal;
+ return nVal;
+}
+
+}
+
+ChartAxisPanel::ChartAxisPanel(
+ weld::Widget* pParent,
+ ChartController* pController)
+ : PanelLayout(pParent, "ChartAxisPanel", "modules/schart/ui/sidebaraxis.ui")
+ , mxCBShowLabel(m_xBuilder->weld_check_button("checkbutton_show_label"))
+ , mxCBReverse(m_xBuilder->weld_check_button("checkbutton_reverse"))
+ , mxLBLabelPos(m_xBuilder->weld_combo_box("comboboxtext_label_position"))
+ , mxGridLabel(m_xBuilder->weld_widget("label_props"))
+ , mxNFRotation(m_xBuilder->weld_metric_spin_button("spinbutton1", FieldUnit::DEGREE))
+ , mxModel(pController->getChartModel())
+ , mxModifyListener(new ChartSidebarModifyListener(this))
+ , mxSelectionListener(new ChartSidebarSelectionListener(this, OBJECTTYPE_AXIS))
+ , mbModelValid(true)
+{
+ Initialize();
+}
+
+ChartAxisPanel::~ChartAxisPanel()
+{
+ doUpdateModel(nullptr);
+
+ mxCBShowLabel.reset();
+ mxCBReverse.reset();
+
+ mxLBLabelPos.reset();
+ mxGridLabel.reset();
+
+ mxNFRotation.reset();
+}
+
+void ChartAxisPanel::Initialize()
+{
+ mxModel->addModifyListener(mxModifyListener);
+
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (xSelectionSupplier.is())
+ xSelectionSupplier->addSelectionChangeListener(mxSelectionListener);
+
+ updateData();
+
+ Link<weld::Toggleable&,void> aLink = LINK(this, ChartAxisPanel, CheckBoxHdl);
+ mxCBShowLabel->connect_toggled(aLink);
+ mxCBReverse->connect_toggled(aLink);
+
+ Link<weld::MetricSpinButton&, void> aSpinButtonLink = LINK(this, ChartAxisPanel, TextRotationHdl);
+ mxNFRotation->connect_value_changed(aSpinButtonLink);
+
+ mxLBLabelPos->connect_changed(LINK(this, ChartAxisPanel, ListBoxHdl));
+}
+
+void ChartAxisPanel::updateData()
+{
+ if (!mbModelValid)
+ return;
+
+ OUString aCID = getCID(mxModel);
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType!=OBJECTTYPE_AXIS)
+ return;
+
+ SolarMutexGuard aGuard;
+
+ mxCBShowLabel->set_active(isLabelShown(mxModel, aCID));
+ mxCBReverse->set_active(isReverse(mxModel, aCID));
+
+ mxLBLabelPos->set_active(getLabelPosition(mxModel, aCID));
+ mxNFRotation->set_value(getAxisRotation(mxModel, aCID), FieldUnit::DEGREE);
+}
+
+std::unique_ptr<PanelLayout> ChartAxisPanel::Create (
+ weld::Widget* pParent,
+ ChartController* pController)
+{
+ if (pParent == nullptr)
+ throw lang::IllegalArgumentException("no parent Window given to ChartAxisPanel::Create", nullptr, 0);
+ return std::make_unique<ChartAxisPanel>(pParent, pController);
+}
+
+void ChartAxisPanel::DataChanged(const DataChangedEvent& rEvent)
+{
+ PanelLayout::DataChanged(rEvent);
+ updateData();
+}
+
+void ChartAxisPanel::HandleContextChange(
+ const vcl::EnumContext& )
+{
+ updateData();
+}
+
+void ChartAxisPanel::NotifyItemUpdate(
+ sal_uInt16 /*nSID*/,
+ SfxItemState /*eState*/,
+ const SfxPoolItem* /*pState*/ )
+{
+}
+
+void ChartAxisPanel::modelInvalid()
+{
+ mbModelValid = false;
+}
+
+void ChartAxisPanel::doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ if (mbModelValid)
+ {
+ mxModel->removeModifyListener(mxModifyListener);
+
+ css::uno::Reference<css::view::XSelectionSupplier> oldSelectionSupplier(
+ mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (oldSelectionSupplier.is()) {
+ oldSelectionSupplier->removeSelectionChangeListener(mxSelectionListener);
+ }
+ }
+
+ mxModel = xModel;
+ mbModelValid = mxModel.is();
+
+ if (!mbModelValid)
+ return;
+
+ mxModel->addModifyListener(mxModifyListener);
+
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (xSelectionSupplier.is())
+ xSelectionSupplier->addSelectionChangeListener(mxSelectionListener);
+}
+
+void ChartAxisPanel::updateModel(css::uno::Reference<css::frame::XModel> xModel)
+{
+ ::chart::ChartModel* pModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
+ assert(!xModel || pModel);
+ doUpdateModel(pModel);
+}
+
+void ChartAxisPanel::selectionChanged(bool bCorrectType)
+{
+ if (bCorrectType)
+ updateData();
+}
+
+IMPL_LINK(ChartAxisPanel, CheckBoxHdl, weld::Toggleable&, rCheckbox, void)
+{
+ OUString aCID = getCID(mxModel);
+ bool bChecked = rCheckbox.get_active();
+
+ if (&rCheckbox == mxCBShowLabel.get())
+ {
+ mxGridLabel->set_sensitive(bChecked);
+ setLabelShown(mxModel, aCID, bChecked);
+ }
+ else if (&rCheckbox == mxCBReverse.get())
+ setReverse(mxModel, aCID, bChecked);
+}
+
+IMPL_LINK_NOARG(ChartAxisPanel, ListBoxHdl, weld::ComboBox&, void)
+{
+ OUString aCID = getCID(mxModel);
+ sal_Int32 nPos = mxLBLabelPos->get_active();
+
+ setLabelPosition(mxModel, aCID, nPos);
+}
+
+IMPL_LINK(ChartAxisPanel, TextRotationHdl, weld::MetricSpinButton&, rMetricField, void)
+{
+ OUString aCID = getCID(mxModel);
+ double nVal = rMetricField.get_value(FieldUnit::DEGREE);
+ setAxisRotation(mxModel, aCID, nVal);
+}
+
+} // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartAxisPanel.hxx b/chart2/source/controller/sidebar/ChartAxisPanel.hxx
new file mode 100644
index 0000000000..e5ed4b5ebc
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartAxisPanel.hxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <sfx2/sidebar/IContextChangeReceiver.hxx>
+#include <sfx2/sidebar/SidebarModelUpdate.hxx>
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include "ChartSidebarModifyListener.hxx"
+#include "ChartSidebarSelectionListener.hxx"
+
+namespace com::sun::star::util { class XModifyListener; }
+namespace com::sun::star::view { class XSelectionChangeListener; }
+
+namespace chart {
+
+class ChartController;
+
+namespace sidebar {
+
+class ChartAxisPanel : public PanelLayout,
+ public ::sfx2::sidebar::IContextChangeReceiver,
+ public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface,
+ public sfx2::sidebar::SidebarModelUpdate,
+ public ChartSidebarModifyListenerParent,
+ public ChartSidebarSelectionListenerParent
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ ChartController* pController);
+
+ virtual void DataChanged(
+ const DataChangedEvent& rEvent) override;
+
+ virtual void HandleContextChange(
+ const vcl::EnumContext& rContext) override;
+
+ virtual void NotifyItemUpdate(
+ const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(
+ const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+ // constructor/destructor
+ ChartAxisPanel(
+ weld::Widget* pParent,
+ ChartController* pController);
+ virtual ~ChartAxisPanel() override;
+
+ virtual void updateData() override;
+ virtual void modelInvalid() override;
+
+ virtual void selectionChanged(bool bCorrectType) override;
+
+ virtual void updateModel(css::uno::Reference<css::frame::XModel> xModel) override;
+
+private:
+ //ui controls
+ std::unique_ptr<weld::CheckButton> mxCBShowLabel;
+ std::unique_ptr<weld::CheckButton> mxCBReverse;
+ std::unique_ptr<weld::ComboBox> mxLBLabelPos;
+ std::unique_ptr<weld::Widget> mxGridLabel;
+ std::unique_ptr<weld::MetricSpinButton> mxNFRotation;
+
+ rtl::Reference<::chart::ChartModel> mxModel;
+ css::uno::Reference<css::util::XModifyListener> mxModifyListener;
+ css::uno::Reference<css::view::XSelectionChangeListener> mxSelectionListener;
+
+ bool mbModelValid;
+
+ void Initialize();
+ void doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel);
+
+ DECL_LINK(CheckBoxHdl, weld::Toggleable&, void);
+ DECL_LINK(ListBoxHdl, weld::ComboBox&, void);
+ DECL_LINK(TextRotationHdl, weld::MetricSpinButton&, void);
+};
+
+} } // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartColorWrapper.cxx b/chart2/source/controller/sidebar/ChartColorWrapper.cxx
new file mode 100644
index 0000000000..f5c7913343
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartColorWrapper.cxx
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include "ChartColorWrapper.hxx"
+#include <ChartModel.hxx>
+
+#include <ObjectIdentifier.hxx>
+#include <PropertyHelper.hxx>
+#include <com/sun/star/chart2/XDiagram.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/frame/XController.hpp>
+
+#include <svx/linectrl.hxx>
+#include <svx/tbcontrl.hxx>
+#include <svx/xlndsit.hxx>
+#include <svx/unomid.hxx>
+
+#include <comphelper/lok.hxx>
+#include <sal/log.hxx>
+#include <sfx2/viewsh.hxx>
+#include <utility>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+namespace chart::sidebar {
+
+namespace {
+
+OUString getCID(const css::uno::Reference<css::frame::XModel>& xModel)
+{
+ if (!xModel.is())
+ return OUString();
+
+ css::uno::Reference<css::frame::XController> xController(xModel->getCurrentController());
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(xController, css::uno::UNO_QUERY);
+ if (!xSelectionSupplier.is())
+ return OUString();
+
+ css::uno::Any aAny = xSelectionSupplier->getSelection();
+ if (!aAny.hasValue())
+ return OUString();
+
+ OUString aCID;
+ aAny >>= aCID;
+
+ return aCID;
+}
+
+css::uno::Reference<css::beans::XPropertySet> getPropSet(
+ const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ OUString aCID = getCID(xModel);
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ ObjectIdentifier::getObjectPropertySet(aCID, xModel);
+
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType == OBJECTTYPE_DIAGRAM)
+ {
+ css::uno::Reference<css::chart2::XDiagram> xDiagram(
+ xPropSet, css::uno::UNO_QUERY);
+ if (!xDiagram.is())
+ return xPropSet;
+
+ xPropSet.set(xDiagram->getWall());
+ }
+
+ return xPropSet;
+}
+
+}
+
+ChartColorWrapper::ChartColorWrapper(
+ rtl::Reference<::chart::ChartModel> xModel,
+ SvxColorToolBoxControl* pControl,
+ OUString aName):
+ mxModel(std::move(xModel)),
+ mpControl(pControl),
+ maPropertyName(std::move(aName))
+{
+}
+
+void ChartColorWrapper::operator()([[maybe_unused]] const OUString& , const NamedColor& rColor)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+
+ if (!xPropSet.is())
+ {
+ SAL_WARN("chart2", "Invalid reference to xPropSet");
+ return;
+ }
+
+ xPropSet->setPropertyValue(maPropertyName, css::uno::Any(rColor.m_aColor));
+}
+
+void ChartColorWrapper::updateModel(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ mxModel = xModel;
+}
+
+void ChartColorWrapper::updateData()
+{
+ static constexpr OUString aLineColor = u"LineColor"_ustr;
+ static const std::u16string_view aCommands[2] = {u".uno:XLineColor", u".uno:FillColor"};
+
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ css::util::URL aUrl;
+ aUrl.Complete = (maPropertyName == aLineColor) ? aCommands[0] : aCommands[1];
+
+ css::frame::FeatureStateEvent aEvent;
+ aEvent.FeatureURL = aUrl;
+ aEvent.IsEnabled = true;
+ aEvent.State = xPropSet->getPropertyValue(maPropertyName);
+ mpControl->statusChanged(aEvent);
+
+ SfxViewShell* pViewShell = SfxViewShell::Current();
+ if (comphelper::LibreOfficeKit::isActive() && pViewShell && (maPropertyName == aLineColor))
+ {
+ OString sCommand = OUStringToOString(aUrl.Complete, RTL_TEXTENCODING_ASCII_US);
+ sal_Int32 nColor = -1;
+ aEvent.State >>= nColor;
+ pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED,
+ sCommand + "=" + OString::number(nColor));
+ }
+}
+
+ChartLineStyleWrapper::ChartLineStyleWrapper(
+ rtl::Reference<::chart::ChartModel> xModel,
+ SvxLineStyleToolBoxControl* pControl)
+ : mxModel(std::move(xModel))
+ , mpControl(pControl)
+{
+}
+
+void ChartLineStyleWrapper::updateModel(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ mxModel = xModel;
+}
+
+namespace
+{
+ css::uno::Any getLineDash(
+ const css::uno::Reference<css::frame::XModel>& xModel, const OUString& rDashName)
+ {
+ css::uno::Reference<css::lang::XMultiServiceFactory> xFact(xModel, css::uno::UNO_QUERY);
+ css::uno::Reference<css::container::XNameAccess> xNameAccess(
+ xFact->createInstance("com.sun.star.drawing.DashTable"),
+ css::uno::UNO_QUERY );
+ if(xNameAccess.is())
+ {
+ if (!xNameAccess->hasByName(rDashName))
+ return css::uno::Any();
+
+ return xNameAccess->getByName(rDashName);
+ }
+
+ return css::uno::Any();
+ }
+}
+
+void ChartLineStyleWrapper::updateData()
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ css::util::URL aUrl;
+ aUrl.Complete = ".uno:XLineStyle";
+
+ css::frame::FeatureStateEvent aEvent;
+ aEvent.IsEnabled = true;
+
+ aEvent.FeatureURL = aUrl;
+ aEvent.State = xPropSet->getPropertyValue("LineStyle");
+ mpControl->statusChanged(aEvent);
+
+ aUrl.Complete = ".uno:LineDash";
+
+ auto aLineDashName = xPropSet->getPropertyValue("LineDashName");
+ OUString aDashName;
+ aLineDashName >>= aDashName;
+ css::uno::Any aLineDash = getLineDash(mxModel, aDashName);
+ XLineDashItem aDashItem;
+ aDashItem.PutValue(aLineDash, MID_LINEDASH);
+
+ aEvent.FeatureURL = aUrl;
+ aDashItem.QueryValue(aEvent.State);
+ mpControl->statusChanged(aEvent);
+}
+
+bool ChartLineStyleWrapper::operator()(std::u16string_view rCommand, const css::uno::Any& rValue)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+
+ if (!xPropSet.is())
+ {
+ SAL_WARN("chart2", "Invalid reference to xPropSet");
+ return false;
+ }
+
+ if (rCommand == u".uno:XLineStyle")
+ {
+ xPropSet->setPropertyValue("LineStyle", rValue);
+ return true;
+ }
+ else if (rCommand == u".uno:LineDash")
+ {
+ XLineDashItem aDashItem;
+ aDashItem.PutValue(rValue, 0);
+ css::uno::Any aAny;
+ aDashItem.QueryValue(aAny, MID_LINEDASH);
+ OUString aDashName = PropertyHelper::addLineDashUniqueNameToTable(aAny,
+ mxModel,
+ "");
+ xPropSet->setPropertyValue("LineDash", aAny);
+ xPropSet->setPropertyValue("LineDashName", css::uno::Any(aDashName));
+ return true;
+ }
+ return false;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartColorWrapper.hxx b/chart2/source/controller/sidebar/ChartColorWrapper.hxx
new file mode 100644
index 0000000000..6894726768
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartColorWrapper.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <ChartModel.hxx>
+
+#include <svx/Palette.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::frame { class XModel; }
+namespace chart { class ChartModel; }
+class SvxColorToolBoxControl;
+class SvxLineStyleToolBoxControl;
+
+namespace chart::sidebar {
+
+class ChartColorWrapper
+{
+public:
+ ChartColorWrapper(rtl::Reference<::chart::ChartModel> xModel,
+ SvxColorToolBoxControl* pControl,
+ OUString rPropertyName);
+
+ void operator()(const OUString& rCommand, const NamedColor& rColor);
+ // ColorSelectFunction signature
+
+ void updateModel(const rtl::Reference<::chart::ChartModel>& xModel);
+
+ void updateData();
+
+private:
+
+ rtl::Reference<::chart::ChartModel> mxModel;
+
+ SvxColorToolBoxControl* mpControl;
+
+ OUString maPropertyName;
+};
+
+class ChartLineStyleWrapper
+{
+public:
+ ChartLineStyleWrapper(rtl::Reference<::chart::ChartModel> xModel,
+ SvxLineStyleToolBoxControl* pControl);
+
+ bool operator()(std::u16string_view rCommand, const css::uno::Any& rValue);
+
+ void updateModel(const rtl::Reference<::chart::ChartModel>& xModel);
+
+ void updateData();
+
+private:
+
+ rtl::Reference<::chart::ChartModel> mxModel;
+
+ SvxLineStyleToolBoxControl* mpControl;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartElementsPanel.cxx b/chart2/source/controller/sidebar/ChartElementsPanel.cxx
new file mode 100644
index 0000000000..b4452e38da
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartElementsPanel.cxx
@@ -0,0 +1,663 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart/ChartLegendExpansion.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include "ChartElementsPanel.hxx"
+#include <ChartController.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <Legend.hxx>
+#include <LegendHelper.hxx>
+#include <ChartModelHelper.hxx>
+#include <AxisHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartModel.hxx>
+#include <BaseCoordinateSystem.hxx>
+
+
+using namespace css;
+using namespace css::uno;
+
+namespace chart::sidebar {
+
+namespace {
+
+enum class GridType
+{
+ VERT_MAJOR,
+ VERT_MINOR,
+ HOR_MAJOR,
+ HOR_MINOR
+};
+
+enum class AxisType
+{
+ X_MAIN,
+ Y_MAIN,
+ Z_MAIN,
+ X_SECOND,
+ Y_SECOND
+};
+
+ChartModel* getChartModel(const css::uno::Reference<css::frame::XModel>& xModel)
+{
+ ChartModel* pModel = dynamic_cast<ChartModel*>(xModel.get());
+
+ return pModel;
+}
+
+bool isLegendVisible(const css::uno::Reference<css::frame::XModel>& xModel)
+{
+ ChartModel* pModel = getChartModel(xModel);
+ if (!pModel)
+ return false;
+
+ rtl::Reference< Legend > xLegendProp = LegendHelper::getLegend(*pModel);
+ if( xLegendProp.is())
+ {
+ try
+ {
+ bool bShow = false;
+ if( xLegendProp->getPropertyValue( "Show") >>= bShow )
+ {
+ return bShow;
+ }
+ }
+ catch(const uno::Exception &)
+ {
+ }
+ }
+
+ return false;
+}
+
+void setLegendVisible(const css::uno::Reference<css::frame::XModel>& xModel, bool bVisible)
+{
+ ChartModel* pModel = getChartModel(xModel);
+ if (!pModel)
+ return;
+
+ if (bVisible)
+ LegendHelper::showLegend(*pModel, comphelper::getProcessComponentContext());
+ else
+ LegendHelper::hideLegend(*pModel);
+}
+
+bool isLegendOverlay(const css::uno::Reference<css::frame::XModel>& xModel)
+{
+ ChartModel* pModel = getChartModel(xModel);
+ if (!pModel)
+ return false;
+
+ rtl::Reference< Legend > xLegendProp = LegendHelper::getLegend(*pModel);
+ if( xLegendProp.is())
+ {
+ try
+ {
+ bool bOverlay = false;
+ if(xLegendProp->getPropertyValue("Overlay") >>= bOverlay)
+ {
+ return bOverlay;
+ }
+ }
+ catch(const uno::Exception &)
+ {
+ }
+ }
+
+ return false;
+}
+
+void setLegendOverlay(const css::uno::Reference<css::frame::XModel>& xModel, bool bOverlay)
+{
+ ChartModel* pModel = getChartModel(xModel);
+ if (!pModel)
+ return;
+
+ rtl::Reference<Legend> xLegendProp = LegendHelper::getLegend(*pModel);
+ if (!xLegendProp.is())
+ return;
+
+ xLegendProp->setPropertyValue("Overlay", css::uno::Any(bOverlay));
+}
+
+bool isTitleVisible(const rtl::Reference<::chart::ChartModel>& xModel, TitleHelper::eTitleType eTitle)
+{
+ rtl::Reference<Title> xTitle = TitleHelper::getTitle(eTitle, xModel);
+ if (!xTitle.is())
+ return false;
+
+ css::uno::Any aAny = xTitle->getPropertyValue("Visible");
+ bool bVisible = aAny.get<bool>();
+ return bVisible;
+}
+
+bool isGridVisible(const rtl::Reference<::chart::ChartModel>& xModel, GridType eType)
+{
+ rtl::Reference< Diagram > xDiagram(xModel->getFirstChartDiagram());
+ if(xDiagram.is())
+ {
+ sal_Int32 nDimensionIndex = 0;
+ if (eType == GridType::HOR_MAJOR || eType == GridType::HOR_MINOR)
+ nDimensionIndex = 1;
+
+ bool bMajor = (eType == GridType::HOR_MAJOR || eType == GridType::VERT_MAJOR);
+
+ bool bHasGrid = AxisHelper::isGridShown(nDimensionIndex, 0, bMajor, xDiagram);
+ return bHasGrid;
+ }
+ return false;
+}
+
+void setGridVisible(const rtl::Reference<::chart::ChartModel>& xModel, GridType eType, bool bVisible)
+{
+ rtl::Reference< Diagram > xDiagram(xModel->getFirstChartDiagram());
+ if(!xDiagram.is())
+ return;
+
+ sal_Int32 nDimensionIndex = 0;
+ if (eType == GridType::HOR_MAJOR || eType == GridType::HOR_MINOR)
+ nDimensionIndex = 1;
+ sal_Int32 nCooSysIndex = 0;
+
+ bool bMajor = (eType == GridType::HOR_MAJOR || eType == GridType::VERT_MAJOR);
+
+ if (bVisible)
+ AxisHelper::showGrid(nDimensionIndex, nCooSysIndex, bMajor,
+ xDiagram);
+ else
+ AxisHelper::hideGrid(nDimensionIndex, nCooSysIndex, bMajor, xDiagram);
+}
+
+bool isAxisVisible(const rtl::Reference<::chart::ChartModel>& xModel, AxisType eType)
+{
+ rtl::Reference< Diagram > xDiagram(xModel->getFirstChartDiagram());
+ if(xDiagram.is())
+ {
+ sal_Int32 nDimensionIndex = 0;
+ if (eType == AxisType::Y_MAIN || eType == AxisType::Y_SECOND)
+ nDimensionIndex = 1;
+ else if (eType == AxisType::Z_MAIN)
+ nDimensionIndex = 2;
+
+ bool bMajor = (eType != AxisType::X_SECOND && eType != AxisType::Y_SECOND);
+
+ bool bHasAxis = AxisHelper::isAxisShown(nDimensionIndex, bMajor, xDiagram);
+ return bHasAxis;
+ }
+ return false;
+}
+
+void setAxisVisible(const rtl::Reference<::chart::ChartModel>& xModel, AxisType eType, bool bVisible)
+{
+ rtl::Reference< Diagram > xDiagram(xModel->getFirstChartDiagram());
+ if(!xDiagram.is())
+ return;
+
+ sal_Int32 nDimensionIndex = 0;
+ if (eType == AxisType::Y_MAIN || eType == AxisType::Y_SECOND)
+ nDimensionIndex = 1;
+ else if (eType == AxisType::Z_MAIN)
+ nDimensionIndex = 2;
+
+ bool bMajor = (eType != AxisType::X_SECOND && eType != AxisType::Y_SECOND);
+
+ if (bVisible)
+ AxisHelper::showAxis(nDimensionIndex, bMajor, xDiagram, comphelper::getProcessComponentContext());
+ else
+ AxisHelper::hideAxis(nDimensionIndex, bMajor, xDiagram);
+}
+
+sal_Int32 getLegendPos(const css::uno::Reference<css::frame::XModel>& xModel)
+{
+ ChartModel* pModel = getChartModel(xModel);
+ if (!pModel)
+ return -1;
+
+ rtl::Reference< Legend > xLegendProp = LegendHelper::getLegend(*pModel);
+ if (!xLegendProp.is())
+ return -1;
+
+ chart2::LegendPosition eLegendPos = chart2::LegendPosition_LINE_END;
+ xLegendProp->getPropertyValue("AnchorPosition") >>= eLegendPos;
+ switch(eLegendPos)
+ {
+ case chart2::LegendPosition_LINE_START:
+ return 3;
+ case chart2::LegendPosition_LINE_END:
+ return 0;
+ case chart2::LegendPosition_PAGE_START:
+ return 1;
+ case chart2::LegendPosition_PAGE_END:
+ return 2;
+ default:
+ return -1;
+ }
+}
+
+void setLegendPos(const css::uno::Reference<css::frame::XModel>& xModel, sal_Int32 nPos)
+{
+ ChartModel* pModel = getChartModel(xModel);
+ if (!pModel)
+ return;
+
+ rtl::Reference< Legend > xLegendProp = LegendHelper::getLegend(*pModel);
+ if (!xLegendProp.is())
+ return;
+
+ chart2::LegendPosition eLegendPos = chart2::LegendPosition_LINE_END;
+ css::chart::ChartLegendExpansion eExpansion = css::chart::ChartLegendExpansion_HIGH;
+ switch(nPos)
+ {
+ case 1:
+ eLegendPos = chart2::LegendPosition_PAGE_START;
+ eExpansion = css::chart::ChartLegendExpansion_WIDE;
+ break;
+ case 3:
+ eLegendPos = chart2::LegendPosition_LINE_START;
+ break;
+ case 0:
+ eLegendPos = chart2::LegendPosition_LINE_END;
+ break;
+ case 2:
+ eLegendPos = chart2::LegendPosition_PAGE_END;
+ eExpansion = css::chart::ChartLegendExpansion_WIDE;
+ break;
+ default:
+ assert(false);
+ }
+
+ xLegendProp->setPropertyValue("AnchorPosition", css::uno::Any(eLegendPos));
+ xLegendProp->setPropertyValue("Expansion", css::uno::Any(eExpansion));
+ xLegendProp->setPropertyValue("RelativePosition", uno::Any());
+}
+
+}
+
+ChartElementsPanel::ChartElementsPanel(
+ weld::Widget* pParent, ChartController* pController)
+ : PanelLayout(pParent, "ChartElementsPanel", "modules/schart/ui/sidebarelements.ui")
+ , mxCBTitle(m_xBuilder->weld_check_button("checkbutton_title"))
+ , mxEditTitle(m_xBuilder->weld_entry("edit_title"))
+ , mxCBSubtitle(m_xBuilder->weld_check_button("checkbutton_subtitle"))
+ , mxEditSubtitle(m_xBuilder->weld_entry("edit_subtitle"))
+ , mxCBXAxis(m_xBuilder->weld_check_button("checkbutton_x_axis"))
+ , mxCBXAxisTitle(m_xBuilder->weld_check_button("checkbutton_x_axis_title"))
+ , mxCBYAxis(m_xBuilder->weld_check_button("checkbutton_y_axis"))
+ , mxCBYAxisTitle(m_xBuilder->weld_check_button("checkbutton_y_axis_title"))
+ , mxCBZAxis(m_xBuilder->weld_check_button("checkbutton_z_axis"))
+ , mxCBZAxisTitle(m_xBuilder->weld_check_button("checkbutton_z_axis_title"))
+ , mxCB2ndXAxis(m_xBuilder->weld_check_button("checkbutton_2nd_x_axis"))
+ , mxCB2ndXAxisTitle(m_xBuilder->weld_check_button("checkbutton_2nd_x_axis_title"))
+ , mxCB2ndYAxis(m_xBuilder->weld_check_button("checkbutton_2nd_y_axis"))
+ , mxCB2ndYAxisTitle(m_xBuilder->weld_check_button("checkbutton_2nd_y_axis_title"))
+ , mxCBLegend(m_xBuilder->weld_check_button("checkbutton_legend"))
+ , mxCBLegendNoOverlay(m_xBuilder->weld_check_button("checkbutton_no_overlay"))
+ , mxCBGridVerticalMajor(m_xBuilder->weld_check_button("checkbutton_gridline_vertical_major"))
+ , mxCBGridHorizontalMajor(m_xBuilder->weld_check_button("checkbutton_gridline_horizontal_major"))
+ , mxCBGridVerticalMinor(m_xBuilder->weld_check_button("checkbutton_gridline_vertical_minor"))
+ , mxCBGridHorizontalMinor(m_xBuilder->weld_check_button("checkbutton_gridline_horizontal_minor"))
+ , mxTextTitle(m_xBuilder->weld_label("text_title"))
+ , mxTextSubTitle(m_xBuilder->weld_label("text_subtitle"))
+ , mxLBAxis(m_xBuilder->weld_label("label_axes"))
+ , mxLBGrid(m_xBuilder->weld_label("label_gri"))
+ , mxLBLegendPosition(m_xBuilder->weld_combo_box("comboboxtext_legend"))
+ , mxBoxLegend(m_xBuilder->weld_widget("box_legend"))
+ , mxModel(pController->getChartModel())
+ , mxListener(new ChartSidebarModifyListener(this))
+ , mbModelValid(true)
+{
+ maTextTitle = mxTextTitle->get_label();
+ maTextSubTitle = mxTextSubTitle->get_label();
+
+ Initialize();
+}
+
+ChartElementsPanel::~ChartElementsPanel()
+{
+ doUpdateModel(nullptr);
+
+ mxCBTitle.reset();
+ mxEditTitle.reset();
+ mxCBSubtitle.reset();
+ mxEditSubtitle.reset();
+ mxCBXAxis.reset();
+ mxCBXAxisTitle.reset();
+ mxCBYAxis.reset();
+ mxCBYAxisTitle.reset();
+ mxCBZAxis.reset();
+ mxCBZAxisTitle.reset();
+ mxCB2ndXAxis.reset();
+ mxCB2ndXAxisTitle.reset();
+ mxCB2ndYAxis.reset();
+ mxCB2ndYAxisTitle.reset();
+ mxCBLegend.reset();
+ mxCBLegendNoOverlay.reset();
+ mxCBGridVerticalMajor.reset();
+ mxCBGridHorizontalMajor.reset();
+ mxCBGridVerticalMinor.reset();
+ mxCBGridHorizontalMinor.reset();
+
+ mxLBLegendPosition.reset();
+ mxBoxLegend.reset();
+
+ mxLBAxis.reset();
+ mxLBGrid.reset();
+
+ mxTextTitle.reset();
+ mxTextSubTitle.reset();
+}
+
+void ChartElementsPanel::Initialize()
+{
+ mxModel->addModifyListener(mxListener);
+ updateData();
+
+ Link<weld::Toggleable&,void> aLink = LINK(this, ChartElementsPanel, CheckBoxHdl);
+ mxCBTitle->connect_toggled(aLink);
+ mxCBSubtitle->connect_toggled(aLink);
+ mxCBXAxis->connect_toggled(aLink);
+ mxCBXAxisTitle->connect_toggled(aLink);
+ mxCBYAxis->connect_toggled(aLink);
+ mxCBYAxisTitle->connect_toggled(aLink);
+ mxCBZAxis->connect_toggled(aLink);
+ mxCBZAxisTitle->connect_toggled(aLink);
+ mxCB2ndXAxis->connect_toggled(aLink);
+ mxCB2ndXAxisTitle->connect_toggled(aLink);
+ mxCB2ndYAxis->connect_toggled(aLink);
+ mxCB2ndYAxisTitle->connect_toggled(aLink);
+ mxCBLegend->connect_toggled(aLink);
+ mxCBLegendNoOverlay->connect_toggled(aLink);
+ mxCBGridVerticalMajor->connect_toggled(aLink);
+ mxCBGridHorizontalMajor->connect_toggled(aLink);
+ mxCBGridVerticalMinor->connect_toggled(aLink);
+ mxCBGridHorizontalMinor->connect_toggled(aLink);
+
+ mxLBLegendPosition->connect_changed(LINK(this, ChartElementsPanel, LegendPosHdl));
+
+ Link<weld::Entry&, void> aEditLink = LINK(this, ChartElementsPanel, EditHdl);
+ mxEditTitle->connect_changed(aEditLink);
+ mxEditSubtitle->connect_changed(aEditLink);
+}
+
+namespace {
+
+rtl::Reference<ChartType> getChartType(const rtl::Reference<ChartModel>& xModel)
+{
+ rtl::Reference<Diagram > xDiagram = xModel->getFirstChartDiagram();
+ if (!xDiagram.is())
+ return nullptr;
+
+ const std::vector<rtl::Reference<BaseCoordinateSystem>> & xCooSysSequence(xDiagram->getBaseCoordinateSystems());
+
+ if (xCooSysSequence.empty())
+ return nullptr;
+
+ const std::vector<rtl::Reference<ChartType>> & xChartTypeSequence(xCooSysSequence[0]->getChartTypes2());
+
+ if (xChartTypeSequence.empty())
+ return nullptr;
+
+ return xChartTypeSequence[0];
+}
+
+}
+
+void ChartElementsPanel::updateData()
+{
+ if (!mbModelValid)
+ return;
+
+ rtl::Reference< Diagram > xDiagram(mxModel->getFirstChartDiagram());
+ sal_Int32 nDimension = 0;
+ if (xDiagram)
+ nDimension = xDiagram->getDimension();
+ SolarMutexGuard aGuard;
+
+ mxCBLegend->set_active(isLegendVisible(mxModel));
+ mxCBLegendNoOverlay->set_sensitive(isLegendVisible(mxModel));
+ mxCBLegendNoOverlay->set_active(!isLegendOverlay(mxModel));
+ mxBoxLegend->set_sensitive(isLegendVisible(mxModel));
+
+ bool hasTitle = isTitleVisible(mxModel, TitleHelper::MAIN_TITLE);
+ mxCBTitle->set_active(hasTitle);
+
+ OUString title = mxEditTitle->get_text();
+ OUString newTitle = TitleHelper::getCompleteString(TitleHelper::getTitle(TitleHelper::MAIN_TITLE, mxModel));
+ if (title != newTitle)
+ mxEditTitle->set_text(newTitle);
+ if (mxEditTitle->get_sensitive() != hasTitle)
+ mxEditTitle->set_sensitive(hasTitle);
+
+ bool hasSubtitle = isTitleVisible(mxModel, TitleHelper::SUB_TITLE);
+ mxCBSubtitle->set_active(hasSubtitle);
+
+ OUString subtitle = mxEditSubtitle->get_text();
+ OUString newSubtitle = TitleHelper::getCompleteString(TitleHelper::getTitle(TitleHelper::SUB_TITLE, mxModel));
+ if (subtitle != newSubtitle)
+ mxEditSubtitle->set_text(newSubtitle);
+ if (mxEditSubtitle->get_sensitive() != hasSubtitle)
+ mxEditSubtitle->set_sensitive(hasSubtitle);
+
+ mxCBXAxisTitle->set_active(isTitleVisible(mxModel, TitleHelper::X_AXIS_TITLE));
+ mxCBYAxisTitle->set_active(isTitleVisible(mxModel, TitleHelper::Y_AXIS_TITLE));
+ mxCBZAxisTitle->set_active(isTitleVisible(mxModel, TitleHelper::Z_AXIS_TITLE));
+ mxCB2ndXAxisTitle->set_active(isTitleVisible(mxModel, TitleHelper::SECONDARY_X_AXIS_TITLE));
+ mxCB2ndYAxisTitle->set_active(isTitleVisible(mxModel, TitleHelper::SECONDARY_Y_AXIS_TITLE));
+ mxCBGridVerticalMajor->set_active(isGridVisible(mxModel, GridType::VERT_MAJOR));
+ mxCBGridHorizontalMajor->set_active(isGridVisible(mxModel, GridType::HOR_MAJOR));
+ mxCBGridVerticalMinor->set_active(isGridVisible(mxModel, GridType::VERT_MINOR));
+ mxCBGridHorizontalMinor->set_active(isGridVisible(mxModel, GridType::HOR_MINOR));
+ mxCBXAxis->set_active(isAxisVisible(mxModel, AxisType::X_MAIN));
+ mxCBYAxis->set_active(isAxisVisible(mxModel, AxisType::Y_MAIN));
+ mxCBZAxis->set_active(isAxisVisible(mxModel, AxisType::Z_MAIN));
+ mxCB2ndXAxis->set_active(isAxisVisible(mxModel, AxisType::X_SECOND));
+ mxCB2ndYAxis->set_active(isAxisVisible(mxModel, AxisType::Y_SECOND));
+
+ bool bSupportsMainAxis = ChartTypeHelper::isSupportingMainAxis(
+ getChartType(mxModel), 0, 0);
+ if (bSupportsMainAxis)
+ {
+ mxCBXAxis->show();
+ mxCBYAxis->show();
+ mxCBZAxis->show();
+ mxCBXAxisTitle->show();
+ mxCBYAxisTitle->show();
+ mxCBZAxisTitle->show();
+ mxCBGridVerticalMajor->show();
+ mxCBGridVerticalMinor->show();
+ mxCBGridHorizontalMajor->show();
+ mxCBGridHorizontalMinor->show();
+ mxLBAxis->show();
+ mxLBGrid->show();
+ }
+ else
+ {
+ mxCBXAxis->hide();
+ mxCBYAxis->hide();
+ mxCBZAxis->hide();
+ mxCBXAxisTitle->hide();
+ mxCBYAxisTitle->hide();
+ mxCBZAxisTitle->hide();
+ mxCBGridVerticalMajor->hide();
+ mxCBGridVerticalMinor->hide();
+ mxCBGridHorizontalMajor->hide();
+ mxCBGridHorizontalMinor->hide();
+ mxLBAxis->hide();
+ mxLBGrid->hide();
+ }
+
+ if (nDimension == 3)
+ {
+ mxCBZAxis->set_sensitive(true);
+ mxCBZAxisTitle->set_sensitive(true);
+ }
+ else
+ {
+ mxCBZAxis->set_sensitive(false);
+ mxCBZAxisTitle->set_sensitive(false);
+ }
+
+ mxLBLegendPosition->set_active(getLegendPos(mxModel));
+}
+
+std::unique_ptr<PanelLayout> ChartElementsPanel::Create (
+ weld::Widget* pParent,
+ ChartController* pController)
+{
+ if (pParent == nullptr)
+ throw lang::IllegalArgumentException("no parent Window given to ChartElementsPanel::Create", nullptr, 0);
+ return std::make_unique<ChartElementsPanel>(pParent, pController);
+}
+
+void ChartElementsPanel::DataChanged(const DataChangedEvent& rEvent)
+{
+ PanelLayout::DataChanged(rEvent);
+ updateData();
+}
+
+void ChartElementsPanel::HandleContextChange(
+ const vcl::EnumContext& rContext)
+{
+ if(maContext == rContext)
+ {
+ // Nothing to do.
+ return;
+ }
+
+ maContext = rContext;
+ updateData();
+}
+
+void ChartElementsPanel::modelInvalid()
+{
+ mbModelValid = false;
+}
+
+void ChartElementsPanel::doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ if (mbModelValid)
+ {
+ mxModel->removeModifyListener(mxListener);
+ }
+
+ mxModel = xModel;
+ mbModelValid = mxModel.is();
+
+ if (!mbModelValid)
+ return;
+
+ mxModel->addModifyListener(mxListener);
+}
+
+void ChartElementsPanel::updateModel(css::uno::Reference<css::frame::XModel> xModel)
+{
+ ::chart::ChartModel* pModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
+ assert(!xModel || pModel);
+ doUpdateModel(pModel);
+}
+
+IMPL_LINK(ChartElementsPanel, CheckBoxHdl, weld::Toggleable&, rCheckBox, void)
+{
+ bool bChecked = rCheckBox.get_active();
+ if (&rCheckBox == mxCBTitle.get())
+ setTitleVisible(TitleHelper::MAIN_TITLE, bChecked);
+ else if (&rCheckBox == mxCBSubtitle.get())
+ setTitleVisible(TitleHelper::SUB_TITLE, bChecked);
+ else if (&rCheckBox == mxCBXAxis.get())
+ setAxisVisible(mxModel, AxisType::X_MAIN, bChecked);
+ else if (&rCheckBox == mxCBXAxisTitle.get())
+ setTitleVisible(TitleHelper::X_AXIS_TITLE, bChecked);
+ else if (&rCheckBox == mxCBYAxis.get())
+ setAxisVisible(mxModel, AxisType::Y_MAIN, bChecked);
+ else if (&rCheckBox == mxCBYAxisTitle.get())
+ setTitleVisible(TitleHelper::Y_AXIS_TITLE, bChecked);
+ else if (&rCheckBox == mxCBZAxis.get())
+ setAxisVisible(mxModel, AxisType::Z_MAIN, bChecked);
+ else if (&rCheckBox == mxCBZAxisTitle.get())
+ setTitleVisible(TitleHelper::Z_AXIS_TITLE, bChecked);
+ else if (&rCheckBox == mxCB2ndXAxis.get())
+ setAxisVisible(mxModel, AxisType::X_SECOND, bChecked);
+ else if (&rCheckBox == mxCB2ndXAxisTitle.get())
+ setTitleVisible(TitleHelper::SECONDARY_X_AXIS_TITLE, bChecked);
+ else if (&rCheckBox == mxCB2ndYAxis.get())
+ setAxisVisible(mxModel, AxisType::Y_SECOND, bChecked);
+ else if (&rCheckBox == mxCB2ndYAxisTitle.get())
+ setTitleVisible(TitleHelper::SECONDARY_Y_AXIS_TITLE, bChecked);
+ else if (&rCheckBox == mxCBLegend.get())
+ {
+ mxBoxLegend->set_sensitive(bChecked);
+ mxCBLegendNoOverlay->set_sensitive(bChecked);
+ setLegendVisible(mxModel, bChecked);
+ }
+ else if (&rCheckBox == mxCBLegendNoOverlay.get())
+ setLegendOverlay(mxModel, !bChecked);
+ else if (&rCheckBox == mxCBGridVerticalMajor.get())
+ setGridVisible(mxModel, GridType::VERT_MAJOR, bChecked);
+ else if (&rCheckBox == mxCBGridHorizontalMajor.get())
+ setGridVisible(mxModel, GridType::HOR_MAJOR, bChecked);
+ else if (&rCheckBox == mxCBGridVerticalMinor.get())
+ setGridVisible(mxModel, GridType::VERT_MINOR, bChecked);
+ else if (&rCheckBox == mxCBGridHorizontalMinor.get())
+ setGridVisible(mxModel, GridType::HOR_MINOR, bChecked);
+
+ updateData();
+}
+
+IMPL_LINK(ChartElementsPanel, EditHdl, weld::Entry&, rEdit, void)
+{
+ // title or subtitle?
+ TitleHelper::eTitleType aTitleType = TitleHelper::MAIN_TITLE;
+ if (&rEdit == mxEditSubtitle.get())
+ aTitleType = TitleHelper::SUB_TITLE;
+
+ // set it
+ OUString aText(rEdit.get_text());
+ TitleHelper::setCompleteString(aText, TitleHelper::getTitle(aTitleType, mxModel), comphelper::getProcessComponentContext());
+}
+
+IMPL_LINK_NOARG(ChartElementsPanel, LegendPosHdl, weld::ComboBox&, void)
+{
+ sal_Int32 nPos = mxLBLegendPosition->get_active();
+ setLegendPos(mxModel, nPos);
+}
+
+void ChartElementsPanel::setTitleVisible(TitleHelper::eTitleType eTitle, bool bVisible)
+{
+ if (bVisible)
+ {
+ OUString aText = eTitle == TitleHelper::SUB_TITLE ? maTextSubTitle : maTextTitle;
+ TitleHelper::createOrShowTitle(eTitle, aText, mxModel, comphelper::getProcessComponentContext());
+ }
+ else
+ {
+ TitleHelper::hideTitle(eTitle, mxModel);
+ }
+}
+
+} // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartElementsPanel.hxx b/chart2/source/controller/sidebar/ChartElementsPanel.hxx
new file mode 100644
index 0000000000..2e0dee28b6
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartElementsPanel.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/sidebar/IContextChangeReceiver.hxx>
+#include <sfx2/sidebar/SidebarModelUpdate.hxx>
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <vcl/EnumContext.hxx>
+#include "ChartSidebarModifyListener.hxx"
+#include <TitleHelper.hxx>
+
+namespace com::sun::star::util { class XModifyListener; }
+
+namespace chart {
+
+class ChartController;
+
+namespace sidebar {
+
+class ChartElementsPanel : public PanelLayout,
+ public ::sfx2::sidebar::IContextChangeReceiver,
+ public sfx2::sidebar::SidebarModelUpdate,
+ public ChartSidebarModifyListenerParent
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ ChartController* pController);
+
+ virtual void DataChanged(
+ const DataChangedEvent& rEvent) override;
+
+ virtual void HandleContextChange(
+ const vcl::EnumContext& rContext) override;
+
+ // constructor/destructor
+ ChartElementsPanel(
+ weld::Widget* pParent,
+ ChartController* pController);
+
+ virtual ~ChartElementsPanel() override;
+
+ virtual void updateData() override;
+ virtual void modelInvalid() override;
+
+ virtual void updateModel(css::uno::Reference<css::frame::XModel> xModel) override;
+
+private:
+ //ui controls
+ std::unique_ptr<weld::CheckButton> mxCBTitle;
+ std::unique_ptr<weld::Entry> mxEditTitle;
+ std::unique_ptr<weld::CheckButton> mxCBSubtitle;
+ std::unique_ptr<weld::Entry> mxEditSubtitle;
+ std::unique_ptr<weld::CheckButton> mxCBXAxis;
+ std::unique_ptr<weld::CheckButton> mxCBXAxisTitle;
+ std::unique_ptr<weld::CheckButton> mxCBYAxis;
+ std::unique_ptr<weld::CheckButton> mxCBYAxisTitle;
+ std::unique_ptr<weld::CheckButton> mxCBZAxis;
+ std::unique_ptr<weld::CheckButton> mxCBZAxisTitle;
+ std::unique_ptr<weld::CheckButton> mxCB2ndXAxis;
+ std::unique_ptr<weld::CheckButton> mxCB2ndXAxisTitle;
+ std::unique_ptr<weld::CheckButton> mxCB2ndYAxis;
+ std::unique_ptr<weld::CheckButton> mxCB2ndYAxisTitle;
+ std::unique_ptr<weld::CheckButton> mxCBLegend;
+ std::unique_ptr<weld::CheckButton> mxCBLegendNoOverlay;
+ std::unique_ptr<weld::CheckButton> mxCBGridVerticalMajor;
+ std::unique_ptr<weld::CheckButton> mxCBGridHorizontalMajor;
+ std::unique_ptr<weld::CheckButton> mxCBGridVerticalMinor;
+ std::unique_ptr<weld::CheckButton> mxCBGridHorizontalMinor;
+ std::unique_ptr<weld::Label> mxTextTitle;
+ std::unique_ptr<weld::Label> mxTextSubTitle;
+ std::unique_ptr<weld::Label> mxLBAxis;
+ std::unique_ptr<weld::Label> mxLBGrid;
+
+ std::unique_ptr<weld::ComboBox> mxLBLegendPosition;
+ std::unique_ptr<weld::Widget> mxBoxLegend;
+
+ vcl::EnumContext maContext;
+
+ rtl::Reference<::chart::ChartModel> mxModel;
+ css::uno::Reference<css::util::XModifyListener> mxListener;
+
+ bool mbModelValid;
+
+ OUString maTextTitle;
+ OUString maTextSubTitle;
+
+ void Initialize();
+ void doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel);
+
+ void setTitleVisible(TitleHelper::eTitleType eTitle, bool bVisible);
+
+ DECL_LINK(CheckBoxHdl, weld::Toggleable&, void);
+ DECL_LINK(EditHdl, weld::Entry&, void);
+ DECL_LINK(LegendPosHdl, weld::ComboBox&, void);
+};
+
+} } // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartErrorBarPanel.cxx b/chart2/source/controller/sidebar/ChartErrorBarPanel.cxx
new file mode 100644
index 0000000000..c9430791b3
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartErrorBarPanel.cxx
@@ -0,0 +1,425 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include "ChartErrorBarPanel.hxx"
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+#include <vcl/svapp.hxx>
+#include <sal/log.hxx>
+
+
+using namespace css;
+using namespace css::uno;
+
+namespace chart::sidebar {
+
+namespace {
+
+enum class ErrorBarDirection
+{
+ POSITIVE,
+ NEGATIVE
+};
+
+css::uno::Reference<css::beans::XPropertySet> getErrorBarPropSet(
+ const rtl::Reference<::chart::ChartModel>& xModel, std::u16string_view rCID)
+{
+ return ObjectIdentifier::getObjectPropertySet(rCID, xModel);
+}
+
+bool showPositiveError(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return false;
+
+ css::uno::Any aAny = xPropSet->getPropertyValue("ShowPositiveError");
+
+ if (!aAny.hasValue())
+ return false;
+
+ bool bShow = false;
+ aAny >>= bShow;
+ return bShow;
+}
+
+bool showNegativeError(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return false;
+
+ css::uno::Any aAny = xPropSet->getPropertyValue("ShowNegativeError");
+
+ if (!aAny.hasValue())
+ return false;
+
+ bool bShow = false;
+ aAny >>= bShow;
+ return bShow;
+}
+
+void setShowPositiveError(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, bool bShow)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return;
+
+ xPropSet->setPropertyValue("ShowPositiveError", css::uno::Any(bShow));
+}
+
+void setShowNegativeError(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, bool bShow)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return;
+
+ xPropSet->setPropertyValue("ShowNegativeError", css::uno::Any(bShow));
+}
+
+struct ErrorBarTypeMap
+{
+ sal_Int32 nPos;
+ sal_Int32 nApi;
+};
+
+ErrorBarTypeMap const aErrorBarType[] = {
+ { 0, css::chart::ErrorBarStyle::ABSOLUTE },
+ { 1, css::chart::ErrorBarStyle::RELATIVE },
+ { 2, css::chart::ErrorBarStyle::FROM_DATA },
+ { 3, css::chart::ErrorBarStyle::STANDARD_DEVIATION },
+ { 4, css::chart::ErrorBarStyle::STANDARD_ERROR },
+ { 5, css::chart::ErrorBarStyle::VARIANCE},
+ { 6, css::chart::ErrorBarStyle::ERROR_MARGIN },
+};
+
+sal_Int32 getTypePos(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return 0;
+
+ css::uno::Any aAny = xPropSet->getPropertyValue("ErrorBarStyle");
+
+ if (!aAny.hasValue())
+ return 0;
+
+ sal_Int32 nApi = 0;
+ aAny >>= nApi;
+
+ for (ErrorBarTypeMap const & i : aErrorBarType)
+ {
+ if (i.nApi == nApi)
+ return i.nPos;
+ }
+
+ return 0;
+}
+
+void setTypePos(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, sal_Int32 nPos)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return;
+
+ sal_Int32 nApi = 0;
+ for (ErrorBarTypeMap const & i : aErrorBarType)
+ {
+ if (i.nPos == nPos)
+ nApi = i.nApi;
+ }
+
+ xPropSet->setPropertyValue("ErrorBarStyle", css::uno::Any(nApi));
+}
+
+double getValue(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, ErrorBarDirection eDir)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return 0;
+
+ OUString aName = "PositiveError";
+ if (eDir == ErrorBarDirection::NEGATIVE)
+ aName = "NegativeError";
+
+ css::uno::Any aAny = xPropSet->getPropertyValue(aName);
+
+ if (!aAny.hasValue())
+ return 0;
+
+ double nVal = 0;
+ aAny >>= nVal;
+
+ return nVal;
+}
+
+void setValue(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, double nVal, ErrorBarDirection eDir)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return;
+
+ OUString aName = "PositiveError";
+ if (eDir == ErrorBarDirection::NEGATIVE)
+ aName = "NegativeError";
+
+ xPropSet->setPropertyValue(aName, css::uno::Any(nVal));
+}
+
+OUString getCID(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ css::uno::Reference<css::frame::XController> xController(xModel->getCurrentController());
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(xController, css::uno::UNO_QUERY);
+ if (!xSelectionSupplier.is())
+ return OUString();
+
+ uno::Any aAny = xSelectionSupplier->getSelection();
+ assert(aAny.hasValue());
+ OUString aCID;
+ aAny >>= aCID;
+#if defined DBG_UTIL && !defined NDEBUG
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType != OBJECTTYPE_DATA_ERRORS_X &&
+ eType != OBJECTTYPE_DATA_ERRORS_Y &&
+ eType != OBJECTTYPE_DATA_ERRORS_Z)
+ SAL_WARN("chart2","Selected item is not an error bar");
+
+#endif
+
+ return aCID;
+}
+
+}
+
+ChartErrorBarPanel::ChartErrorBarPanel(weld::Widget* pParent, ChartController* pController)
+ : PanelLayout(pParent, "ChartErrorBarPanel", "modules/schart/ui/sidebarerrorbar.ui")
+ , mxRBPosAndNeg(m_xBuilder->weld_radio_button("radiobutton_positive_negative"))
+ , mxRBPos(m_xBuilder->weld_radio_button("radiobutton_positive"))
+ , mxRBNeg(m_xBuilder->weld_radio_button("radiobutton_negative"))
+ , mxLBType(m_xBuilder->weld_combo_box("comboboxtext_type"))
+ , mxMFPos(m_xBuilder->weld_spin_button("spinbutton_pos"))
+ , mxMFNeg(m_xBuilder->weld_spin_button("spinbutton_neg"))
+ , mxModel(pController->getChartModel())
+ , mxListener(new ChartSidebarModifyListener(this))
+ , mbModelValid(true)
+{
+ Initialize();
+}
+
+ChartErrorBarPanel::~ChartErrorBarPanel()
+{
+ doUpdateModel(nullptr);
+
+ mxRBPosAndNeg.reset();
+ mxRBPos.reset();
+ mxRBNeg.reset();
+
+ mxLBType.reset();
+
+ mxMFPos.reset();
+ mxMFNeg.reset();
+}
+
+void ChartErrorBarPanel::Initialize()
+{
+ mxModel->addModifyListener(mxListener);
+ mxRBNeg->set_active(false);
+ mxRBPos->set_active(false);
+ mxRBPosAndNeg->set_active(false);
+
+ updateData();
+
+ Link<weld::Toggleable&,void> aLink = LINK(this, ChartErrorBarPanel, RadioBtnHdl);
+ mxRBPosAndNeg->connect_toggled(aLink);
+ mxRBPos->connect_toggled(aLink);
+ mxRBNeg->connect_toggled(aLink);
+
+ mxLBType->connect_changed(LINK(this, ChartErrorBarPanel, ListBoxHdl));
+
+ Link<weld::SpinButton&,void> aLink2 = LINK(this, ChartErrorBarPanel, NumericFieldHdl);
+ mxMFPos->connect_value_changed(aLink2);
+ mxMFNeg->connect_value_changed(aLink2);
+}
+
+void ChartErrorBarPanel::updateData()
+{
+ if (!mbModelValid)
+ return;
+
+ OUString aCID = getCID(mxModel);
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType != OBJECTTYPE_DATA_ERRORS_X &&
+ eType != OBJECTTYPE_DATA_ERRORS_Y &&
+ eType != OBJECTTYPE_DATA_ERRORS_Z)
+ return;
+
+ bool bPos = showPositiveError(mxModel, aCID);
+ bool bNeg = showNegativeError(mxModel, aCID);
+
+ SolarMutexGuard aGuard;
+
+ if (bPos && bNeg)
+ mxRBPosAndNeg->set_active(true);
+ else if (bPos)
+ mxRBPos->set_active(true);
+ else if (bNeg)
+ mxRBNeg->set_active(true);
+
+ sal_Int32 nTypePos = getTypePos(mxModel, aCID);
+ mxLBType->set_active(nTypePos);
+
+ if (nTypePos <= 1)
+ {
+ if (bPos)
+ mxMFPos->set_sensitive(true);
+ else
+ mxMFPos->set_sensitive(false);
+
+ if (bNeg)
+ mxMFNeg->set_sensitive(true);
+ else
+ mxMFNeg->set_sensitive(false);
+
+ double nValPos = getValue(mxModel, aCID, ErrorBarDirection::POSITIVE);
+ double nValNeg = getValue(mxModel, aCID, ErrorBarDirection::NEGATIVE);
+
+ mxMFPos->set_value(nValPos);
+ mxMFNeg->set_value(nValNeg);
+ }
+ else
+ {
+ mxMFPos->set_sensitive(false);
+ mxMFNeg->set_sensitive(false);
+ }
+}
+
+std::unique_ptr<PanelLayout> ChartErrorBarPanel::Create (
+ weld::Widget* pParent,
+ ChartController* pController)
+{
+ if (pParent == nullptr)
+ throw lang::IllegalArgumentException("no parent Window given to ChartErrorBarPanel::Create", nullptr, 0);
+ return std::make_unique<ChartErrorBarPanel>(pParent, pController);
+}
+
+void ChartErrorBarPanel::DataChanged(const DataChangedEvent& rEvent)
+{
+ PanelLayout::DataChanged(rEvent);
+ updateData();
+}
+
+void ChartErrorBarPanel::HandleContextChange(
+ const vcl::EnumContext& )
+{
+ updateData();
+}
+
+void ChartErrorBarPanel::NotifyItemUpdate(
+ sal_uInt16 /*nSID*/,
+ SfxItemState /*eState*/,
+ const SfxPoolItem* /*pState*/ )
+{
+}
+
+void ChartErrorBarPanel::modelInvalid()
+{
+ mbModelValid = false;
+}
+
+void ChartErrorBarPanel::doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ if (mbModelValid)
+ {
+ mxModel->removeModifyListener(mxListener);
+ }
+
+ mxModel = xModel;
+ mbModelValid = mxModel.is();
+
+ if (!mbModelValid)
+ return;
+
+ mxModel->addModifyListener(mxListener);
+}
+
+void ChartErrorBarPanel::updateModel(css::uno::Reference<css::frame::XModel> xModel)
+{
+ ::chart::ChartModel* pModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
+ assert(!xModel || pModel);
+ doUpdateModel(pModel);
+}
+
+IMPL_LINK_NOARG(ChartErrorBarPanel, RadioBtnHdl, weld::Toggleable&, void)
+{
+ OUString aCID = getCID(mxModel);
+ bool bPos = mxRBPosAndNeg->get_active() || mxRBPos->get_active();
+ bool bNeg = mxRBPosAndNeg->get_active() || mxRBNeg->get_active();
+
+ setShowPositiveError(mxModel, aCID, bPos);
+ setShowNegativeError(mxModel, aCID, bNeg);
+}
+
+IMPL_LINK_NOARG(ChartErrorBarPanel, ListBoxHdl, weld::ComboBox&, void)
+{
+ OUString aCID = getCID(mxModel);
+ sal_Int32 nPos = mxLBType->get_active();
+
+ setTypePos(mxModel, aCID, nPos);
+}
+
+IMPL_LINK(ChartErrorBarPanel, NumericFieldHdl, weld::SpinButton&, rMetricField, void)
+{
+ OUString aCID = getCID(mxModel);
+ double nVal = rMetricField.get_value();
+ if (&rMetricField == mxMFPos.get())
+ setValue(mxModel, aCID, nVal, ErrorBarDirection::POSITIVE);
+ else if (&rMetricField == mxMFNeg.get())
+ setValue(mxModel, aCID, nVal, ErrorBarDirection::NEGATIVE);
+}
+
+} // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartErrorBarPanel.hxx b/chart2/source/controller/sidebar/ChartErrorBarPanel.hxx
new file mode 100644
index 0000000000..92f7afb0ad
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartErrorBarPanel.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <sfx2/sidebar/IContextChangeReceiver.hxx>
+#include <sfx2/sidebar/SidebarModelUpdate.hxx>
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include "ChartSidebarModifyListener.hxx"
+
+namespace com::sun::star::util { class XModifyListener; }
+
+namespace chart {
+
+class ChartController;
+class ChartModel;
+
+namespace sidebar {
+
+class ChartErrorBarPanel : public PanelLayout,
+ public ::sfx2::sidebar::IContextChangeReceiver,
+ public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface,
+ public sfx2::sidebar::SidebarModelUpdate,
+ public ChartSidebarModifyListenerParent
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ ChartController* pController);
+
+ virtual void DataChanged(
+ const DataChangedEvent& rEvent) override;
+
+ virtual void HandleContextChange(
+ const vcl::EnumContext& rContext) override;
+
+ virtual void NotifyItemUpdate(
+ const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(
+ const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+ // constructor/destructor
+ ChartErrorBarPanel(
+ weld::Widget* pParent,
+ ChartController* pController);
+ virtual ~ChartErrorBarPanel() override;
+
+ virtual void updateData() override;
+ virtual void modelInvalid() override;
+
+ virtual void updateModel(css::uno::Reference<css::frame::XModel> xModel) override;
+
+private:
+ //ui controls
+ std::unique_ptr<weld::RadioButton> mxRBPosAndNeg;
+ std::unique_ptr<weld::RadioButton> mxRBPos;
+ std::unique_ptr<weld::RadioButton> mxRBNeg;
+
+ std::unique_ptr<weld::ComboBox> mxLBType;
+
+ std::unique_ptr<weld::SpinButton> mxMFPos;
+ std::unique_ptr<weld::SpinButton> mxMFNeg;
+
+ rtl::Reference<::chart::ChartModel> mxModel;
+ css::uno::Reference<css::util::XModifyListener> mxListener;
+
+ bool mbModelValid;
+
+ void Initialize();
+ void doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel);
+
+ DECL_LINK(RadioBtnHdl, weld::Toggleable&, void);
+ DECL_LINK(ListBoxHdl, weld::ComboBox&, void);
+ DECL_LINK(NumericFieldHdl, weld::SpinButton&, void);
+};
+
+} } // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartLinePanel.cxx b/chart2/source/controller/sidebar/ChartLinePanel.cxx
new file mode 100644
index 0000000000..453c573e51
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartLinePanel.cxx
@@ -0,0 +1,290 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ChartLinePanel.hxx"
+
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+
+#include <svx/xlnwtit.hxx>
+#include <svx/xlinjoit.hxx>
+#include <svx/xlntrit.hxx>
+
+#include <svx/linectrl.hxx>
+#include <svx/tbcontrl.hxx>
+#include <sfx2/weldutils.hxx>
+#include <vcl/svapp.hxx>
+
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/chart2/XDiagram.hpp>
+
+#include <comphelper/lok.hxx>
+#include <sfx2/viewsh.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+namespace chart::sidebar {
+
+namespace {
+
+SvxLineStyleToolBoxControl* getLineStyleToolBoxControl(const ToolbarUnoDispatcher& rToolBoxColor)
+{
+ css::uno::Reference<css::frame::XToolbarController> xController = rToolBoxColor.GetControllerForCommand(".uno:XLineStyle");
+ SvxLineStyleToolBoxControl* pToolBoxLineStyleControl = dynamic_cast<SvxLineStyleToolBoxControl*>(xController.get());
+ return pToolBoxLineStyleControl;
+}
+
+SvxColorToolBoxControl* getColorToolBoxControl(const ToolbarUnoDispatcher& rToolBoxLineStyle)
+{
+ css::uno::Reference<css::frame::XToolbarController> xController = rToolBoxLineStyle.GetControllerForCommand(".uno:XLineColor");
+ SvxColorToolBoxControl* pToolBoxColorControl = dynamic_cast<SvxColorToolBoxControl*>(xController.get());
+ return pToolBoxColorControl;
+}
+
+OUString getCID(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ css::uno::Reference<css::frame::XController> xController(xModel->getCurrentController());
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(xController, css::uno::UNO_QUERY);
+ if (!xSelectionSupplier.is())
+ return OUString();
+
+ css::uno::Any aAny = xSelectionSupplier->getSelection();
+ if (!aAny.hasValue())
+ return OUString();
+
+ OUString aCID;
+ aAny >>= aCID;
+
+ return aCID;
+}
+
+css::uno::Reference<css::beans::XPropertySet> getPropSet(
+ const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ OUString aCID = getCID(xModel);
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ ObjectIdentifier::getObjectPropertySet(aCID, xModel);
+
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType == OBJECTTYPE_DIAGRAM)
+ {
+ css::uno::Reference<css::chart2::XDiagram> xDiagram(
+ xPropSet, css::uno::UNO_QUERY);
+ if (!xDiagram.is())
+ return xPropSet;
+
+ xPropSet.set(xDiagram->getWall());
+ }
+
+ return xPropSet;
+}
+
+class PreventUpdate
+{
+public:
+ explicit PreventUpdate(bool& bUpdate):
+ mbUpdate(bUpdate)
+ {
+ mbUpdate = false;
+ }
+
+ ~PreventUpdate()
+ {
+ mbUpdate = true;
+ }
+
+private:
+ bool& mbUpdate;
+};
+
+}
+
+std::unique_ptr<PanelLayout> ChartLinePanel::Create(
+ weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ ChartController* pController)
+{
+ if (pParent == nullptr)
+ throw css::lang::IllegalArgumentException("no parent Window given to ChartAxisPanel::Create", nullptr, 0);
+ if (!rxFrame.is())
+ throw css::lang::IllegalArgumentException("no XFrame given to ChartAxisPanel::Create", nullptr, 1);
+
+ return std::make_unique<ChartLinePanel>(pParent, rxFrame, pController);
+}
+
+ChartLinePanel::ChartLinePanel(weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ ChartController* pController):
+ svx::sidebar::LinePropertyPanelBase(pParent, rxFrame),
+ mxModel(pController->getChartModel()),
+ mxListener(new ChartSidebarModifyListener(this)),
+ mxSelectionListener(new ChartSidebarSelectionListener(this)),
+ mbUpdate(true),
+ mbModelValid(true),
+ maLineColorWrapper(mxModel, getColorToolBoxControl(*mxColorDispatch), "LineColor"),
+ maLineStyleWrapper(mxModel, getLineStyleToolBoxControl(*mxLineStyleDispatch))
+{
+ disableArrowHead();
+ std::vector<ObjectType> aAcceptedTypes { OBJECTTYPE_PAGE, OBJECTTYPE_DIAGRAM,
+ OBJECTTYPE_DATA_SERIES, OBJECTTYPE_DATA_POINT,
+ OBJECTTYPE_TITLE, OBJECTTYPE_LEGEND, OBJECTTYPE_DATA_CURVE,
+ OBJECTTYPE_DATA_AVERAGE_LINE, OBJECTTYPE_AXIS};
+ mxSelectionListener->setAcceptedTypes(std::move(aAcceptedTypes));
+ Initialize();
+}
+
+ChartLinePanel::~ChartLinePanel()
+{
+ doUpdateModel(nullptr);
+}
+
+void ChartLinePanel::Initialize()
+{
+ mxModel->addModifyListener(mxListener);
+
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (xSelectionSupplier.is())
+ xSelectionSupplier->addSelectionChangeListener(mxSelectionListener);
+
+ SvxColorToolBoxControl* pToolBoxColor = getColorToolBoxControl(*mxColorDispatch);
+ pToolBoxColor->setColorSelectFunction(maLineColorWrapper);
+
+ SvxLineStyleToolBoxControl* pToolBoxLineStyle = getLineStyleToolBoxControl(*mxLineStyleDispatch);
+ pToolBoxLineStyle->setLineStyleSelectFunction(maLineStyleWrapper);
+
+ setMapUnit(MapUnit::Map100thMM);
+ updateData();
+}
+
+void ChartLinePanel::updateData()
+{
+ if (!mbUpdate || !mbModelValid)
+ return;
+
+ SolarMutexGuard aGuard;
+ css::uno::Reference<css::beans::XPropertySet> xPropSet = getPropSet(mxModel);
+ if (!xPropSet.is())
+ return;
+
+ sal_uInt16 nLineTransparence = 0;
+ xPropSet->getPropertyValue("LineTransparence") >>= nLineTransparence;
+ XLineTransparenceItem aLineTransparenceItem(nLineTransparence);
+ updateLineTransparence(false, true, &aLineTransparenceItem);
+
+ sal_uInt32 nWidth = 0;
+ xPropSet->getPropertyValue("LineWidth") >>= nWidth;
+ XLineWidthItem aWidthItem(nWidth);
+ updateLineWidth(false, true, &aWidthItem);
+
+ maLineStyleWrapper.updateData();
+ maLineColorWrapper.updateData();
+}
+
+void ChartLinePanel::modelInvalid()
+{
+ mbModelValid = false;
+}
+
+void ChartLinePanel::selectionChanged(bool bCorrectType)
+{
+ if (bCorrectType)
+ updateData();
+}
+
+void ChartLinePanel::doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ if (mbModelValid)
+ {
+ mxModel->removeModifyListener(mxListener);
+
+ css::uno::Reference<css::view::XSelectionSupplier> oldSelectionSupplier(
+ mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (oldSelectionSupplier.is()) {
+ oldSelectionSupplier->removeSelectionChangeListener(mxSelectionListener);
+ }
+ }
+
+ mxModel = xModel;
+ mbModelValid = mxModel.is();
+
+ if (!mbModelValid)
+ return;
+
+ maLineStyleWrapper.updateModel(mxModel);
+ maLineColorWrapper.updateModel(mxModel);
+
+ mxModel->addModifyListener(mxListener);
+
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (xSelectionSupplier.is())
+ xSelectionSupplier->addSelectionChangeListener(mxSelectionListener);
+}
+
+void ChartLinePanel::updateModel(css::uno::Reference<css::frame::XModel> xModel)
+{
+ ::chart::ChartModel* pModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
+ assert(!xModel || pModel);
+ doUpdateModel(pModel);
+}
+
+void ChartLinePanel::setLineJoint(const XLineJointItem* pItem)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getPropSet(mxModel);
+
+ if (!xPropSet.is())
+ return;
+
+ PreventUpdate aPreventUpdate(mbUpdate);
+ if (pItem)
+ xPropSet->setPropertyValue("LineJoint", css::uno::Any(pItem->GetValue()));
+}
+
+void ChartLinePanel::setLineCap(const XLineCapItem* /*pItem*/)
+{
+}
+
+void ChartLinePanel::setLineTransparency(const XLineTransparenceItem& rItem)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getPropSet(mxModel);
+
+ if (!xPropSet.is())
+ return;
+
+ PreventUpdate aPreventUpdate(mbUpdate);
+ xPropSet->setPropertyValue("LineTransparence", css::uno::Any(rItem.GetValue()));
+}
+
+void ChartLinePanel::setLineWidth(const XLineWidthItem& rItem)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getPropSet(mxModel);
+
+ if (!xPropSet.is())
+ return;
+
+ PreventUpdate aPreventUpdate(mbUpdate);
+ xPropSet->setPropertyValue("LineWidth", css::uno::Any(rItem.GetValue()));
+}
+
+void ChartLinePanel::updateLineWidth(bool bDisabled, bool bSetOrDefault, const SfxPoolItem* pItem)
+{
+ LinePropertyPanelBase::updateLineWidth(bDisabled, bSetOrDefault, pItem);
+
+ SfxViewShell* pViewShell = SfxViewShell::Current();
+ if (comphelper::LibreOfficeKit::isActive() && pViewShell)
+ {
+ pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED,
+ ".uno:LineWidth=" + OString::number(mnWidthCoreValue));
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartLinePanel.hxx b/chart2/source/controller/sidebar/ChartLinePanel.hxx
new file mode 100644
index 0000000000..002ca51cc1
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartLinePanel.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sfx2/sidebar/SidebarModelUpdate.hxx>
+#include <svx/sidebar/LinePropertyPanelBase.hxx>
+
+#include "ChartSidebarModifyListener.hxx"
+#include "ChartSidebarSelectionListener.hxx"
+#include "ChartColorWrapper.hxx"
+
+class XLineCapItem;
+class XLineDashItem;
+class XLineEndItem;
+class XLineJointItem;
+class XLineStartItem;
+class XLineStyleItem;
+class XLineTransparenceItem;
+class XLineWidthItem;
+
+namespace chart {
+
+class ChartController;
+
+namespace sidebar {
+
+class ChartLinePanel : public svx::sidebar::LinePropertyPanelBase,
+ public sfx2::sidebar::SidebarModelUpdate,
+ public ChartSidebarModifyListenerParent,
+ public ChartSidebarSelectionListenerParent
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ ChartController* pController);
+
+ // constructor/destructor
+ ChartLinePanel(
+ weld::Widget* pParent,
+ const css::uno::Reference<css::frame::XFrame>& rxFrame,
+ ChartController* pController);
+
+ virtual ~ChartLinePanel() override;
+
+ virtual void updateData() override;
+ virtual void modelInvalid() override;
+
+ virtual void selectionChanged(bool bCorrectType) override;
+
+ virtual void updateModel(css::uno::Reference<css::frame::XModel> xModel) override;
+
+ virtual void setLineWidth(const XLineWidthItem& rItem) override;
+
+protected:
+
+ virtual void setLineTransparency(const XLineTransparenceItem& rItem) override;
+ virtual void setLineJoint(const XLineJointItem* pItem) override;
+ virtual void setLineCap(const XLineCapItem* pItem) override;
+
+ virtual void updateLineWidth(bool bDisabled, bool bSetOrDefault, const SfxPoolItem* pItem) override;
+
+private:
+
+ rtl::Reference<::chart::ChartModel> mxModel;
+ css::uno::Reference<css::util::XModifyListener> mxListener;
+ rtl::Reference<ChartSidebarSelectionListener> mxSelectionListener;
+
+ void Initialize();
+ void doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel);
+
+ bool mbUpdate;
+ bool mbModelValid;
+ ChartColorWrapper maLineColorWrapper;
+ ChartLineStyleWrapper maLineStyleWrapper;
+};
+
+} } // end of namespace svx::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartSeriesPanel.cxx b/chart2/source/controller/sidebar/ChartSeriesPanel.cxx
new file mode 100644
index 0000000000..48eaa5a3f2
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartSeriesPanel.cxx
@@ -0,0 +1,474 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+
+#include <vcl/svapp.hxx>
+#include <sal/log.hxx>
+
+#include "ChartSeriesPanel.hxx"
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+#include <ChartType.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <StatisticsHelper.hxx>
+#include <BaseCoordinateSystem.hxx>
+
+#include <comphelper/processfactory.hxx>
+
+using namespace css;
+using namespace css::uno;
+
+namespace chart::sidebar {
+
+namespace {
+
+bool isDataLabelVisible(const rtl::Reference<::chart::ChartModel>& xModel, std::u16string_view rCID)
+{
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xSeries.is())
+ return false;
+
+ return DataSeriesHelper::hasDataLabelsAtSeries(xSeries);
+}
+
+void setDataLabelVisible(const rtl::Reference<::chart::ChartModel>& xModel, std::u16string_view rCID, bool bVisible)
+{
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xSeries.is())
+ return;
+
+ if (bVisible)
+ DataSeriesHelper::insertDataLabelsToSeriesAndAllPoints(xSeries);
+ else
+ DataSeriesHelper::deleteDataLabelsFromSeriesAndAllPoints(xSeries);
+}
+
+struct LabelPlacementMap
+{
+ sal_Int32 nPos;
+ sal_Int32 nApi;
+};
+
+LabelPlacementMap const aLabelPlacementMap[] = {
+ { 0, css::chart::DataLabelPlacement::TOP },
+ { 1, css::chart::DataLabelPlacement::BOTTOM },
+ { 2, css::chart::DataLabelPlacement::CENTER },
+ { 3, css::chart::DataLabelPlacement::OUTSIDE },
+ { 4, css::chart::DataLabelPlacement::INSIDE },
+ { 5, css::chart::DataLabelPlacement::NEAR_ORIGIN }
+};
+
+sal_Int32 getDataLabelPlacement(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID)
+{
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xSeries.is())
+ return 0;
+
+ css::uno::Any aAny = xSeries->getPropertyValue("LabelPlacement");
+ if (!aAny.hasValue())
+ return 0;
+
+ sal_Int32 nPlacement = 0;
+ aAny >>= nPlacement;
+
+ for (LabelPlacementMap const & i : aLabelPlacementMap)
+ {
+ if (i.nApi == nPlacement)
+ return i.nPos;
+ }
+
+ return 0;
+}
+
+void setDataLabelPlacement(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, sal_Int32 nPos)
+{
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xSeries.is())
+ return;
+
+ sal_Int32 nApi = 0;
+ for (LabelPlacementMap const & i : aLabelPlacementMap)
+ {
+ if (i.nPos == nPos)
+ {
+ nApi = i.nApi;
+ break;
+ }
+ }
+
+ xSeries->setPropertyValue("LabelPlacement", css::uno::Any(nApi));
+}
+
+bool isTrendlineVisible(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID)
+{
+ rtl::Reference< DataSeries > xRegressionCurveContainer =
+ ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xRegressionCurveContainer.is())
+ return false;
+
+ return !xRegressionCurveContainer->getRegressionCurves2().empty();
+}
+
+void setTrendlineVisible(const rtl::Reference<::chart::ChartModel>&
+ xModel, std::u16string_view rCID, bool bVisible)
+{
+ rtl::Reference< DataSeries > xRegressionCurveContainer =
+ ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xRegressionCurveContainer.is())
+ return;
+
+ if (bVisible)
+ {
+ RegressionCurveHelper::addRegressionCurve(
+ SvxChartRegress::Linear,
+ xRegressionCurveContainer);
+ }
+ else
+ RegressionCurveHelper::removeAllExceptMeanValueLine(
+ xRegressionCurveContainer );
+
+}
+
+bool isErrorBarVisible(const rtl::Reference<::chart::ChartModel>& xModel,
+ std::u16string_view rCID, bool bYError)
+{
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xSeries.is())
+ return false;
+
+ return StatisticsHelper::hasErrorBars(xSeries, bYError);
+}
+
+void setErrorBarVisible(const rtl::Reference<::chart::ChartModel>&
+ xModel, std::u16string_view rCID, bool bYError, bool bVisible)
+{
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xSeries.is())
+ return;
+
+ if (bVisible)
+ {
+ StatisticsHelper::addErrorBars( xSeries,
+ css::chart::ErrorBarStyle::STANDARD_DEVIATION,
+ bYError);
+ }
+ else
+ {
+ StatisticsHelper::removeErrorBars( xSeries, bYError );
+ }
+}
+
+bool isPrimaryAxis(const rtl::Reference<::chart::ChartModel>&
+ xModel, std::u16string_view rCID)
+{
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xSeries.is())
+ return true;
+
+ return DataSeriesHelper::getAttachedAxisIndex(xSeries) == 0;
+}
+
+void setAttachedAxisType(const rtl::Reference<::chart::ChartModel>&
+ xModel, std::u16string_view rCID, bool bPrimary)
+{
+ const rtl::Reference<DataSeries> xDataSeries = ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xDataSeries.is())
+ return;
+
+ rtl::Reference<Diagram> xDiagram = xModel->getFirstChartDiagram();
+ xDiagram->attachSeriesToAxis(bPrimary, xDataSeries, comphelper::getProcessComponentContext());
+}
+
+rtl::Reference<ChartType> getChartType(
+ const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ rtl::Reference<Diagram> xDiagram = xModel->getFirstChartDiagram();
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & xCooSysSequence( xDiagram->getBaseCoordinateSystems());
+ return xCooSysSequence[0]->getChartTypes2()[0];
+}
+
+OUString getSeriesLabel(const rtl::Reference<::chart::ChartModel>& xModel, std::u16string_view rCID)
+{
+ rtl::Reference< DataSeries > xSeries =
+ ObjectIdentifier::getDataSeriesForCID(rCID, xModel);
+
+ if (!xSeries.is())
+ return OUString();
+
+ rtl::Reference<ChartType> xChartType = getChartType(xModel);
+ return xSeries->getLabelForRole(xChartType->getRoleOfSequenceForSeriesLabel());
+}
+
+OUString getCID(const css::uno::Reference<css::frame::XModel>& xModel)
+{
+ css::uno::Reference<css::frame::XController> xController(xModel->getCurrentController());
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(xController, css::uno::UNO_QUERY);
+ if (!xSelectionSupplier.is())
+ return OUString();
+
+ uno::Any aAny = xSelectionSupplier->getSelection();
+ if (!aAny.hasValue())
+ return OUString();
+
+ OUString aCID;
+ aAny >>= aCID;
+
+ if (aCID.isEmpty())
+ return OUString();
+
+#if defined DBG_UTIL && !defined NDEBUG
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType != OBJECTTYPE_DATA_SERIES &&
+ eType != OBJECTTYPE_DATA_POINT &&
+ eType != OBJECTTYPE_DATA_CURVE)
+ SAL_WARN("chart2","Selected item is not a chart series");
+#endif
+
+ return aCID;
+}
+
+}
+
+ChartSeriesPanel::ChartSeriesPanel(
+ weld::Widget* pParent,
+ ChartController* pController)
+ : PanelLayout(pParent, "ChartSeriesPanel", "modules/schart/ui/sidebarseries.ui")
+ , mxCBLabel(m_xBuilder->weld_check_button("checkbutton_label"))
+ , mxCBTrendline(m_xBuilder->weld_check_button("checkbutton_trendline"))
+ , mxCBXError(m_xBuilder->weld_check_button("checkbutton_x_error"))
+ , mxCBYError(m_xBuilder->weld_check_button("checkbutton_y_error"))
+ , mxRBPrimaryAxis(m_xBuilder->weld_radio_button("radiobutton_primary_axis"))
+ , mxRBSecondaryAxis(m_xBuilder->weld_radio_button("radiobutton_secondary_axis"))
+ , mxBoxLabelPlacement(m_xBuilder->weld_widget("datalabel_box"))
+ , mxLBLabelPlacement(m_xBuilder->weld_combo_box("comboboxtext_label"))
+ , mxFTSeriesName(m_xBuilder->weld_label("label_series_name"))
+ , mxFTSeriesTemplate(m_xBuilder->weld_label("label_series_tmpl"))
+ , mxModel(pController->getChartModel())
+ , mxListener(new ChartSidebarModifyListener(this))
+ , mxSelectionListener(new ChartSidebarSelectionListener(this, OBJECTTYPE_DATA_SERIES))
+ , mbModelValid(true)
+{
+ Initialize();
+}
+
+ChartSeriesPanel::~ChartSeriesPanel()
+{
+ doUpdateModel(nullptr);
+
+ mxCBLabel.reset();
+ mxCBTrendline.reset();
+ mxCBXError.reset();
+ mxCBYError.reset();
+
+ mxRBPrimaryAxis.reset();
+ mxRBSecondaryAxis.reset();
+
+ mxBoxLabelPlacement.reset();
+ mxLBLabelPlacement.reset();
+
+ mxFTSeriesName.reset();
+ mxFTSeriesTemplate.reset();
+}
+
+void ChartSeriesPanel::Initialize()
+{
+ mxModel->addModifyListener(mxListener);
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (xSelectionSupplier.is())
+ xSelectionSupplier->addSelectionChangeListener(mxSelectionListener);
+
+ updateData();
+
+ Link<weld::Toggleable&,void> aLink = LINK(this, ChartSeriesPanel, CheckBoxHdl);
+ mxCBLabel->connect_toggled(aLink);
+ mxCBTrendline->connect_toggled(aLink);
+ mxCBXError->connect_toggled(aLink);
+ mxCBYError->connect_toggled(aLink);
+
+ Link<weld::Toggleable&,void> aLink2 = LINK(this, ChartSeriesPanel, RadioBtnHdl);
+ mxRBPrimaryAxis->connect_toggled(aLink2);
+ mxRBSecondaryAxis->connect_toggled(aLink2);
+
+ mxLBLabelPlacement->connect_changed(LINK(this, ChartSeriesPanel, ListBoxHdl));
+}
+
+void ChartSeriesPanel::updateData()
+{
+ if (!mbModelValid)
+ return;
+
+ OUString aCID = getCID(mxModel);
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType!=OBJECTTYPE_DATA_SERIES &&
+ eType != OBJECTTYPE_DATA_POINT &&
+ eType != OBJECTTYPE_DATA_CURVE)
+ return;
+
+ SolarMutexGuard aGuard;
+ bool bLabelVisible = isDataLabelVisible(mxModel, aCID);
+ mxCBLabel->set_active(bLabelVisible);
+ mxCBTrendline->set_active(isTrendlineVisible(mxModel, aCID));
+ mxCBXError->set_active(isErrorBarVisible(mxModel, aCID, false));
+ mxCBYError->set_active(isErrorBarVisible(mxModel, aCID, true));
+
+ bool bPrimaryAxis = isPrimaryAxis(mxModel, aCID);
+ mxRBPrimaryAxis->set_active(bPrimaryAxis);
+ mxRBSecondaryAxis->set_active(!bPrimaryAxis);
+
+ mxBoxLabelPlacement->set_sensitive(bLabelVisible);
+ mxLBLabelPlacement->set_active(getDataLabelPlacement(mxModel, aCID));
+
+ OUString aFrameLabel = mxFTSeriesTemplate->get_label();
+ aFrameLabel = aFrameLabel.replaceFirst("%1", getSeriesLabel(mxModel, aCID));
+ mxFTSeriesName->set_label(aFrameLabel);
+}
+
+std::unique_ptr<PanelLayout> ChartSeriesPanel::Create (
+ weld::Widget* pParent,
+ ChartController* pController)
+{
+ if (pParent == nullptr)
+ throw lang::IllegalArgumentException("no parent Window given to ChartSeriesPanel::Create", nullptr, 0);
+
+ return std::make_unique<ChartSeriesPanel>(pParent, pController);
+}
+
+void ChartSeriesPanel::DataChanged(const DataChangedEvent& rEvent)
+{
+ PanelLayout::DataChanged(rEvent);
+ updateData();
+}
+
+void ChartSeriesPanel::HandleContextChange(
+ const vcl::EnumContext& )
+{
+ updateData();
+}
+
+void ChartSeriesPanel::NotifyItemUpdate(
+ sal_uInt16 /*nSID*/,
+ SfxItemState /*eState*/,
+ const SfxPoolItem* /*pState*/ )
+{
+}
+
+void ChartSeriesPanel::modelInvalid()
+{
+ mbModelValid = false;
+}
+
+void ChartSeriesPanel::doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ if (mbModelValid)
+ {
+ mxModel->removeModifyListener(mxListener);
+ }
+
+ css::uno::Reference<css::view::XSelectionSupplier> oldSelectionSupplier(
+ mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (oldSelectionSupplier.is()) {
+ oldSelectionSupplier->removeSelectionChangeListener(mxSelectionListener);
+ }
+
+ mxModel = xModel;
+ mbModelValid = mxModel.is();
+
+ if (!mbModelValid)
+ return;
+
+ mxModel->addModifyListener(mxListener);
+
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(mxModel->getCurrentController(), css::uno::UNO_QUERY);
+ if (xSelectionSupplier.is())
+ xSelectionSupplier->addSelectionChangeListener(mxSelectionListener);
+}
+
+void ChartSeriesPanel::updateModel(css::uno::Reference<css::frame::XModel> xModel)
+{
+ ::chart::ChartModel* pModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
+ assert(!xModel || pModel);
+ doUpdateModel(pModel);
+}
+
+void ChartSeriesPanel::selectionChanged(bool bCorrectType)
+{
+ if (bCorrectType)
+ updateData();
+}
+
+IMPL_LINK(ChartSeriesPanel, CheckBoxHdl, weld::Toggleable&, rCheckBox, void)
+{
+ bool bChecked = rCheckBox.get_active();
+ OUString aCID = getCID(mxModel);
+ if (&rCheckBox == mxCBLabel.get())
+ setDataLabelVisible(mxModel, aCID, bChecked);
+ else if (&rCheckBox == mxCBTrendline.get())
+ setTrendlineVisible(mxModel, aCID, bChecked);
+ else if (&rCheckBox == mxCBXError.get())
+ setErrorBarVisible(mxModel, aCID, false, bChecked);
+ else if (&rCheckBox == mxCBYError.get())
+ setErrorBarVisible(mxModel, aCID, true, bChecked);
+}
+
+IMPL_LINK_NOARG(ChartSeriesPanel, RadioBtnHdl, weld::Toggleable&, void)
+{
+ OUString aCID = getCID(mxModel);
+ bool bChecked = mxRBPrimaryAxis->get_active();
+
+ setAttachedAxisType(mxModel, aCID, bChecked);
+}
+
+IMPL_LINK_NOARG(ChartSeriesPanel, ListBoxHdl, weld::ComboBox&, void)
+{
+ OUString aCID = getCID(mxModel);
+
+ sal_Int32 nPos = mxLBLabelPlacement->get_active();
+ setDataLabelPlacement(mxModel, aCID, nPos);
+}
+
+} // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartSeriesPanel.hxx b/chart2/source/controller/sidebar/ChartSeriesPanel.hxx
new file mode 100644
index 0000000000..5b69cc3b95
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartSeriesPanel.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/sidebar/ControllerItem.hxx>
+#include <sfx2/sidebar/IContextChangeReceiver.hxx>
+#include <sfx2/sidebar/SidebarModelUpdate.hxx>
+#include <sfx2/sidebar/PanelLayout.hxx>
+
+#include "ChartSidebarModifyListener.hxx"
+#include "ChartSidebarSelectionListener.hxx"
+
+namespace com::sun::star::util { class XModifyListener; }
+namespace com::sun::star::view { class XSelectionChangeListener; }
+
+namespace chart {
+
+class ChartController;
+
+namespace sidebar {
+
+class ChartSeriesPanel : public PanelLayout,
+ public ::sfx2::sidebar::IContextChangeReceiver,
+ public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface,
+ public sfx2::sidebar::SidebarModelUpdate,
+ public ChartSidebarModifyListenerParent,
+ public ChartSidebarSelectionListenerParent
+{
+public:
+ static std::unique_ptr<PanelLayout> Create(
+ weld::Widget* pParent,
+ ChartController* pController);
+
+ virtual void DataChanged(
+ const DataChangedEvent& rEvent) override;
+
+ virtual void HandleContextChange(
+ const vcl::EnumContext& rContext) override;
+
+ virtual void NotifyItemUpdate(
+ const sal_uInt16 nSId,
+ const SfxItemState eState,
+ const SfxPoolItem* pState) override;
+
+ virtual void GetControlState(
+ const sal_uInt16 /*nSId*/,
+ boost::property_tree::ptree& /*rState*/) override {};
+
+ // constructor/destructor
+ ChartSeriesPanel(
+ weld::Widget* pParent,
+ ChartController* pController);
+ virtual ~ChartSeriesPanel() override;
+
+ virtual void updateData() override;
+ virtual void modelInvalid() override;
+
+ virtual void selectionChanged(bool bCorrectType) override;
+
+ virtual void updateModel(css::uno::Reference<css::frame::XModel> xModel) override;
+
+private:
+ //ui controls
+ std::unique_ptr<weld::CheckButton> mxCBLabel;
+ std::unique_ptr<weld::CheckButton> mxCBTrendline;
+ std::unique_ptr<weld::CheckButton> mxCBXError;
+ std::unique_ptr<weld::CheckButton> mxCBYError;
+
+ std::unique_ptr<weld::RadioButton> mxRBPrimaryAxis;
+ std::unique_ptr<weld::RadioButton> mxRBSecondaryAxis;
+
+ std::unique_ptr<weld::Widget> mxBoxLabelPlacement;
+ std::unique_ptr<weld::ComboBox> mxLBLabelPlacement;
+
+ std::unique_ptr<weld::Label> mxFTSeriesName;
+ std::unique_ptr<weld::Label> mxFTSeriesTemplate;
+
+ rtl::Reference<::chart::ChartModel> mxModel;
+ css::uno::Reference<css::util::XModifyListener> mxListener;
+ css::uno::Reference<css::view::XSelectionChangeListener> mxSelectionListener;
+
+ bool mbModelValid;
+
+ void Initialize();
+ void doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel);
+
+ DECL_LINK(CheckBoxHdl, weld::Toggleable&, void);
+ DECL_LINK(RadioBtnHdl, weld::Toggleable&, void);
+ DECL_LINK(ListBoxHdl, weld::ComboBox&, void);
+};
+
+} } // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartSidebarModifyListener.cxx b/chart2/source/controller/sidebar/ChartSidebarModifyListener.cxx
new file mode 100644
index 0000000000..adee06ddd5
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartSidebarModifyListener.cxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ChartSidebarModifyListener.hxx"
+
+namespace chart::sidebar
+{
+ChartSidebarModifyListenerParent::~ChartSidebarModifyListenerParent() {}
+
+ChartSidebarModifyListener::ChartSidebarModifyListener(ChartSidebarModifyListenerParent* pParent)
+ : mpParent(pParent)
+{
+}
+
+ChartSidebarModifyListener::~ChartSidebarModifyListener() {}
+
+void ChartSidebarModifyListener::modified(const css::lang::EventObject& /*rEvent*/)
+{
+ if (mpParent)
+ mpParent->updateData();
+}
+
+void ChartSidebarModifyListener::disposing(const css::lang::EventObject& /*rEvent*/)
+{
+ if (!mpParent)
+ return;
+
+ mpParent->modelInvalid();
+ mpParent = nullptr;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartSidebarModifyListener.hxx b/chart2/source/controller/sidebar/ChartSidebarModifyListener.hxx
new file mode 100644
index 0000000000..afcbbdab51
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartSidebarModifyListener.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <cppuhelper/implbase.hxx>
+
+namespace chart::sidebar
+{
+class ChartSidebarModifyListenerParent
+{
+public:
+ virtual ~ChartSidebarModifyListenerParent();
+
+ virtual void updateData() = 0;
+
+ virtual void modelInvalid() = 0;
+};
+
+class ChartSidebarModifyListener : public cppu::WeakImplHelper<css::util::XModifyListener>
+{
+public:
+ explicit ChartSidebarModifyListener(ChartSidebarModifyListenerParent* pParent);
+ virtual ~ChartSidebarModifyListener() override;
+
+ virtual void SAL_CALL modified(const css::lang::EventObject& rEvent) override;
+
+ virtual void SAL_CALL disposing(const css::lang::EventObject& rEvent) override;
+
+private:
+ ChartSidebarModifyListenerParent* mpParent;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartSidebarSelectionListener.cxx b/chart2/source/controller/sidebar/ChartSidebarSelectionListener.cxx
new file mode 100644
index 0000000000..c3757a3b87
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartSidebarSelectionListener.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ChartSidebarSelectionListener.hxx"
+
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/frame/XController.hpp>
+
+#include <ObjectIdentifier.hxx>
+
+namespace chart::sidebar {
+
+ChartSidebarSelectionListenerParent::~ChartSidebarSelectionListenerParent()
+{
+}
+
+ChartSidebarSelectionListener::ChartSidebarSelectionListener(
+ ChartSidebarSelectionListenerParent* pParent):
+ mpParent(pParent)
+{
+}
+
+ChartSidebarSelectionListener::ChartSidebarSelectionListener(
+ ChartSidebarSelectionListenerParent* pParent,
+ ObjectType eType):
+ mpParent(pParent)
+{
+ maTypes.push_back(eType);
+}
+
+ChartSidebarSelectionListener::~ChartSidebarSelectionListener()
+{
+}
+
+void ChartSidebarSelectionListener::selectionChanged(const css::lang::EventObject& rEvent)
+{
+ if (!mpParent)
+ return;
+
+ bool bCorrectObjectSelected = false;
+
+ css::uno::Reference<css::frame::XController> xController(rEvent.Source, css::uno::UNO_QUERY);
+ if (xController.is())
+ {
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(xController, css::uno::UNO_QUERY);
+ if (xSelectionSupplier.is())
+ {
+ css::uno::Any aAny = xSelectionSupplier->getSelection();
+ if (aAny.hasValue())
+ {
+ OUString aCID;
+ aAny >>= aCID;
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ bCorrectObjectSelected = std::any_of(maTypes.begin(), maTypes.end(),
+ [eType](const ObjectType& eTypeInVector) { return eType == eTypeInVector; });
+ }
+ }
+ }
+
+ mpParent->selectionChanged(bCorrectObjectSelected);
+}
+
+void ChartSidebarSelectionListener::disposing(const css::lang::EventObject& /*rEvent*/)
+{
+ if (!mpParent)
+ return;
+
+ mpParent = nullptr;
+}
+
+void ChartSidebarSelectionListener::setAcceptedTypes(std::vector<ObjectType>&& aTypes)
+{
+ maTypes = std::move(aTypes);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartSidebarSelectionListener.hxx b/chart2/source/controller/sidebar/ChartSidebarSelectionListener.hxx
new file mode 100644
index 0000000000..e8cea5003f
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartSidebarSelectionListener.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <ObjectIdentifier.hxx>
+
+#include <vector>
+
+namespace chart::sidebar
+{
+class ChartSidebarSelectionListenerParent
+{
+public:
+ virtual ~ChartSidebarSelectionListenerParent();
+
+ virtual void selectionChanged(bool bSelected) = 0;
+};
+
+class ChartSidebarSelectionListener
+ : public cppu::WeakImplHelper<css::view::XSelectionChangeListener>
+{
+public:
+ // listen to all chart selection changes
+ explicit ChartSidebarSelectionListener(ChartSidebarSelectionListenerParent* pParent);
+ // only listen to the changes of eType
+ ChartSidebarSelectionListener(ChartSidebarSelectionListenerParent* pParent, ObjectType eType);
+ virtual ~ChartSidebarSelectionListener() override;
+
+ virtual void SAL_CALL selectionChanged(const css::lang::EventObject& rEvent) override;
+
+ virtual void SAL_CALL disposing(const css::lang::EventObject& rEvent) override;
+
+ void setAcceptedTypes(std::vector<ObjectType>&& aTypes);
+
+private:
+ ChartSidebarSelectionListenerParent* mpParent;
+
+ std::vector<ObjectType> maTypes;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartTypePanel.cxx b/chart2/source/controller/sidebar/ChartTypePanel.cxx
new file mode 100644
index 0000000000..69409a8d67
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartTypePanel.cxx
@@ -0,0 +1,438 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ChartTypePanel.hxx"
+#include <TimerTriggeredControllerLock.hxx>
+
+#include <ChartController.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <ChartResourceGroups.hxx>
+#include <ChartTypeDialogController.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <unonames.hxx>
+
+#include <svtools/valueset.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace css;
+using namespace css::uno;
+
+namespace chart::sidebar
+{
+ChartTypePanel::ChartTypePanel(weld::Widget* pParent, ::chart::ChartController* pController)
+ : PanelLayout(pParent, "ChartTypePanel", "modules/schart/ui/sidebartype.ui")
+ , mxListener(new ChartSidebarModifyListener(this))
+ , mbModelValid(true)
+ , m_pDim3DLookResourceGroup(new Dim3DLookResourceGroup(m_xBuilder.get()))
+ , m_pStackingResourceGroup(new StackingResourceGroup(m_xBuilder.get()))
+ , m_pSplineResourceGroup(
+ new SplineResourceGroup(m_xBuilder.get(), pController->GetChartFrame()))
+ , m_pGeometryResourceGroup(new GeometryResourceGroup(m_xBuilder.get()))
+ , m_pSortByXValuesResourceGroup(new SortByXValuesResourceGroup(m_xBuilder.get()))
+ , m_xChartModel(pController->getChartModel())
+ , m_aChartTypeDialogControllerList(0)
+ , m_pCurrentMainType(nullptr)
+ , m_nChangingCalls(0)
+ , m_aTimerTriggeredControllerLock(m_xChartModel)
+ , m_xMainTypeList(m_xBuilder->weld_combo_box("cmb_chartType"))
+ , m_xSubTypeList(new ValueSet(m_xBuilder->weld_scrolled_window("subtypewin", true)))
+ , m_xSubTypeListWin(new weld::CustomWeld(*m_xBuilder, "subtype", *m_xSubTypeList))
+{
+ Size aSize(m_xSubTypeList->GetDrawingArea()->get_ref_device().LogicToPixel(
+ Size(120, 40), MapMode(MapUnit::MapAppFont)));
+ m_xSubTypeListWin->set_size_request(aSize.Width(), aSize.Height());
+
+ m_xMainTypeList->connect_changed(LINK(this, ChartTypePanel, SelectMainTypeHdl));
+ m_xSubTypeList->SetSelectHdl(LINK(this, ChartTypePanel, SelectSubTypeHdl));
+
+ m_xSubTypeList->SetStyle(m_xSubTypeList->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER
+ | WB_NAMEFIELD | WB_FLATVALUESET | WB_3DLOOK);
+ m_xSubTypeList->SetColCount(4);
+ m_xSubTypeList->SetLineCount(1);
+
+ bool bEnableComplexChartTypes = true;
+ uno::Reference<beans::XPropertySet> xProps(static_cast<cppu::OWeakObject*>(m_xChartModel.get()),
+ uno::UNO_QUERY);
+ if (xProps.is())
+ {
+ try
+ {
+ xProps->getPropertyValue("EnableComplexChartTypes") >>= bEnableComplexChartTypes;
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ }
+
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<ColumnChartDialogController>());
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<BarChartDialogController>());
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<PieChartDialogController>());
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<AreaChartDialogController>());
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<LineChartDialogController>());
+ if (bEnableComplexChartTypes)
+ {
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<XYChartDialogController>());
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<BubbleChartDialogController>());
+ }
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<NetChartDialogController>());
+ if (bEnableComplexChartTypes)
+ {
+ m_aChartTypeDialogControllerList.push_back(std::make_unique<StockChartDialogController>());
+ }
+ m_aChartTypeDialogControllerList.push_back(
+ std::make_unique<CombiColumnLineChartDialogController>());
+
+ for (auto const& elem : m_aChartTypeDialogControllerList)
+ {
+ m_xMainTypeList->append("", elem->getName(), elem->getImage());
+ elem->setChangeListener(this);
+ }
+
+ m_pDim3DLookResourceGroup->setChangeListener(this);
+ m_pStackingResourceGroup->setChangeListener(this);
+ m_pSplineResourceGroup->setChangeListener(this);
+ m_pGeometryResourceGroup->setChangeListener(this);
+ m_pSortByXValuesResourceGroup->setChangeListener(this);
+
+ Initialize();
+}
+
+ChartTypePanel::~ChartTypePanel()
+{
+ doUpdateModel(nullptr);
+
+ //delete all dialog controller
+ m_aChartTypeDialogControllerList.clear();
+
+ //delete all resource helpers
+ m_pDim3DLookResourceGroup.reset();
+ m_pStackingResourceGroup.reset();
+ m_pSplineResourceGroup.reset();
+ m_pGeometryResourceGroup.reset();
+ m_pSortByXValuesResourceGroup.reset();
+ m_xSubTypeListWin.reset();
+ m_xSubTypeList.reset();
+
+ m_xSubTypeListWin.reset();
+ m_xSubTypeList.reset();
+ m_xMainTypeList.reset();
+}
+
+IMPL_LINK_NOARG(ChartTypePanel, SelectMainTypeHdl, weld::ComboBox&, void) { selectMainType(); }
+
+IMPL_LINK_NOARG(ChartTypePanel, SelectSubTypeHdl, ValueSet*, void)
+{
+ if (m_pCurrentMainType)
+ {
+ ChartTypeParameter aParameter(getCurrentParameter());
+ m_pCurrentMainType->adjustParameterToSubType(aParameter);
+ fillAllControls(aParameter, false);
+ commitToModel(aParameter);
+ }
+}
+
+void ChartTypePanel::Initialize()
+{
+ if (!m_xChartModel.is())
+ return;
+ rtl::Reference<::chart::ChartTypeManager> xChartTypeManager = m_xChartModel->getTypeManager();
+ rtl::Reference<Diagram> xDiagram = m_xChartModel->getFirstChartDiagram();
+ Diagram::tTemplateWithServiceName aTemplate;
+ if (xDiagram)
+ aTemplate = xDiagram->getTemplate(xChartTypeManager);
+ OUString aServiceName(aTemplate.sServiceName);
+
+ bool bFound = false;
+
+ sal_uInt16 nM = 0;
+ for (auto const& elem : m_aChartTypeDialogControllerList)
+ {
+ if (elem->isSubType(aServiceName))
+ {
+ bFound = true;
+
+ m_xMainTypeList->set_active(nM);
+ showAllControls(*elem);
+ uno::Reference<beans::XPropertySet> xTemplateProps(
+ static_cast<cppu::OWeakObject*>(aTemplate.xChartTypeTemplate.get()),
+ uno::UNO_QUERY);
+ ChartTypeParameter aParameter
+ = elem->getChartTypeParameterForService(aServiceName, xTemplateProps);
+ m_pCurrentMainType = getSelectedMainType();
+
+ //set ThreeDLookScheme
+ aParameter.eThreeDLookScheme = xDiagram->detectScheme();
+ if (!aParameter.b3DLook
+ && aParameter.eThreeDLookScheme != ThreeDLookScheme::ThreeDLookScheme_Realistic)
+ aParameter.eThreeDLookScheme = ThreeDLookScheme::ThreeDLookScheme_Realistic;
+
+ try
+ {
+ xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES)
+ >>= aParameter.bSortByXValues;
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ fillAllControls(aParameter);
+ if (m_pCurrentMainType)
+ m_pCurrentMainType->fillExtraControls(m_xChartModel, xTemplateProps);
+ break;
+ }
+ ++nM;
+ }
+
+ if (!bFound)
+ {
+ m_xSubTypeList->Hide();
+ m_pDim3DLookResourceGroup->showControls(false);
+ m_pStackingResourceGroup->showControls(false);
+ m_pSplineResourceGroup->showControls(false);
+ m_pGeometryResourceGroup->showControls(false);
+ m_pSortByXValuesResourceGroup->showControls(false);
+ }
+}
+
+void ChartTypePanel::updateData()
+{
+ // Chart Type related
+ if (!m_xChartModel.is())
+ return;
+ rtl::Reference<::chart::ChartTypeManager> xChartTypeManager = m_xChartModel->getTypeManager();
+ rtl::Reference<Diagram> xDiagram = m_xChartModel->getFirstChartDiagram();
+ Diagram::tTemplateWithServiceName aTemplate;
+ if (xDiagram)
+ aTemplate = xDiagram->getTemplate(xChartTypeManager);
+ OUString aServiceName(aTemplate.sServiceName);
+
+ //sal_uInt16 nM = 0;
+ for (auto const& elem : m_aChartTypeDialogControllerList)
+ {
+ if (elem->isSubType(aServiceName))
+ {
+ //m_pMainTypeList->SelectEntryPos(nM);
+ //m_pMainTypeList->select_entry_region(nM, nM);
+ break;
+ }
+ //++nM;
+ }
+}
+
+void ChartTypePanel::DataChanged(const DataChangedEvent& rEvent)
+{
+ PanelLayout::DataChanged(rEvent);
+ updateData();
+}
+
+void ChartTypePanel::HandleContextChange(const vcl::EnumContext& rContext)
+{
+ if (maContext == rContext)
+ {
+ // Nothing to do.
+ return;
+ }
+
+ maContext = rContext;
+ updateData();
+}
+
+void ChartTypePanel::modelInvalid() { mbModelValid = false; }
+
+void ChartTypePanel::doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ if (mbModelValid)
+ {
+ m_xChartModel->removeModifyListener(mxListener);
+ }
+
+ m_xChartModel = xModel;
+ mbModelValid = m_xChartModel.is();
+
+ if (!mbModelValid)
+ return;
+
+ m_xChartModel->addModifyListener(mxListener);
+}
+
+void ChartTypePanel::updateModel(css::uno::Reference<css::frame::XModel> xModel)
+{
+ ::chart::ChartModel* pModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
+ assert(!xModel || pModel);
+ doUpdateModel(pModel);
+}
+
+rtl::Reference<::chart::ChartTypeTemplate> ChartTypePanel::getCurrentTemplate() const
+{
+ if (m_pCurrentMainType && m_xChartModel.is())
+ {
+ ChartTypeParameter aParameter(getCurrentParameter());
+ m_pCurrentMainType->adjustParameterToSubType(aParameter);
+ rtl::Reference<::chart::ChartTypeManager> xChartTypeManager
+ = m_xChartModel->getTypeManager();
+ return m_pCurrentMainType->getCurrentTemplate(aParameter, xChartTypeManager);
+ }
+ return nullptr;
+}
+
+ChartTypeDialogController* ChartTypePanel::getSelectedMainType()
+{
+ ChartTypeDialogController* pTypeController = nullptr;
+ auto nM = static_cast<std::vector<ChartTypeDialogController*>::size_type>(
+ m_xMainTypeList->get_active());
+ if (nM < m_aChartTypeDialogControllerList.size())
+ pTypeController = m_aChartTypeDialogControllerList[nM].get();
+ return pTypeController;
+}
+
+void ChartTypePanel::showAllControls(ChartTypeDialogController& rTypeController)
+{
+ m_xMainTypeList->show();
+ m_xSubTypeList->Show();
+
+ bool bShow = rTypeController.shouldShow_3DLookControl();
+ m_pDim3DLookResourceGroup->showControls(bShow);
+ bShow = rTypeController.shouldShow_StackingControl();
+ m_pStackingResourceGroup->showControls(bShow);
+ bShow = rTypeController.shouldShow_SplineControl();
+ m_pSplineResourceGroup->showControls(bShow);
+ bShow = rTypeController.shouldShow_GeometryControl();
+ m_pGeometryResourceGroup->showControls(bShow);
+ bShow = rTypeController.shouldShow_SortByXValuesResourceGroup();
+ m_pSortByXValuesResourceGroup->showControls(bShow);
+ rTypeController.showExtraControls(m_xBuilder.get());
+}
+
+void ChartTypePanel::fillAllControls(const ChartTypeParameter& rParameter,
+ bool bAlsoResetSubTypeList)
+{
+ m_nChangingCalls++;
+ if (m_pCurrentMainType && bAlsoResetSubTypeList)
+ {
+ m_pCurrentMainType->fillSubTypeList(*m_xSubTypeList, rParameter);
+ }
+ m_xSubTypeList->SelectItem(static_cast<sal_uInt16>(rParameter.nSubTypeIndex));
+ m_pDim3DLookResourceGroup->fillControls(rParameter);
+ m_pStackingResourceGroup->fillControls(rParameter);
+ m_pSplineResourceGroup->fillControls(rParameter);
+ m_pGeometryResourceGroup->fillControls(rParameter);
+ m_pSortByXValuesResourceGroup->fillControls(rParameter);
+ m_nChangingCalls--;
+}
+
+ChartTypeParameter ChartTypePanel::getCurrentParameter() const
+{
+ ChartTypeParameter aParameter;
+ aParameter.nSubTypeIndex = static_cast<sal_Int32>(m_xSubTypeList->GetSelectedItemId());
+ m_pDim3DLookResourceGroup->fillParameter(aParameter);
+ m_pStackingResourceGroup->fillParameter(aParameter);
+ m_pSplineResourceGroup->fillParameter(aParameter);
+ m_pGeometryResourceGroup->fillParameter(aParameter);
+ m_pSortByXValuesResourceGroup->fillParameter(aParameter);
+ return aParameter;
+}
+
+void ChartTypePanel::stateChanged()
+{
+ if (m_nChangingCalls)
+ return;
+ m_nChangingCalls++;
+
+ ChartTypeParameter aParameter(getCurrentParameter());
+ if (m_pCurrentMainType)
+ {
+ m_pCurrentMainType->adjustParameterToSubType(aParameter);
+ m_pCurrentMainType->adjustSubTypeAndEnableControls(aParameter);
+ }
+ commitToModel(aParameter);
+
+ //detect the new ThreeDLookScheme
+ rtl::Reference<Diagram> xDiagram = m_xChartModel->getFirstChartDiagram();
+ aParameter.eThreeDLookScheme = xDiagram->detectScheme();
+ try
+ {
+ xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues;
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ //the controls have to be enabled/disabled accordingly
+ fillAllControls(aParameter);
+
+ m_nChangingCalls--;
+}
+
+void ChartTypePanel::commitToModel(const ChartTypeParameter& rParameter)
+{
+ if (!m_pCurrentMainType)
+ return;
+
+ m_aTimerTriggeredControllerLock.startTimer();
+ m_pCurrentMainType->commitToModel(rParameter, m_xChartModel);
+}
+
+void ChartTypePanel::selectMainType()
+{
+ ChartTypeParameter aParameter(getCurrentParameter());
+
+ if (m_pCurrentMainType)
+ {
+ m_pCurrentMainType->adjustParameterToSubType(aParameter);
+ m_pCurrentMainType->hideExtraControls();
+ }
+
+ m_pCurrentMainType = getSelectedMainType();
+ if (!m_pCurrentMainType)
+ return;
+
+ showAllControls(*m_pCurrentMainType);
+
+ m_pCurrentMainType->adjustParameterToMainType(aParameter);
+ commitToModel(aParameter);
+ //detect the new ThreeDLookScheme
+ aParameter.eThreeDLookScheme = m_xChartModel->getFirstChartDiagram()->detectScheme();
+ if (!aParameter.b3DLook
+ && aParameter.eThreeDLookScheme != ThreeDLookScheme::ThreeDLookScheme_Realistic)
+ aParameter.eThreeDLookScheme = ThreeDLookScheme::ThreeDLookScheme_Realistic;
+
+ rtl::Reference<Diagram> xDiagram = m_xChartModel->getFirstChartDiagram();
+ try
+ {
+ xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues;
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ fillAllControls(aParameter);
+ uno::Reference<beans::XPropertySet> xTemplateProps(
+ static_cast<cppu::OWeakObject*>(getCurrentTemplate().get()), uno::UNO_QUERY);
+ m_pCurrentMainType->fillExtraControls(m_xChartModel, xTemplateProps);
+}
+} // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/sidebar/ChartTypePanel.hxx b/chart2/source/controller/sidebar/ChartTypePanel.hxx
new file mode 100644
index 0000000000..8df0020431
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartTypePanel.hxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/sidebar/IContextChangeReceiver.hxx>
+#include <sfx2/sidebar/SidebarModelUpdate.hxx>
+#include <sfx2/sidebar/PanelLayout.hxx>
+#include <vcl/EnumContext.hxx>
+#include "ChartSidebarModifyListener.hxx"
+#include <ChartTypeDialogController.hxx>
+#include <ChartTypeTemplateProvider.hxx>
+#include <TimerTriggeredControllerLock.hxx>
+
+namespace com::sun::star::util
+{
+class XModifyListener;
+}
+
+namespace weld
+{
+class CustomWeld;
+}
+
+namespace chart
+{
+class ChartController;
+class Dim3DLookResourceGroup;
+class StackingResourceGroup;
+class SplineResourceGroup;
+class GeometryResourceGroup;
+class ChartTypeParameter;
+class SortByXValuesResourceGroup;
+
+namespace sidebar
+{
+class ChartTypePanel : public ResourceChangeListener,
+ public PanelLayout,
+ public ::sfx2::sidebar::IContextChangeReceiver,
+ public sfx2::sidebar::SidebarModelUpdate,
+ public ChartSidebarModifyListenerParent,
+ public ChartTypeTemplateProvider
+{
+public:
+ virtual void DataChanged(const DataChangedEvent& rEvent) override;
+
+ virtual void HandleContextChange(const vcl::EnumContext& rContext) override;
+
+ // constructor/destructor
+ ChartTypePanel(weld::Widget* pParent, ::chart::ChartController* pController);
+
+ virtual ~ChartTypePanel() override;
+
+ virtual void updateData() override;
+ virtual void modelInvalid() override;
+
+ virtual void updateModel(css::uno::Reference<css::frame::XModel> xModel) override;
+
+ virtual rtl::Reference<::chart::ChartTypeTemplate> getCurrentTemplate() const override;
+
+private:
+ ChartTypeDialogController* getSelectedMainType();
+ void showAllControls(ChartTypeDialogController& rTypeController);
+ void fillAllControls(const ChartTypeParameter& rParameter, bool bAlsoResetSubTypeList = true);
+ ChartTypeParameter getCurrentParameter() const;
+
+ virtual void stateChanged() override;
+
+ void commitToModel(const ChartTypeParameter& rParameter);
+ void selectMainType();
+
+ DECL_LINK(SelectMainTypeHdl, weld::ComboBox&, void);
+ DECL_LINK(SelectSubTypeHdl, ValueSet*, void);
+
+ vcl::EnumContext maContext;
+
+ css::uno::Reference<css::util::XModifyListener> mxListener;
+
+ bool mbModelValid;
+
+ void Initialize();
+ void doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel);
+
+ std::unique_ptr<Dim3DLookResourceGroup> m_pDim3DLookResourceGroup;
+ std::unique_ptr<StackingResourceGroup> m_pStackingResourceGroup;
+ std::unique_ptr<SplineResourceGroup> m_pSplineResourceGroup;
+ std::unique_ptr<GeometryResourceGroup> m_pGeometryResourceGroup;
+ std::unique_ptr<SortByXValuesResourceGroup> m_pSortByXValuesResourceGroup;
+
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+
+ std::vector<std::unique_ptr<ChartTypeDialogController>> m_aChartTypeDialogControllerList;
+ ChartTypeDialogController* m_pCurrentMainType;
+
+ sal_Int32 m_nChangingCalls;
+
+ TimerTriggeredControllerLock m_aTimerTriggeredControllerLock;
+
+ std::unique_ptr<weld::ComboBox> m_xMainTypeList;
+ std::unique_ptr<ValueSet> m_xSubTypeList;
+ std::unique_ptr<weld::CustomWeld> m_xSubTypeListWin;
+};
+}
+} // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/controller/uitest/uiobject.cxx b/chart2/source/controller/uitest/uiobject.cxx
new file mode 100644
index 0000000000..531978db13
--- /dev/null
+++ b/chart2/source/controller/uitest/uiobject.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <memory>
+#include <uiobject.hxx>
+
+#include <ChartWindow.hxx>
+#include <ChartView.hxx>
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+#include <ObjectHierarchy.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+
+#include <comphelper/servicehelper.hxx>
+
+#include <utility>
+#include <vcl/svapp.hxx>
+
+#include <algorithm>
+#include <iterator>
+
+ChartUIObject::ChartUIObject(const VclPtr<chart::ChartWindow>& xChartWindow,
+ OUString aCID):
+ maCID(std::move(aCID)),
+ mxChartWindow(xChartWindow)
+{
+}
+
+StringMap ChartUIObject::get_state()
+{
+ StringMap aMap;
+ aMap["CID"] = maCID;
+
+ return aMap;
+}
+
+void ChartUIObject::execute(const OUString& rAction,
+ const StringMap& rParameters)
+{
+ if (rAction == "SELECT")
+ {
+ std::unique_ptr<UIObject> pWindow = mxChartWindow->GetUITestFactory()(mxChartWindow.get());
+
+ StringMap aParams;
+ aParams["NAME"] = maCID;
+ pWindow->execute(rAction, aParams);
+ }
+ else if (rAction == "COMMAND")
+ {
+ // first select object
+ std::unique_ptr<UIObject> pWindow = mxChartWindow->GetUITestFactory()(mxChartWindow.get());
+
+ StringMap aParams;
+ aParams["NAME"] = maCID;
+ pWindow->execute("SELECT", aParams);
+
+ auto itr = rParameters.find("COMMAND");
+ if (itr == rParameters.end())
+ throw css::uno::RuntimeException("missing COMMAND parameter");
+
+ maCommands.emplace_back(new OUString(itr->second));
+ OUString* pCommand = maCommands.rbegin()->get();
+
+ Application::PostUserEvent(LINK(this, ChartUIObject, PostCommand), pCommand);
+ }
+}
+
+IMPL_LINK(ChartUIObject, PostCommand, void*, pCommand, void)
+{
+ css::util::URL aURL;
+ aURL.Path = *static_cast<OUString*>(pCommand);
+ mxChartWindow->GetController()->dispatch(aURL, css::uno::Sequence<css::beans::PropertyValue>());
+}
+
+std::unique_ptr<UIObject> ChartUIObject::get_child(const OUString& rID)
+{
+ std::unique_ptr<UIObject> pWindow = mxChartWindow->GetUITestFactory()(mxChartWindow.get());
+
+ return pWindow->get_child(rID);
+}
+
+std::set<OUString> ChartUIObject::get_children() const
+{
+ std::unique_ptr<UIObject> pWindow = mxChartWindow->GetUITestFactory()(mxChartWindow.get());
+
+ return pWindow->get_children();
+}
+
+OUString ChartUIObject::get_type() const
+{
+ return "ChartUIObject for type: ";
+}
+
+ChartWindowUIObject::ChartWindowUIObject(const VclPtr<chart::ChartWindow>& xChartWindow):
+ WindowUIObject(xChartWindow),
+ mxChartWindow(xChartWindow)
+{
+}
+
+StringMap ChartWindowUIObject::get_state()
+{
+ StringMap aMap = WindowUIObject::get_state();
+
+ chart::ChartController* pController = mxChartWindow->GetController();
+ if (pController)
+ {
+ css::uno::Any aAny = pController->getSelection();
+ OUString aSelectedObject;
+ aAny >>= aSelectedObject;
+ aMap["SelectedObject"] = aSelectedObject;
+ }
+
+ return aMap;
+}
+
+void ChartWindowUIObject::execute(const OUString& rAction,
+ const StringMap& rParameters)
+{
+ if (rAction == "SELECT")
+ {
+ auto itr = rParameters.find("NAME");
+ if (itr == rParameters.end())
+ throw css::uno::RuntimeException("Missing Parameter 'NAME' for action 'SELECT'");
+
+
+ const OUString& rName = itr->second;
+ css::uno::Any aAny;
+ aAny <<= rName;
+
+ chart::ChartController* pController = mxChartWindow->GetController();
+ pController->select(aAny);
+ }
+ else
+ WindowUIObject::execute(rAction, rParameters);
+}
+
+std::unique_ptr<UIObject> ChartWindowUIObject::get_child(const OUString& rID)
+{
+ if (chart::ObjectIdentifier::isCID(rID))
+ return std::unique_ptr<UIObject>(new ChartUIObject(mxChartWindow, rID));
+
+ throw css::uno::RuntimeException("unknown child");
+}
+
+namespace {
+
+void recursiveAdd(chart::ObjectIdentifier const & rID, std::set<OUString>& rChildren, const chart::ObjectHierarchy& rHierarchy)
+{
+ std::vector<chart::ObjectIdentifier> aChildIdentifiers = rHierarchy.getChildren(rID);
+ std::transform(aChildIdentifiers.begin(), aChildIdentifiers.end(), std::inserter(rChildren, rChildren.begin()),
+ [](const chart::ObjectIdentifier& rObject)
+ {
+ return rObject.getObjectCID();
+ }
+ );
+
+ for (const chart::ObjectIdentifier& ID: aChildIdentifiers)
+ recursiveAdd(ID, rChildren, rHierarchy);
+}
+
+}
+
+std::set<OUString> ChartWindowUIObject::get_children() const
+{
+ std::set<OUString> aChildren;
+
+ chart::ChartController* pController = mxChartWindow->GetController();
+ if (!pController)
+ return aChildren;
+
+ rtl::Reference<::chart::ChartModel> xChartDoc = pController->getChartModel();
+ rtl::Reference<::chart::ChartView> xChartView = pController->getChartView();
+ chart::ExplicitValueProvider* pValueProvider = xChartView.get();
+ chart::ObjectHierarchy aHierarchy(xChartDoc, pValueProvider);
+ chart::ObjectIdentifier aIdentifier = chart::ObjectHierarchy::getRootNodeOID();
+ aChildren.insert(aIdentifier.getObjectCID());
+
+ recursiveAdd(aIdentifier, aChildren, aHierarchy);
+
+ return aChildren;
+}
+
+std::unique_ptr<UIObject> ChartWindowUIObject::create(vcl::Window* pWindow)
+{
+ chart::ChartWindow* pChartWindow = dynamic_cast<chart::ChartWindow*>(pWindow);
+ assert(pChartWindow);
+
+ return std::unique_ptr<UIObject>(new ChartWindowUIObject(pChartWindow));
+}
+
+OUString ChartWindowUIObject::get_name() const
+{
+ return "ChartWindowUIObject";
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/Axis.hxx b/chart2/source/inc/Axis.hxx
new file mode 100644
index 0000000000..902a67487c
--- /dev/null
+++ b/chart2/source/inc/Axis.hxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "OPropertySet.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/chart2/XAxis.hpp>
+#include <com/sun/star/chart2/XTitled.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include "ModifyListenerHelper.hxx"
+#include "charttoolsdllapi.hxx"
+#include "PropertyHelper.hxx"
+
+namespace chart
+{
+class GridProperties;
+class Title;
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::chart2::XAxis,
+ css::chart2::XTitled,
+ css::lang::XServiceInfo,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ Axis_Base;
+}
+
+class OOO_DLLPUBLIC_CHARTTOOLS Axis final :
+ public impl::Axis_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit Axis();
+ virtual ~Axis() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+private:
+ explicit Axis( const Axis & rOther );
+
+ // late initialization to call after copy-constructing
+ void Init();
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+public:
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XAxis ____
+ virtual void SAL_CALL setScaleData( const css::chart2::ScaleData& rScaleData ) override;
+ virtual css::chart2::ScaleData SAL_CALL getScaleData() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getGridProperties() override;
+ virtual css::uno::Sequence< css::uno::Reference< css::beans::XPropertySet > > SAL_CALL getSubGridProperties() override;
+ virtual css::uno::Sequence< css::uno::Reference< css::beans::XPropertySet > > SAL_CALL getSubTickProperties() override;
+
+ // ____ XTitled ____
+ virtual css::uno::Reference< css::chart2::XTitle > SAL_CALL getTitleObject() override;
+ virtual void SAL_CALL setTitleObject(
+ const css::uno::Reference< css::chart2::XTitle >& Title ) override;
+
+ // ____ XCloneable ____
+ // Note: the coordinate systems are not cloned!
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ rtl::Reference< ::chart::Title > getTitleObject2() const;
+ void setTitleObject( const rtl::Reference< ::chart::Title >& xNewTitle );
+
+ rtl::Reference< ::chart::GridProperties > getGridProperties2();
+ std::vector< rtl::Reference< ::chart::GridProperties > > getSubGridProperties2();
+
+private:
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ void fireModifyEvent();
+
+ void AllocateSubGrids();
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+
+ css::chart2::ScaleData m_aScaleData;
+
+ rtl::Reference< ::chart::GridProperties > m_xGrid;
+
+ std::vector< rtl::Reference< ::chart::GridProperties > > m_aSubGridProperties;
+
+ rtl::Reference< ::chart::Title > m_xTitle;
+};
+
+OOO_DLLPUBLIC_CHARTTOOLS const ::chart::tPropertyValueMap & StaticAxisDefaults();
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/AxisHelper.hxx b/chart2/source/inc/AxisHelper.hxx
new file mode 100644
index 0000000000..5b9de9d9a1
--- /dev/null
+++ b/chart2/source/inc/AxisHelper.hxx
@@ -0,0 +1,211 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+#include <com/sun/star/chart2/ScaleData.hpp>
+#include <rtl/ref.hxx>
+
+#include <vector>
+
+namespace chart { class ChartModel; }
+namespace chart { class ExplicitCategoriesProvider; }
+namespace chart { class ReferenceSizeProvider; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XAxis; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::chart2 { class XChartType; }
+namespace com::sun::star::chart2 { class XCoordinateSystem; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::chart2 { class XScaling; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+class Axis;
+class BaseCoordinateSystem;
+class ChartType;
+class Diagram;
+class GridProperties;
+
+class OOO_DLLPUBLIC_CHARTTOOLS AxisHelper
+{
+public:
+ static css::uno::Reference< css::chart2::XScaling > createLinearScaling();
+ static css::uno::Reference< css::chart2::XScaling > createLogarithmicScaling( double fBase = 10.0 );
+
+ static css::chart2::ScaleData createDefaultScale();
+
+ static void removeExplicitScaling( css::chart2::ScaleData& rScaleData );
+
+ static bool isLogarithmic( const css::uno::Reference< css::chart2::XScaling >& xScaling );
+
+ static void checkDateAxis( css::chart2::ScaleData& rScale, ExplicitCategoriesProvider* pExplicitCategoriesProvider, bool bChartTypeAllowsDateAxis );
+ static css::chart2::ScaleData getDateCheckedScale( const rtl::Reference< ::chart::Axis >& xAxis, ChartModel& rModel );
+
+ static sal_Int32 getExplicitNumberFormatKeyForAxis(
+ const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference< ::chart::BaseCoordinateSystem >& xCorrespondingCoordinateSystem
+ , const rtl::Reference< ::chart::ChartModel>& xChartDoc
+ , bool bSearchForParallelAxisIfNothingIsFound );
+
+ static rtl::Reference< ::chart::Axis >
+ createAxis( sal_Int32 nDimensionIndex, bool bMainAxis
+ , const rtl::Reference< ::chart::Diagram >& xDiagram
+ , const css::uno::Reference< css::uno::XComponentContext >& xContext
+ , ReferenceSizeProvider * pRefSizeProvider = nullptr );
+
+ static rtl::Reference< ::chart::Axis >
+ createAxis(
+ sal_Int32 nDimensionIndex
+ , sal_Int32 nAxisIndex // 0==main or 1==secondary axis
+ , const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys
+ , const css::uno::Reference< css::uno::XComponentContext > & xContext
+ , ReferenceSizeProvider * pRefSizeProvider = nullptr );
+
+ static void showAxis( sal_Int32 nDimensionIndex, bool bMainAxis
+ , const rtl::Reference< ::chart::Diagram >& xDiagram
+ , const css::uno::Reference< css::uno::XComponentContext >& xContext
+ , ReferenceSizeProvider * pRefSizeProvider = nullptr );
+
+ static void showGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
+ , const rtl::Reference< ::chart::Diagram >& xDiagram );
+
+ static void hideAxis( sal_Int32 nDimensionIndex, bool bMainAxis
+ , const rtl::Reference< ::chart::Diagram >& xDiagram );
+ static void hideGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
+ , const rtl::Reference< ::chart::Diagram >& xDiagram );
+
+ static bool isAxisShown( sal_Int32 nDimensionIndex, bool bMainAxis
+ , const rtl::Reference< ::chart::Diagram >& xDiagram );
+ static bool isGridShown( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
+ , const rtl::Reference< ::chart::Diagram >& xDiagram );
+
+ static void makeAxisVisible( const rtl::Reference< ::chart::Axis >& xAxis );
+ static void makeGridVisible( const rtl::Reference< ::chart::GridProperties >& xGridProperties );
+
+ static void makeAxisInvisible( const rtl::Reference< ::chart::Axis >& xAxis );
+ static void makeGridInvisible( const rtl::Reference< ::chart::GridProperties >& xGridProperties );
+
+ static void hideAxisIfNoDataIsAttached( const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference< ::chart::Diagram >& xDiagram);
+
+ SAL_DLLPRIVATE static bool areAxisLabelsVisible( const rtl::Reference< ::chart::Axis >& xAxisProperties );
+ static bool isAxisVisible( const rtl::Reference< ::chart::Axis >& xAxis );
+ static bool isGridVisible( const rtl::Reference< ::chart::GridProperties >& xGridProperties );
+
+ static rtl::Reference< ::chart::BaseCoordinateSystem >
+ getCoordinateSystemByIndex(
+ const rtl::Reference< ::chart::Diagram >& xDiagram
+ , sal_Int32 nIndex );
+
+ static rtl::Reference< ::chart::BaseCoordinateSystem >
+ getCoordinateSystemOfAxis(
+ const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference< ::chart::Diagram >& xDiagram );
+
+ static rtl::Reference< ::chart::Axis >
+ getAxis( sal_Int32 nDimensionIndex, bool bMainAxis
+ , const rtl::Reference< ::chart::Diagram >& xDiagram );
+ static rtl::Reference< ::chart::Axis >
+ getAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex
+ , const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys );
+
+ static rtl::Reference< ::chart::Axis >
+ getCrossingMainAxis( const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys );
+
+ static rtl::Reference< ::chart::Axis >
+ getParallelAxis( const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference< ::chart::Diagram >& xDiagram );
+
+ static rtl::Reference< ::chart::GridProperties >
+ getGridProperties( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys
+ , sal_Int32 nDimensionIndex
+ , sal_Int32 nAxisIndex //0: Primary axis, 1: secondary axis
+ , sal_Int32 nSubGridIndex //-1: Main Grid; 0: First SubGrid etc
+ );
+
+ static sal_Int32 getDimensionIndexOfAxis(
+ const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference< ::chart::Diagram >& xDiagram );
+
+ static bool getIndicesForAxis(
+ const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys
+ , sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex );
+
+ static bool getIndicesForAxis(
+ const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference< ::chart::Diagram >& xDiagram
+ , sal_Int32& rOutCooSysIndex, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex );
+
+ /** @param bOnlyVisible if </TRUE>, only axes with property "Show" set to
+ </sal_True> are returned
+ */
+ static std::vector< rtl::Reference< ::chart::Axis > >
+ getAllAxesOfDiagram( const rtl::Reference< ::chart::Diagram >& xDiagram
+ , bool bOnlyVisible = false );
+
+ /** @param bOnlyVisible if </TRUE>, only axes with property "Show" set to
+ </sal_True> are returned
+ */
+ SAL_DLLPRIVATE static std::vector< rtl::Reference< ::chart::Axis > >
+ getAllAxesOfCoordinateSystem( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys
+ , bool bOnlyVisible = false );
+
+ static std::vector< rtl::Reference< ::chart::GridProperties > >
+ getAllGrids( const rtl::Reference< ::chart::Diagram >& xDiagram );
+
+ static void getAxisOrGridPossibilities( css::uno::Sequence< sal_Bool >& rPossibilityList
+ , const rtl::Reference< ::chart::Diagram>& xDiagram, bool bAxis=true );
+
+ static void getAxisOrGridExistence( css::uno::Sequence< sal_Bool >& rExistenceList
+ , const rtl::Reference< ::chart::Diagram>& xDiagram, bool bAxis=true );
+
+ static bool changeVisibilityOfGrids( const rtl::Reference< ::chart::Diagram>& xDiagram
+ , const css::uno::Sequence< sal_Bool >& rOldExistenceList
+ , const css::uno::Sequence< sal_Bool >& rNewExistenceList );
+
+ static bool changeVisibilityOfAxes( const rtl::Reference< ::chart::Diagram>& xDiagram
+ , const css::uno::Sequence< sal_Bool >& rOldExistenceList
+ , const css::uno::Sequence< sal_Bool >& rNewExistenceList
+ , const css::uno::Reference< css::uno::XComponentContext >& xContext
+ , ReferenceSizeProvider * pRefSizeProvider );
+
+ static bool shouldAxisBeDisplayed( const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys );
+ static bool isSecondaryYAxisNeeded( const rtl::Reference<
+ ::chart::BaseCoordinateSystem >& xCooSys );
+
+ static rtl::Reference< ::chart::ChartType >
+ getChartTypeByIndex( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys,
+ sal_Int32 nIndex );
+
+ static void setRTLAxisLayout( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys );
+
+ static rtl::Reference< ::chart::ChartType >
+ getFirstChartTypeWithSeriesAttachedToAxisIndex( const rtl::Reference< ::chart::Diagram >& xDiagram, const sal_Int32 nAttachedAxisIndex );
+
+ static bool isAxisPositioningEnabled();
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/AxisIndexDefines.hxx b/chart2/source/inc/AxisIndexDefines.hxx
new file mode 100644
index 0000000000..5e6d32d691
--- /dev/null
+++ b/chart2/source/inc/AxisIndexDefines.hxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/types.h>
+
+namespace chart
+{
+const sal_Int32 MAIN_AXIS_INDEX = 0;
+const sal_Int32 SECONDARY_AXIS_INDEX = 1;
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/BaseCoordinateSystem.hxx b/chart2/source/inc/BaseCoordinateSystem.hxx
new file mode 100644
index 0000000000..71f226abcd
--- /dev/null
+++ b/chart2/source/inc/BaseCoordinateSystem.hxx
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "OPropertySet.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/chart2/XCoordinateSystem.hpp>
+#include <com/sun/star/chart2/XChartTypeContainer.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include "ModifyListenerHelper.hxx"
+
+#include <vector>
+
+namespace chart
+{
+class Axis;
+class ChartType;
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper
+ < css::lang::XServiceInfo,
+ css::chart2::XCoordinateSystem,
+ css::chart2::XChartTypeContainer,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ BaseCoordinateSystem_Base;
+}
+
+class SAL_DLLPUBLIC_RTTI BaseCoordinateSystem :
+ public impl::BaseCoordinateSystem_Base,
+ public ::property::OPropertySet
+{
+public:
+ BaseCoordinateSystem( sal_Int32 nDimensionCount );
+ explicit BaseCoordinateSystem( const BaseCoordinateSystem & rSource );
+ virtual ~BaseCoordinateSystem() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+ // ____ XCoordinateSystem ____
+ virtual ::sal_Int32 SAL_CALL getDimension() override;
+ virtual void SAL_CALL setAxisByDimension(
+ ::sal_Int32 nDimension,
+ const css::uno::Reference< css::chart2::XAxis >& xAxis,
+ ::sal_Int32 nIndex ) override;
+ virtual css::uno::Reference< css::chart2::XAxis > SAL_CALL getAxisByDimension(
+ ::sal_Int32 nDimension, ::sal_Int32 nIndex ) override;
+ virtual ::sal_Int32 SAL_CALL getMaximumAxisIndexByDimension( ::sal_Int32 nDimension ) override;
+
+ // ____ XChartTypeContainer ____
+ virtual void SAL_CALL addChartType(
+ const css::uno::Reference< css::chart2::XChartType >& aChartType ) override;
+ virtual void SAL_CALL removeChartType(
+ const css::uno::Reference< css::chart2::XChartType >& aChartType ) override;
+ virtual css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > > SAL_CALL getChartTypes() override;
+ virtual void SAL_CALL setChartTypes(
+ const css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > >& aChartTypes ) final override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ void setAxisByDimension( sal_Int32 nDimension, const rtl::Reference< ::chart::Axis >& xAxis, sal_Int32 nIndex );
+ const rtl::Reference< ::chart::Axis > & getAxisByDimension2(sal_Int32 nDimension, sal_Int32 nIndex ) const;
+
+ void setChartTypes( const std::vector< rtl::Reference< ::chart::ChartType > >& aChartTypes );
+ const std::vector< rtl::Reference<::chart::ChartType > > & getChartTypes2() const { return m_aChartTypes; }
+
+protected:
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ void fireModifyEvent();
+
+private:
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+ sal_Int32 m_nDimensionCount;
+ typedef std::vector< std::vector< rtl::Reference< ::chart::Axis > > > tAxisVecVecType;
+ tAxisVecVecType m_aAllAxis; //outer sequence is the dimension; inner sequence is the axis index that indicates main or secondary axis
+ std::vector< rtl::Reference<::chart::ChartType > > m_aChartTypes;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/BaseGFXHelper.hxx b/chart2/source/inc/BaseGFXHelper.hxx
new file mode 100644
index 0000000000..18481031e2
--- /dev/null
+++ b/chart2/source/inc/BaseGFXHelper.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <basegfx/tuple/b3dtuple.hxx>
+#include <basegfx/vector/b3dvector.hxx>
+#include <basegfx/range/b3drange.hxx>
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include "charttoolsdllapi.hxx"
+
+namespace com::sun::star::awt { struct Rectangle; }
+namespace com::sun::star::drawing { struct PolyPolygonShape3D; }
+
+namespace chart::BaseGFXHelper
+{
+
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DRange getBoundVolume( const css::drawing::PolyPolygonShape3D& rPolyPoly );
+
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DRange getBoundVolume( const std::vector<std::vector<css::drawing::Position3D>>& rPolyPoly );
+
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B2IRectangle makeRectangle(
+ const css::awt::Point& rPosition,
+ const css::awt::Size& rSize );
+
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B2IRectangle makeRectangle( const css::awt::Rectangle& rRect );
+
+OOO_DLLPUBLIC_CHARTTOOLS css::awt::Point B2IRectangleToAWTPoint(
+ const ::basegfx::B2IRectangle& rB2IRectangle );
+
+OOO_DLLPUBLIC_CHARTTOOLS css::awt::Size B2IRectangleToAWTSize(
+ const ::basegfx::B2IRectangle& rB2IRectangle );
+
+OOO_DLLPUBLIC_CHARTTOOLS css::awt::Rectangle toAwtRectangle(const basegfx::B2IRectangle& rB2IRectangle);
+
+::basegfx::B3DVector Direction3DToB3DVector(
+ const css::drawing::Direction3D& rDirection );
+
+css::drawing::Direction3D B3DVectorToDirection3D(
+ const ::basegfx::B3DVector& rB3DVector );
+
+::basegfx::B3DVector Position3DToB3DVector(
+ const css::drawing::Position3D& rPosition );
+
+css::drawing::Position3D B3DVectorToPosition3D(
+ const ::basegfx::B3DVector& rB3DVector );
+
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DHomMatrix HomogenMatrixToB3DHomMatrix(
+ const css::drawing::HomogenMatrix & rHomogenMatrix );
+
+OOO_DLLPUBLIC_CHARTTOOLS
+css::drawing::HomogenMatrix B3DHomMatrixToHomogenMatrix(
+ const ::basegfx::B3DHomMatrix & rB3DMatrix );
+
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DTuple GetRotationFromMatrix(
+ const ::basegfx::B3DHomMatrix & rB3DMatrix );
+
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DTuple GetScaleFromMatrix(
+ const ::basegfx::B3DHomMatrix & rB3DMatrix );
+
+void ReduceToRotationMatrix( ::basegfx::B3DHomMatrix & rB3DMatrix );
+
+} // namespace chart::BaseGFXHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/CachedDataSequence.hxx b/chart2/source/inc/CachedDataSequence.hxx
new file mode 100644
index 0000000000..e9c1b9d50d
--- /dev/null
+++ b/chart2/source/inc/CachedDataSequence.hxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+// helper classes
+#include <cppuhelper/compbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <comphelper/proparrhlp.hxx>
+
+// interfaces and types
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/chart2/data/XDataSequence.hpp>
+#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include "ModifyListenerHelper.hxx"
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakComponentImplHelper<
+ css::chart2::data::XDataSequence,
+ css::chart2::data::XNumericalDataSequence,
+ css::chart2::data::XTextualDataSequence,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo >
+ CachedDataSequence_Base;
+}
+
+/**
+ * This sequence object does store actual values within, hence "cached".
+ */
+class CachedDataSequence final :
+ public ::comphelper::OMutexAndBroadcastHelper,
+ public ::comphelper::OPropertyContainer,
+ public ::comphelper::OPropertyArrayUsageHelper< CachedDataSequence >,
+ public impl::CachedDataSequence_Base
+{
+public:
+ /** constructs an empty sequence
+ */
+ CachedDataSequence();
+
+ explicit CachedDataSequence( const css::uno::Reference< css::uno::XComponentContext > & xContext );
+
+ /** creates a sequence and initializes it with the given string. This is
+ especially useful for labels, which only have one element.
+ */
+ explicit CachedDataSequence( const OUString & rSingleText );
+
+ /// Copy CTOR
+ explicit CachedDataSequence( const CachedDataSequence & rSource );
+
+ virtual ~CachedDataSequence() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+private:
+ // ____ XPropertySet ____
+ /// @see css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+ /// @see ::comphelper::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ /// @see ::comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+
+ // ____ XDataSequence ____
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getData() override;
+ virtual OUString SAL_CALL getSourceRangeRepresentation() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL generateLabel(
+ css::chart2::data::LabelOrigin nLabelOrigin ) override;
+ virtual ::sal_Int32 SAL_CALL getNumberFormatKeyByIndex( ::sal_Int32 nIndex ) override;
+
+ // ____ XNumericalDataSequence ____
+ /// @see css::chart::data::XNumericalDataSequence
+ virtual css::uno::Sequence< double > SAL_CALL getNumericalData() override;
+
+ // ____ XTextualDataSequence ____
+ /// @see css::chart::data::XTextualDataSequence
+ virtual css::uno::Sequence< OUString > SAL_CALL getTextualData() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ // css::lang::XInitialization:
+ virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > & aArguments) override;
+
+ // <properties>
+ sal_Int32 m_nNumberFormatKey;
+ OUString m_sRole;
+ // </properties>
+
+ enum DataType
+ {
+ NUMERICAL,
+ TEXTUAL,
+ MIXED
+ };
+
+ /** This method registers all properties. It should be called by all
+ constructors.
+ */
+ void registerProperties();
+
+ /** is used by interface method getNumericalData().
+ */
+ css::uno::Sequence< double > Impl_getNumericalData() const;
+ /** is used by interface method getTextualData().
+ */
+ css::uno::Sequence< OUString > Impl_getTextualData() const;
+ /** is used by interface method getData().
+ */
+ css::uno::Sequence< css::uno::Any > Impl_getMixedData() const;
+
+ enum DataType m_eCurrentDataType;
+
+ css::uno::Sequence< double > m_aNumericalSequence;
+ css::uno::Sequence< OUString > m_aTextualSequence;
+ css::uno::Sequence< css::uno::Any > m_aMixedSequence;
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ChangingResource.hxx b/chart2/source/inc/ChangingResource.hxx
new file mode 100644
index 0000000000..bde5b09234
--- /dev/null
+++ b/chart2/source/inc/ChangingResource.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+namespace chart
+{
+class ChangingResource;
+class ResourceChangeListener
+{
+public:
+ virtual void stateChanged() = 0;
+ virtual ~ResourceChangeListener();
+};
+
+class ChangingResource
+{
+public:
+ ChangingResource();
+ virtual ~ChangingResource();
+
+ void setChangeListener(ResourceChangeListener* pListener);
+
+protected:
+ ResourceChangeListener* m_pChangeListener;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/CharacterProperties.hxx b/chart2/source/inc/CharacterProperties.hxx
new file mode 100644
index 0000000000..4dd7a4fbd1
--- /dev/null
+++ b/chart2/source/inc/CharacterProperties.hxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "PropertyHelper.hxx"
+#include "FastPropertyIdRanges.hxx"
+#include "charttoolsdllapi.hxx"
+#include <com/sun/star/awt/FontDescriptor.hpp>
+
+#include <vector>
+
+namespace com::sun::star::beans { class XMultiPropertySet; }
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart
+{
+
+// implements services
+// com.sun.star.style.CharacterProperties
+// com.sun.star.style.CharacterPropertiesAsian
+// com.sun.star.style.CharacterPropertiesComplex
+namespace CharacterProperties
+{
+ // FastProperty Ids for properties
+ enum
+ {
+ // com.sun.star.style.CharacterProperties
+ PROP_CHAR_FONT_NAME = FAST_PROPERTY_ID_START_CHAR_PROP, // ?
+ PROP_CHAR_FONT_STYLE_NAME,
+ PROP_CHAR_FONT_FAMILY,
+ PROP_CHAR_FONT_CHAR_SET,
+ PROP_CHAR_FONT_PITCH,
+ PROP_CHAR_COLOR,
+// PROP_CHAR_BACKGROUND_COLOR,
+// PROP_CHAR_BACKGROUND_TRANSPARENCY, alpha channel in COLOR
+ PROP_CHAR_ESCAPEMENT,
+ PROP_CHAR_CHAR_HEIGHT,
+ PROP_CHAR_UNDERLINE,
+ PROP_CHAR_UNDERLINE_COLOR,
+ PROP_CHAR_UNDERLINE_HAS_COLOR,
+ PROP_CHAR_OVERLINE,
+ PROP_CHAR_OVERLINE_COLOR,
+ PROP_CHAR_OVERLINE_HAS_COLOR,
+ PROP_CHAR_WEIGHT,
+ PROP_CHAR_POSTURE,
+ PROP_CHAR_AUTO_KERNING,
+ PROP_CHAR_KERNING,
+// PROP_CHAR_CASE_MAPPING,
+// PROP_CHAR_ROTATION,
+//-- PROP_CHAR_ROTATION_IS_FIT_TO_LINE,
+// PROP_CHAR_SCALE_WIDTH,
+ PROP_CHAR_ESCAPEMENT_HEIGHT,
+
+// PROP_CHAR_CROSSED_OUT,
+ PROP_CHAR_STRIKE_OUT,
+ PROP_CHAR_WORD_MODE,
+// PROP_CHAR_FLASH,
+ PROP_CHAR_LOCALE,
+//-- PROP_CHAR_KEEP_TOGETHER,
+//-- PROP_CHAR_NO_LINE_BREAK,
+ PROP_CHAR_SHADOWED,
+ PROP_CHAR_CONTOURED,
+ PROP_CHAR_RELIEF,
+//-- PROP_CHAR_COMBINE_IS_ON,
+//-- PROP_CHAR_COMBINE_PREFIX,
+//-- PROP_CHAR_COMBINE_SUFFIX,
+
+ PROP_CHAR_EMPHASIS,
+// PROP_CHAR_RUBY_TEXT,
+// PROP_CHAR_RUBY_ADJUST,
+// PROP_CHAR_RUBY_STYLE_NAME,
+// PROP_CHAR_RUBY_IS_ABOVE,
+// PROP_CHAR_INHIBIT_HYPHENATION,
+
+ // Asian (com.sun.star.style.CharacterPropertiesAsian)
+ PROP_CHAR_ASIAN_FONT_NAME,
+ PROP_CHAR_ASIAN_FONT_STYLE_NAME,
+ PROP_CHAR_ASIAN_FONT_FAMILY,
+ PROP_CHAR_ASIAN_CHAR_SET,
+ PROP_CHAR_ASIAN_FONT_PITCH,
+ PROP_CHAR_ASIAN_CHAR_HEIGHT,
+ PROP_CHAR_ASIAN_WEIGHT,
+ PROP_CHAR_ASIAN_POSTURE,
+ PROP_CHAR_ASIAN_LOCALE,
+//-- PROP_CHAR_ASIAN_USE_SCRIPT_TYPE_DISTANCE,
+//-- PROP_CHAR_ASIAN_USE_FORBIDDEN_RULES,
+//-- PROP_CHAR_ASIAN_HANGING_PUNCTUATION_ALLOWED,
+
+ // Complex Text Layout (com.sun.star.style.CharacterPropertiesComplex)
+ PROP_CHAR_COMPLEX_FONT_NAME,
+ PROP_CHAR_COMPLEX_FONT_STYLE_NAME,
+ PROP_CHAR_COMPLEX_FONT_FAMILY,
+ PROP_CHAR_COMPLEX_CHAR_SET,
+ PROP_CHAR_COMPLEX_FONT_PITCH,
+ PROP_CHAR_COMPLEX_CHAR_HEIGHT,
+ PROP_CHAR_COMPLEX_WEIGHT,
+ PROP_CHAR_COMPLEX_POSTURE,
+ PROP_CHAR_COMPLEX_LOCALE,
+ PROP_PARA_IS_CHARACTER_DISTANCE,
+
+ PROP_WRITING_MODE,
+
+ // don't use
+ FAST_PROPERTY_ID_END_CHAR_PROP
+ };
+
+ OOO_DLLPUBLIC_CHARTTOOLS void AddPropertiesToVector(
+ std::vector< css::beans::Property > & rOutProperties );
+
+ OOO_DLLPUBLIC_CHARTTOOLS void AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap );
+
+ OOO_DLLPUBLIC_CHARTTOOLS bool IsCharacterPropertyHandle( sal_Int32 nHandle );
+
+ OOO_DLLPUBLIC_CHARTTOOLS css::awt::FontDescriptor createFontDescriptorFromPropertySet(
+ const css::uno::Reference< css::beans::XMultiPropertySet > & xMultiPropSet );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ChartModelHelper.hxx b/chart2/source/inc/ChartModelHelper.hxx
new file mode 100644
index 0000000000..9c18af92be
--- /dev/null
+++ b/chart2/source/inc/ChartModelHelper.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/awt/Size.hpp>
+#include "charttoolsdllapi.hxx"
+#include <rtl/ref.hxx>
+
+#include <vector>
+
+namespace chart { class ChartModel; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::chart2 { class XChartType; }
+namespace com::sun::star::chart2 { class XCoordinateSystem; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::chart2::data { class XDataProvider; }
+namespace com::sun::star::chart2::data { class XRangeHighlighter; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::view { class XSelectionSupplier; }
+
+namespace chart
+{
+class BaseCoordinateSystem;
+class ChartType;
+class DataSeries;
+class Diagram;
+class InternalDataProvider;
+
+class OOO_DLLPUBLIC_CHARTTOOLS ChartModelHelper
+{
+public:
+ static rtl::Reference< InternalDataProvider > createInternalDataProvider(
+ const rtl::Reference<::chart::ChartModel>& xChartDoc, bool bConnectToModel );
+
+ static rtl::Reference< ::chart::BaseCoordinateSystem >
+ getFirstCoordinateSystem( const rtl::Reference<::chart::ChartModel>& xModel );
+
+ static std::vector< rtl::Reference< ::chart::DataSeries > >
+ getDataSeries( const rtl::Reference< ::chart::ChartModel > & xModel );
+
+ static rtl::Reference< ChartType >
+ getChartTypeOfSeries(
+ const rtl::Reference<::chart::ChartModel>& xModel
+ , const rtl::Reference< ::chart::DataSeries >& xGivenDataSeries );
+
+ static css::awt::Size getDefaultPageSize();
+
+ static css::awt::Size getPageSize( const rtl::Reference<::chart::ChartModel>& xModel );
+
+ static void triggerRangeHighlighting( const rtl::Reference<::chart::ChartModel>& xModel );
+
+ static bool isIncludeHiddenCells( const rtl::Reference<::chart::ChartModel>& xChartModel );
+
+ static bool setIncludeHiddenCells( bool bIncludeHiddenCells, ChartModel& rModel);
+
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ChartResourceGroupDlgs.hxx b/chart2/source/inc/ChartResourceGroupDlgs.hxx
new file mode 100644
index 0000000000..e545854889
--- /dev/null
+++ b/chart2/source/inc/ChartResourceGroupDlgs.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+
+namespace chart
+{
+class ChartTypeParameter;
+
+class SplinePropertiesDialog final : public weld::GenericDialogController
+{
+public:
+ explicit SplinePropertiesDialog(weld::Window* pParent);
+
+ void fillControls(const ChartTypeParameter& rParameter);
+ void fillParameter(ChartTypeParameter& rParameter, bool bSmoothLines);
+
+private:
+ DECL_LINK(SplineTypeListBoxHdl, weld::ComboBox&, void);
+
+private:
+ std::unique_ptr<weld::ComboBox> m_xLB_Spline_Type;
+ std::unique_ptr<weld::SpinButton> m_xMF_SplineResolution;
+ std::unique_ptr<weld::Label> m_xFT_SplineOrder;
+ std::unique_ptr<weld::SpinButton> m_xMF_SplineOrder;
+};
+
+class SteppedPropertiesDialog final : public weld::GenericDialogController
+{
+public:
+ explicit SteppedPropertiesDialog(weld::Window* pParent);
+
+ void fillControls(const ChartTypeParameter& rParameter);
+ void fillParameter(ChartTypeParameter& rParameter, bool bSteppedLines);
+
+private:
+ std::unique_ptr<weld::RadioButton> m_xRB_Start;
+ std::unique_ptr<weld::RadioButton> m_xRB_End;
+ std::unique_ptr<weld::RadioButton> m_xRB_CenterX;
+ std::unique_ptr<weld::RadioButton> m_xRB_CenterY;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ChartResourceGroups.hxx b/chart2/source/inc/ChartResourceGroups.hxx
new file mode 100644
index 0000000000..9ae397d84f
--- /dev/null
+++ b/chart2/source/inc/ChartResourceGroups.hxx
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "res_BarGeometry.hxx"
+#include "ChangingResource.hxx"
+#include "ChartTypeDialogController.hxx"
+#include "ChartResourceGroupDlgs.hxx"
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+class SplinePropertiesDialog;
+class SteppedPropertiesDialog;
+
+enum
+{
+ POS_3DSCHEME_SIMPLE = 0,
+ POS_3DSCHEME_REALISTIC = 1
+};
+
+class Dim3DLookResourceGroup final : public ChangingResource
+{
+public:
+ explicit Dim3DLookResourceGroup(weld::Builder* pBuilder);
+
+ void showControls(bool bShow);
+
+ void fillControls(const ChartTypeParameter& rParameter);
+ void fillParameter(ChartTypeParameter& rParameter);
+
+private:
+ DECL_LINK(Dim3DLookCheckHdl, weld::Toggleable&, void);
+ DECL_LINK(SelectSchemeHdl, weld::ComboBox&, void);
+
+private:
+ std::unique_ptr<weld::CheckButton> m_xCB_3DLook;
+ std::unique_ptr<weld::ComboBox> m_xLB_Scheme;
+};
+
+class SortByXValuesResourceGroup final : public ChangingResource
+{
+public:
+ explicit SortByXValuesResourceGroup(weld::Builder* pBuilder);
+
+ void showControls(bool bShow);
+
+ void fillControls(const ChartTypeParameter& rParameter);
+ void fillParameter(ChartTypeParameter& rParameter);
+
+private:
+ DECL_LINK(SortByXValuesCheckHdl, weld::Toggleable&, void);
+
+private:
+ std::unique_ptr<weld::CheckButton> m_xCB_XValueSorting;
+};
+
+class StackingResourceGroup final : public ChangingResource
+{
+public:
+ explicit StackingResourceGroup(weld::Builder* pBuilder);
+
+ void showControls(bool bShow);
+
+ void fillControls(const ChartTypeParameter& rParameter);
+ void fillParameter(ChartTypeParameter& rParameter);
+
+private:
+ DECL_LINK(StackingChangeHdl, weld::Toggleable&, void);
+ DECL_LINK(StackingEnableHdl, weld::Toggleable&, void);
+
+private:
+ std::unique_ptr<weld::CheckButton> m_xCB_Stacked;
+ std::unique_ptr<weld::RadioButton> m_xRB_Stack_Y;
+ std::unique_ptr<weld::RadioButton> m_xRB_Stack_Y_Percent;
+ std::unique_ptr<weld::RadioButton> m_xRB_Stack_Z;
+};
+
+#define POS_LINETYPE_STRAIGHT 0
+#define POS_LINETYPE_SMOOTH 1
+#define POS_LINETYPE_STEPPED 2
+
+class SplineResourceGroup final : public ChangingResource
+{
+public:
+ explicit SplineResourceGroup(weld::Builder* pBuilder, weld::Window* pParent);
+
+ void showControls(bool bShow);
+
+ void fillControls(const ChartTypeParameter& rParameter);
+ void fillParameter(ChartTypeParameter& rParameter);
+
+private:
+ DECL_LINK(LineTypeChangeHdl, weld::ComboBox&, void);
+ DECL_LINK(SplineDetailsDialogHdl, weld::Button&, void);
+ DECL_LINK(SteppedDetailsDialogHdl, weld::Button&, void);
+ std::shared_ptr<SplinePropertiesDialog> getSplinePropertiesDialog();
+ std::shared_ptr<SteppedPropertiesDialog> getSteppedPropertiesDialog();
+
+private:
+ weld::Window* m_pParent;
+ std::unique_ptr<weld::Label> m_xFT_LineType;
+ std::unique_ptr<weld::ComboBox> m_xLB_LineType;
+ std::unique_ptr<weld::Button> m_xPB_DetailsDialog;
+ std::shared_ptr<SplinePropertiesDialog> m_xSplinePropertiesDialog;
+ std::shared_ptr<SteppedPropertiesDialog> m_xSteppedPropertiesDialog;
+};
+
+class GeometryResourceGroup final : public ChangingResource
+{
+public:
+ explicit GeometryResourceGroup(weld::Builder* pBuilder);
+
+ void showControls(bool bShow);
+
+ void fillControls(const ChartTypeParameter& rParameter);
+ void fillParameter(ChartTypeParameter& rParameter);
+
+private:
+ DECL_LINK(GeometryChangeHdl, weld::TreeView&, void);
+
+private:
+ BarGeometryResources m_aGeometryResources;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ChartType.hxx b/chart2/source/inc/ChartType.hxx
new file mode 100644
index 0000000000..267d06f406
--- /dev/null
+++ b/chart2/source/inc/ChartType.hxx
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "OPropertySet.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/chart2/XChartType.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <rtl/ref.hxx>
+
+#include <vector>
+#include "charttoolsdllapi.hxx"
+
+namespace chart
+{
+class BaseCoordinateSystem;
+class DataSeries;
+class ModifyEventForwarder;
+
+enum
+{
+ PROP_PIECHARTTYPE_USE_RINGS,
+ PROP_PIECHARTTYPE_3DRELATIVEHEIGHT
+};
+
+
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::lang::XServiceInfo,
+ css::chart2::XChartType,
+ css::chart2::XDataSeriesContainer,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ ChartType_Base;
+}
+
+class OOO_DLLPUBLIC_CHARTTOOLS ChartType :
+ public impl::ChartType_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit ChartType();
+ virtual ~ChartType() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+
+ explicit ChartType( const ChartType & rOther );
+
+ // ____ XChartType ____
+ // still abstract ! implement !
+ virtual OUString SAL_CALL getChartType() override = 0;
+ virtual css::uno::Reference< css::chart2::XCoordinateSystem > SAL_CALL
+ createCoordinateSystem( ::sal_Int32 DimensionCount ) final override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedMandatoryRoles() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedOptionalRoles() override;
+ virtual OUString SAL_CALL getRoleOfSequenceForSeriesLabel() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedPropertyRoles() override;
+
+ // ____ XDataSeriesContainer ____
+ virtual void SAL_CALL addDataSeries(
+ const css::uno::Reference< css::chart2::XDataSeries >& aDataSeries ) override;
+ virtual void SAL_CALL removeDataSeries(
+ const css::uno::Reference< css::chart2::XDataSeries >& aDataSeries ) override;
+ virtual css::uno::Sequence< css::uno::Reference< css::chart2::XDataSeries > > SAL_CALL getDataSeries() override;
+ virtual void SAL_CALL setDataSeries(
+ const css::uno::Sequence< css::uno::Reference< css::chart2::XDataSeries > >& aDataSeries ) override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const = 0;
+
+ void addDataSeries(
+ const rtl::Reference< ::chart::DataSeries >& aDataSeries );
+ void removeDataSeries(
+ const rtl::Reference< ::chart::DataSeries >& aDataSeries );
+ void setDataSeries(
+ const std::vector< rtl::Reference< ::chart::DataSeries > >& aDataSeries );
+ const std::vector< rtl::Reference< ::chart::DataSeries > > & getDataSeries2() const { return m_aDataSeries; }
+
+ virtual rtl::Reference< ::chart::BaseCoordinateSystem >
+ createCoordinateSystem2( sal_Int32 DimensionCount );
+
+protected:
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ void fireModifyEvent();
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+protected:
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+
+private:
+ void impl_addDataSeriesWithoutNotification(
+ const rtl::Reference< ::chart::DataSeries >& aDataSeries );
+
+private:
+ typedef
+ std::vector< rtl::Reference< ::chart::DataSeries > > tDataSeriesContainerType;
+
+ // --- mutable members: the following members need mutex guard ---
+
+ tDataSeriesContainerType m_aDataSeries;
+
+ bool m_bNotifyChanges;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ChartTypeDialogController.hxx b/chart2/source/inc/ChartTypeDialogController.hxx
new file mode 100644
index 0000000000..4c03ff269e
--- /dev/null
+++ b/chart2/source/inc/ChartTypeDialogController.hxx
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <map>
+
+#include "ChangingResource.hxx"
+#include "ThreeDHelper.hxx"
+
+#include <com/sun/star/chart2/CurveStyle.hpp>
+#include <vcl/weld.hxx>
+
+namespace com::sun::star::beans
+{
+class XPropertySet;
+}
+namespace com::sun::star::chart2
+{
+class XChartDocument;
+}
+namespace com::sun::star::lang
+{
+class XMultiServiceFactory;
+}
+
+class ValueSet;
+
+namespace chart
+{
+class ChartModel;
+class ChartTypeTemplate;
+class ChartTypeManager;
+
+enum GlobalStackMode
+{
+ GlobalStackMode_NONE,
+ GlobalStackMode_STACK_Y,
+ GlobalStackMode_STACK_Y_PERCENT,
+ GlobalStackMode_STACK_Z
+};
+
+class ChartTypeParameter
+{
+public:
+ ChartTypeParameter(sal_Int32 nSubTypeIndex, bool bXAxisWithValues = false, bool b3DLook = false,
+ GlobalStackMode eStackMode = GlobalStackMode_NONE, bool _bSymbols = true,
+ bool _bLines = true,
+ css::chart2::CurveStyle eCurveStyle = css::chart2::CurveStyle_LINES);
+ ChartTypeParameter();
+
+ bool mapsToSameService(const ChartTypeParameter& rParameter) const;
+ bool mapsToSimilarService(const ChartTypeParameter& rParameter,
+ sal_Int32 nTheHigherTheLess) const;
+
+ sal_Int32 nSubTypeIndex; //starting with 1
+
+ bool bXAxisWithValues;
+ bool b3DLook;
+ bool bSymbols;
+ bool bLines;
+
+ GlobalStackMode eStackMode;
+ css::chart2::CurveStyle eCurveStyle;
+
+ sal_Int32 nCurveResolution;
+ sal_Int32 nSplineOrder;
+
+ sal_Int32 nGeometry3D;
+
+ ThreeDLookScheme eThreeDLookScheme;
+ bool bSortByXValues;
+
+ bool mbRoundedEdge;
+};
+
+typedef std::map<OUString, ChartTypeParameter> tTemplateServiceChartTypeParameterMap;
+
+class ChartTypeDialogController : public ChangingResource
+{
+public:
+ ChartTypeDialogController();
+ virtual ~ChartTypeDialogController() override;
+
+ virtual OUString getName() = 0;
+ virtual OUString getImage() = 0;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const = 0;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList, const ChartTypeParameter& rParameter);
+
+ virtual bool shouldShow_3DLookControl() const;
+ virtual bool shouldShow_StackingControl() const;
+ virtual bool shouldShow_SplineControl() const;
+ virtual bool shouldShow_GeometryControl() const;
+ virtual bool shouldShow_SortByXValuesResourceGroup() const;
+
+ virtual void showExtraControls(weld::Builder* pBuilder);
+ virtual void hideExtraControls() const;
+ virtual void
+ fillExtraControls(const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const css::uno::Reference<css::beans::XPropertySet>& xTemplateProps) const;
+ /// @throws css::uno::RuntimeException
+ virtual void setTemplateProperties(
+ const css::uno::Reference<css::beans::XPropertySet>& xTemplateProps) const;
+
+ bool isSubType(const OUString& rServiceName);
+ ChartTypeParameter getChartTypeParameterForService(
+ const OUString& rServiceName,
+ const css::uno::Reference<css::beans::XPropertySet>& xTemplateProps);
+ virtual void adjustSubTypeAndEnableControls(
+ ChartTypeParameter&
+ rParameter); //if you have different counts of subtypes you may need to adjust the index
+ virtual void adjustParameterToSubType(ChartTypeParameter& rParameter);
+ virtual void adjustParameterToMainType(ChartTypeParameter& rParameter);
+ OUString getServiceNameForParameter(const ChartTypeParameter& rParameter) const;
+ void commitToModel(const ChartTypeParameter& rParameter,
+ const rtl::Reference<::chart::ChartModel>& xChartModel);
+ rtl::Reference<::chart::ChartTypeTemplate>
+ getCurrentTemplate(const ChartTypeParameter& rParameter,
+ const rtl::Reference<::chart::ChartTypeManager>& xTemplateManager) const;
+
+protected:
+ bool bSupportsXAxisWithValues;
+ bool bSupports3D;
+};
+
+class ColumnOrBarChartDialogController_Base : public ChartTypeDialogController
+{
+public:
+ ColumnOrBarChartDialogController_Base();
+ virtual ~ColumnOrBarChartDialogController_Base() override;
+
+ virtual bool shouldShow_3DLookControl() const override;
+ virtual bool shouldShow_GeometryControl() const override;
+
+ virtual void adjustSubTypeAndEnableControls(ChartTypeParameter& rParameter) override;
+};
+
+class ColumnChartDialogController final : public ColumnOrBarChartDialogController_Base
+{
+public:
+ ColumnChartDialogController();
+ virtual ~ColumnChartDialogController() override;
+
+ virtual OUString getName() override;
+ virtual OUString getImage() override;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList,
+ const ChartTypeParameter& rParameter) override;
+};
+
+class BarChartDialogController final : public ColumnOrBarChartDialogController_Base
+{
+public:
+ BarChartDialogController();
+ virtual ~BarChartDialogController() override;
+
+ virtual OUString getName() override;
+ virtual OUString getImage() override;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList,
+ const ChartTypeParameter& rParameter) override;
+};
+
+class PieChartDialogController final : public ChartTypeDialogController
+{
+public:
+ PieChartDialogController();
+ virtual ~PieChartDialogController() override;
+
+ virtual OUString getName() override;
+ virtual OUString getImage() override;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList,
+ const ChartTypeParameter& rParameter) override;
+ virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override;
+
+ virtual bool shouldShow_3DLookControl() const override;
+};
+
+class LineChartDialogController final : public ChartTypeDialogController
+{
+public:
+ LineChartDialogController();
+ virtual ~LineChartDialogController() override;
+
+ virtual OUString getName() override;
+ virtual OUString getImage() override;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList,
+ const ChartTypeParameter& rParameter) override;
+ virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override;
+ virtual void adjustParameterToMainType(ChartTypeParameter& rParameter) override;
+
+ virtual bool shouldShow_StackingControl() const override;
+ virtual bool shouldShow_SplineControl() const override;
+};
+
+class XYChartDialogController final : public ChartTypeDialogController
+{
+public:
+ XYChartDialogController();
+ virtual ~XYChartDialogController() override;
+
+ virtual OUString getName() override;
+ virtual OUString getImage() override;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList,
+ const ChartTypeParameter& rParameter) override;
+ virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override;
+
+ virtual bool shouldShow_SplineControl() const override;
+ virtual bool shouldShow_SortByXValuesResourceGroup() const override;
+};
+
+class AreaChartDialogController final : public ChartTypeDialogController
+{
+public:
+ AreaChartDialogController();
+ virtual ~AreaChartDialogController() override;
+
+ virtual OUString getName() override;
+ virtual OUString getImage() override;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList,
+ const ChartTypeParameter& rParameter) override;
+ virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override;
+ virtual void adjustParameterToMainType(ChartTypeParameter& rParameter) override;
+
+ virtual bool shouldShow_3DLookControl() const override;
+};
+
+class NetChartDialogController final : public ChartTypeDialogController
+{
+public:
+ NetChartDialogController();
+ virtual ~NetChartDialogController() override;
+
+ virtual OUString getName() override;
+ virtual OUString getImage() override;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList,
+ const ChartTypeParameter& rParameter) override;
+ virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override;
+
+ virtual bool shouldShow_StackingControl() const override;
+};
+
+class StockChartDialogController final : public ChartTypeDialogController
+{
+public:
+ StockChartDialogController();
+ virtual ~StockChartDialogController() override;
+
+ virtual OUString getName() override;
+ virtual OUString getImage() override;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList,
+ const ChartTypeParameter& rParameter) override;
+ virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override;
+};
+
+class CombiColumnLineChartDialogController final : public ChartTypeDialogController
+{
+public:
+ CombiColumnLineChartDialogController();
+
+ virtual OUString getName() override;
+ virtual OUString getImage() override;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList,
+ const ChartTypeParameter& rParameter) override;
+ virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override;
+
+ virtual void showExtraControls(weld::Builder* pBuilder) override;
+ virtual void hideExtraControls() const override;
+ virtual void fillExtraControls(
+ const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const css::uno::Reference<css::beans::XPropertySet>& xTemplateProps) const override;
+
+ virtual void setTemplateProperties(
+ const css::uno::Reference<css::beans::XPropertySet>& xTemplateProps) const override;
+
+private:
+ DECL_LINK(ChangeLineCountHdl, weld::SpinButton&, void);
+
+private:
+ std::unique_ptr<weld::Label> m_xFT_NumberOfLines;
+ std::unique_ptr<weld::SpinButton> m_xMF_NumberOfLines;
+};
+
+class BubbleChartDialogController final : public ChartTypeDialogController
+{
+public:
+ BubbleChartDialogController();
+ virtual ~BubbleChartDialogController() override;
+
+ virtual OUString getName() override;
+ virtual OUString getImage() override;
+ virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const override;
+ virtual void fillSubTypeList(ValueSet& rSubTypeList,
+ const ChartTypeParameter& rParameter) override;
+ virtual void adjustParameterToSubType(ChartTypeParameter& rParameter) override;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ChartTypeHelper.hxx b/chart2/source/inc/ChartTypeHelper.hxx
new file mode 100644
index 0000000000..379f96ad0e
--- /dev/null
+++ b/chart2/source/inc/ChartTypeHelper.hxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include "charttoolsdllapi.hxx"
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::chart2 { class XChartType; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+
+namespace chart
+{
+class ChartType;
+class DataSeries;
+
+class OOO_DLLPUBLIC_CHARTTOOLS ChartTypeHelper
+{
+public:
+ static bool isSupportingGeometryProperties( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount );
+ static bool isSupportingStatisticProperties( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount );
+ static bool isSupportingRegressionProperties(const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount );
+ static bool isSupportingMainAxis( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount, sal_Int32 nDimensionIndex );
+ static bool isSupportingSecondaryAxis( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount );
+ static bool isSupportingAreaProperties( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount );
+ static bool isSupportingSymbolProperties( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount );
+ static bool isSupportingOverlapAndGapWidthProperties( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount );
+ static bool isSupportingBarConnectors( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount );
+ static bool isSupportingRightAngledAxes( const rtl::Reference< ::chart::ChartType >& xChartType );
+ static bool isSupportingAxisSideBySide( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount );
+ static bool isSupportingStartingAngle( const rtl::Reference< ::chart::ChartType >& xChartType );
+ //starting value for bars or baseline for areas for example
+ static bool isSupportingBaseValue( const rtl::Reference< ::chart::ChartType >& xChartType );
+ static bool isSupportingAxisPositioning( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount, sal_Int32 nDimensionIndex );
+ static bool isSupportingDateAxis( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionIndex );
+ static bool isSupportingComplexCategory( const rtl::Reference< ::chart::ChartType >& xChartType );
+ static bool isSupportingCategoryPositioning( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount );
+ static bool shiftCategoryPosAtXAxisPerDefault( const rtl::Reference< ::chart::ChartType >& xChartType );
+
+ //returns sequence of css::chart::DataLabelPlacement
+ static css::uno::Sequence < sal_Int32 > getSupportedLabelPlacements(
+ const rtl::Reference< ::chart::ChartType >& xChartType, bool bSwapXAndY
+ , const rtl::Reference< ::chart::DataSeries >& xSeries );
+
+ //returns sequence of css::chart::MissingValueTreatment
+ static css::uno::Sequence < sal_Int32 > getSupportedMissingValueTreatments(
+ const rtl::Reference< ::chart::ChartType >& xChartType );
+
+ SAL_DLLPRIVATE static css::drawing::Direction3D getDefaultSimpleLightDirection( const rtl::Reference< ::chart::ChartType >& xChartType );
+ SAL_DLLPRIVATE static css::drawing::Direction3D getDefaultRealisticLightDirection( const rtl::Reference< ::chart::ChartType >& xChartType );
+ SAL_DLLPRIVATE static sal_Int32 getDefaultDirectLightColor( bool bSimple, const rtl::Reference< ::chart::ChartType >& xChartType );
+ SAL_DLLPRIVATE static sal_Int32 getDefaultAmbientLightColor( bool bSimple, const rtl::Reference< ::chart::ChartType >& xChartType );
+ static sal_Int32 getNumberOfDisplayedSeries( const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nNumberOfSeries );
+ SAL_DLLPRIVATE static bool noBordersForSimpleScheme( const rtl::Reference< ::chart::ChartType >& xChartType );
+
+ static bool isSeriesInFrontOfAxisLine( const rtl::Reference< ::chart::ChartType >& xChartType );
+
+ static sal_Int32 //one of css::chart2::AxisType
+ getAxisType( const rtl::Reference< ::chart::ChartType >& xChartType
+ , sal_Int32 nDimensionIndex );
+
+ static OUString getRoleOfSequenceForYAxisNumberFormatDetection( const rtl::Reference<
+ ::chart::ChartType >& xChartType );
+
+ static OUString getRoleOfSequenceForDataLabelNumberFormatDetection( const rtl::Reference<
+ ::chart::ChartType >& xChartType );
+
+ static bool isSupportingOnlyDeepStackingFor3D( const rtl::Reference< ::chart::ChartType >& xChartType );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ChartTypeTemplate.hxx b/chart2/source/inc/ChartTypeTemplate.hxx
new file mode 100644
index 0000000000..b22165e79f
--- /dev/null
+++ b/chart2/source/inc/ChartTypeTemplate.hxx
@@ -0,0 +1,283 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include "DataInterpreter.hxx"
+#include "StackMode.hxx"
+#include <com/sun/star/chart2/XChartTypeTemplate.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include "charttoolsdllapi.hxx"
+#include <rtl/ref.hxx>
+#include <vector>
+
+namespace com::sun::star::beans { struct PropertyValue; }
+namespace com::sun::star::chart2 { class XChartType; }
+namespace com::sun::star::chart2 { class XCoordinateSystem; }
+namespace com::sun::star::chart2 { class XCoordinateSystemContainer; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::chart2::data { class XDataSource; }
+namespace com::sun::star::chart2::data { class XLabeledDataSequence; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+class BaseCoordinateSystem;
+class ChartType;
+class DataSeries;
+class Diagram;
+class LabeledDataSequence;
+
+/** For creating diagrams and modifying existing diagrams. A base class that
+ implements XChartTypeTemplate and offers some tooling for classes that
+ derive from this class.
+
+ createDiagramByDataSource
+
+ This does the following steps using some virtual helper-methods, that may be
+ overridden by derived classes:
+
+ * creates an XDiagram via service-factory.
+
+ * convert the given XDataSource to a sequence of XDataSeries using the
+ method createDataSeries(). In this class the DataInterpreter helper class
+ is used to create a standard interpretation (just y-values).
+
+ * call applyDefaultStyle() for all XDataSeries in order to apply default
+ styles. In this class the series get the system-wide default colors as
+ "Color" property.
+
+ * call applyStyle() for applying chart-type specific styles to all series.
+ The default implementation is empty.
+
+ * call createCoordinateSystems() and apply them to the diagram. As
+ default one cartesian system with Scales using a linear Scaling is
+ created.
+
+ * createChartTypes() is called in order to define the structure of the
+ diagram. For details see comment of this function. As default this
+ method creates a tree where all series appear in one branch with the chart
+ type determined by getChartTypeForNewSeries(). The stacking is determined
+ via the method getStackMode().
+
+ * create an XLegend via the global service factory, set it at the diagram.
+ */
+class OOO_DLLPUBLIC_CHARTTOOLS ChartTypeTemplate : public ::cppu::WeakImplHelper<
+ css::chart2::XChartTypeTemplate,
+ css::lang::XServiceName >
+{
+public:
+ explicit ChartTypeTemplate( css::uno::Reference< css::uno::XComponentContext > const & xContext,
+ OUString aServiceName );
+ virtual ~ChartTypeTemplate() override;
+
+ rtl::Reference< ::chart::Diagram > createDiagramByDataSource2(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments );
+
+ // ____ XChartTypeTemplate ____
+ virtual css::uno::Reference< css::chart2::XDiagram > SAL_CALL createDiagramByDataSource(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments ) override final;
+ /// denotes if the chart needs categories at the first scale
+ virtual sal_Bool SAL_CALL supportsCategories() override;
+ virtual void SAL_CALL changeDiagram(
+ const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) override final;
+ virtual void SAL_CALL changeDiagramData(
+ const css::uno::Reference< css::chart2::XDiagram >& xDiagram,
+ const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments ) override final;
+ virtual sal_Bool SAL_CALL matchesTemplate(
+ const css::uno::Reference< css::chart2::XDiagram >& xDiagram,
+ sal_Bool bAdaptProperties ) override final;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getDataInterpreter() override final;
+ virtual css::uno::Reference< ::css::chart2::XChartType > SAL_CALL getChartTypeForNewSeries(
+ const css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes ) override final;
+ virtual void SAL_CALL applyStyle(
+ const css::uno::Reference< css::chart2::XDataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount ) override final;
+ virtual void SAL_CALL resetStyles(
+ const css::uno::Reference< css::chart2::XDiagram >& xDiagram ) override final;
+
+ void changeDiagram(
+ const rtl::Reference< ::chart::Diagram >& xDiagram );
+ void changeDiagramData(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments );
+ virtual bool matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties );
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForNewSeries2( const std::vector<
+ rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) = 0;
+ virtual rtl::Reference< ::chart::DataInterpreter > getDataInterpreter2();
+ virtual void applyStyle2(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount );
+ virtual void resetStyles2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram );
+
+ /// @throws css::uno::RuntimeException
+ void applyStyles(
+ const rtl::Reference< ::chart::Diagram >& xDiagram );
+
+ // ____ XServiceName ____
+ virtual OUString SAL_CALL getServiceName() override;
+
+ // Methods to override for automatic creation
+
+ /// returns 2 by default. Supported are 2 and 3
+ virtual sal_Int32 getDimension() const;
+
+ /** returns StackMode::NONE by default. This is a global flag used for all
+ series of a specific chart type. If percent stacking is supported, the
+ percent stacking mode is retrieved from the first chart type (index 0)
+
+ @param nChartTypeIndex denotes the index of the charttype in means
+ defined by the template creation order, i.e., 0 means the first
+ chart type that a template creates.
+ */
+ virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const;
+
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForIndex( sal_Int32 nChartTypeIndex ) = 0;
+
+ virtual bool isSwapXAndY() const;
+
+ // Methods for creating the diagram piecewise
+
+ /** Allows derived classes to manipulate the diagrams whole, like changing
+ the wall color. The default implementation is empty. It is called by
+ FillDiagram which is called by createDiagramByDataSource and
+ changeDiagram
+ */
+ virtual void adaptDiagram(
+ const rtl::Reference< ::chart::Diagram > & xDiagram );
+
+ /** Creates a 2d or 3d cartesian coordinate system with mathematically
+ oriented, linear scales with auto-min/max. If the given
+ CoordinateSystemContainer is not empty, those coordinate system should
+ be reused.
+
+ <p>The dimension depends on the value returned by getDimension().</p>
+ */
+ virtual void createCoordinateSystems(
+ const rtl::Reference< ::chart::Diagram > & xDiagram );
+
+ /** Sets categories at the scales of dimension 0 and the percent stacking at
+ the scales of dimension 1 of all given coordinate systems.
+
+ <p>Called by FillDiagram.</p>
+ */
+ virtual void adaptScales(
+ const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > & aCooSysSeq,
+ const css::uno::Reference< css::chart2::data::XLabeledDataSequence > & xCategories );
+
+ /** create a data series tree, that fits the requirements of the chart type.
+
+ <p>As default, this creates a tree with the following structure:</p>
+
+ <pre>
+ root
+ |
+ +-- chart type (determined by getChartTypeForNewSeries())
+ |
+ +-- category (DiscreteStackableScaleGroup using scale 0)
+ |
+ +-- values (ContinuousStackableScaleGroup using scale 1)
+ |
+ +-- series 0
+ |
+ +-- series 1
+ |
+ ...
+ |
+ +.. series n-1
+ </pre>
+
+ <p>If there are less than two scales available the returned tree is
+ empty.</p>
+ */
+ virtual void createChartTypes(
+ const std::vector<
+ std::vector<
+ rtl::Reference<
+ ::chart::DataSeries > > > & aSeriesSeq,
+ const std::vector<
+ rtl::Reference<
+ ::chart::BaseCoordinateSystem > > & rCoordSys,
+ const std::vector< rtl::Reference< ChartType > > & aOldChartTypesSeq
+ );
+
+ /** create axes and add them to the given container. If there are already
+ compatible axes in the container these should be maintained.
+
+ <p>As default, this method creates as many axes as there are dimensions
+ in the given first coordinate system. Each of the axis
+ represents one of the dimensions of the coordinate systems. If there are series
+ requesting a secondary axes a secondary y axes is added</p>
+ */
+ void createAxes(
+ const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > & rCoordSys );
+
+ /** Give the number of requested axis per dimension here. Default is one
+ axis for each dimension
+ */
+ virtual sal_Int32 getAxisCountByDimension( sal_Int32 nDimension );
+
+ /** adapt properties of existing axes and remove superfluous axes
+ */
+ virtual void adaptAxes(
+ const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > & rCoordSys );
+
+ const css::uno::Reference< css::uno::XComponentContext >&
+ GetComponentContext() const { return m_xContext;}
+
+ static void copyPropertiesFromOldToNewCoordinateSystem(
+ const std::vector< rtl::Reference< ChartType > > & rOldChartTypesSeq,
+ const rtl::Reference< ChartType > & xNewChartType );
+
+protected:
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ mutable rtl::Reference< ::chart::DataInterpreter > m_xDataInterpreter;
+
+private:
+ const OUString m_aServiceName;
+
+private:
+ /** modifies the given diagram
+ */
+ void FillDiagram( const rtl::Reference< ::chart::Diagram >& xDiagram,
+ const std::vector<
+ std::vector<
+ rtl::Reference<
+ ::chart::DataSeries > > > & aSeriesSeq,
+ const css::uno::Reference< css::chart2::data::XLabeledDataSequence >& xCategories,
+ const std::vector< rtl::Reference< ChartType > > & aOldChartTypesSeq);
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ChartTypeTemplateProvider.hxx b/chart2/source/inc/ChartTypeTemplateProvider.hxx
new file mode 100644
index 0000000000..400b1c8e28
--- /dev/null
+++ b/chart2/source/inc/ChartTypeTemplateProvider.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ref.hxx>
+
+namespace chart
+{
+class ChartTypeTemplate;
+
+class ChartTypeTemplateProvider
+{
+public:
+ virtual rtl::Reference<::chart::ChartTypeTemplate> getCurrentTemplate() const = 0;
+ virtual ~ChartTypeTemplateProvider() {}
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ChartViewHelper.hxx b/chart2/source/inc/ChartViewHelper.hxx
new file mode 100644
index 0000000000..be70dd9fec
--- /dev/null
+++ b/chart2/source/inc/ChartViewHelper.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+#include <rtl/ref.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+
+namespace com::sun::star::chart2
+{
+class XChartDocument;
+}
+
+namespace chart
+{
+class ChartModel;
+
+namespace ChartViewHelper
+{
+OOO_DLLPUBLIC_CHARTTOOLS void setViewToDirtyState(const rtl::Reference<ChartModel>& xChartModel);
+OOO_DLLPUBLIC_CHARTTOOLS void
+setViewToDirtyState_UNO(const css::uno::Reference<css::chart2::XChartDocument>& xChartModel);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/CloneHelper.hxx b/chart2/source/inc/CloneHelper.hxx
new file mode 100644
index 0000000000..c0896efb5c
--- /dev/null
+++ b/chart2/source/inc/CloneHelper.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/util/XCloneable.hpp>
+#include <rtl/ref.hxx>
+#include <algorithm>
+#include <iterator>
+#include <vector>
+
+namespace chart::CloneHelper
+{
+
+/// functor that clones a UNO-Reference
+template< class Interface >
+ struct CreateRefClone
+{
+ css::uno::Reference<Interface> operator() ( const css::uno::Reference<Interface> & xOther )
+ {
+ css::uno::Reference<Interface> xResult;
+ css::uno::Reference< css::util::XCloneable >
+ xCloneable( xOther, css::uno::UNO_QUERY );
+ if( xCloneable.is())
+ xResult.set( xCloneable->createClone(), css::uno::UNO_QUERY );
+
+ return xResult;
+ }
+};
+
+/// clones a vector of UNO-References
+template< class Interface >
+ void CloneRefVector(
+ const std::vector< css::uno::Reference< Interface > > & rSource,
+ std::vector< css::uno::Reference< Interface > > & rDestination )
+{
+ std::transform( rSource.begin(), rSource.end(),
+ std::back_inserter( rDestination ),
+ CreateRefClone< Interface >());
+}
+
+template< class T >
+ void CloneRefVector(
+ const std::vector< rtl::Reference< T > > & rSource,
+ std::vector< rtl::Reference< T > > & rDestination )
+{
+ for (const auto & rSourceItem : rSource)
+ rDestination.push_back(static_cast<T*>(rSourceItem->createClone().get()));
+}
+
+/// clones a UNO-sequence of UNO-References
+template< class Interface >
+ void CloneRefSequence(
+ const css::uno::Sequence< css::uno::Reference<Interface> > & rSource,
+ css::uno::Sequence< css::uno::Reference<Interface> > & rDestination )
+{
+ rDestination.realloc( rSource.getLength());
+ std::transform( rSource.begin(), rSource.end(),
+ rDestination.getArray(),
+ CreateRefClone< Interface >());
+}
+
+} // namespace chart::CloneHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ColorPerPointHelper.hxx b/chart2/source/inc/ColorPerPointHelper.hxx
new file mode 100644
index 0000000000..43a8d56802
--- /dev/null
+++ b/chart2/source/inc/ColorPerPointHelper.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::uno { template <class interface_type> class Reference; }
+
+namespace chart
+{
+class DataSeries;
+
+class OOO_DLLPUBLIC_CHARTTOOLS ColorPerPointHelper
+{
+public:
+ static bool hasPointOwnColor(
+ const rtl::Reference< ::chart::DataSeries >& xDataSeries
+ , sal_Int32 nPointIndex
+ , const css::uno::Reference< css::beans::XPropertySet >& xDataPointProperties //may be NULL this is just for performance
+ );
+
+ // returns true if AttributedDataPoints contains nPointIndex and the
+ // property Color is DEFAULT
+ SAL_DLLPRIVATE static bool hasPointOwnProperties(
+ const rtl::Reference< ::chart::DataSeries >& xDataSeries
+ , sal_Int32 nPointIndex );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/CommonConverters.hxx b/chart2/source/inc/CommonConverters.hxx
new file mode 100644
index 0000000000..c6dc7b2ecd
--- /dev/null
+++ b/chart2/source/inc/CommonConverters.hxx
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/drawing/HomogenMatrix3.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b3dpoint.hxx>
+#include <basegfx/vector/b3dvector.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include "charttoolsdllapi.hxx"
+
+namespace com::sun::star::awt { struct Rectangle; }
+namespace com::sun::star::chart2::data { class XDataSequence; }
+namespace com::sun::star::drawing { struct PolyPolygonBezierCoords; }
+
+namespace chart
+{
+
+/**
+diverse methods for class conversions; e.g. ::basegfx::B3DHomMatrix to HomogenMatrix
+and operations e.g drawing::Position3D + drawing::Direction3D
+*/
+
+/** ::basegfx::B3DHomMatrix -> HomogenMatrix
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::drawing::HomogenMatrix
+ B3DHomMatrixToHomogenMatrix( const ::basegfx::B3DHomMatrix& rM );
+
+/** HomogenMatrix -> ::basegfx::B3DHomMatrix
+*/
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DHomMatrix HomogenMatrixToB3DHomMatrix( const css::drawing::HomogenMatrix& rHM );
+
+/** ::basegfx::B3DHomMatrix -> B2DHomMatrix
+*/
+OOO_DLLPUBLIC_CHARTTOOLS
+::basegfx::B2DHomMatrix IgnoreZ( const ::basegfx::B3DHomMatrix& rM );
+
+/** B2DHomMatrix <-> HomogenMatrix3
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::drawing::HomogenMatrix3
+ B2DHomMatrixToHomogenMatrix3( const ::basegfx::B2DHomMatrix& rM );
+
+/** Position3D -> B3DPoint
+*/
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DPoint Position3DToB3DPoint( const css::drawing::Position3D& rPosition );
+
+/** B3DVector -> Direction3D
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Direction3D B3DVectorToDirection3D( const ::basegfx::B3DVector& rVector);
+
+/** B3DPoint -> Position3D
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D B3DPointToPosition3D( const ::basegfx::B3DPoint& rPoint);
+
+/** Direction3D -> B3DVector
+*/
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DVector Direction3DToB3DVector( const css::drawing::Direction3D& rDirection);
+
+/** PolyPolygonShape3D + drawing::Position3D -> PolyPolygonShape3D
+*/
+OOO_DLLPUBLIC_CHARTTOOLS
+void AddPointToPoly( css::drawing::PolyPolygonShape3D& rPoly
+ , const css::drawing::Position3D& rPos
+ , sal_Int32 nSequenceIndex=0 );
+OOO_DLLPUBLIC_CHARTTOOLS
+void AddPointToPoly( std::vector<std::vector<css::drawing::Position3D>>& rPoly
+ , const css::drawing::Position3D& rPos
+ , sal_Int32 nSequenceIndex=0 );
+
+/** get a single Point from a Polygon
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D getPointFromPoly(
+ const std::vector<std::vector<css::drawing::Position3D>>& rPolygon
+ , sal_Int32 nPointIndex, sal_Int32 nPolyIndex );
+OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D getPointFromPoly(
+ const css::drawing::PolyPolygonShape3D& rPolygon
+ , sal_Int32 nPointIndex, sal_Int32 nPolyIndex );
+
+OOO_DLLPUBLIC_CHARTTOOLS
+void addPolygon( std::vector<std::vector<css::drawing::Position3D>>& rRet
+ , const std::vector<std::vector<css::drawing::Position3D>>& rAdd );
+/** PolyPolygonShape3D + PolyPolygonShape3D -> PolyPolygonShape3D
+*/
+OOO_DLLPUBLIC_CHARTTOOLS
+void appendPoly( std::vector<std::vector<css::drawing::Position3D>>& rRet
+ , const std::vector<std::vector<css::drawing::Position3D>>& rAdd );
+
+/** PolyPolygonBezierCoords -> PolyPolygonShape3D
+*/
+OOO_DLLPUBLIC_CHARTTOOLS
+css::drawing::PolyPolygonShape3D BezierToPoly(
+ const css::drawing::PolyPolygonBezierCoords& rBezier );
+
+/** PolyPolygonShape3D -> drawing::PointSequenceSequence (2D)
+*/
+OOO_DLLPUBLIC_CHARTTOOLS
+css::drawing::PointSequenceSequence PolyToPointSequence(
+ const css::drawing::PolyPolygonShape3D& rPolyPolygon );
+OOO_DLLPUBLIC_CHARTTOOLS
+css::drawing::PointSequenceSequence PolyToPointSequence(
+ const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon );
+
+/** PolyPolygonShape3D -> basegfx::B2DPolyPolygon (2D)
+*/
+OOO_DLLPUBLIC_CHARTTOOLS
+basegfx::B2DPolyPolygon PolyToB2DPolyPolygon(
+ const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon );
+
+/** drawing::PointSequenceSequence + drawing::PointSequenceSequence
+*/
+OOO_DLLPUBLIC_CHARTTOOLS
+void appendPointSequence( css::drawing::PointSequenceSequence& rTarget
+ , const css::drawing::PointSequenceSequence& rAdd );
+
+/** Position3D + Direction3D == Position3D
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D
+ operator+( const css::drawing::Position3D& rPos
+ , const css::drawing::Direction3D& rDirection);
+
+/** Position3D - Position3D == Direction3D
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Direction3D
+ operator-( const css::drawing::Position3D& rPos1
+ , const css::drawing::Position3D& rPos2);
+
+/** awt::Rect --> awt::Point (2D)
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::awt::Point ToPoint( const css::awt::Rectangle& rRectangle );
+
+/** awt::Rect --> awt::Size (2D)
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::awt::Size ToSize( const css::awt::Rectangle& rRectangle );
+
+/** Position3D --> awt::Point (2D)
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::awt::Point Position3DToAWTPoint( const css::drawing::Position3D& rPos );
+
+/** Direction3D --> awt::Size (2D)
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::awt::Size Direction3DToAWTSize( const css::drawing::Direction3D& rDirection );
+
+/** Sequence<double> -> drawing::Position3D
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D
+ SequenceToPosition3D( const css::uno::Sequence< double >& rSeq );
+
+/** chart2::XDataSequence -> uno::Sequence< double >
+*/
+
+OOO_DLLPUBLIC_CHARTTOOLS
+css::uno::Sequence< double > DataSequenceToDoubleSequence(
+ const css::uno::Reference< css::chart2::data::XDataSequence > & xDataSequence );
+
+OOO_DLLPUBLIC_CHARTTOOLS
+css::uno::Sequence< OUString > DataSequenceToStringSequence(
+ const css::uno::Reference< css::chart2::data::XDataSequence > & xDataSequence );
+
+/** std::vector< std::vector< T > > -> std::vector< T >
+ */
+template< typename T >
+std::vector< T >
+ FlattenSequence( const std::vector< std::vector< T > > & aSeqSeq )
+{
+ sal_Int32 nOuter, nInner, nCount = 0,
+ nResultSize = 0;
+ const sal_Int32 nOuterSize = aSeqSeq.size();
+ for( nOuter=0; nOuter<nOuterSize; ++nOuter )
+ nResultSize += aSeqSeq[nOuter].size();
+ std::vector< T > aResult( nResultSize );
+
+ for( nOuter=0; nOuter<nOuterSize; ++nOuter )
+ {
+ const sal_Int32 nInnerSize = aSeqSeq[nOuter].size();
+ for( nInner=0; nInner<nInnerSize; ++nInner, ++nCount )
+ aResult[nCount] = aSeqSeq[nOuter][nInner];
+ }
+ return aResult;
+}
+
+OOO_DLLPUBLIC_CHARTTOOLS
+bool hasDoubleValue( const css::uno::Any& rAny );
+
+OOO_DLLPUBLIC_CHARTTOOLS
+bool hasLongOrShortValue( const css::uno::Any& rAny );
+OOO_DLLPUBLIC_CHARTTOOLS
+sal_Int16 getShortForLongAlso( const css::uno::Any& rAny );
+
+OOO_DLLPUBLIC_CHARTTOOLS
+bool replaceParamterInString( OUString & rInOutResourceString,
+ std::u16string_view rParamToReplace,
+ std::u16string_view rReplaceWith );
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/CommonFunctors.hxx b/chart2/source/inc/CommonFunctors.hxx
new file mode 100644
index 0000000000..7bb776490c
--- /dev/null
+++ b/chart2/source/inc/CommonFunctors.hxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <o3tl/any.hxx>
+#include <rtl/math.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <rtl/ustring.hxx>
+#include "charttoolsdllapi.hxx"
+
+#include <limits>
+
+namespace chart::CommonFunctors
+{
+
+/** unary function to convert any type T into a css::uno::Any.
+
+ <p>uno::makeAny is an inline function. Thus is cannot be taken directly
+ (via mem_fun_ptr)</p>
+*/
+template< typename T >
+ struct makeAny
+{
+ css::uno::Any operator() ( const T & aVal )
+ {
+ return css::uno::Any( aVal );
+ }
+};
+
+/** unary function to convert css::uno::Any into a double number.
+
+ <p>In case no number can be generated from the Any, NaN is returned.</p>
+*/
+struct OOO_DLLPUBLIC_CHARTTOOLS AnyToDouble
+{
+ double operator() ( const css::uno::Any & rAny )
+ {
+ double fResult = std::numeric_limits<double>::quiet_NaN();
+ rAny >>= fResult;
+ return fResult;
+ }
+};
+
+/** unary function to convert css::uno::Any into an
+ OUString.
+*/
+struct OOO_DLLPUBLIC_CHARTTOOLS AnyToString
+{
+ OUString operator() ( const css::uno::Any & rAny )
+ {
+ if( auto pDouble = o3tl::tryAccess<double>(rAny) )
+ {
+ if( std::isnan(*pDouble) )
+ return OUString();
+ return ::rtl::math::doubleToUString(
+ * pDouble,
+ rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, // use maximum decimal places available
+ '.', // decimal separator
+ true // remove trailing zeros
+ );
+ }
+ else if( auto s = o3tl::tryAccess<OUString>(rAny) )
+ {
+ return *s;
+ }
+
+ return OUString();
+ }
+};
+
+/** unary function to convert an OUString into a double number.
+
+ <p>For conversion rtl::math::StringToDouble is used.</p>
+ */
+struct OOO_DLLPUBLIC_CHARTTOOLS OUStringToDouble
+{
+ double operator() ( std::u16string_view rStr )
+ {
+ rtl_math_ConversionStatus eConversionStatus;
+ double fResult = ::rtl::math::stringToDouble( rStr, '.', ',', & eConversionStatus );
+
+ if( eConversionStatus != rtl_math_ConversionStatus_Ok )
+ return std::numeric_limits<double>::quiet_NaN();
+
+ return fResult;
+ }
+};
+
+/** unary function to convert a double number into an OUString.
+
+ <p>For conversion rtl::math::DoubleToOUString is used.</p>
+ */
+struct OOO_DLLPUBLIC_CHARTTOOLS DoubleToOUString
+{
+ OUString operator() ( double fNumber )
+ {
+ return ::rtl::math::doubleToUString(
+ fNumber,
+ rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, // use maximum decimal places available
+ '.',
+ true
+ );
+ }
+};
+
+} // namespace chart::CommonFunctors
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ConfigColorScheme.hxx b/chart2/source/inc/ConfigColorScheme.hxx
new file mode 100644
index 0000000000..8375c60027
--- /dev/null
+++ b/chart2/source/inc/ConfigColorScheme.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/chart2/XColorScheme.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <memory>
+#include <string_view>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+
+OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference< css::chart2::XColorScheme > createConfigColorScheme(
+ const css::uno::Reference< css::uno::XComponentContext > & xContext );
+
+namespace impl
+{
+class ChartConfigItem;
+}
+
+class ConfigColorScheme final :
+ public ::cppu::WeakImplHelper<
+ css::chart2::XColorScheme,
+ css::lang::XServiceInfo >
+{
+public:
+ explicit ConfigColorScheme( const css::uno::Reference< css::uno::XComponentContext > & xContext );
+ virtual ~ConfigColorScheme() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ ConfigItemListener ____
+ void notify();
+
+protected:
+ // ____ XColorScheme ____
+ virtual ::sal_Int32 SAL_CALL getColorByIndex( ::sal_Int32 nIndex ) override;
+
+private:
+ void retrieveConfigColors();
+
+ // member variables
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ std::unique_ptr< impl::ChartConfigItem > m_apChartConfigItem;
+ mutable css::uno::Sequence< sal_Int64 > m_aColorSequence;
+ mutable sal_Int32 m_nNumberOfColors;
+ bool m_bNeedsUpdate;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ControllerLockGuard.hxx b/chart2/source/inc/ControllerLockGuard.hxx
new file mode 100644
index 0000000000..f9de7aa5b4
--- /dev/null
+++ b/chart2/source/inc/ControllerLockGuard.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+#include <rtl/ref.hxx>
+
+namespace chart
+{
+class ChartModel;
+}
+namespace com::sun::star::frame
+{
+class XModel;
+}
+
+namespace chart
+{
+/** This guard calls lockControllers at the given Model in the CTOR and
+ unlockControllers in the DTOR. Using this ensures that controllers do not
+ remain locked when leaving a function even in case an exception is thrown.
+ */
+class OOO_DLLPUBLIC_CHARTTOOLS ControllerLockGuardUNO
+{
+public:
+ explicit ControllerLockGuardUNO(rtl::Reference<::chart::ChartModel> xModel);
+ ~ControllerLockGuardUNO();
+
+private:
+ rtl::Reference<::chart::ChartModel> mxModel;
+};
+
+class ControllerLockGuard
+{
+public:
+ explicit ControllerLockGuard(ChartModel& rModel);
+ ~ControllerLockGuard();
+
+private:
+ ChartModel& mrModel;
+};
+
+/** This helper class can be used to pass a locking mechanism to other objects
+ without exposing the full XModel to it.
+
+ Use the ControllerLockHelperGuard to lock/unlock the model during a block of
+ instructions.
+ */
+class OOO_DLLPUBLIC_CHARTTOOLS ControllerLockHelper
+{
+public:
+ explicit ControllerLockHelper(rtl::Reference<::chart::ChartModel> xModel);
+ ~ControllerLockHelper();
+
+ SAL_DLLPRIVATE void lockControllers();
+ SAL_DLLPRIVATE void unlockControllers();
+
+private:
+ rtl::Reference<::chart::ChartModel> m_xModel;
+};
+
+/** This guard calls lockControllers at the given ControllerLockHelper in the
+ CTOR and unlockControllers in the DTOR. Using this ensures that controllers
+ do not remain locked when leaving a function even in case an exception is
+ thrown.
+ */
+class OOO_DLLPUBLIC_CHARTTOOLS ControllerLockHelperGuard
+{
+public:
+ explicit ControllerLockHelperGuard(ControllerLockHelper& rHelper);
+ ~ControllerLockHelperGuard();
+
+private:
+ ControllerLockHelper& m_rHelper;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/DataInterpreter.hxx b/chart2/source/inc/DataInterpreter.hxx
new file mode 100644
index 0000000000..7638e5ccee
--- /dev/null
+++ b/chart2/source/inc/DataInterpreter.hxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "DataSeries.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <rtl/ref.hxx>
+#include <vector>
+
+namespace chart
+{
+class DataSeries;
+class DataSource;
+class LabeledDataSequence;
+
+/** offers tooling to interpret different data sources in a structural
+ and chart-type-dependent way.
+ */
+struct InterpretedData
+{
+ std::vector< std::vector< rtl::Reference<::chart::DataSeries> > > Series;
+ css::uno::Reference< css::chart2::data::XLabeledDataSequence > Categories;
+};
+
+/** offers tooling to interpret different data sources in a structural
+ and chart-type-dependent way.
+ */
+class SAL_DLLPUBLIC_RTTI DataInterpreter : public ::cppu::WeakImplHelper<
+ css::lang::XServiceInfo >
+{
+public:
+ explicit DataInterpreter();
+ virtual ~DataInterpreter() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // convenience methods
+ static OUString GetRole( const css::uno::Reference< css::chart2::data::XDataSequence > & xSeq );
+
+ static void SetRole(
+ const css::uno::Reference< css::chart2::data::XDataSequence > & xSeq,
+ const OUString & rRole );
+
+ static css::uno::Any GetProperty(
+ const css::uno::Sequence<css::beans::PropertyValue > & aArguments,
+ std::u16string_view rName );
+
+ static bool HasCategories(
+ const css::uno::Sequence< css::beans::PropertyValue > & rArguments,
+ const std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > & rData );
+
+ static bool UseCategoriesAsX(
+ const css::uno::Sequence< css::beans::PropertyValue > & rArguments );
+
+ static std::vector<css::uno::Reference< css::chart2::data::XLabeledDataSequence >> getDataSequences(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xSource);
+
+ // ____ DataInterpreter ____
+ /** Interprets the given data.
+
+ @param xSource
+ the data source.
+
+ @param aArguments
+ Arguments that tell the template how to slice the given
+ range. The properties should be defined in a separate
+ service.
+
+ <p>For standard parameters that may be used, see the
+ service StandardDiagramCreationParameters.
+ </p>
+
+ @param aSeriesToReUse
+ use all the data series given here for the result before
+ creating new ones.
+ */
+ virtual InterpretedData interpretDataSource(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments,
+ const std::vector< rtl::Reference< ::chart::DataSeries > >& aSeriesToReUse );
+
+ /** Re-interprets the data given in <code>aInterpretedData</code>
+ while keeping the number of data series and the categories.
+ */
+ virtual InterpretedData reinterpretDataSeries(
+ const InterpretedData& aInterpretedData );
+
+ /** parses the given data and states, if a
+ reinterpretDataSeries() call can be done
+ without data loss.
+
+ @return
+ `TRUE`, if the data given in
+ <code>aInterpretedData</code> has a similar structure than
+ the one required is used as output of the data interpreter.
+ */
+ virtual bool isDataCompatible(
+ const InterpretedData& aInterpretedData );
+
+ /** Try to reverse the operation done in
+ interpretDataSource().
+
+ <p>In case <code>aInterpretedData</code> is the result of
+ interpretDataSource()( <code>xSource</code> ),
+ the result of this method should be <code>xSource</code>.</p>
+ */
+ static rtl::Reference< ::chart::DataSource > mergeInterpretedData(
+ const InterpretedData& aInterpretedData );
+
+ /** Get chart information that is specific to a particular chart
+ type, by key.
+
+ @param sKey
+ name of the piece of data to retrieve.
+
+ <p>Supported key strings:</p>
+ <ul>
+ <li><tt>"stock variant"</tt>: stock chart variant,
+ with 0 = neither Open Values nor volume, 1 = Open Values,
+ 2 = volume, 3 = both. Valid for candlestick charts.</li>
+ </ul>
+
+ @return
+ The value requested, or nothing if not present.
+ */
+ virtual css::uno::Any getChartTypeSpecificData(
+ const OUString& sKey );
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/DataSeries.hxx b/chart2/source/inc/DataSeries.hxx
new file mode 100644
index 0000000000..e643486d59
--- /dev/null
+++ b/chart2/source/inc/DataSeries.hxx
@@ -0,0 +1,190 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+// UNO types
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/chart2/data/XDataSink.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+// helper classes
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include "ModifyListenerHelper.hxx"
+#include "PropertyHelper.hxx"
+
+// STL
+#include <vector>
+#include <map>
+
+#include "OPropertySet.hxx"
+#include "charttoolsdllapi.hxx"
+
+namespace com::sun::star::beans { class XPropertySet; }
+
+namespace chart
+{
+class LabeledDataSequence;
+class RegressionCurveModel;
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::chart2::XDataSeries,
+ css::chart2::data::XDataSink,
+ css::chart2::data::XDataSource,
+ css::lang::XServiceInfo,
+ css::chart2::XRegressionCurveContainer,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ DataSeries_Base;
+}
+
+class OOO_DLLPUBLIC_CHARTTOOLS DataSeries
+ final
+ : public impl::DataSeries_Base
+ , public ::property::OPropertySet
+{
+public:
+ explicit DataSeries();
+ virtual ~DataSeries() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+ explicit DataSeries( const DataSeries & rOther );
+
+ // ____ XDataSeries ____
+ /// @see css::chart2::XDataSeries
+ virtual css::uno::Reference< css::beans::XPropertySet >
+ SAL_CALL getDataPointByIndex( sal_Int32 nIndex ) override;
+ virtual void SAL_CALL resetDataPoint( sal_Int32 nIndex ) override;
+ virtual void SAL_CALL resetAllDataPoints() override;
+
+ // ____ XDataSink ____
+ /// @see css::chart2::data::XDataSink
+ virtual void SAL_CALL setData( const css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > >& aData ) override;
+
+ // ____ XDataSource ____
+ /// @see css::chart2::data::XDataSource
+ virtual css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > SAL_CALL getDataSequences() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual void SAL_CALL getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle ) const override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast
+ ( sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ /// @see css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ /// make original interface function visible again
+ using ::com::sun::star::beans::XFastPropertySet::getFastPropertyValue;
+
+ // ____ XRegressionCurveContainer ____
+ /// @see css::chart2::XRegressionCurveContainer
+ virtual void SAL_CALL addRegressionCurve(
+ const css::uno::Reference< css::chart2::XRegressionCurve >& aRegressionCurve ) override;
+ virtual void SAL_CALL removeRegressionCurve(
+ const css::uno::Reference< css::chart2::XRegressionCurve >& aRegressionCurve ) override;
+ virtual css::uno::Sequence< css::uno::Reference< css::chart2::XRegressionCurve > > SAL_CALL getRegressionCurves() override;
+ virtual void SAL_CALL setRegressionCurves(
+ const css::uno::Sequence< css::uno::Reference< css::chart2::XRegressionCurve > >& aRegressionCurves ) override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ typedef std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > tDataSequenceContainer;
+
+ void setData( const tDataSequenceContainer& aData );
+ const tDataSequenceContainer & getDataSequences2() const { return m_aDataSequences; }
+
+ typedef
+ std::vector< rtl::Reference< ::chart::RegressionCurveModel > >
+ tRegressionCurveContainerType;
+
+ const tRegressionCurveContainerType & getRegressionCurves2() const { return m_aRegressionCurves; }
+
+ /** Get the label of a series (e.g. for the legend)
+
+ @param rLabelSequenceRole
+ The data sequence contained in xSeries that has this role will be used
+ to take its label.
+ */
+ OUString getLabelForRole( const OUString & rLabelSequenceRole );
+
+ bool hasUnhiddenData();
+
+private:
+
+ // late initialization to call after copy-constructing
+ void Init( const DataSeries & rOther );
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ void fireModifyEvent();
+
+ tDataSequenceContainer m_aDataSequences;
+
+ typedef std::map< sal_Int32,
+ css::uno::Reference< css::beans::XPropertySet > > tDataPointAttributeContainer;
+ tDataPointAttributeContainer m_aAttributedDataPoints;
+
+ tRegressionCurveContainerType m_aRegressionCurves;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+OOO_DLLPUBLIC_CHARTTOOLS const tPropertyValueMap & StaticDataSeriesDefaults();
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/DataSeriesHelper.hxx b/chart2/source/inc/DataSeriesHelper.hxx
new file mode 100644
index 0000000000..b1f4e0ba34
--- /dev/null
+++ b/chart2/source/inc/DataSeriesHelper.hxx
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "StackMode.hxx"
+#include "charttoolsdllapi.hxx"
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+
+#include <vector>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XChartType; }
+namespace com::sun::star::chart2 { class XCoordinateSystem; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::chart2::data { class XDataSequence; }
+namespace com::sun::star::chart2::data { class XDataSource; }
+namespace com::sun::star::chart2::data { class XLabeledDataSequence; }
+namespace com::sun::star::uno { class Any; }
+namespace com::sun::star::uno { template <class E> class Sequence; }
+namespace chart { class BaseCoordinateSystem; }
+namespace chart { class ChartType; }
+namespace chart { class DataSource; }
+namespace chart { class Diagram; }
+namespace chart { class DataSeries; }
+namespace chart { class LabeledDataSequence; }
+
+namespace chart::DataSeriesHelper
+{
+
+OOO_DLLPUBLIC_CHARTTOOLS OUString
+ getRole( const css::uno::Reference<css::chart2::data::XLabeledDataSequence>& xLabeledDataSequence );
+
+/** Retrieves the data sequence in the given data source that matches the
+ given role. If more than one sequences match the role, the first match
+ is returned. If no sequence matches, an empty reference is returned.
+
+ @param aSource
+ The data source containing all data sequences to be searched through.
+
+ @param aRole
+ The role that is to be filtered out.
+*/
+OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference< css::chart2::data::XLabeledDataSequence >
+ getDataSequenceByRole( const css::uno::Reference< css::chart2::data::XDataSource > & xSource,
+ const OUString& aRole,
+ bool bMatchPrefix = false );
+
+/** Retrieves all data sequences in the given data source that match the given
+ role prefix.
+
+ @param aSource
+ The data source containing all data sequences to be searched through.
+
+ @param aRole
+ The role that is to be filtered out.
+*/
+OOO_DLLPUBLIC_CHARTTOOLS std::vector<
+ css::uno::Reference< css::chart2::data::XLabeledDataSequence > >
+ getAllDataSequencesByRole( const css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > & aDataSequences,
+ const OUString& aRole );
+OOO_DLLPUBLIC_CHARTTOOLS std::vector<
+ css::uno::Reference< css::chart2::data::XLabeledDataSequence > >
+ getAllDataSequencesByRole( const std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > & aDataSequences,
+ const OUString& aRole );
+
+OOO_DLLPUBLIC_CHARTTOOLS
+std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence > >
+getAllDataSequences(
+ const std::vector<rtl::Reference<::chart::DataSeries> >& aSeries );
+
+/** Retrieves all data sequences found in the given data series and puts them
+ into a data source. The order of sequences will match the order of the data
+ series.
+ */
+OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference< ::chart::DataSource >
+ getDataSource( const std::vector< rtl::Reference< ::chart::DataSeries > > & aSeries );
+
+OOO_DLLPUBLIC_CHARTTOOLS void setStackModeAtSeries(
+ const std::vector< rtl::Reference< ::chart::DataSeries > > & aSeries,
+ const rtl::Reference< ::chart::BaseCoordinateSystem > & xCorrespondingCoordinateSystem,
+ StackMode eStackMode );
+
+OOO_DLLPUBLIC_CHARTTOOLS sal_Int32 getAttachedAxisIndex(
+ const rtl::Reference< ::chart::DataSeries > & xSeries );
+
+/// @param nAxisIndex, if -1 it is determined by the given data series via getAttachedAxisIndex
+OOO_DLLPUBLIC_CHARTTOOLS sal_Int32 getNumberFormatKeyFromAxis(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ const rtl::Reference< ::chart::BaseCoordinateSystem > & xCorrespondingCoordinateSystem,
+ sal_Int32 nDimensionIndex,
+ sal_Int32 nAxisIndex = -1 );
+
+OOO_DLLPUBLIC_CHARTTOOLS
+rtl::Reference< ::chart::BaseCoordinateSystem >
+ getCoordinateSystemOfSeries(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ const rtl::Reference< ::chart::Diagram > & xDiagram );
+
+OOO_DLLPUBLIC_CHARTTOOLS
+rtl::Reference< ::chart::ChartType >
+ getChartTypeOfSeries(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ const rtl::Reference< ::chart::Diagram > & xDiagram );
+
+OOO_DLLPUBLIC_CHARTTOOLS void deleteSeries(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ const rtl::Reference< ::chart::ChartType > & xChartType );
+
+OOO_DLLPUBLIC_CHARTTOOLS void switchSymbolsOnOrOff(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ bool bSymbolsOn, sal_Int32 nSeriesIndex );
+
+OOO_DLLPUBLIC_CHARTTOOLS void switchLinesOnOrOff(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ bool bLinesOn );
+
+OOO_DLLPUBLIC_CHARTTOOLS
+void makeLinesThickOrThin( const rtl::Reference< ::chart::DataSeries > & xSeries, bool bThick );
+
+OOO_DLLPUBLIC_CHARTTOOLS void setPropertyAlsoToAllAttributedDataPoints(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ const OUString& rPropertyName,
+ const css::uno::Any& rPropertyValue );
+
+
+OOO_DLLPUBLIC_CHARTTOOLS bool hasAttributedDataPointDifferentValue(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ const OUString& rPropertyName,
+ const css::uno::Any& rPropertyValue );
+
+OOO_DLLPUBLIC_CHARTTOOLS
+sal_Int32 translateIndexFromHiddenToFullSequence( sal_Int32 nClippedIndex, const css::uno::Reference<
+ css::chart2::data::XDataSequence >& xDataSequence, bool bTranslate );
+
+OOO_DLLPUBLIC_CHARTTOOLS bool hasDataLabelsAtSeries( const rtl::Reference< ::chart::DataSeries >& xSeries );
+
+OOO_DLLPUBLIC_CHARTTOOLS bool hasDataLabelsAtPoints( const rtl::Reference< ::chart::DataSeries >& xSeries );
+
+OOO_DLLPUBLIC_CHARTTOOLS bool hasDataLabelAtPoint( const rtl::Reference< ::chart::DataSeries >& xSeries, sal_Int32 nPointIndex );
+
+OOO_DLLPUBLIC_CHARTTOOLS void insertDataLabelsToSeriesAndAllPoints( const rtl::Reference< ::chart::DataSeries >& xSeries );
+
+OOO_DLLPUBLIC_CHARTTOOLS void insertDataLabelToPoint( const css::uno::Reference< css::beans::XPropertySet >& xPointPropertySet );
+
+OOO_DLLPUBLIC_CHARTTOOLS void deleteDataLabelsFromSeriesAndAllPoints( const rtl::Reference< ::chart::DataSeries >& xSeries );
+
+OOO_DLLPUBLIC_CHARTTOOLS void deleteDataLabelsFromPoint( const css::uno::Reference< css::beans::XPropertySet >& xPointPropertySet );
+
+} // namespace chart::DataSeriesHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/DataSeriesProperties.hxx b/chart2/source/inc/DataSeriesProperties.hxx
new file mode 100644
index 0000000000..7d36721ef0
--- /dev/null
+++ b/chart2/source/inc/DataSeriesProperties.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "PropertyHelper.hxx"
+#include "FastPropertyIdRanges.hxx"
+
+#include <vector>
+
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart::DataSeriesProperties
+{
+ enum
+ {
+ PROP_DATASERIES_ATTRIBUTED_DATA_POINTS = FAST_PROPERTY_ID_START_DATA_SERIES,
+ PROP_DATASERIES_STACKING_DIRECTION,
+ PROP_DATASERIES_VARY_COLORS_BY_POINT,
+ PROP_DATASERIES_ATTACHED_AXIS_INDEX,
+ PROP_DATASERIES_SHOW_LEGEND_ENTRY,
+ PROP_DATASERIES_DELETED_LEGEND_ENTRIES,
+ PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES
+ };
+
+ void AddPropertiesToVector(
+ std::vector< css::beans::Property > & rOutProperties );
+
+ void AddDefaultsToMap( tPropertyValueMap & rOutMap );
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/DataSource.hxx b/chart2/source/inc/DataSource.hxx
new file mode 100644
index 0000000000..6e9b84ed9b
--- /dev/null
+++ b/chart2/source/inc/DataSource.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <com/sun/star/chart2/data/XDataSink.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <vector>
+#include "charttoolsdllapi.hxx"
+
+namespace chart
+{
+class LabeledDataSequence;
+
+class OOO_DLLPUBLIC_CHARTTOOLS DataSource final : public
+ ::cppu::WeakImplHelper<
+ css::lang::XServiceInfo,
+ css::chart2::data::XDataSource,
+ css::chart2::data::XDataSink >
+{
+public:
+ explicit DataSource();
+ explicit DataSource(
+ const css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > & rSequences );
+ explicit DataSource(
+ const std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > & rSequences );
+
+ virtual ~DataSource() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XDataSource ____
+ virtual css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > SAL_CALL
+ getDataSequences() override;
+
+ // ____ XDataSink ____
+ virtual void SAL_CALL setData( const css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > >& aData ) override;
+
+private:
+ css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > >
+ m_aDataSeq;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/DataSourceHelper.hxx b/chart2/source/inc/DataSourceHelper.hxx
new file mode 100644
index 0000000000..52ed689459
--- /dev/null
+++ b/chart2/source/inc/DataSourceHelper.hxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+#include <rtl/ref.hxx>
+
+namespace chart { class ChartModel; }
+namespace com::sun::star::beans { struct PropertyValue; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::chart2::data { class XDataSequence; }
+namespace com::sun::star::chart2::data { class XDataSource; }
+namespace com::sun::star::chart2::data { class XLabeledDataSequence; }
+namespace com::sun::star::frame { class XModel; }
+
+namespace chart
+{
+class DataSource;
+class Diagram;
+class LabeledDataSequence;
+
+class OOO_DLLPUBLIC_CHARTTOOLS DataSourceHelper
+{
+public:
+ static css::uno::Reference< css::chart2::data::XDataSequence >
+ createCachedDataSequence();
+
+ static css::uno::Reference< css::chart2::data::XDataSequence >
+ createCachedDataSequence( const OUString & rSingleText );
+
+ static rtl::Reference< LabeledDataSequence >
+ createLabeledDataSequence(
+ const css::uno::Reference< css::chart2::data::XDataSequence >& xValues ,
+ const css::uno::Reference< css::chart2::data::XDataSequence >& xLabels );
+
+ static rtl::Reference< LabeledDataSequence >
+ createLabeledDataSequence(
+ const css::uno::Reference< css::chart2::data::XDataSequence >& xValues );
+
+ static rtl::Reference< LabeledDataSequence >
+ createLabeledDataSequence();
+
+ static css::uno::Sequence< css::beans::PropertyValue >
+ createArguments(
+ bool bUseColumns, bool bFirstCellAsLabel, bool bHasCategories );
+
+ static css::uno::Sequence<
+ css::beans::PropertyValue > createArguments(
+ const OUString & rRangeRepresentation,
+ const css::uno::Sequence< sal_Int32 >& rSequenceMapping,
+ bool bUseColumns, bool bFirstCellAsLabel, bool bHasCategories );
+
+ SAL_DLLPRIVATE static void readArguments( const css::uno::Sequence< css::beans::PropertyValue >& rArguments
+ , OUString & rRangeRepresentation, css::uno::Sequence< sal_Int32 >& rSequenceMapping
+ , bool& bUseColumns, bool& bFirstCellAsLabel, bool& bHasCategories );
+
+ static rtl::Reference< ::chart::DataSource >
+ pressUsedDataIntoRectangularFormat( const rtl::Reference< ::chart::ChartModel >& xChartDoc );
+
+ SAL_DLLPRIVATE static css::uno::Sequence< OUString > getUsedDataRanges(
+ const rtl::Reference< ::chart::Diagram > & xDiagram );
+
+ static css::uno::Sequence< OUString > getUsedDataRanges(
+ const rtl::Reference<::chart::ChartModel> & xChartModel );
+
+ static rtl::Reference< ::chart::DataSource > getUsedData(
+ ChartModel& rModel );
+
+ static bool detectRangeSegmentation(
+ const rtl::Reference<::chart::ChartModel>& xChartModel
+ , OUString& rOutRangeString
+ , css::uno::Sequence< sal_Int32 >& rSequenceMapping
+ , bool& rOutUseColumns
+ , bool& rOutFirstCellAsLabel
+ , bool& rOutHasCategories );
+
+ static void setRangeSegmentation(
+ const rtl::Reference<::chart::ChartModel>& xChartModel
+ , const css::uno::Sequence< sal_Int32 >& rSequenceMapping
+ , bool bUseColumns
+ , bool bFirstCellAsLabel
+ , bool bUseCategories );
+
+ /** Returns true, if all arguments necessary for getting all data by a
+ rectangular region are returned by detectArguments at the given
+ document's data provider.
+
+ Currently, this is: CellRangeRepresentation, DataRowSource,
+ HasCategories and FirstCellAsLabel.
+ */
+ static bool allArgumentsForRectRangeDetected(
+ const rtl::Reference<::chart::ChartModel>& xChartDocument );
+
+ SAL_DLLPRIVATE static css::uno::Sequence< OUString > getRangesFromLabeledDataSequence(
+ const css::uno::Reference< css::chart2::data::XLabeledDataSequence > & xLSeq );
+
+ SAL_DLLPRIVATE static OUString getRangeFromValues(
+ const css::uno::Reference< css::chart2::data::XLabeledDataSequence > & xLSeq );
+
+ SAL_DLLPRIVATE static css::uno::Sequence< OUString > getRangesFromDataSource(
+ const css::uno::Reference< css::chart2::data::XDataSource > & xSource );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/DataTable.hxx b/chart2/source/inc/DataTable.hxx
new file mode 100644
index 0000000000..da15e264f4
--- /dev/null
+++ b/chart2/source/inc/DataTable.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "OPropertySet.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+
+#include "charttoolsdllapi.hxx"
+#include <com/sun/star/chart2/XDataTable.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include "ModifyListenerHelper.hxx"
+
+namespace chart
+{
+typedef cppu::WeakImplHelper<css::chart2::XDataTable, css::lang::XServiceInfo,
+ css::util::XCloneable, css::util::XModifyBroadcaster,
+ css::util::XModifyListener>
+ DataTable_Base;
+
+/** Data table implementation */
+class OOO_DLLPUBLIC_CHARTTOOLS DataTable final : public DataTable_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit DataTable();
+ virtual ~DataTable() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+ explicit DataTable(DataTable const& rOther);
+
+private:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue(sal_Int32 nHandle, css::uno::Any& rAny) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+public:
+ // ____ XPropertySet ____
+ virtual css::uno::Reference<css::beans::XPropertySetInfo>
+ SAL_CALL getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL
+ addModifyListener(const css::uno::Reference<css::util::XModifyListener>& aListener) override;
+ virtual void SAL_CALL
+ removeModifyListener(const css::uno::Reference<css::util::XModifyListener>& aListener) override;
+
+private:
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(const css::lang::EventObject& aEvent) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/Diagram.hxx b/chart2/source/inc/Diagram.hxx
new file mode 100644
index 0000000000..1d3e8bd789
--- /dev/null
+++ b/chart2/source/inc/Diagram.hxx
@@ -0,0 +1,381 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "OPropertySet.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <com/sun/star/chart2/XDiagram.hpp>
+#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
+#include <com/sun/star/chart2/XTitled.hpp>
+#include <com/sun/star/chart/X3DDefaultSetter.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include "ModifyListenerHelper.hxx"
+#include "charttoolsdllapi.hxx"
+
+#include <vector>
+
+namespace com::sun::star::beans { struct PropertyValue; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2::data { class XDataSource; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+class Axis;
+class BaseCoordinateSystem;
+class ChartType;
+class ChartTypeManager;
+class ChartTypeTemplate;
+class DataSeries;
+class Legend;
+class DataTable;
+class RegressionCurveModel;
+enum class StackMode;
+class Wall;
+enum class ThreeDLookScheme;
+
+enum class DiagramPositioningMode
+{
+ Auto, Excluding, Including
+};
+
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::chart2::XDiagram,
+ css::lang::XServiceInfo,
+ css::chart2::XCoordinateSystemContainer,
+ css::chart2::XTitled,
+ css::chart::X3DDefaultSetter,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener,
+ css::util::XCloneable >
+ Diagram_Base;
+}
+
+class OOO_DLLPUBLIC_CHARTTOOLS Diagram
+ final
+ : public impl::Diagram_Base
+ , public ::property::OPropertySet
+{
+public:
+ Diagram( css::uno::Reference< css::uno::XComponentContext > xContext );
+ virtual ~Diagram() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+ explicit Diagram( const Diagram & rOther );
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XFastPropertySet ____
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const css::uno::Any& rValue ) override;
+
+ /// make original interface function visible again
+ using ::com::sun::star::beans::XFastPropertySet::getFastPropertyValue;
+
+ virtual void SAL_CALL getFastPropertyValue(
+ css::uno::Any& rValue, sal_Int32 nHandle ) const override;
+
+ // ____ XDiagram ____
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getWall() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getFloor() override;
+ virtual css::uno::Reference< css::chart2::XLegend > SAL_CALL getLegend() override;
+ virtual void SAL_CALL setLegend( const css::uno::Reference<
+ css::chart2::XLegend >& xLegend ) override;
+ virtual css::uno::Reference< css::chart2::XColorScheme > SAL_CALL getDefaultColorScheme() override;
+ virtual void SAL_CALL setDefaultColorScheme(
+ const css::uno::Reference< css::chart2::XColorScheme >& xColorScheme ) override;
+ virtual void SAL_CALL setDiagramData(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments ) override;
+
+ virtual css::uno::Reference<css::chart2::XDataTable> SAL_CALL getDataTable() override;
+ virtual void SAL_CALL setDataTable(const css::uno::Reference<css::chart2::XDataTable>& xDataTable) override;
+
+ // ____ XCoordinateSystemContainer ____
+ virtual void SAL_CALL addCoordinateSystem(
+ const css::uno::Reference< css::chart2::XCoordinateSystem >& aCoordSys ) override;
+ virtual void SAL_CALL removeCoordinateSystem(
+ const css::uno::Reference< css::chart2::XCoordinateSystem >& aCoordSys ) override;
+ virtual css::uno::Sequence< css::uno::Reference< css::chart2::XCoordinateSystem > > SAL_CALL getCoordinateSystems() override;
+ virtual void SAL_CALL setCoordinateSystems(
+ const css::uno::Sequence< css::uno::Reference< css::chart2::XCoordinateSystem > >& aCoordinateSystems ) override;
+
+ // ____ XTitled ____
+ virtual css::uno::Reference<
+ css::chart2::XTitle > SAL_CALL getTitleObject() override;
+ virtual void SAL_CALL setTitleObject( const css::uno::Reference<
+ css::chart2::XTitle >& Title ) override;
+
+ // ____ X3DDefaultSetter ____
+ virtual void SAL_CALL set3DSettingsToDefault() override;
+ virtual void SAL_CALL setDefaultRotation() override;
+ virtual void SAL_CALL setDefaultIllumination() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ typedef
+ std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > >
+ tCoordinateSystemContainerType;
+
+ tCoordinateSystemContainerType getBaseCoordinateSystems() const;
+ void setCoordinateSystems(
+ const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > >& aCoordinateSystems );
+
+ rtl::Reference< ::chart::Legend > getLegend2() const;
+ void setLegend(const rtl::Reference< ::chart::Legend > &);
+
+ void setDataTable(const rtl::Reference<::chart::DataTable>& xNewDataTable);
+ rtl::Reference<::chart::DataTable> getDataTableRef() const;
+
+ DiagramPositioningMode getDiagramPositioningMode();
+
+ //returns integer from constant group css::chart::MissingValueTreatment
+ sal_Int32 getCorrectedMissingValueTreatment(
+ const rtl::Reference< ::chart::ChartType >& xChartType );
+
+ void setGeometry3D( sal_Int32 nNewGeometry );
+
+ sal_Int32 getGeometry3D( bool& rbFound, bool& rbAmbiguous );
+
+ bool isPieOrDonutChart();
+
+ bool isSupportingFloorAndWall();
+
+ /**
+ * Move a series forward or backward.
+ *
+ * @param xDiagram
+ * Reference to the diagram that contains the series.
+ *
+ * @param xGivenDataSeries
+ * Reference to the series that should be moved.
+ *
+ * @param bForward
+ * Direction in which the series should be moved.
+ *
+ * @returns </sal_True> if the series was moved successfully.
+ *
+ */
+ bool moveSeries(
+ const rtl::Reference< DataSeries >& xGivenDataSeries,
+ bool bForward );
+
+ /**
+ * Test if a series can be moved.
+ *
+ * @param xDiagram
+ * Reference to the diagram that contains the series.
+ *
+ * @param xGivenDataSeries
+ * Reference to the series that should be tested for moving.
+ *
+ * @param bForward
+ * Direction of the move to be checked.
+ *
+ * @returns </sal_True> if the series can be moved.
+ *
+ */
+ bool isSeriesMoveable(
+ const rtl::Reference< DataSeries >& xGivenDataSeries,
+ bool bForward );
+
+ std::vector< rtl::Reference< ChartType > > getChartTypes();
+
+ rtl::Reference< ChartType > getChartTypeByIndex( sal_Int32 nIndex );
+
+ bool isSupportingDateAxis();
+
+ css::uno::Reference< css::chart2::data::XLabeledDataSequence >
+ getCategories();
+
+ void setCategories(
+ const css::uno::Reference< css::chart2::data::XLabeledDataSequence >& xCategories,
+ bool bSetAxisType = false, // when this flag is true ...
+ bool bCategoryAxis = true);// set the AxisType to CATEGORY or back to REALNUMBER
+
+ bool isCategory();
+
+ /** return all data series in this diagram grouped by chart-types
+ */
+ std::vector<
+ std::vector<
+ rtl::Reference< ::chart::DataSeries > > >
+ getDataSeriesGroups();
+
+ std::vector< rtl::Reference< ::chart::DataSeries > >
+ getDataSeries();
+
+ rtl::Reference< ChartType >
+ getChartTypeOfSeries( const rtl::Reference< DataSeries >& xSeries );
+
+ rtl::Reference< ::chart::Axis > getAttachedAxis(
+ const rtl::Reference< ::chart::DataSeries >& xSeries );
+
+ bool attachSeriesToAxis( bool bMainAxis,
+ const rtl::Reference< DataSeries >& xSeries,
+ const css::uno::Reference< css::uno::XComponentContext > & xContext,
+ bool bAdaptAxes=true );
+
+ /** Replaces all occurrences of xCooSysToReplace in the tree with
+ xReplacement in the diagram's tree
+ */
+ SAL_DLLPRIVATE void replaceCoordinateSystem(
+ const rtl::Reference< ::chart::BaseCoordinateSystem > & xCooSysToReplace,
+ const rtl::Reference< ::chart::BaseCoordinateSystem > & xReplacement );
+
+
+ /** Returns the dimension found for all chart types in the tree. If the
+ dimension is not unique, 0 is returned.
+ */
+ sal_Int32 getDimension();
+
+ /** Sets the dimension of the diagram given.
+
+ 1. Sets the dimension of all used ChartTypes
+ 2. Adapts the DataSeriesTree to reflect the new dimension
+ 3. If new coordinate-systems have to be created, adapts the
+ XCoordinateSystemContainer of the diagram.
+ */
+ void setDimension( sal_Int32 nNewDimensionCount );
+
+
+ StackMode getStackMode(bool& rbFound, bool& rbAmbiguous);
+
+ /** The stacking mode is only set at the series found inside
+ the first chart type. This is the standard for all current
+ templates (the only template that has more than one chart-type and
+ allows stacking is bar/line combi, and for this the stacking only
+ applies to the first chart type/the bars)
+ */
+ void setStackMode(StackMode eStackMode);
+
+
+ /** Sets the "SwapXAndYAxis" property at all coordinate systems found in the
+ given diagram.
+
+ "vertical==true" for bar charts, "vertical==false" for column charts
+ */
+ void setVertical( bool bVertical );
+
+ /** Gets the "SwapXAndYAxis" property at all coordinate systems found in the
+ given diagram.
+
+ "vertical==true" for bar charts, "vertical==false" for column charts
+ */
+ bool getVertical( bool& rbOutFoundResult, bool& rbOutAmbiguousResult );
+
+ struct tTemplateWithServiceName {
+ rtl::Reference< ::chart::ChartTypeTemplate > xChartTypeTemplate;
+ OUString sServiceName;
+ };
+
+ /** tries to find a template in the chart-type manager that matches this
+ diagram.
+
+ @return
+ A pair containing a template with the correct properties set as
+ first entry and the service name of the templates second entry. If
+ no template was found both elements are empty.
+ */
+ tTemplateWithServiceName
+ getTemplate(const rtl::Reference< ::chart::ChartTypeManager > & xChartTypeManager);
+
+ std::vector<rtl::Reference<::chart::RegressionCurveModel> >
+ getAllRegressionCurvesNotMeanValueLine();
+
+ double getCameraDistance();
+ void setCameraDistance( double fCameraDistance );
+
+ void getRotation(
+ sal_Int32& rnHorizontalAngleDegree, sal_Int32& rnVerticalAngleDegree );
+ void setRotation(
+ sal_Int32 nHorizontalAngleDegree, sal_Int32 nVerticalYAngleDegree );
+ void getRotationAngle(
+ double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad );
+ void setRotationAngle(
+ double fXAngleRad, double fYAngleRad, double fZAngleRad );
+
+ ThreeDLookScheme detectScheme();
+ void setScheme( ThreeDLookScheme aScheme );
+
+ void setDefaultRotation( bool bPieOrDonut );
+
+ void switchRightAngledAxes( bool bRightAngledAxes );
+
+private:
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ void fireModifyEvent();
+
+ css::uno::Reference<css::uno::XComponentContext> m_xContext;
+ tCoordinateSystemContainerType m_aCoordSystems;
+
+ rtl::Reference<Wall> m_xWall;
+ rtl::Reference<Wall> m_xFloor;
+
+ css::uno::Reference<css::chart2::XTitle> m_xTitle;
+
+ rtl::Reference<::chart::Legend> m_xLegend;
+ rtl::Reference<::chart::DataTable> m_xDataTable;
+ css::uno::Reference<css::chart2::XColorScheme> m_xColorScheme;
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/DiagramHelper.hxx b/chart2/source/inc/DiagramHelper.hxx
new file mode 100644
index 0000000000..c65bce883d
--- /dev/null
+++ b/chart2/source/inc/DiagramHelper.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "StackMode.hxx"
+#include "charttoolsdllapi.hxx"
+#include "ChartTypeTemplate.hxx"
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <rtl/ref.hxx>
+
+#include <vector>
+
+namespace chart { class ChartModel; }
+namespace com::sun::star::chart2 { class XAxis; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::chart2 { class XChartType; }
+namespace com::sun::star::chart2 { class XCoordinateSystem; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2::data { class XLabeledDataSequence; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::util { class XNumberFormats; }
+namespace com::sun::star::util { class XNumberFormatsSupplier; }
+
+namespace chart
+{
+class Axis;
+class BaseCoordinateSystem;
+class ChartType;
+class ChartTypeManager;
+class ChartTypeTemplate;
+class DataSeries;
+class Diagram;
+class LabeledDataSequence;
+
+class OOO_DLLPUBLIC_CHARTTOOLS DiagramHelper
+{
+public:
+
+ /** Retrieves the stackmode of the first DataSeries or none. If the series have differing stack
+ modes, rbAmbiguous is set to true. If no series is there rbFound is set to false.
+
+ @param xCorrespondingCoordinateSystem
+ The coordinate system in which the given chart type xChartType is
+ located. (This is needed for determining percent stacking. If
+ omitted, the result will just indicate "not stacked", "stacked" or
+ "ambiguous")
+ */
+ static StackMode getStackModeFromChartType(
+ const rtl::Reference< ::chart::ChartType > & xChartType,
+ bool& rbFound, bool& rbAmbiguous,
+ const rtl::Reference< ::chart::BaseCoordinateSystem > & xCorrespondingCoordinateSystem
+ );
+
+ static bool isSeriesAttachedToMainAxis(
+ const rtl::Reference< ::chart::DataSeries >& xDataSeries );
+
+ static css::uno::Sequence< OUString >
+ getExplicitSimpleCategories( ChartModel& rModel );
+
+ SAL_DLLPRIVATE static css::uno::Sequence< OUString >
+ generateAutomaticCategoriesFromCooSys(
+ const rtl::Reference< ::chart::BaseCoordinateSystem > & xCooSys );
+
+ static void switchToDateCategories(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc );
+
+ static void switchToTextCategories(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc );
+
+ static bool isDateNumberFormat( sal_Int32 nNumberFormat, const css::uno::Reference< css::util::XNumberFormats >& xNumberFormats );
+ static sal_Int32 getDateNumberFormat( const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier );
+ static sal_Int32 getDateTimeInputNumberFormat( const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier, double fNumber );
+
+ static sal_Int32 getPercentNumberFormat( const css::uno::Reference<
+ css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier );
+
+ SAL_DLLPRIVATE static bool areChartTypesCompatible(
+ const rtl::Reference< ::chart::ChartType >& xFirstType,
+ const rtl::Reference< ::chart::ChartType >& xSecondType );
+
+ static bool setDiagramPositioning( const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const css::awt::Rectangle& rPosRect /*100th mm*/ );
+
+ static css::awt::Rectangle getDiagramRectangleFromModel( const rtl::Reference<::chart::ChartModel>& xChartModel );
+
+ static bool switchDiagramPositioningToExcludingPositioning( ChartModel& rModel
+ , bool bResetModifiedState //set model back to unchanged if it was unchanged before
+ , bool bConvertAlsoFromAutoPositioning );
+
+private:
+ DiagramHelper() = delete;
+
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/DisposeHelper.hxx b/chart2/source/inc/DisposeHelper.hxx
new file mode 100644
index 0000000000..58dc2d5c55
--- /dev/null
+++ b/chart2/source/inc/DisposeHelper.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/lang/XComponent.hpp>
+
+namespace chart::DisposeHelper
+{
+template <class T> void Dispose(const T& xInterface)
+{
+ css::uno::Reference<css::lang::XComponent> xComponent(xInterface, css::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+}
+
+template <class T> void DisposeAndClear(css::uno::Reference<T>& rInterface)
+{
+ Dispose<css::uno::Reference<T>>(rInterface);
+ rInterface.clear();
+}
+
+template <class Container> void DisposeAllElements(Container& rContainer)
+{
+ for (const auto& rElement : rContainer)
+ {
+ Dispose<typename Container::value_type>(rElement);
+ }
+}
+
+} // namespace chart::DisposeHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ErrorBar.hxx b/chart2/source/inc/ErrorBar.hxx
new file mode 100644
index 0000000000..ed6d646be5
--- /dev/null
+++ b/chart2/source/inc/ErrorBar.hxx
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/chart2/data/XDataSink.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/util/Color.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include "ModifyListenerHelper.hxx"
+
+
+#include <vector>
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::lang::XServiceInfo,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener,
+ css::chart2::data::XDataSource,
+ css::chart2::data::XDataSink,
+ css::beans::XPropertySet,
+ css::beans::XPropertyState >
+ ErrorBar_Base;
+}
+
+class ErrorBar final : public impl::ErrorBar_Base
+{
+private:
+ OUString maDashName;
+ css::drawing::LineDash maLineDash;
+ sal_Int32 mnLineWidth;
+ css::drawing::LineStyle meLineStyle;
+ css::util::Color maLineColor;
+ sal_Int16 mnLineTransparence;
+ css::drawing::LineJoint meLineJoint;
+ bool mbShowPositiveError;
+ bool mbShowNegativeError;
+ double mfPositiveError;
+ double mfNegativeError;
+ double mfWeight;
+ sal_Int32 meStyle;
+
+public:
+ OOO_DLLPUBLIC_CHARTTOOLS explicit ErrorBar();
+ virtual ~ErrorBar() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+
+ // XPropertyState
+ virtual css::beans::PropertyState SAL_CALL getPropertyState( const OUString& rPropName ) override;
+ virtual css::uno::Sequence< css::beans::PropertyState > SAL_CALL getPropertyStates(
+ const css::uno::Sequence< OUString >& rPropNames ) override;
+ virtual void SAL_CALL setPropertyToDefault( const OUString& rPropName ) override;
+ virtual css::uno::Any SAL_CALL getPropertyDefault( const OUString& rPropName ) override;
+
+private:
+ ErrorBar( const ErrorBar & rOther );
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ XDataSink ____
+ virtual void SAL_CALL setData( const css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > >& aData ) override;
+
+ // ____ XDataSource ____
+ virtual css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > SAL_CALL getDataSequences() override;
+
+ typedef std::vector< css::uno::Reference<
+ css::chart2::data::XLabeledDataSequence > > tDataSequenceContainer;
+ tDataSequenceContainer m_aDataSequences;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/EventListenerHelper.hxx b/chart2/source/inc/EventListenerHelper.hxx
new file mode 100644
index 0000000000..19c93c152f
--- /dev/null
+++ b/chart2/source/inc/EventListenerHelper.hxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/lang/XComponent.hpp>
+
+#include <algorithm>
+#include <utility>
+
+namespace com::sun::star::lang { class XEventListener; }
+
+namespace chart
+{
+namespace EventListenerHelper
+{
+
+namespace impl
+{
+
+template< class InterfaceRef >
+struct addListenerFunctor
+{
+ explicit addListenerFunctor( css::uno::Reference< css::lang::XEventListener > xListener ) :
+ m_xListener(std::move( xListener ))
+ {}
+
+ void operator() ( const InterfaceRef & xObject )
+ {
+ css::uno::Reference< css::lang::XComponent >
+ xBroadcaster( xObject, css::uno::UNO_QUERY );
+ if( xBroadcaster.is() && m_xListener.is())
+ xBroadcaster->addEventListener( m_xListener );
+ }
+private:
+ css::uno::Reference< css::lang::XEventListener > m_xListener;
+};
+
+template< class InterfaceRef >
+struct removeListenerFunctor
+{
+ explicit removeListenerFunctor( css::uno::Reference< css::lang::XEventListener > xListener ) :
+ m_xListener(std::move( xListener ))
+ {}
+
+ void operator() ( const InterfaceRef & xObject )
+ {
+ css::uno::Reference< css::lang::XComponent >
+ xBroadcaster( xObject, css::uno::UNO_QUERY );
+ if( xBroadcaster.is() && m_xListener.is())
+ xBroadcaster->removeEventListener( m_xListener );
+ }
+private:
+ css::uno::Reference< css::lang::XEventListener > m_xListener;
+};
+
+} // namespace impl
+
+template< class InterfaceRef >
+void addListener(
+ const InterfaceRef & xObject,
+ const css::uno::Reference< css::lang::XEventListener > & xListener )
+{
+ if( xListener.is())
+ {
+ impl::addListenerFunctor< InterfaceRef > aFunctor( xListener );
+ aFunctor( xObject );
+ }
+}
+
+template< class Container >
+void addListenerToAllElements(
+ const Container & rContainer,
+ const css::uno::Reference< css::lang::XEventListener > & xListener )
+{
+ if( xListener.is())
+ std::for_each( rContainer.begin(), rContainer.end(),
+ impl::addListenerFunctor< typename Container::value_type >( xListener ));
+}
+
+template< class InterfaceRef >
+void removeListener(
+ const InterfaceRef & xObject,
+ const css::uno::Reference< css::lang::XEventListener > & xListener )
+{
+ if( xListener.is())
+ {
+ impl::removeListenerFunctor< InterfaceRef > aFunctor( xListener );
+ aFunctor( xObject );
+ }
+}
+
+template< class Container >
+void removeListenerFromAllElements(
+ const Container & rContainer,
+ const css::uno::Reference< css::lang::XEventListener > & xListener )
+{
+ if( xListener.is())
+ std::for_each( rContainer.begin(), rContainer.end(),
+ impl::removeListenerFunctor< typename Container::value_type >( xListener ));
+}
+
+} // namespace EventListenerHelper
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ExplicitCategoriesProvider.hxx b/chart2/source/inc/ExplicitCategoriesProvider.hxx
new file mode 100644
index 0000000000..c393b49a86
--- /dev/null
+++ b/chart2/source/inc/ExplicitCategoriesProvider.hxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+#include <unotools/weakref.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+
+#include <utility>
+#include <vector>
+
+namespace chart { class ChartModel; }
+namespace com::sun::star::chart2 { class XCoordinateSystem; }
+namespace com::sun::star::chart2::data { class XDataSequence; }
+namespace com::sun::star::chart2::data { class XLabeledDataSequence; }
+namespace com::sun::star::uno { class Any; }
+
+namespace chart
+{
+class BaseCoordinateSystem;
+class LabeledDataSequence;
+
+struct OOO_DLLPUBLIC_CHARTTOOLS ComplexCategory
+{
+ OUString Text;
+ sal_Int32 Count;
+
+ ComplexCategory( OUString aText, sal_Int32 nCount ) : Text(std::move( aText )), Count (nCount)
+ {}
+};
+
+class SplitCategoriesProvider
+{
+public:
+ virtual ~SplitCategoriesProvider();
+
+ virtual sal_Int32 getLevelCount() const = 0;
+ virtual css::uno::Sequence< OUString > getStringsForLevel( sal_Int32 nIndex ) const = 0;
+};
+
+class OOO_DLLPUBLIC_CHARTTOOLS ExplicitCategoriesProvider final
+{
+public:
+ ExplicitCategoriesProvider( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSysModel
+ , ChartModel& rChartModel
+ );
+ ~ExplicitCategoriesProvider();
+
+ void init();
+
+ css::uno::Reference< css::chart2::data::XDataSequence > getOriginalCategories();
+
+ css::uno::Sequence< OUString > const & getSimpleCategories();
+ const std::vector<ComplexCategory>* getCategoriesByLevel( sal_Int32 nLevel );
+
+ static OUString getCategoryByIndex(
+ const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSysModel
+ , ChartModel& rModel
+ , sal_Int32 nIndex );
+
+ static css::uno::Sequence< OUString > getExplicitSimpleCategories(
+ const SplitCategoriesProvider& rSplitCategoriesProvider );
+
+ static void convertCategoryAnysToText( css::uno::Sequence< OUString >& rOutTexts
+ , const css::uno::Sequence< css::uno::Any >& rInAnys
+ , ChartModel& rModel );
+
+ bool hasComplexCategories() const;
+ sal_Int32 getCategoryLevelCount() const;
+
+ const std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence> >&
+ getSplitCategoriesList() const { return m_aSplitCategoriesList;}
+
+ bool isDateAxis();
+ const std::vector< double >& getDateCategories();
+
+private:
+ ExplicitCategoriesProvider(ExplicitCategoriesProvider const &) = delete;
+ ExplicitCategoriesProvider& operator =(ExplicitCategoriesProvider const &) = delete;
+
+ bool volatile m_bDirty;
+ unotools::WeakReference< ::chart::BaseCoordinateSystem > m_xCooSysModel;
+ ChartModel& mrModel;
+ css::uno::Reference< css::chart2::data::XLabeledDataSequence> m_xOriginalCategories;
+
+ bool m_bIsExplicitCategoriesInited;
+ css::uno::Sequence< OUString > m_aExplicitCategories;
+ std::vector< std::vector< ComplexCategory > > m_aComplexCats;
+ std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence> > m_aSplitCategoriesList;
+
+ bool m_bIsDateAxis;
+ bool m_bIsAutoDate;
+ std::vector< double > m_aDateCategories;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ExponentialRegressionCurveCalculator.hxx b/chart2/source/inc/ExponentialRegressionCurveCalculator.hxx
new file mode 100644
index 0000000000..c929ac80cd
--- /dev/null
+++ b/chart2/source/inc/ExponentialRegressionCurveCalculator.hxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "RegressionCurveCalculator.hxx"
+
+namespace chart
+{
+
+class ExponentialRegressionCurveCalculator final : public RegressionCurveCalculator
+{
+public:
+ ExponentialRegressionCurveCalculator();
+ virtual ~ExponentialRegressionCurveCalculator() override;
+
+protected:
+ virtual OUString ImplGetRepresentation(
+ const css::uno::Reference<css::util::XNumberFormatter>& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const override;
+
+private:
+ // ____ XRegressionCurveCalculator ____
+ virtual void SAL_CALL recalculateRegression(
+ const css::uno::Sequence<double>& aXValues,
+ const css::uno::Sequence<double>& aYValues ) override;
+
+ virtual double SAL_CALL getCurveValue( double x ) override;
+
+ virtual css::uno::Sequence<css::geometry::RealPoint2D> SAL_CALL getCurveValues(
+ double min,
+ double max,
+ sal_Int32 nPointCount,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingX,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation ) override;
+
+ // formula is: f(x) = m_fSign * exp(m_fLogIntercept) * exp( m_fLogSlope * x )
+ // mathematical model f(x) = Intercept * Slope^x
+ double m_fLogSlope;
+ double m_fLogIntercept;
+ double m_fSign;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/FastPropertyIdRanges.hxx b/chart2/source/inc/FastPropertyIdRanges.hxx
new file mode 100644
index 0000000000..d06809e44c
--- /dev/null
+++ b/chart2/source/inc/FastPropertyIdRanges.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+namespace chart
+{
+enum FastPropertyIdRanges
+{
+ FAST_PROPERTY_ID_START = 10000,
+ FAST_PROPERTY_ID_START_DATA_SERIES = FAST_PROPERTY_ID_START + 1000,
+ FAST_PROPERTY_ID_START_DATA_POINT = FAST_PROPERTY_ID_START + 2000,
+ FAST_PROPERTY_ID_START_CHAR_PROP = FAST_PROPERTY_ID_START + 3000,
+ FAST_PROPERTY_ID_START_LINE_PROP = FAST_PROPERTY_ID_START + 4000,
+ FAST_PROPERTY_ID_START_FILL_PROP = FAST_PROPERTY_ID_START + 5000,
+ FAST_PROPERTY_ID_START_USERDEF_PROP = FAST_PROPERTY_ID_START + 6000,
+ FAST_PROPERTY_ID_START_SCENE_PROP = FAST_PROPERTY_ID_START + 7000,
+ // FAST_PROPERTY_ID_START_NAMED_FILL_PROP = FAST_PROPERTY_ID_START + 8000,
+ // FAST_PROPERTY_ID_START_NAMED_LINE_PROP = FAST_PROPERTY_ID_START + 9000,
+ FAST_PROPERTY_ID_START_CHART_STATISTIC_PROP = FAST_PROPERTY_ID_START + 12000,
+ FAST_PROPERTY_ID_START_CHART_SYMBOL_PROP = FAST_PROPERTY_ID_START + 13000,
+ FAST_PROPERTY_ID_START_CHART_DATACAPTION_PROP = FAST_PROPERTY_ID_START + 14000,
+ FAST_PROPERTY_ID_START_CHART_SPLINE_PROP = FAST_PROPERTY_ID_START + 15000,
+ FAST_PROPERTY_ID_START_CHART_STOCK_PROP = FAST_PROPERTY_ID_START + 16000,
+ FAST_PROPERTY_ID_START_CHART_AUTOPOSITION_PROP = FAST_PROPERTY_ID_START + 17000,
+ FAST_PROPERTY_ID_START_SCALE_TEXT_PROP = FAST_PROPERTY_ID_START + 18000,
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/FillProperties.hxx b/chart2/source/inc/FillProperties.hxx
new file mode 100644
index 0000000000..84759cfa0c
--- /dev/null
+++ b/chart2/source/inc/FillProperties.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "PropertyHelper.hxx"
+#include "FastPropertyIdRanges.hxx"
+#include "charttoolsdllapi.hxx"
+
+#include <vector>
+
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart
+{
+
+// implements service FillProperties
+namespace FillProperties
+{
+ // FastProperty Ids for properties
+ enum
+ {
+ // com.sun.star.drawing.FillProperties
+ PROP_FILL_STYLE = FAST_PROPERTY_ID_START_FILL_PROP
+ , PROP_FILL_COLOR
+ , PROP_FILL_TRANSPARENCE
+ , PROP_FILL_TRANSPARENCE_GRADIENT_NAME
+// , PROP_FILL_TRANSPARENCE_GRADIENT //optional
+ , PROP_FILL_GRADIENT_NAME
+ , PROP_FILL_GRADIENT_STEPCOUNT
+// , PROP_FILL_GRADIENT //optional
+ , PROP_FILL_HATCH_NAME
+// , PROP_FILL_HATCH //optional
+ // bitmap properties start
+ , PROP_FILL_BITMAP_NAME
+// , PROP_FILL_BITMAP //optional
+// , PROP_FILL_BITMAP_URL //optional
+ , PROP_FILL_BITMAP_OFFSETX
+ , PROP_FILL_BITMAP_OFFSETY
+ , PROP_FILL_BITMAP_POSITION_OFFSETX
+ , PROP_FILL_BITMAP_POSITION_OFFSETY
+ , PROP_FILL_BITMAP_RECTANGLEPOINT
+ , PROP_FILL_BITMAP_LOGICALSIZE
+ , PROP_FILL_BITMAP_SIZEX
+ , PROP_FILL_BITMAP_SIZEY
+ , PROP_FILL_BITMAP_MODE
+ // bitmap properties end
+ , PROP_FILL_BACKGROUND
+ };
+
+ OOO_DLLPUBLIC_CHARTTOOLS void AddPropertiesToVector(
+ std::vector< css::beans::Property > & rOutProperties );
+
+ OOO_DLLPUBLIC_CHARTTOOLS void AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/FormattedString.hxx b/chart2/source/inc/FormattedString.hxx
new file mode 100644
index 0000000000..23c81454fa
--- /dev/null
+++ b/chart2/source/inc/FormattedString.hxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "OPropertySet.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include "ModifyListenerHelper.hxx"
+#include "PropertyHelper.hxx"
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::chart2::XDataPointCustomLabelField, // inherits from XFormattedString2
+ css::lang::XServiceInfo,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ FormattedString_Base;
+}
+
+class FormattedString final :
+ public impl::FormattedString_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit FormattedString();
+ virtual ~FormattedString() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+ virtual void SAL_CALL setPropertyValue(const OUString& p1, const css::uno::Any& p2) override
+ { ::property::OPropertySet::setPropertyValue(p1, p2); }
+ virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& p1) override
+ { return ::property::OPropertySet::getPropertyValue(p1); }
+ virtual void SAL_CALL addPropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2) override
+ { ::property::OPropertySet::addPropertyChangeListener(p1, p2); }
+ virtual void SAL_CALL removePropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2) override
+ { ::property::OPropertySet::removePropertyChangeListener(p1, p2); }
+ virtual void SAL_CALL addVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2) override
+ { ::property::OPropertySet::addVetoableChangeListener(p1, p2); }
+ virtual void SAL_CALL removeVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2) override
+ { ::property::OPropertySet::removeVetoableChangeListener(p1, p2); }
+
+ explicit FormattedString( const FormattedString & rOther );
+
+ // ____ XFormattedString ____
+ virtual OUString SAL_CALL getString() override;
+ virtual void SAL_CALL setString( const OUString& String ) override;
+
+ // ____ XDataPointCustomLabelField ____
+ virtual css::chart2::DataPointCustomLabelFieldType SAL_CALL getFieldType() override;
+ virtual void SAL_CALL
+ setFieldType( const css::chart2::DataPointCustomLabelFieldType FieldType ) override;
+ virtual OUString SAL_CALL getGuid() override;
+ void SAL_CALL setGuid( const OUString& guid ) override;
+ virtual sal_Bool SAL_CALL getDataLabelsRange() override;
+ virtual void SAL_CALL setDataLabelsRange( sal_Bool dataLabelsRange ) override;
+ virtual OUString SAL_CALL getCellRange() override;
+ virtual void SAL_CALL setCellRange( const OUString& cellRange ) override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+private:
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ void fireModifyEvent();
+
+ // ____ XFormattedString ____
+ OUString m_aString;
+
+ // ____ XDataPointCustomLabelField ____
+ css::chart2::DataPointCustomLabelFieldType m_aType;
+ OUString m_aGuid;
+ OUString m_aCellRange;
+ bool m_bDataLabelsRange;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+OOO_DLLPUBLIC_CHARTTOOLS const ::chart::tPropertyValueMap & StaticFormattedStringDefaults();
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/FormattedStringHelper.hxx b/chart2/source/inc/FormattedStringHelper.hxx
new file mode 100644
index 0000000000..9e4d33b6af
--- /dev/null
+++ b/chart2/source/inc/FormattedStringHelper.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <vector>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XFormattedString2; }
+namespace com::sun::star::uno { template <class interface_type> class Reference; }
+
+namespace chart
+{
+class FormattedString;
+
+class FormattedStringHelper
+{
+public:
+ static rtl::Reference< ::chart::FormattedString >
+ createFormattedString(
+ const OUString & rString
+ , const css::uno::Reference< css::beans::XPropertySet > & xTextProperties ) noexcept;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/GridProperties.hxx b/chart2/source/inc/GridProperties.hxx
new file mode 100644
index 0000000000..e5264a1b2f
--- /dev/null
+++ b/chart2/source/inc/GridProperties.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include "ModifyListenerHelper.hxx"
+
+#include "OPropertySet.hxx"
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::lang::XServiceInfo,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ GridProperties_Base;
+}
+
+class OOO_DLLPUBLIC_CHARTTOOLS GridProperties final :
+ public impl::GridProperties_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit GridProperties();
+ explicit GridProperties( const GridProperties & rOther );
+ virtual ~GridProperties() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+private:
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/InternalData.hxx b/chart2/source/inc/InternalData.hxx
new file mode 100644
index 0000000000..9d9abeb3a7
--- /dev/null
+++ b/chart2/source/inc/InternalData.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <vector>
+#include <valarray>
+
+namespace chart
+{
+
+class InternalData
+{
+public:
+ InternalData();
+
+ void createDefaultData();
+
+ void setData( const css::uno::Sequence< css::uno::Sequence< double > > & rDataInRows );
+ css::uno::Sequence< css::uno::Sequence< double > > getData() const;
+
+ css::uno::Sequence< double > getColumnValues( sal_Int32 nColumnIndex ) const;
+ css::uno::Sequence< double > getRowValues( sal_Int32 nRowIndex ) const;
+
+ void setColumnValues( sal_Int32 nColumnIndex, const std::vector< double > & rNewData );
+ void setRowValues( sal_Int32 nRowIndex, const std::vector< double > & rNewData );
+
+ void setComplexColumnLabel( sal_Int32 nColumnIndex, std::vector< css::uno::Any >&& rComplexLabel );
+ void setComplexRowLabel( sal_Int32 nRowIndex, std::vector< css::uno::Any >&& rComplexLabel );
+
+ std::vector< css::uno::Any > getComplexColumnLabel( sal_Int32 nColumnIndex ) const;
+ std::vector< css::uno::Any > getComplexRowLabel( sal_Int32 nRowIndex ) const;
+
+ void swapRowWithNext( sal_Int32 nRowIndex );
+ void swapColumnWithNext( sal_Int32 nColumnIndex );
+
+ void insertColumn( sal_Int32 nAfterIndex );
+ void insertRow( sal_Int32 nAfterIndex );
+ void deleteColumn( sal_Int32 nAtIndex );
+ void deleteRow( sal_Int32 nAtIndex );
+
+ /// @return the index of the newly appended column
+ sal_Int32 appendColumn();
+ /// @return the index of the newly appended row
+ sal_Int32 appendRow();
+
+ sal_Int32 getRowCount() const;
+ sal_Int32 getColumnCount() const;
+
+ typedef std::vector< std::vector< css::uno::Any > > tVecVecAny; //inner index is hierarchical level
+
+ void setComplexRowLabels( tVecVecAny&& rNewRowLabels );
+ const tVecVecAny& getComplexRowLabels() const;
+ void setComplexColumnLabels( tVecVecAny&& rNewColumnLabels );
+ const tVecVecAny& getComplexColumnLabels() const;
+
+ void dump() const;
+
+private: //methods
+ /** resizes the data if at least one of the given dimensions is larger than
+ before. The data is never becoming smaller only larger.
+
+ @return </true>, if the data was enlarged
+ */
+ bool enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount );
+
+private:
+ sal_Int32 m_nColumnCount;
+ sal_Int32 m_nRowCount;
+
+ typedef std::valarray< double > tDataType;
+ tDataType m_aData;
+ tVecVecAny m_aRowLabels;//outer index is row index, inner index is category level
+ tVecVecAny m_aColumnLabels;//outer index is column index
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/InternalDataProvider.hxx b/chart2/source/inc/InternalDataProvider.hxx
new file mode 100644
index 0000000000..a5032efcda
--- /dev/null
+++ b/chart2/source/inc/InternalDataProvider.hxx
@@ -0,0 +1,220 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "InternalData.hxx"
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/chart/XDateCategories.hpp>
+#include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <rtl/ref.hxx>
+
+#include <map>
+
+namespace com::sun::star::chart2 { class XChartDocument; }
+
+namespace chart
+{
+class ChartModel;
+class UncachedDataSequence;
+
+namespace impl
+{
+
+typedef ::cppu::WeakImplHelper<
+ css::chart2::XInternalDataProvider,
+ css::chart2::data::XRangeXMLConversion,
+ css::chart2::XAnyDescriptionAccess,
+ css::chart::XDateCategories,
+ css::util::XCloneable,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo >
+ InternalDataProvider_Base;
+}
+
+/** Data provider that handles data internally. This is used for charts with
+ their own data.
+
+ <p>The format for single ranges is "categories|label n|n" where n is a
+ non-negative number. Meaning return all categories, the label of sequence n,
+ or the data of sequence n.</p>
+
+ <p>The format for a complete range is "all". (Do we need more than
+ that?)</p>
+ */
+class InternalDataProvider final :
+ public impl::InternalDataProvider_Base
+{
+public:
+ explicit InternalDataProvider();
+
+ // #i120559# allow handing over a default for data orientation
+ // (DataInColumns) that will be used when no data is available
+ explicit InternalDataProvider(
+ const rtl::Reference< ::chart::ChartModel > & xChartDoc,
+ bool bConnectToModel,
+ bool bDefaultDataInColumns );
+ explicit InternalDataProvider( const InternalDataProvider & rOther );
+ virtual ~InternalDataProvider() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XInternalDataProvider ____
+ virtual sal_Bool SAL_CALL hasDataByRangeRepresentation( const OUString& aRange ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL
+ getDataByRangeRepresentation( const OUString& aRange ) override;
+ virtual void SAL_CALL setDataByRangeRepresentation(
+ const OUString& aRange,
+ const css::uno::Sequence< css::uno::Any >& aNewData ) override;
+ virtual void SAL_CALL insertSequence( ::sal_Int32 nAfterIndex ) override;
+ virtual void SAL_CALL deleteSequence( ::sal_Int32 nAtIndex ) override;
+ virtual void SAL_CALL appendSequence() override;
+ virtual void SAL_CALL insertComplexCategoryLevel( ::sal_Int32 nLevel ) override;
+ virtual void SAL_CALL deleteComplexCategoryLevel( ::sal_Int32 nLevel ) override;
+ virtual void SAL_CALL insertDataPointForAllSequences( ::sal_Int32 nAfterIndex ) override;
+ virtual void SAL_CALL deleteDataPointForAllSequences( ::sal_Int32 nAtIndex ) override;
+ virtual void SAL_CALL swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex ) override;
+ virtual void SAL_CALL registerDataSequenceForChanges(
+ const css::uno::Reference< css::chart2::data::XDataSequence >& xSeq ) override;
+
+ // ____ XDataProvider (base of XInternalDataProvider) ____
+ virtual sal_Bool SAL_CALL createDataSourcePossible(
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments ) override;
+ virtual css::uno::Reference< css::chart2::data::XDataSource > SAL_CALL createDataSource(
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments ) override;
+ virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL detectArguments(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource ) override;
+ virtual sal_Bool SAL_CALL createDataSequenceByRangeRepresentationPossible(
+ const OUString& aRangeRepresentation ) override;
+ virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL createDataSequenceByRangeRepresentation(
+ const OUString& aRangeRepresentation ) override;
+
+ virtual css::uno::Reference<css::chart2::data::XDataSequence> SAL_CALL
+ createDataSequenceByValueArray( const OUString& aRole, const OUString& aRangeRepresentation,
+ const OUString& aRoleQualifier ) override;
+
+ virtual css::uno::Reference< css::sheet::XRangeSelection > SAL_CALL getRangeSelection() override;
+
+ // ____ XRangeXMLConversion ____
+ virtual OUString SAL_CALL convertRangeToXML(
+ const OUString& aRangeRepresentation ) override;
+ virtual OUString SAL_CALL convertRangeFromXML(
+ const OUString& aXMLRange ) override;
+
+ // ____ XDateCategories ____
+ virtual css::uno::Sequence< double > SAL_CALL getDateCategories() override;
+ virtual void SAL_CALL setDateCategories( const css::uno::Sequence< double >& rDates ) override;
+
+ // ____ XAnyDescriptionAccess ____
+ virtual css::uno::Sequence< css::uno::Sequence< css::uno::Any > > SAL_CALL
+ getAnyRowDescriptions() override;
+ virtual void SAL_CALL setAnyRowDescriptions(
+ const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& aRowDescriptions ) override;
+ virtual css::uno::Sequence< css::uno::Sequence< css::uno::Any > > SAL_CALL
+ getAnyColumnDescriptions() override;
+ virtual void SAL_CALL setAnyColumnDescriptions(
+ const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& aColumnDescriptions ) override;
+
+ // ____ XComplexDescriptionAccess (base of XAnyDescriptionAccess) ____
+ virtual css::uno::Sequence< css::uno::Sequence< OUString > > SAL_CALL
+ getComplexRowDescriptions() override;
+ virtual void SAL_CALL setComplexRowDescriptions(
+ const css::uno::Sequence< css::uno::Sequence< OUString > >& aRowDescriptions ) override;
+ virtual css::uno::Sequence< css::uno::Sequence< OUString > > SAL_CALL
+ getComplexColumnDescriptions() override;
+ virtual void SAL_CALL setComplexColumnDescriptions(
+ const css::uno::Sequence< css::uno::Sequence< OUString > >& aColumnDescriptions ) override;
+
+ // ____ XChartDataArray (base of XComplexDescriptionAccess) ____
+ virtual css::uno::Sequence< css::uno::Sequence< double > > SAL_CALL getData() override;
+ virtual void SAL_CALL setData(
+ const css::uno::Sequence< css::uno::Sequence< double > >& aData ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getRowDescriptions() override;
+ virtual void SAL_CALL setRowDescriptions(
+ const css::uno::Sequence< OUString >& aRowDescriptions ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getColumnDescriptions() override;
+ virtual void SAL_CALL setColumnDescriptions(
+ const css::uno::Sequence< OUString >& aColumnDescriptions ) override;
+
+ // ____ XChartData (base of XChartDataArray) ____
+ virtual void SAL_CALL addChartDataChangeEventListener(
+ const css::uno::Reference< css::chart::XChartDataChangeEventListener >& aListener ) override;
+ virtual void SAL_CALL removeChartDataChangeEventListener(
+ const css::uno::Reference< css::chart::XChartDataChangeEventListener >& aListener ) override;
+ virtual double SAL_CALL getNotANumber() override;
+ virtual sal_Bool SAL_CALL isNotANumber(
+ double nNumber ) override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+ // css::lang::XInitialization:
+ virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > & aArguments) override;
+
+private:
+ void addDataSequenceToMap(
+ const OUString & rRangeRepresentation,
+ const css::uno::Reference< css::chart2::data::XDataSequence > & xSequence );
+
+ css::uno::Reference< css::chart2::data::XDataSequence >
+ createDataSequenceAndAddToMap( const OUString & rRangeRepresentation,
+ const OUString & rRole );
+ rtl::Reference< UncachedDataSequence >
+ createDataSequenceAndAddToMap( const OUString & rRangeRepresentation );
+
+ rtl::Reference<UncachedDataSequence>
+ createDataSequenceFromArray( const OUString& rArrayStr, std::u16string_view rRole,
+ std::u16string_view rRoleQualifier);
+
+ void deleteMapReferences( const OUString & rRangeRepresentation );
+
+ void adaptMapReferences(
+ const OUString & rOldRangeRepresentation,
+ const OUString & rNewRangeRepresentation );
+
+ void increaseMapReferences( sal_Int32 nBegin, sal_Int32 nEnd );
+ void decreaseMapReferences( sal_Int32 nBegin, sal_Int32 nEnd );
+
+ typedef std::multimap< OUString,
+ css::uno::WeakReference< css::chart2::data::XDataSequence > >
+ tSequenceMap;
+ typedef std::pair< tSequenceMap::iterator, tSequenceMap::iterator > tSequenceMapRange;
+
+ /** cache for all sequences that have been returned.
+
+ If the range-representation of a sequence changes and it is still
+ referred to by some component (weak reference is valid), the range will
+ be adapted.
+ */
+ tSequenceMap m_aSequenceMap;
+ InternalData m_aInternalData;
+ bool m_bDataInColumns;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/LabeledDataSequence.hxx b/chart2/source/inc/LabeledDataSequence.hxx
new file mode 100644
index 0000000000..ab5338420b
--- /dev/null
+++ b/chart2/source/inc/LabeledDataSequence.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/chart2/data/XLabeledDataSequence2.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include "ModifyListenerHelper.hxx"
+#include "charttoolsdllapi.hxx"
+
+namespace com::sun::star::chart2::data { class XDataSequence; }
+namespace com::sun::star::util { class XCloneable; }
+namespace com::sun::star::util { class XModifyListener; }
+
+namespace chart
+{
+
+namespace impl
+{
+typedef cppu::WeakImplHelper<
+ css::chart2::data::XLabeledDataSequence2,
+ css::lang::XServiceInfo >
+ LabeledDataSequence_Base;
+}
+
+class OOO_DLLPUBLIC_CHARTTOOLS LabeledDataSequence final :
+ public impl::LabeledDataSequence_Base
+{
+public:
+ explicit LabeledDataSequence();
+ explicit LabeledDataSequence(const LabeledDataSequence &);
+ explicit LabeledDataSequence(
+ css::uno::Reference< css::chart2::data::XDataSequence > xValues );
+ explicit LabeledDataSequence(
+ css::uno::Reference< css::chart2::data::XDataSequence > xValues,
+ css::uno::Reference< css::chart2::data::XDataSequence > xLabels );
+
+ virtual ~LabeledDataSequence() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XLabeledDataSequence ____
+ virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL getValues() override;
+ virtual void SAL_CALL setValues(
+ const css::uno::Reference< css::chart2::data::XDataSequence >& xSequence ) override;
+ virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL getLabel() override;
+ virtual void SAL_CALL setLabel(
+ const css::uno::Reference< css::chart2::data::XDataSequence >& xSequence ) override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+private:
+ css::uno::Reference< css::chart2::data::XDataSequence > m_xData;
+ css::uno::Reference< css::chart2::data::XDataSequence > m_xLabel;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/Legend.hxx b/chart2/source/inc/Legend.hxx
new file mode 100644
index 0000000000..9caa0c7b06
--- /dev/null
+++ b/chart2/source/inc/Legend.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "OPropertySet.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <com/sun/star/chart2/XLegend.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include "ModifyListenerHelper.hxx"
+#include "charttoolsdllapi.hxx"
+#include "PropertyHelper.hxx"
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::chart2::XLegend,
+ css::lang::XServiceInfo,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ Legend_Base;
+}
+
+class OOO_DLLPUBLIC_CHARTTOOLS Legend final :
+ public impl::Legend_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit Legend();
+ virtual ~Legend() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+ explicit Legend( const Legend & rOther );
+
+private:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+public:
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+private:
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+OOO_DLLPUBLIC_CHARTTOOLS const ::chart::tPropertyValueMap& StaticLegendDefaults();
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/LegendHelper.hxx b/chart2/source/inc/LegendHelper.hxx
new file mode 100644
index 0000000000..f2bf2e55fe
--- /dev/null
+++ b/chart2/source/inc/LegendHelper.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <rtl/ref.hxx>
+#include "charttoolsdllapi.hxx"
+
+namespace chart { class ChartModel; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::chart2 { class XLegend; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+class Diagram;
+class Legend;
+
+class OOO_DLLPUBLIC_CHARTTOOLS LegendHelper
+{
+public:
+ static rtl::Reference< ::chart::Legend >
+ showLegend( ChartModel& rModel
+ , const css::uno::Reference< css::uno::XComponentContext >& xContext );
+
+ static void hideLegend( ChartModel& rModel );
+
+ static rtl::Reference< ::chart::Legend >
+ getLegend( ChartModel& rModel
+ , const css::uno::Reference< css::uno::XComponentContext >& xContext = nullptr
+ , bool bCreate = false );
+
+ /** returns <FALSE/>, if either there is no legend at the diagram, or there
+ is a legend which has a "Show" property of value <FALSE/>. Otherwise,
+ <TRUE/> is returned.
+ */
+ static bool hasLegend( const rtl::Reference< ::chart::Diagram > & xDiagram );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/LifeTime.hxx b/chart2/source/inc/LifeTime.hxx
new file mode 100644
index 0000000000..e16edd1e59
--- /dev/null
+++ b/chart2/source/inc/LifeTime.hxx
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <mutex>
+#include <osl/conditn.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include "charttoolsdllapi.hxx"
+
+namespace com::sun::star::document { class XStorageChangeListener; }
+namespace com::sun::star::lang { class XComponent; }
+namespace com::sun::star::lang { class XEventListener; }
+namespace com::sun::star::util { class CloseVetoException; }
+namespace com::sun::star::util { class XCloseListener; }
+namespace com::sun::star::util { class XCloseable; }
+namespace com::sun::star::util { class XModifyListener; }
+namespace com::sun::star::view { class XSelectionChangeListener; }
+
+namespace apphelper
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS LifeTimeManager
+{
+friend class LifeTimeGuard;
+public:
+ LifeTimeManager( css::lang::XComponent* pComponent );
+ virtual ~LifeTimeManager();
+
+ bool impl_isDisposed( bool bAssert=true );
+ /// @throws css::uno::RuntimeException
+ bool dispose();
+
+ mutable std::mutex m_aAccessMutex;
+ ::comphelper::OInterfaceContainerHelper4<css::util::XCloseListener> m_aCloseListeners;
+ ::comphelper::OInterfaceContainerHelper4<css::util::XModifyListener> m_aModifyListeners;
+ ::comphelper::OInterfaceContainerHelper4<css::document::XStorageChangeListener> m_aStorageChangeListeners;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListeners;
+ ::comphelper::OInterfaceContainerHelper4<css::view::XSelectionChangeListener> m_aSelectionChangeListeners;
+
+protected:
+ SAL_DLLPRIVATE virtual bool impl_canStartApiCall();
+ SAL_DLLPRIVATE virtual void impl_apiCallCountReachedNull(std::unique_lock<std::mutex>& /*rGuard*/){}
+
+ SAL_DLLPRIVATE void impl_registerApiCall(bool bLongLastingCall);
+ SAL_DLLPRIVATE void impl_unregisterApiCall(std::unique_lock<std::mutex>& rGuard, bool bLongLastingCall);
+
+ css::lang::XComponent* m_pComponent;
+ ::osl::Condition m_aNoAccessCountCondition;
+ sal_Int32 m_nAccessCount;
+ bool volatile m_bDisposed;
+ bool volatile m_bInDispose;
+ ::osl::Condition m_aNoLongLastingCallCountCondition;
+ sal_Int32 m_nLongLastingCallCount;
+};
+
+class CloseableLifeTimeManager final : public LifeTimeManager
+{
+ css::util::XCloseable* m_pCloseable;
+
+ ::osl::Condition m_aEndTryClosingCondition;
+ bool volatile m_bClosed;
+ bool volatile m_bInTryClose;
+ //the ownership between model and controller is not clear at first
+ //each controller might consider him as owner of the model first
+ //at start the model is not considered as owner of itself
+ bool volatile m_bOwnership;
+
+public:
+ CloseableLifeTimeManager( css::util::XCloseable* pCloseable
+ , css::lang::XComponent* pComponent );
+ virtual ~CloseableLifeTimeManager() override;
+
+ bool impl_isDisposedOrClosed( bool bAssert=true );
+/// @throws css::uno::Exception
+ bool g_close_startTryClose(bool bDeliverOwnership);
+/// @throws css::util::CloseVetoException
+ void g_close_isNeedToCancelLongLastingCalls( bool bDeliverOwnership, css::util::CloseVetoException const & ex );
+ void g_close_endTryClose(bool bDeliverOwnership );
+ void g_close_endTryClose_doClose();
+/// @throws css::uno::RuntimeException
+ void g_addCloseListener( const css::uno::Reference< css::util::XCloseListener > & xListener );
+
+private:
+ virtual bool impl_canStartApiCall() override;
+ virtual void impl_apiCallCountReachedNull(std::unique_lock<std::mutex>& rGuard) override;
+
+ void impl_setOwnership( bool bDeliverOwnership, bool bMyVeto );
+ void impl_doClose(std::unique_lock<std::mutex>& rGuard);
+};
+
+/*
+Use this Guard in your ApiCalls to protect access on resources
+which will be released in dispose.
+It's guaranteed that the release of resources only starts if your
+guarded call has finished.
+! It's only partly guaranteed that this resources will not change during the call.
+See the example for details.
+
+This class is to be used as described in the example.
+
+If this guard is used in all api calls of an XCloseable object
+it's guaranteed that the closeable will close itself after finishing the last call
+if it should do so.
+
+ ::ApiCall
+{
+ //hold no mutex!!!
+ LifeTimeGuard aLifeTimeGuard(m_aLifeTimeManager);
+
+ //mutex is acquired; call is not registered
+
+ if(!aLifeTimeGuard.startApiCall())
+ return ; //behave as passive as possible, if disposed or closed
+
+ //mutex is acquired, call is registered
+ {
+ //you might access some private members here
+ //but then you need to protect access to these members always like this
+ //never call to the outside here
+ }
+
+ aLifeTimeGuard.clear(); //!!!
+
+ //Mutex is released, the running call is still registered
+ //this call will finish before the 'release-section' in dispose is allowed to start
+
+ {
+ //you might access some private members here guarded with your own mutex
+ //but release your mutex at the end of this block
+ }
+
+ //you can call to the outside (without holding the mutex) without becoming disposed
+
+ //End of method -> ~LifeTimeGuard
+ //-> call is unregistered
+ //-> this object might be disposed now
+}
+
+your XComponent::dispose method has to be implemented in the following way:
+
+ ::dispose()
+{
+ //hold no mutex!!!
+ if( !m_aLifeTimeManager.dispose() )
+ return;
+
+ //--release all resources and references
+
+}
+
+*/
+
+class LifeTimeGuard
+{
+
+public:
+ LifeTimeGuard( LifeTimeManager& rManager )
+ : m_guard( rManager.m_aAccessMutex )
+ , m_rManager(rManager)
+ , m_bCallRegistered(false)
+ , m_bLongLastingCallRegistered(false)
+ {
+
+ }
+ bool startApiCall(bool bLongLastingCall=false);
+ ~LifeTimeGuard();
+ void clear() { m_guard.unlock(); }
+
+private:
+ std::unique_lock<std::mutex> m_guard;
+ LifeTimeManager& m_rManager;
+ bool m_bCallRegistered;
+ bool m_bLongLastingCallRegistered;
+
+private:
+ LifeTimeGuard( const LifeTimeGuard& ) = delete;
+ LifeTimeGuard& operator= ( const LifeTimeGuard& ) = delete;
+};
+
+}//end namespace apphelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/LinePropertiesHelper.hxx b/chart2/source/inc/LinePropertiesHelper.hxx
new file mode 100644
index 0000000000..2999de81a7
--- /dev/null
+++ b/chart2/source/inc/LinePropertiesHelper.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "PropertyHelper.hxx"
+#include "FastPropertyIdRanges.hxx"
+#include "charttoolsdllapi.hxx"
+
+#include <vector>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::beans { struct Property; }
+namespace com::sun::star::uno { template <class interface_type> class Reference; }
+
+namespace chart
+{
+
+// implements service LineProperties
+namespace LinePropertiesHelper
+{
+ // FastProperty Ids for properties
+ enum
+ {
+ // com.sun.star.drawing.LineProperties
+ PROP_LINE_STYLE = FAST_PROPERTY_ID_START_LINE_PROP,
+ PROP_LINE_DASH,
+ PROP_LINE_DASH_NAME, //not in service description
+ PROP_LINE_COLOR,
+ PROP_LINE_TRANSPARENCE,
+ PROP_LINE_WIDTH,
+ PROP_LINE_JOINT,
+ PROP_LINE_CAP
+ };
+
+ OOO_DLLPUBLIC_CHARTTOOLS void AddPropertiesToVector(
+ std::vector< css::beans::Property > & rOutProperties );
+
+ OOO_DLLPUBLIC_CHARTTOOLS void AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap );
+
+ bool IsLineVisible( const css::uno::Reference<
+ css::beans::XPropertySet >& xLineProperties );
+ void SetLineVisible( const css::uno::Reference<
+ css::beans::XPropertySet >& xLineProperties );
+ void SetLineInvisible( const css::uno::Reference<
+ css::beans::XPropertySet >& xLineProperties );
+ void SetLineColor( const css::uno::Reference<
+ css::beans::XPropertySet >& xGridProperties, sal_Int32 nColor );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/LinearRegressionCurveCalculator.hxx b/chart2/source/inc/LinearRegressionCurveCalculator.hxx
new file mode 100644
index 0000000000..05853b26a8
--- /dev/null
+++ b/chart2/source/inc/LinearRegressionCurveCalculator.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "PolynomialRegressionCurveCalculator.hxx"
+
+namespace chart
+{
+
+class LinearRegressionCurveCalculator final : public PolynomialRegressionCurveCalculator
+{
+public:
+ LinearRegressionCurveCalculator();
+ virtual ~LinearRegressionCurveCalculator() override;
+
+private:
+ virtual void SAL_CALL setRegressionProperties(
+ sal_Int32 aDegree,
+ sal_Bool aForceIntercept,
+ double aInterceptValue,
+ sal_Int32 aPeriod,
+ sal_Int32 nMovingType) override;
+
+ virtual css::uno::Sequence<css::geometry::RealPoint2D> SAL_CALL getCurveValues(
+ double min,
+ double max,
+ sal_Int32 nPointCount,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingX,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation ) override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/LogarithmicRegressionCurveCalculator.hxx b/chart2/source/inc/LogarithmicRegressionCurveCalculator.hxx
new file mode 100644
index 0000000000..02fa1fc22b
--- /dev/null
+++ b/chart2/source/inc/LogarithmicRegressionCurveCalculator.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "RegressionCurveCalculator.hxx"
+
+namespace chart
+{
+
+class LogarithmicRegressionCurveCalculator final : public RegressionCurveCalculator
+{
+public:
+ LogarithmicRegressionCurveCalculator();
+ virtual ~LogarithmicRegressionCurveCalculator() override;
+
+protected:
+ virtual OUString ImplGetRepresentation(
+ const css::uno::Reference<css::util::XNumberFormatter>& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const override;
+
+private:
+ // ____ XRegressionCurveCalculator ____
+ virtual void SAL_CALL recalculateRegression(
+ const css::uno::Sequence<double>& aXValues,
+ const css::uno::Sequence<double>& aYValues ) override;
+
+ virtual double SAL_CALL getCurveValue( double x ) override;
+
+ virtual css::uno::Sequence<css::geometry::RealPoint2D> SAL_CALL getCurveValues(
+ double min,
+ double max,
+ sal_Int32 nPointCount,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingX,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation ) override;
+
+ // formula is: f(x) = m_fSlope * log( x ) + m_fIntercept
+ double m_fSlope;
+ double m_fIntercept;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/MeanValueRegressionCurveCalculator.hxx b/chart2/source/inc/MeanValueRegressionCurveCalculator.hxx
new file mode 100644
index 0000000000..be46e97388
--- /dev/null
+++ b/chart2/source/inc/MeanValueRegressionCurveCalculator.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "RegressionCurveCalculator.hxx"
+
+namespace chart
+{
+
+class MeanValueRegressionCurveCalculator final : public RegressionCurveCalculator
+{
+public:
+ MeanValueRegressionCurveCalculator();
+ virtual ~MeanValueRegressionCurveCalculator() override;
+
+protected:
+ virtual OUString ImplGetRepresentation(
+ const css::uno::Reference<css::util::XNumberFormatter>& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const override;
+
+private:
+ // ____ XRegressionCurveCalculator ____
+ virtual void SAL_CALL recalculateRegression(
+ const css::uno::Sequence<double>& aXValues,
+ const css::uno::Sequence<double>& aYValues ) override;
+
+ virtual double SAL_CALL getCurveValue( double x ) override;
+
+ virtual css::uno::Sequence<css::geometry::RealPoint2D> SAL_CALL getCurveValues(
+ double min,
+ double max,
+ sal_Int32 nPointCount,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingX,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation ) override;
+
+ // formula is: f(x) = m_fMeanValue
+ double m_fMeanValue;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/MediaDescriptorHelper.hxx b/chart2/source/inc/MediaDescriptorHelper.hxx
new file mode 100644
index 0000000000..cfef8fc14f
--- /dev/null
+++ b/chart2/source/inc/MediaDescriptorHelper.hxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include "charttoolsdllapi.hxx"
+
+namespace com::sun::star::beans { struct PropertyValue; }
+namespace com::sun::star::embed { class XStorage; }
+namespace com::sun::star::io { class XInputStream; }
+namespace com::sun::star::io { class XOutputStream; }
+namespace com::sun::star::io { class XStream; }
+
+/*
+* This class helps to read and write the properties mentioned in the service description
+* com.sun.star.document.MediaDescriptor from and to a sequence of PropertyValues.
+* Properties that are not mentioned in the service description
+* are stored in the member AdditionalProperties.
+*
+* As an additional feature this helper class can generate a reduced sequence of PropertyValues
+* that does not contain properties which are known to be only view relevant. This
+* reduced sequence than might be attached to a model directly.
+*/
+
+namespace apphelper
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS MediaDescriptorHelper final
+{
+public:
+ MediaDescriptorHelper( const css::uno::Sequence< css::beans::PropertyValue > & rMediaDescriptor );
+
+ const css::uno::Sequence< css::beans::PropertyValue >& getReducedForModel() const { return m_aModelProperties;}
+
+ //all properties given in the constructor are stored in the following three sequences
+
+ //properties which should be given to a model are additionally stored in this sequence (not documented properties and deprecated properties are not included!)
+ css::uno::Sequence< css::beans::PropertyValue >
+ m_aModelProperties; //these are properties which are not described in service com.sun.star.document.MediaDescriptor
+
+ OUString FilterName; //internal filter name.
+ bool ISSET_FilterName;
+
+ OUString HierarchicalDocumentName;
+
+ css::uno::Reference< css::io::XOutputStream >
+ OutputStream; //a stream to receive the document data for saving
+ bool ISSET_OutputStream;
+ css::uno::Reference< css::io::XInputStream >
+ InputStream; //content of document.
+ bool ISSET_InputStream;
+
+ bool ReadOnly; //open document readonly.
+
+ OUString URL;// FileName, URL of the document.
+ bool ISSET_URL;
+
+ // new framework objects
+ css::uno::Reference< css::embed::XStorage >
+ Storage;
+ bool ISSET_Storage;
+ css::uno::Reference< css::io::XStream >
+ Stream;
+ bool ISSET_Stream;
+
+private:
+ SAL_DLLPRIVATE void impl_init();
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ModifyListenerCallBack.hxx b/chart2/source/inc/ModifyListenerCallBack.hxx
new file mode 100644
index 0000000000..406804189e
--- /dev/null
+++ b/chart2/source/inc/ModifyListenerCallBack.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <tools/link.hxx>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include "charttoolsdllapi.hxx"
+
+namespace chart
+{
+/** Use this class as a member if you want to listen on a XModifyBroadcaster
+without becoming a XModifyListener yourself
+ */
+
+class ModifyListenerCallBack_impl;
+
+class OOO_DLLPUBLIC_CHARTTOOLS ModifyListenerCallBack final
+{
+public:
+ explicit ModifyListenerCallBack(const Link<void*, void>& rCallBack);
+
+ ~ModifyListenerCallBack();
+
+ void startListening(
+ const ::com::sun::star::uno::Reference<::com::sun::star::util::XModifyBroadcaster>&
+ xBroadcaster);
+ SAL_DLLPRIVATE void stopListening();
+
+private: //methods
+ ModifyListenerCallBack(const ModifyListenerCallBack&) = delete;
+
+private: //member
+ ModifyListenerCallBack_impl* pModifyListener_impl;
+ css::uno::Reference<css::util::XModifyListener> m_xModifyListener;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ModifyListenerHelper.hxx b/chart2/source/inc/ModifyListenerHelper.hxx
new file mode 100644
index 0000000000..ee90d407a6
--- /dev/null
+++ b/chart2/source/inc/ModifyListenerHelper.hxx
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <comphelper/interfacecontainer4.hxx>
+#include <comphelper/compbase.hxx>
+#include <rtl/ref.hxx>
+
+#include <mutex>
+#include <algorithm>
+#include <utility>
+
+namespace chart
+{
+
+/** This helper class serves as forwarder of modify events. It can be used
+ whenever an object has to send modify events after it gets a modify event of
+ one of its children.
+ */
+class ModifyEventForwarder final :
+ public ::comphelper::WeakComponentImplHelper<
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+{
+public:
+ ModifyEventForwarder();
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+private:
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ WeakComponentImplHelperBase ____
+ virtual void disposing(std::unique_lock<std::mutex>& ) override;
+
+ comphelper::OInterfaceContainerHelper4<css::util::XModifyListener> m_aModifyListeners;
+};
+
+}
+
+namespace chart::ModifyListenerHelper
+{
+
+namespace impl
+{
+
+template< class InterfaceRef >
+struct addListenerFunctor
+{
+ explicit addListenerFunctor( css::uno::Reference< css::util::XModifyListener > xListener ) :
+ m_xListener(std::move( xListener ))
+ {}
+
+ void operator() ( const InterfaceRef & xObject )
+ {
+ css::uno::Reference< css::util::XModifyBroadcaster >
+ xBroadcaster( xObject, css::uno::UNO_QUERY );
+ if( xBroadcaster.is() && m_xListener.is())
+ xBroadcaster->addModifyListener( m_xListener );
+ }
+private:
+ css::uno::Reference< css::util::XModifyListener > m_xListener;
+};
+
+template< class InterfaceRef >
+struct removeListenerFunctor
+{
+ explicit removeListenerFunctor( css::uno::Reference< css::util::XModifyListener > xListener ) :
+ m_xListener(std::move( xListener ))
+ {}
+
+ void operator() ( const InterfaceRef & xObject )
+ {
+ css::uno::Reference< css::util::XModifyBroadcaster >
+ xBroadcaster( xObject, css::uno::UNO_QUERY );
+ if( xBroadcaster.is() && m_xListener.is())
+ xBroadcaster->removeModifyListener( m_xListener );
+ }
+private:
+ css::uno::Reference< css::util::XModifyListener > m_xListener;
+};
+
+template< class Pair >
+struct addListenerToMappedElementFunctor
+{
+ explicit addListenerToMappedElementFunctor( css::uno::Reference< css::util::XModifyListener > xListener ) :
+ m_xListener(std::move( xListener ))
+ {}
+
+ void operator() ( const Pair & aPair )
+ {
+ css::uno::Reference< css::util::XModifyBroadcaster >
+ xBroadcaster( aPair.second, css::uno::UNO_QUERY );
+ if( xBroadcaster.is() && m_xListener.is())
+ xBroadcaster->addModifyListener( m_xListener );
+ }
+private:
+ css::uno::Reference< css::util::XModifyListener > m_xListener;
+};
+
+template< class Pair >
+struct removeListenerFromMappedElementFunctor
+{
+ explicit removeListenerFromMappedElementFunctor( css::uno::Reference< css::util::XModifyListener > xListener ) :
+ m_xListener(std::move( xListener ))
+ {}
+
+ void operator() ( const Pair & aPair )
+ {
+ css::uno::Reference< css::util::XModifyBroadcaster >
+ xBroadcaster( aPair.second, css::uno::UNO_QUERY );
+ if( xBroadcaster.is() && m_xListener.is())
+ xBroadcaster->removeModifyListener( m_xListener );
+ }
+private:
+ css::uno::Reference< css::util::XModifyListener > m_xListener;
+};
+
+} // namespace impl
+
+template< class InterfaceRef >
+void addListener(
+ const InterfaceRef & xObject,
+ const css::uno::Reference< css::util::XModifyListener > & xListener )
+{
+ if( xListener.is())
+ {
+ impl::addListenerFunctor< InterfaceRef > aFunctor( xListener );
+ aFunctor( xObject );
+ }
+}
+template< class T >
+void addListener(
+ const rtl::Reference<T> & xBroadcaster,
+ const css::uno::Reference< css::util::XModifyListener > & xListener )
+{
+ if( xBroadcaster && xListener )
+ xBroadcaster->addModifyListener( xListener );
+}
+
+template< class Container >
+void addListenerToAllElements(
+ const Container & rContainer,
+ const css::uno::Reference< css::util::XModifyListener > & xListener )
+{
+ if( xListener.is())
+ std::for_each( rContainer.begin(), rContainer.end(),
+ impl::addListenerFunctor< typename Container::value_type >( xListener ));
+}
+
+template< class T >
+void addListenerToAllElements(
+ const std::vector<rtl::Reference<T>> & rContainer,
+ const css::uno::Reference< css::util::XModifyListener > & xListener )
+{
+ if( !xListener )
+ return;
+ for (auto const & i : rContainer)
+ i->addModifyListener(xListener);
+}
+
+template< class Container >
+void addListenerToAllMapElements(
+ const Container & rContainer,
+ const css::uno::Reference< css::util::XModifyListener > & xListener )
+{
+ if( xListener.is())
+ std::for_each( rContainer.begin(), rContainer.end(),
+ impl::addListenerToMappedElementFunctor< typename Container::value_type >( xListener ));
+}
+
+template< class InterfaceRef >
+void removeListener(
+ const InterfaceRef & xObject,
+ const css::uno::Reference< css::util::XModifyListener > & xListener )
+{
+ if( xListener.is())
+ {
+ impl::removeListenerFunctor< InterfaceRef > aFunctor( xListener );
+ aFunctor( xObject );
+ }
+}
+
+template< class T >
+void removeListener(
+ const rtl::Reference<T> & xBroadcaster,
+ const css::uno::Reference< css::util::XModifyListener > & xListener )
+{
+ if( xBroadcaster && xListener )
+ xBroadcaster->removeModifyListener( xListener );
+}
+
+template< class Container >
+void removeListenerFromAllElements(
+ const Container & rContainer,
+ const css::uno::Reference< css::util::XModifyListener > & xListener )
+{
+ if( xListener.is())
+ std::for_each( rContainer.begin(), rContainer.end(),
+ impl::removeListenerFunctor< typename Container::value_type >( xListener ));
+}
+
+template< class T >
+void removeListenerFromAllElements(
+ const std::vector<rtl::Reference<T>> & rContainer,
+ const css::uno::Reference< css::util::XModifyListener > & xListener )
+{
+ if( !xListener )
+ return;
+ for (auto const & i : rContainer)
+ i->removeModifyListener(xListener);
+}
+
+template< class Container >
+void removeListenerFromAllMapElements(
+ const Container & rContainer,
+ const css::uno::Reference< css::util::XModifyListener > & xListener )
+{
+ if( xListener.is())
+ std::for_each( rContainer.begin(), rContainer.end(),
+ impl::removeListenerFromMappedElementFunctor< typename Container::value_type >( xListener ));
+}
+
+} // namespace chart::ModifyListenerHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/MovingAverageRegressionCurveCalculator.hxx b/chart2/source/inc/MovingAverageRegressionCurveCalculator.hxx
new file mode 100644
index 0000000000..f7e25fe513
--- /dev/null
+++ b/chart2/source/inc/MovingAverageRegressionCurveCalculator.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "RegressionCurveCalculator.hxx"
+#include "RegressionCalculationHelper.hxx"
+#include <vector>
+
+namespace chart
+{
+
+class MovingAverageRegressionCurveCalculator final : public RegressionCurveCalculator
+{
+public:
+ MovingAverageRegressionCurveCalculator();
+ virtual ~MovingAverageRegressionCurveCalculator() override;
+
+protected:
+ virtual OUString ImplGetRepresentation(
+ const css::uno::Reference<css::util::XNumberFormatter>& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const override;
+
+private:
+ // ____ XRegressionCurveCalculator ____
+ virtual void SAL_CALL recalculateRegression(
+ const css::uno::Sequence<double>& aXValues,
+ const css::uno::Sequence<double>& aYValues ) override;
+
+ virtual double SAL_CALL getCurveValue( double x ) override;
+
+ virtual css::uno::Sequence<css::geometry::RealPoint2D> SAL_CALL getCurveValues(
+ double min,
+ double max,
+ sal_Int32 nPointCount,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingX,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation ) override;
+
+ void calculateValues(RegressionCalculationHelper::tDoubleVectorPair aValues, bool bUseXAvg);
+ void calculateValuesCentral(RegressionCalculationHelper::tDoubleVectorPair aValues);
+ std::vector<double> aYList;
+ std::vector<double> aXList;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/NameContainer.hxx b/chart2/source/inc/NameContainer.hxx
new file mode 100644
index 0000000000..12fc76978b
--- /dev/null
+++ b/chart2/source/inc/NameContainer.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <map>
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::container::XNameContainer,
+ css::lang::XServiceInfo,
+ css::util::XCloneable >
+ NameContainer_Base;
+}
+
+/// Contains the XML namespaces map
+///
+class NameContainer final : public impl::NameContainer_Base
+{
+public:
+ NameContainer();
+ explicit NameContainer( const NameContainer & rOther );
+ virtual ~NameContainer() override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XNameContainer
+ virtual void SAL_CALL insertByName( const OUString& aName, const css::uno::Any& aElement ) override;
+ virtual void SAL_CALL removeByName( const OUString& Name ) override;
+
+ // XNameReplace
+ virtual void SAL_CALL replaceByName( const OUString& aName, const css::uno::Any& aElement ) override;
+
+ // XNameAccess
+ virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override;
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override;
+
+ // XElementAccess
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+
+ // XCloneable
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+private: //member
+
+ typedef std::map< OUString, css::uno::Any > tContentMap;
+ tContentMap m_aMap;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/NumberFormatterWrapper.hxx b/chart2/source/inc/NumberFormatterWrapper.hxx
new file mode 100644
index 0000000000..c3412fc9c9
--- /dev/null
+++ b/chart2/source/inc/NumberFormatterWrapper.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <tools/date.hxx>
+
+class SvNumberFormatter;
+class Color;
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS NumberFormatterWrapper final
+{
+public:
+ NumberFormatterWrapper( const css::uno::Reference< css::util::XNumberFormatsSupplier >& xSupplier );
+ ~NumberFormatterWrapper();
+
+ SvNumberFormatter* getSvNumberFormatter() const { return m_pNumberFormatter;}
+ const css::uno::Reference< css::util::XNumberFormatsSupplier >&
+ getNumberFormatsSupplier() const { return m_xNumberFormatsSupplier; };
+
+ OUString getFormattedString( sal_Int32 nNumberFormatKey, double fValue, Color& rLabelColor, bool& rbColorChanged ) const;
+ Date getNullDate() const;
+
+private: //private member
+ css::uno::Reference< css::util::XNumberFormatsSupplier >
+ m_xNumberFormatsSupplier;
+
+ SvNumberFormatter* m_pNumberFormatter;
+ css::uno::Any m_aNullDate;
+};
+
+class FixedNumberFormatter final
+{
+public:
+ FixedNumberFormatter( const css::uno::Reference< css::util::XNumberFormatsSupplier >& xSupplier
+ , sal_Int32 nNumberFormatKey );
+ ~FixedNumberFormatter();
+
+ OUString getFormattedString( double fValue, Color& rLabelColor, bool& rbColorChanged ) const;
+
+private:
+ NumberFormatterWrapper m_aNumberFormatterWrapper;
+ sal_uInt32 m_nNumberFormatKey;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/OPropertySet.hxx b/chart2/source/inc/OPropertySet.hxx
new file mode 100644
index 0000000000..aa5d2e7cd4
--- /dev/null
+++ b/chart2/source/inc/OPropertySet.hxx
@@ -0,0 +1,233 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+// helper classes
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+// interfaces and types
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/XMultiPropertyStates.hpp>
+#include <com/sun/star/style/XStyleSupplier.hpp>
+#include "charttoolsdllapi.hxx"
+
+#include <unordered_map>
+
+namespace property
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS OPropertySet :
+ protected cppu::BaseMutex,
+ public ::cppu::OBroadcastHelper,
+ // includes beans::XPropertySet, XMultiPropertySet and XFastPropertySet
+ public ::cppu::OPropertySetHelper,
+ // includes uno::XWeak (and XInterface, esp. ref-counting)
+
+ public css::lang::XTypeProvider,
+ public css::beans::XPropertyState,
+ public css::beans::XMultiPropertyStates,
+ public css::style::XStyleSupplier
+{
+public:
+ OPropertySet();
+ virtual ~OPropertySet();
+
+protected:
+ explicit OPropertySet( const OPropertySet & rOther );
+
+ void SetNewValuesExplicitlyEvenIfTheyEqualDefault();
+
+ /** implement this method to provide default values for all properties
+ supporting defaults. If a property does not have a default value, you
+ may throw an UnknownPropertyException.
+ We pass the any by reference because this code is very hot and doing
+ it this way is cheaper than the two step process of constructing a new
+ any and then assigning to via a return value.
+
+ @throws css::beans::UnknownPropertyException
+ @throws css::uno::RuntimeException
+ */
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const = 0;
+
+ /** The InfoHelper table contains all property names and types of
+ this object.
+
+ @return the object that provides information for the
+ PropertySetInfo
+
+ @see ::cppu::OPropertySetHelper
+ */
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override = 0;
+
+ /** Try to convert the value <code>rValue</code> to the type required by the
+ property associated with <code>nHandle</code>.
+
+ Override this method to take influence in modification of properties.
+
+ If the conversion changed , </sal_True> is returned and the converted value
+ is in <code>rConvertedValue</code>. The former value is contained in
+ <code>rOldValue</code>.
+
+ After this call returns successfully, the vetoable listeners are
+ notified.
+
+ @throws IllegalArgumentException, if the conversion was not successful,
+ or if there is no corresponding property to the given handle.
+
+ @param rConvertedValue the converted value. Only set if return is true.
+ @param rOldValue the old value. Only set if return is true.
+ @param nHandle the handle of the property.
+
+ @return true, if the conversion was successful and converted value
+ differs from the old value.
+
+ @see ::cppu::OPropertySetHelper
+ */
+ virtual sal_Bool SAL_CALL convertFastPropertyValue
+ ( css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override final;
+
+ /** The same as setFastPropertyValue; nHandle is always valid.
+ The changes must not be broadcasted in this method.
+
+ @attention
+ Although you are permitted to throw any UNO exception, only the following
+ are valid for usage:
+ -- css::beans::UnknownPropertyException
+ -- css::beans::PropertyVetoException
+ -- css::lang::IllegalArgumentException
+ -- css::lang::WrappedTargetException
+ -- css::uno::RuntimeException
+
+ @param nHandle handle
+ @param rValue value
+
+ @see ::cppu::OPropertySetHelper
+ */
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast
+ ( sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ /**
+ The same as getFastPropertyValue, but return the value through rValue and
+ nHandle is always valid.
+
+ @see ::cppu::OPropertySetHelper
+ */
+ virtual void SAL_CALL getFastPropertyValue
+ ( css::uno::Any& rValue,
+ sal_Int32 nHandle ) const override;
+
+ /** implement this method in derived classes to get called when properties
+ change.
+ */
+ virtual void firePropertyChangeEvent();
+
+public:
+ /// make original interface function visible again
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+
+ // Interfaces
+
+ // ____ XInterface ____
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+
+ // ____ XTypeProvider ____
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL
+ getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL
+ getImplementationId() override;
+
+ // ____ XPropertyState ____
+ virtual css::beans::PropertyState SAL_CALL
+ getPropertyState( const OUString& PropertyName ) override final;
+ virtual css::uno::Sequence< css::beans::PropertyState > SAL_CALL
+ getPropertyStates( const css::uno::Sequence< OUString >& aPropertyName ) override final;
+ virtual void SAL_CALL
+ setPropertyToDefault( const OUString& PropertyName ) override final;
+ virtual css::uno::Any SAL_CALL
+ getPropertyDefault( const OUString& aPropertyName ) override final;
+
+ // ____ XMultiPropertyStates ____
+ // Note: getPropertyStates() is already implemented in XPropertyState with the
+ // same signature
+ virtual void SAL_CALL
+ setAllPropertiesToDefault() override final;
+ virtual void SAL_CALL
+ setPropertiesToDefault( const css::uno::Sequence< OUString >& aPropertyNames ) override final;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL
+ getPropertyDefaults( const css::uno::Sequence< OUString >& aPropertyNames ) override final;
+
+ // ____ XStyleSupplier ____
+ virtual css::uno::Reference< css::style::XStyle > SAL_CALL getStyle() override final;
+ virtual void SAL_CALL setStyle( const css::uno::Reference< css::style::XStyle >& xStyle ) override final;
+
+ // ____ XMultiPropertySet ____
+ virtual void SAL_CALL setPropertyValues(
+ const css::uno::Sequence< OUString >& PropertyNames,
+ const css::uno::Sequence< css::uno::Any >& Values ) override final;
+
+ // ____ XFastPropertySet ____
+ virtual void SAL_CALL setFastPropertyValue( sal_Int32 nHandle, const css::uno::Any& rValue ) override final;
+
+ // Note: it is assumed that the base class implements setPropertyValue by
+ // using setFastPropertyValue
+
+private:
+ /** supports states DIRECT_VALUE and DEFAULT_VALUE
+ */
+ css::beans::PropertyState
+ GetPropertyStateByHandle( sal_Int32 nHandle ) const;
+
+ css::uno::Sequence< css::beans::PropertyState >
+ GetPropertyStatesByHandle( const std::vector< sal_Int32 > & aHandles ) const;
+
+ void SetPropertyToDefault( sal_Int32 nHandle );
+ void SetPropertiesToDefault( const std::vector< sal_Int32 > & aHandles );
+ void SetAllPropertiesToDefault();
+
+ /** @param rValue is set to the value for the property given in nHandle. If
+ the property is not set, the style chain is searched for any
+ instance set there. If there was no value found either in the
+ property set itself or any of its styles, rValue remains
+ unchanged and false is returned.
+
+ @return false if the property is default, true otherwise.
+ */
+ bool GetPropertyValueByHandle(
+ css::uno::Any & rValue,
+ sal_Int32 nHandle ) const;
+
+ void SetPropertyValueByHandle( sal_Int32 nHandle,
+ const css::uno::Any & rValue );
+
+ bool SetStyle( const css::uno::Reference< css::style::XStyle > & xStyle );
+
+ bool m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault;
+ std::unordered_map< sal_Int32, css::uno::Any > m_aProperties;
+ css::uno::Reference< css::style::XStyle > m_xStyle;
+};
+
+} // namespace property
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ObjectIdentifier.hxx b/chart2/source/inc/ObjectIdentifier.hxx
new file mode 100644
index 0000000000..c6d0c724bd
--- /dev/null
+++ b/chart2/source/inc/ObjectIdentifier.hxx
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include "TitleHelper.hxx"
+#include "charttoolsdllapi.hxx"
+
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+
+namespace chart { class ChartModel; }
+namespace com::sun::star::awt { struct Point; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XAxis; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::chart2 { class XCoordinateSystem; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::drawing { class XShape; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::uno { class XInterface; }
+
+namespace chart
+{
+class Axis;
+class BaseCoordinateSystem;
+class DataSeries;
+class Diagram;
+class Legend;
+
+enum ObjectType
+{
+ OBJECTTYPE_PAGE,
+ OBJECTTYPE_TITLE,
+ OBJECTTYPE_LEGEND,
+ OBJECTTYPE_LEGEND_ENTRY,
+ OBJECTTYPE_DIAGRAM,
+ OBJECTTYPE_DIAGRAM_WALL,
+ OBJECTTYPE_DIAGRAM_FLOOR,
+ OBJECTTYPE_AXIS,
+ OBJECTTYPE_AXIS_UNITLABEL,
+ OBJECTTYPE_GRID,
+ OBJECTTYPE_SUBGRID,
+ OBJECTTYPE_DATA_SERIES,
+ OBJECTTYPE_DATA_POINT,
+ OBJECTTYPE_DATA_LABELS,
+ OBJECTTYPE_DATA_LABEL,
+ OBJECTTYPE_DATA_ERRORS_X,
+ OBJECTTYPE_DATA_ERRORS_Y,
+ OBJECTTYPE_DATA_ERRORS_Z,
+ OBJECTTYPE_DATA_CURVE,//e.g. a statistical method printed as line
+ OBJECTTYPE_DATA_AVERAGE_LINE,
+ OBJECTTYPE_DATA_CURVE_EQUATION,
+ OBJECTTYPE_DATA_STOCK_RANGE,
+ OBJECTTYPE_DATA_STOCK_LOSS,
+ OBJECTTYPE_DATA_STOCK_GAIN,
+ OBJECTTYPE_DATA_TABLE,
+ OBJECTTYPE_SHAPE,
+ OBJECTTYPE_UNKNOWN
+};
+
+class OOO_DLLPUBLIC_CHARTTOOLS ObjectIdentifier
+{
+ //CID == ClassifiedIdentifier <--> name of shape
+ //semicolon, colon, equal sign and slash have special meanings in a CID
+ //and are therefore not allowed in its components
+
+ //syntax of a CID: CID:/classification/ObjectID
+
+ //where classification: nothing or "MultiClick" or "DragMethod=DragMethodServiceName" and "DragParameter=DragParameterString"
+ // or a combination of these separated with a colon
+ //where DragMethodServiceName can be a selfdefined servicename for special actions //todo define standard service for this purpose
+ //where DragParameterString is any string you like to transport information to your special drag service
+ // only semicolon, colon, equal sign and slash are not allowed characters
+ // also the keywords used in the ObjectIdentifiers are not allowed
+
+ //where ObjectID: Parent-Particle:Particle //e.g. Series=2:Point=22
+ //where Particle: Type=ParticleID //e.g. Point=22
+ //where Type: getStringForType( ObjectType eType ) or other string
+
+public:
+ ObjectIdentifier();
+ ObjectIdentifier( OUString aObjectCID );
+ ObjectIdentifier( const css::uno::Reference< css::drawing::XShape >& rxShape );
+ ObjectIdentifier( const css::uno::Any& rAny );
+
+ bool operator==( const ObjectIdentifier& rOID ) const;
+ bool operator!=( const ObjectIdentifier& rOID ) const;
+ bool operator<( const ObjectIdentifier& rOID ) const;
+
+ static OUString createClassifiedIdentifierForObject(
+ const css::uno::Reference< css::uno::XInterface >& xObject
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+ static OUString createClassifiedIdentifierForObject(
+ const rtl::Reference< ::chart::Title >& xObject
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+ static OUString createClassifiedIdentifierForObject(
+ const rtl::Reference< ::chart::Legend >& xObject
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+ static OUString createClassifiedIdentifierForObject(
+ const rtl::Reference< ::chart::Axis >& xObject
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+
+ static OUString createClassifiedIdentifierForParticle(
+ std::u16string_view rParticle );
+
+ static OUString createClassifiedIdentifierForParticles(
+ std::u16string_view rParentParticle
+ , std::u16string_view rChildParticle
+ , std::u16string_view rDragMethodServiceName = std::u16string_view()
+ , std::u16string_view rDragParameterString = std::u16string_view() );
+
+ static OUString createClassifiedIdentifierForGrid(
+ const css::uno::Reference< css::chart2::XAxis >& xAxis
+ , const rtl::Reference<::chart::ChartModel>& xChartModel
+ , sal_Int32 nSubIndex = -1 );//-1: main grid, 0: first subgrid etc
+
+ SAL_DLLPRIVATE static OUString createParticleForDiagram();
+
+ static OUString createParticleForCoordinateSystem(
+ const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+
+ static OUString createParticleForAxis(
+ sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+
+ static OUString createParticleForGrid(
+ sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+
+ static OUString createParticleForSeries( sal_Int32 nDiagramIndex, sal_Int32 nCooSysIndex
+ , sal_Int32 nChartTypeIndex, sal_Int32 nSeriesIndex );
+
+ static OUString createParticleForLegend(
+ const rtl::Reference<::chart::ChartModel>& xChartModel );
+
+ /** Creates an identifier for the data table */
+ static OUString createParticleForDataTable(
+ const rtl::Reference<::chart::ChartModel>& xChartModel );
+
+ static OUString addChildParticle( std::u16string_view rParticle, std::u16string_view rChildParticle );
+ static OUString createChildParticleWithIndex( ObjectType eObjectType, sal_Int32 nIndex );
+ static sal_Int32 getIndexFromParticleOrCID( std::u16string_view rParticleOrCID );
+
+ static OUString createClassifiedIdentifier(
+ enum ObjectType eObjectType //e.g. OBJECTTYPE_DATA_SERIES
+ , std::u16string_view rParticleID );//e.g. SeriesID
+
+ static OUString createClassifiedIdentifierWithParent(
+ enum ObjectType //e.g. OBJECTTYPE_DATA_POINT or OBJECTTYPE_GRID
+ , std::u16string_view rParticleID //for points or subgrids this is an Index or otherwise an identifier from the model object
+ , std::u16string_view rParentPartical //e.g. "Series=SeriesID" or "Grid=GridId"
+ , std::u16string_view rDragMethodServiceName = std::u16string_view()
+ , std::u16string_view rDragParameterString = std::u16string_view()
+ );
+
+ static bool isCID( std::u16string_view rName );
+ static std::u16string_view getDragMethodServiceName( std::u16string_view rClassifiedIdentifier );
+ static std::u16string_view getDragParameterString( std::u16string_view rCID );
+ static bool isDragableObject( std::u16string_view rClassifiedIdentifier );
+ bool isDragableObject() const;
+ static bool isRotateableObject( std::u16string_view rClassifiedIdentifier );
+ static bool isMultiClickObject( std::u16string_view rClassifiedIdentifier );
+ static bool areSiblings( std::u16string_view rCID1, std::u16string_view rCID2 );//identical object is no sibling
+ static bool areIdenticalObjects( std::u16string_view rCID1, std::u16string_view rCID2 );
+
+ static OUString getStringForType( ObjectType eObjectType );
+ static ObjectType getObjectType( std::u16string_view rCID );
+ ObjectType getObjectType() const;
+
+ static OUString createSeriesSubObjectStub( ObjectType eSubObjectType
+ , std::u16string_view rSeriesParticle
+ , std::u16string_view rDragMethodServiceName = std::u16string_view()
+ , std::u16string_view rDragParameterString = std::u16string_view() );
+ static OUString createPointCID( std::u16string_view rPointCID_Stub, sal_Int32 nIndex );
+
+ static OUString createDataCurveCID( std::u16string_view rSeriesParticle, sal_Int32 nCurveIndex, bool bAverageLine );
+ static OUString createDataCurveEquationCID( std::u16string_view rSeriesParticle, sal_Int32 nCurveIndex );
+
+ SAL_DLLPRIVATE static OUString getObjectID( std::u16string_view rCID );
+ static std::u16string_view getParticleID( std::u16string_view rCID );
+ static std::u16string_view getFullParentParticle( std::u16string_view rCID );
+
+ //returns the series particle of a CID when the CID is a child of the series
+ static OUString getSeriesParticleFromCID( std::u16string_view rCID );
+
+ //return the model object that is indicated by rObjectCID
+ static css::uno::Reference< css::beans::XPropertySet >
+ getObjectPropertySet(
+ std::u16string_view rObjectCID
+ , const rtl::Reference< ::chart::ChartModel >& xChartDocument );
+
+ //return the axis object that belongs to rObjectCID if any
+ static rtl::Reference< ::chart::Axis >
+ getAxisForCID(
+ std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+
+ //return the series object that belongs to rObjectCID if any
+ static rtl::Reference< ::chart::DataSeries >
+ getDataSeriesForCID(
+ std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+
+ static rtl::Reference< ::chart::Diagram >
+ getDiagramForCID(
+ std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel );
+
+ static const OUString& getPieSegmentDragMethodServiceName();
+ static OUString createPieSegmentDragParameterString(
+ sal_Int32 nOffsetPercent
+ , const css::awt::Point& rMinimumPosition
+ , const css::awt::Point& rMaximumPosition );
+ static bool parsePieSegmentDragParameterString( std::u16string_view rDragParameterString
+ , sal_Int32& rOffsetPercent
+ , css::awt::Point& rMinimumPosition
+ , css::awt::Point& rMaximumPosition );
+
+ static TitleHelper::eTitleType getTitleTypeForCID( std::u16string_view rCID );
+
+ static OUString getMovedSeriesCID( std::u16string_view rObjectCID, bool bForward );
+
+ bool isValid() const;
+ bool isAutoGeneratedObject() const;
+ bool isAdditionalShape() const;
+ const OUString& getObjectCID() const { return m_aObjectCID;}
+ const css::uno::Reference< css::drawing::XShape >& getAdditionalShape() const { return m_xAdditionalShape;}
+ css::uno::Any getAny() const;
+
+private:
+ // #i12587# support for shapes in chart
+ // For autogenerated chart objects a CID is specified in m_aObjectCID,
+ // for all other objects m_xAdditionalShape is set.
+ // Note, that if m_aObjectCID is set, m_xAdditionalShape must be empty
+ // and vice versa.
+ OUString m_aObjectCID;
+ css::uno::Reference< css::drawing::XShape > m_xAdditionalShape;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/PolynomialRegressionCurveCalculator.hxx b/chart2/source/inc/PolynomialRegressionCurveCalculator.hxx
new file mode 100644
index 0000000000..73512497b1
--- /dev/null
+++ b/chart2/source/inc/PolynomialRegressionCurveCalculator.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "RegressionCurveCalculator.hxx"
+#include <vector>
+
+namespace RegressionCalculationHelper
+{
+ typedef std::pair< std::vector< double >, std::vector< double > > tDoubleVectorPair;
+}
+
+namespace chart
+{
+
+class PolynomialRegressionCurveCalculator : public RegressionCurveCalculator
+{
+public:
+ PolynomialRegressionCurveCalculator();
+ virtual ~PolynomialRegressionCurveCalculator() override;
+
+protected:
+ virtual OUString ImplGetRepresentation(
+ const css::uno::Reference<css::util::XNumberFormatter>& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaMaxWidth = nullptr ) const override;
+
+ virtual double SAL_CALL getCurveValue( double x ) override;
+
+private:
+ // ____ XRegressionCurveCalculator ____
+ virtual void SAL_CALL recalculateRegression(
+ const css::uno::Sequence<double>& aXValues,
+ const css::uno::Sequence<double>& aYValues ) override;
+
+ void computeCorrelationCoefficient(
+ RegressionCalculationHelper::tDoubleVectorPair& rValues,
+ const sal_Int32 aNoValues,
+ double yAverage );
+
+ std::vector<double> mCoefficients;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/PopupRequest.hxx b/chart2/source/inc/PopupRequest.hxx
new file mode 100644
index 0000000000..a755fdfa3c
--- /dev/null
+++ b/chart2/source/inc/PopupRequest.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+
+#include <comphelper/compbase.hxx>
+#include <com/sun/star/awt/XRequestCallback.hpp>
+
+namespace chart
+{
+namespace impl
+{
+typedef comphelper::WeakComponentImplHelper<css::awt::XRequestCallback> PopupRequest_Base;
+}
+
+class OOO_DLLPUBLIC_CHARTTOOLS PopupRequest final : public impl::PopupRequest_Base
+{
+public:
+ explicit PopupRequest();
+ virtual ~PopupRequest() override;
+
+ css::uno::Reference<css::awt::XCallback> const& getCallback() const { return m_xCallback; }
+
+ // ____ XRequestCallback ____
+ virtual void SAL_CALL addCallback(const css::uno::Reference<::css::awt::XCallback>& xCallback,
+ const css::uno::Any& aData) override;
+
+private:
+ css::uno::Reference<css::awt::XCallback> m_xCallback;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/PotentialRegressionCurveCalculator.hxx b/chart2/source/inc/PotentialRegressionCurveCalculator.hxx
new file mode 100644
index 0000000000..a0d05b4a2f
--- /dev/null
+++ b/chart2/source/inc/PotentialRegressionCurveCalculator.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "RegressionCurveCalculator.hxx"
+
+namespace chart
+{
+
+class PotentialRegressionCurveCalculator final : public RegressionCurveCalculator
+{
+public:
+ PotentialRegressionCurveCalculator();
+ virtual ~PotentialRegressionCurveCalculator() override;
+
+protected:
+ virtual OUString ImplGetRepresentation(
+ const css::uno::Reference<css::util::XNumberFormatter>& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const override;
+
+private:
+ // ____ XRegressionCurveCalculator ____
+ virtual void SAL_CALL recalculateRegression(
+ const css::uno::Sequence<double>& aXValues,
+ const css::uno::Sequence<double>& aYValues ) override;
+
+ virtual double SAL_CALL getCurveValue( double x ) override;
+
+ virtual css::uno::Sequence<css::geometry::RealPoint2D> SAL_CALL getCurveValues(
+ double min,
+ double max,
+ sal_Int32 nPointCount,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingX,
+ const css::uno::Reference<css::chart2::XScaling>& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation ) override;
+
+ // formula is: f(x) = x ^ m_fSlope * m_fSign * m_fIntercept
+ double m_fSlope;
+ double m_fIntercept;
+ double m_fSign;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/PropertyHelper.hxx b/chart2/source/inc/PropertyHelper.hxx
new file mode 100644
index 0000000000..14aa576095
--- /dev/null
+++ b/chart2/source/inc/PropertyHelper.hxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include "charttoolsdllapi.hxx"
+
+#include <unordered_map>
+
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+
+namespace chart
+{
+
+typedef int tPropertyValueMapKey;
+
+typedef std::unordered_map<tPropertyValueMapKey, css::uno::Any> tPropertyValueMap;
+
+namespace PropertyHelper
+{
+
+/** adds a line dash with a unique name to the gradient obtained by the given
+ factory.
+
+ @return The name used for storing this element in the table
+*/
+OOO_DLLPUBLIC_CHARTTOOLS OUString addLineDashUniqueNameToTable(
+ const css::uno::Any & rValue,
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & xFact,
+ const OUString & rPreferredName );
+
+/** adds a gradient with a unique name to the gradient obtained by the given
+ factory.
+
+ @return The name used for storing this element in the table
+*/
+OOO_DLLPUBLIC_CHARTTOOLS OUString addGradientUniqueNameToTable(
+ const css::uno::Any & rValue,
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & xFact,
+ const OUString & rPreferredName );
+
+/** adds a transparency gradient with a unique name to the gradient obtained
+ by the given factory.
+
+ @return The name used for storing this element in the table
+*/
+OOO_DLLPUBLIC_CHARTTOOLS
+OUString addTransparencyGradientUniqueNameToTable(
+ const css::uno::Any & rValue,
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & xFact,
+ const OUString & rPreferredName );
+
+/** adds a hatch with a unique name to the gradient obtained by the given
+ factory.
+
+ @return The name used for storing this element in the table
+*/
+OOO_DLLPUBLIC_CHARTTOOLS OUString addHatchUniqueNameToTable(
+ const css::uno::Any & rValue,
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & xFact,
+ const OUString & rPreferredName );
+
+/** adds a bitmap with a unique name to the gradient obtained by the given
+ factory.
+
+ @return The name used for storing this element in the table
+*/
+OOO_DLLPUBLIC_CHARTTOOLS OUString addBitmapUniqueNameToTable(
+ const css::uno::Any & rValue,
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & xFact,
+ const OUString & rPreferredName );
+
+/** Set a property to a certain value in the given map. This works for
+ properties that are already set, and those which are not yet in the map.
+
+ @param any is the value encapsulated in the variant type Any
+ */
+OOO_DLLPUBLIC_CHARTTOOLS
+void setPropertyValueAny( tPropertyValueMap & rOutMap, tPropertyValueMapKey key,
+ const css::uno::Any & rAny );
+
+/** Set a property to a certain value in the given map. This works for
+ properties that are already set, and those which are not yet in the map.
+
+ @param value is the value of type Value that will be put into a variant type
+ Any before set in the property map.
+ */
+template< typename Value >
+ void setPropertyValue( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const Value & value )
+{
+ setPropertyValueAny( rOutMap, key, css::uno::Any( value ));
+}
+
+template<>
+ void setPropertyValue< css::uno::Any >( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const css::uno::Any & rAny );
+
+OOO_DLLPUBLIC_CHARTTOOLS void setPropertyValueDefaultAny( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const css::uno::Any & rAny );
+
+/** Calls setPropertyValue() but asserts that the given property hasn't been set
+ before.
+ */
+template< typename Value >
+ void setPropertyValueDefault( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const Value & value )
+{
+ setPropertyValueDefaultAny( rOutMap, key, css::uno::Any( value ));
+}
+
+/** Calls setPropertyValue() but asserts that the given property hasn't been set
+ before.
+ */
+template<>
+ void setPropertyValueDefault< css::uno::Any >( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const css::uno::Any & rAny );
+
+/** Calls setPropertyValueDefault() with an empty Any as value
+ */
+OOO_DLLPUBLIC_CHARTTOOLS void setEmptyPropertyValueDefault( tPropertyValueMap & rOutMap, tPropertyValueMapKey key );
+
+} // namespace PropertyHelper
+
+struct OOO_DLLPUBLIC_CHARTTOOLS PropertyNameLess
+{
+ bool operator() ( const css::beans::Property & first,
+ const css::beans::Property & second )
+ {
+ return ( first.Name.compareTo( second.Name ) < 0 );
+ }
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/RangeHighlighter.hxx b/chart2/source/inc/RangeHighlighter.hxx
new file mode 100644
index 0000000000..c7bcdd2c5c
--- /dev/null
+++ b/chart2/source/inc/RangeHighlighter.hxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <comphelper/compbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <com/sun/star/chart2/data/XRangeHighlighter.hpp>
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star {
+ namespace chart2 {
+ class XDiagram;
+ class XDataSeries;
+ class XAxis;
+ }
+}
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::view { class XSelectionSupplier; }
+
+namespace chart
+{
+class ChartModel;
+class DataSeries;
+class Diagram;
+
+namespace impl
+{
+typedef comphelper::WeakComponentImplHelper<
+ css::chart2::data::XRangeHighlighter,
+ css::view::XSelectionChangeListener
+ >
+ RangeHighlighter_Base;
+}
+
+class RangeHighlighter final :
+ public impl::RangeHighlighter_Base
+{
+public:
+ explicit RangeHighlighter(
+ const rtl::Reference< ::chart::ChartModel > & xSelectionSupplier );
+ virtual ~RangeHighlighter() override;
+
+protected:
+ // ____ XRangeHighlighter ____
+ virtual css::uno::Sequence< css::chart2::data::HighlightedRange > SAL_CALL getSelectedRanges() override;
+ virtual void SAL_CALL addSelectionChangeListener(
+ const css::uno::Reference< css::view::XSelectionChangeListener >& xListener ) override;
+ virtual void SAL_CALL removeSelectionChangeListener(
+ const css::uno::Reference< css::view::XSelectionChangeListener >& xListener ) override;
+
+ // ____ XSelectionChangeListener ____
+ virtual void SAL_CALL selectionChanged(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XSelectionChangeListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ WeakComponentImplHelperBase ____
+ // is called when dispose() is called at this component
+ virtual void disposing(std::unique_lock<std::mutex>&) override;
+
+private:
+ void fireSelectionEvent();
+ void startListening();
+ void stopListening();
+ void determineRanges();
+
+ void fillRangesForDiagram( const rtl::Reference< ::chart::Diagram > & xDiagram );
+ void fillRangesForDataSeries( const css::uno::Reference< css::chart2::XDataSeries > & xSeries );
+ void fillRangesForCategories( const css::uno::Reference< css::chart2::XAxis > & xAxis );
+ void fillRangesForDataPoint( const rtl::Reference< ::chart::DataSeries > & xDataSeries, sal_Int32 nIndex );
+ void fillRangesForErrorBars( const css::uno::Reference< css::beans::XPropertySet > & xErrorBar,
+ const css::uno::Reference< css::chart2::XDataSeries > & xDataSeries );
+
+ css::uno::Reference< css::view::XSelectionSupplier >
+ m_xSelectionSupplier;
+ rtl::Reference< ::chart::ChartModel > m_xChartModel;
+ css::uno::Reference< css::view::XSelectionChangeListener >
+ m_xListener;
+ css::uno::Sequence< css::chart2::data::HighlightedRange >
+ m_aSelectedRanges;
+ sal_Int32 m_nAddedListenerCount;
+ bool m_bIncludeHiddenCells;
+ comphelper::OInterfaceContainerHelper4<css::view::XSelectionChangeListener> maSelectionChangeListeners;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ReferenceSizeProvider.hxx b/chart2/source/inc/ReferenceSizeProvider.hxx
new file mode 100644
index 0000000000..dbacd093ff
--- /dev/null
+++ b/chart2/source/inc/ReferenceSizeProvider.hxx
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/awt/Size.hpp>
+#include "charttoolsdllapi.hxx"
+#include <rtl/ref.hxx>
+#include <ChartModel.hxx>
+
+namespace com::sun::star {
+ namespace chart2 {
+ class XTitle;
+ class XTitled;
+ class XChartDocument;
+ }
+ namespace beans {
+ class XPropertySet;
+ }
+}
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS ReferenceSizeProvider
+{
+public:
+
+ enum AutoResizeState
+ {
+ AUTO_RESIZE_YES,
+ AUTO_RESIZE_NO,
+ AUTO_RESIZE_AMBIGUOUS,
+ AUTO_RESIZE_UNKNOWN
+ };
+
+ ReferenceSizeProvider(
+ css::awt::Size aPageSize,
+ const rtl::Reference<::chart::ChartModel> & xChartDoc );
+
+ const css::awt::Size& getPageSize() const { return m_aPageSize;}
+
+ /** Retrieves the state auto-resize from all objects that support this
+ feature. If all objects return the same state, AUTO_RESIZE_YES or
+ AUTO_RESIZE_NO is returned.
+
+ If no object supporting the feature is found, AUTO_RESIZE_UNKNOWN is
+ returned. If there are multiple objects, some with state YES and some
+ with state NO, AUTO_RESIZE_AMBIGUOUS is returned.
+ */
+ static AutoResizeState getAutoResizeState(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc );
+
+ /** sets or resets the auto-resize at all objects that support this feature
+ for text to the opposite of the current setting. If the current state
+ is ambiguous, it is turned on. If the current state is unknown it stays
+ unknown.
+ */
+ void toggleAutoResizeState();
+
+ /** Sets the ReferencePageSize according to the internal settings of this
+ class at the XPropertySet, and the adapted font sizes if bAdaptFontSizes
+ is </sal_True>.
+ */
+ SAL_DLLPRIVATE void setValuesAtPropertySet(
+ const css::uno::Reference< css::beans::XPropertySet > & xProp,
+ bool bAdaptFontSizes = true );
+
+ /** Sets the ReferencePageSize according to the internal settings of this
+ class at the XTitle, and the adapted font sizes at the contained
+ XFormattedStrings
+ */
+ SAL_DLLPRIVATE void setValuesAtTitle(
+ const css::uno::Reference< css::chart2::XTitle > & xTitle );
+
+ /** Sets the internal value at all data series in the currently set model.
+ This is useful, if you have changed a chart-type and thus probably added
+ some new data series via model functionality.
+ */
+ void setValuesAtAllDataSeries();
+
+private:
+ SAL_DLLPRIVATE bool useAutoScale() const { return m_bUseAutoScale;}
+
+ /** sets the auto-resize at all objects that support this feature for text.
+ eNewState must be either AUTO_RESIZE_YES or AUTO_RESIZE_NO
+ */
+ SAL_DLLPRIVATE void setAutoResizeState( AutoResizeState eNewState );
+
+ /** Retrieves the auto-resize state from the given propertyset. The result
+ will be put into eInOutState. If you initialize eInOutState with
+ AUTO_RESIZE_UNKNOWN, you will get the actual state. If you pass any
+ other state, the result will be the accumulated state,
+ esp. AUTO_RESIZE_AMBIGUOUS, if the value was NO before, and is YES for
+ the current property set, or the other way round.
+ */
+ SAL_DLLPRIVATE static void getAutoResizeFromPropSet(
+ const css::uno::Reference< css::beans::XPropertySet > & xProp,
+ AutoResizeState & rInOutState );
+
+ SAL_DLLPRIVATE void impl_setValuesAtTitled(
+ const css::uno::Reference< css::chart2::XTitled > & xTitled );
+ SAL_DLLPRIVATE static void impl_getAutoResizeFromTitled(
+ const css::uno::Reference< css::chart2::XTitled > & xTitled,
+ AutoResizeState & rInOutState );
+
+ css::awt::Size m_aPageSize;
+ rtl::Reference<::chart::ChartModel> m_xChartDoc;
+ bool m_bUseAutoScale;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/RegressionCalculationHelper.hxx b/chart2/source/inc/RegressionCalculationHelper.hxx
new file mode 100644
index 0000000000..0b9600e99d
--- /dev/null
+++ b/chart2/source/inc/RegressionCalculationHelper.hxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <cmath>
+#include <utility>
+#include <vector>
+
+namespace chart::RegressionCalculationHelper
+{
+
+typedef std::pair< std::vector< double >, std::vector< double > > tDoubleVectorPair;
+
+/** takes the given x- and y-values and copies them into the resulting pair,
+ which contains x-values in the first element and the y-values in the second
+ one. All tuples for which aPred is false are not copied.
+
+ <p>The function below provide a set of useful predicates that can be
+ used to pass as parameter aPred.</p>
+ */
+template< class Pred >
+tDoubleVectorPair
+ cleanup( const css::uno::Sequence< double > & rXValues,
+ const css::uno::Sequence< double > & rYValues,
+ Pred aPred )
+{
+ tDoubleVectorPair aResult;
+ sal_Int32 nSize = std::min( rXValues.getLength(), rYValues.getLength());
+ for( sal_Int32 i=0; i<nSize; ++i )
+ {
+ if( aPred( rXValues[i], rYValues[i] ))
+ {
+ aResult.first.push_back( rXValues[i] );
+ aResult.second.push_back( rYValues[i] );
+ }
+ }
+
+ return aResult;
+}
+
+class isValid
+{
+public:
+ bool operator()( double x, double y )
+ { return ! ( std::isnan( x ) ||
+ std::isnan( y ) ||
+ std::isinf( x ) ||
+ std::isinf( y ) );
+ }
+};
+
+class isValidAndXPositive
+{
+public:
+ bool operator()( double x, double y )
+ { return ! ( std::isnan( x ) ||
+ std::isnan( y ) ||
+ std::isinf( x ) ||
+ std::isinf( y ) ||
+ x <= 0.0 );
+ }
+};
+
+class isValidAndYPositive
+{
+public:
+ bool operator()( double x, double y )
+ { return ! ( std::isnan( x ) ||
+ std::isnan( y ) ||
+ std::isinf( x ) ||
+ std::isinf( y ) ||
+ y <= 0.0 );
+ }
+};
+
+class isValidAndYNegative
+{
+public:
+ bool operator()( double x, double y )
+ { return ! ( std::isnan( x ) ||
+ std::isnan( y ) ||
+ std::isinf( x ) ||
+ std::isinf( y ) ||
+ y >= 0.0 );
+ }
+};
+
+class isValidAndBothPositive
+{
+public:
+ bool operator()( double x, double y )
+ { return ! ( std::isnan( x ) ||
+ std::isnan( y ) ||
+ std::isinf( x ) ||
+ std::isinf( y ) ||
+ x <= 0.0 ||
+ y <= 0.0 );
+ }
+};
+
+class isValidAndXPositiveAndYNegative
+{
+public:
+ bool operator()( double x, double y )
+ { return ! ( std::isnan( x ) ||
+ std::isnan( y ) ||
+ std::isinf( x ) ||
+ std::isinf( y ) ||
+ x <= 0.0 ||
+ y >= 0.0 );
+ }
+};
+
+} // namespace chart::RegressionCalculationHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/RegressionCurveCalculator.hxx b/chart2/source/inc/RegressionCurveCalculator.hxx
new file mode 100644
index 0000000000..ebb3ad40f6
--- /dev/null
+++ b/chart2/source/inc/RegressionCurveCalculator.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <com/sun/star/chart2/XRegressionCurveCalculator.hpp>
+
+namespace com::sun::star::util { class XNumberFormatsSupplier; }
+namespace com::sun::star::util { class XNumberFormatter; }
+
+namespace chart
+{
+
+class RegressionCurveCalculator : public
+ cppu::WeakImplHelper< css::chart2::XRegressionCurveCalculator >
+{
+public:
+ RegressionCurveCalculator();
+ virtual ~RegressionCurveCalculator() override;
+
+ static bool isLinearScaling(
+ const css::uno::Reference< css::chart2::XScaling >& xScaling );
+
+ static bool isLogarithmicScaling(
+ const css::uno::Reference< css::chart2::XScaling >& xScaling );
+
+ // ____ XRegressionCurveCalculator ____
+ virtual void SAL_CALL setRegressionProperties(
+ sal_Int32 aDegree,
+ sal_Bool aForceIntercept,
+ double aInterceptValue,
+ sal_Int32 aPeriod,
+ sal_Int32 nMovingType) override;
+
+ virtual void SAL_CALL recalculateRegression(
+ const css::uno::Sequence< double >& aXValues,
+ const css::uno::Sequence< double >& aYValues ) override = 0;
+
+ virtual double SAL_CALL getCurveValue( double x ) override = 0;
+
+ virtual css::uno::Sequence< css::geometry::RealPoint2D > SAL_CALL getCurveValues(
+ double min,
+ double max,
+ sal_Int32 nPointCount,
+ const css::uno::Reference< css::chart2::XScaling >& xScalingX,
+ const css::uno::Reference< css::chart2::XScaling >& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation ) override;
+
+ virtual double SAL_CALL getCorrelationCoefficient() override;
+
+ virtual OUString SAL_CALL getRepresentation() override;
+
+ virtual OUString SAL_CALL getFormattedRepresentation(
+ const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumFmtSupplier,
+ sal_Int32 nNumberFormatKey, sal_Int32 nFormulaLength ) override;
+
+ virtual void SAL_CALL setXYNames(
+ const OUString& aXName, const OUString& aYName ) override;
+
+protected:
+ virtual OUString ImplGetRepresentation(
+ const css::uno::Reference< css::util::XNumberFormatter >& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength = nullptr ) const = 0;
+
+ static OUString getFormattedString(
+ const css::uno::Reference< css::util::XNumberFormatter >& xNumFormatter,
+ sal_Int32 nNumberFormatKey,
+ double fNumber,
+ const sal_Int32* pStringLength );
+
+ static void addStringToEquation( OUStringBuffer& aStrEquation, sal_Int32& nLineLength, OUStringBuffer const & aAddString, const sal_Int32* pMaxLength );
+
+ double m_fCorrelationCoefficient;
+
+ sal_Int32 mDegree;
+ bool mForceIntercept;
+ double mInterceptValue;
+ sal_Int32 mPeriod;
+ OUString mXName, mYName;
+ sal_Int32 mnMovingType;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/RegressionCurveHelper.hxx b/chart2/source/inc/RegressionCurveHelper.hxx
new file mode 100644
index 0000000000..f9d9195064
--- /dev/null
+++ b/chart2/source/inc/RegressionCurveHelper.hxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svx/chrtitem.hxx>
+#include "charttoolsdllapi.hxx"
+#include <rtl/ref.hxx>
+
+#include <vector>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::chart2 { class XRegressionCurve; }
+namespace com::sun::star::chart2 { class XRegressionCurveCalculator; }
+namespace com::sun::star::chart2 { class XRegressionCurveContainer; }
+namespace com::sun::star::chart2::data { class XDataSource; }
+namespace com::sun::star::frame { class XModel; }
+namespace chart { class ChartModel; }
+namespace chart { class DataSeries; }
+namespace chart { class RegressionCurveModel; }
+namespace chart { class RegressionCurveCalculator; }
+
+namespace chart::RegressionCurveHelper
+{
+ /// returns a model mean-value line
+ rtl::Reference<::chart::RegressionCurveModel> createMeanValueLine();
+
+ /// returns a model regression curve
+ rtl::Reference<::chart::RegressionCurveModel>
+ createRegressionCurveByServiceName( std::u16string_view aServiceName );
+
+ OOO_DLLPUBLIC_CHARTTOOLS bool hasMeanValueLine(
+ const css::uno::Reference<css::chart2::XRegressionCurveContainer> & xRegCnt );
+ OOO_DLLPUBLIC_CHARTTOOLS bool hasMeanValueLine(
+ const rtl::Reference<::chart::DataSeries> & xRegCnt );
+
+ OOO_DLLPUBLIC_CHARTTOOLS bool isMeanValueLine(
+ const css::uno::Reference<css::chart2::XRegressionCurve> & xRegCurve );
+ OOO_DLLPUBLIC_CHARTTOOLS bool isMeanValueLine(
+ const rtl::Reference<::chart::RegressionCurveModel> & xRegCurve );
+
+ OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference<::chart::RegressionCurveModel>
+ getMeanValueLine(
+ const css::uno::Reference<css::chart2::XRegressionCurveContainer> & xRegCnt );
+ OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference<::chart::RegressionCurveModel>
+ getMeanValueLine(
+ const rtl::Reference<::chart::DataSeries> & xRegCnt );
+
+ /** creates a mean-value line and adds it to the container.
+
+ @param xSeriesProp
+ If set, this property-set will be used to apply a line color
+ */
+ OOO_DLLPUBLIC_CHARTTOOLS void addMeanValueLine(
+ css::uno::Reference<css::chart2::XRegressionCurveContainer> const & xRegCnt,
+ const css::uno::Reference<css::beans::XPropertySet>& xSeriesProp );
+ OOO_DLLPUBLIC_CHARTTOOLS void addMeanValueLine(
+ rtl::Reference<::chart::DataSeries> const & xRegCnt,
+ const css::uno::Reference<css::beans::XPropertySet>& xSeriesProp );
+
+ OOO_DLLPUBLIC_CHARTTOOLS void removeMeanValueLine(
+ css::uno::Reference<css::chart2::XRegressionCurveContainer> const & xRegCnt );
+ OOO_DLLPUBLIC_CHARTTOOLS void removeMeanValueLine(
+ rtl::Reference<::chart::DataSeries> const & xRegCnt );
+
+ /** Returns the first regression curve found that is not of type
+ mean-value line
+ */
+ OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference<::chart::RegressionCurveModel>
+ getFirstCurveNotMeanValueLine(
+ const css::uno::Reference<css::chart2::XRegressionCurveContainer>& xCurveContainer );
+ OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference<::chart::RegressionCurveModel>
+ getFirstCurveNotMeanValueLine(
+ const rtl::Reference<::chart::DataSeries>& xCurveContainer );
+
+ /** Returns the regression curve found at the index provided.
+ */
+ OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference<::chart::RegressionCurveModel>
+ getRegressionCurveAtIndex(
+ const rtl::Reference<::chart::DataSeries>& xCurveContainer,
+ sal_Int32 aIndex);
+
+ /** Returns the type of the first regression curve found that is not of type
+ mean-value line
+ */
+ OOO_DLLPUBLIC_CHARTTOOLS SvxChartRegress getFirstRegressTypeNotMeanValueLine(
+ const css::uno::Reference<css::chart2::XRegressionCurveContainer>& xCurveContainer );
+
+ OOO_DLLPUBLIC_CHARTTOOLS SvxChartRegress getRegressionType(
+ const css::uno::Reference<css::chart2::XRegressionCurve>& xCurve );
+
+ /** @param xPropertySource is taken as source to copy all properties from if
+ not null
+ @param xEquationProperties is set at the new regression curve as
+ equation properties if not null
+ */
+ OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference<::chart::RegressionCurveModel>
+ addRegressionCurve(
+ SvxChartRegress eType,
+ css::uno::Reference<css::chart2::XRegressionCurveContainer> const & xCurveContainer,
+ const css::uno::Reference<css::beans::XPropertySet >& xPropertySource =
+ css::uno::Reference<css::beans::XPropertySet>(),
+ const css::uno::Reference<css::beans::XPropertySet>& xEquationProperties =
+ css::uno::Reference<css::beans::XPropertySet>() );
+ OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference<::chart::RegressionCurveModel>
+ addRegressionCurve(
+ SvxChartRegress eType,
+ rtl::Reference<::chart::DataSeries> const & xCurveContainer,
+ const css::uno::Reference<css::beans::XPropertySet >& xPropertySource =
+ css::uno::Reference<css::beans::XPropertySet>(),
+ const css::uno::Reference<css::beans::XPropertySet>& xEquationProperties =
+ css::uno::Reference<css::beans::XPropertySet>() );
+
+ OOO_DLLPUBLIC_CHARTTOOLS bool removeAllExceptMeanValueLine(
+ rtl::Reference<::chart::DataSeries> const & xCurveContainer );
+
+ OOO_DLLPUBLIC_CHARTTOOLS void removeEquations(
+ rtl::Reference<::chart::DataSeries> const & xCurveContainer );
+
+ OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference<::chart::RegressionCurveModel>
+ changeRegressionCurveType(
+ SvxChartRegress eType,
+ css::uno::Reference<css::chart2::XRegressionCurveContainer> const & xRegressionCurveContainer,
+ css::uno::Reference<css::chart2::XRegressionCurve> const & xRegressionCurve );
+
+ /// returns a calculator object for regression curves (used by the view)
+ OOO_DLLPUBLIC_CHARTTOOLS rtl::Reference<::chart::RegressionCurveCalculator>
+ createRegressionCurveCalculatorByServiceName( std::u16string_view aServiceName );
+
+ /** recalculates the regression parameters according to the data given in
+ the data source.
+
+ A sequence having the role "values-x" will be used as x-values for the
+ calculation if found. Otherwise a sequence (1, 2, 3, ...) of category
+ indexes will be used for the recalculateRegression() method of the
+ regression curve.
+
+ The first sequence having the role "values-y" will be used as y-values
+ for the recalculateRegression() method of the regression curve.
+
+ @param bUseXValuesIfAvailable
+ If false, the sequence (1, 2, 3, ...) will always be used, even if
+ there is a data-sequence with role "values-x"
+ */
+ void initializeCurveCalculator(
+ const css::uno::Reference<css::chart2::XRegressionCurveCalculator>& xOutCurveCalculator,
+ const css::uno::Reference<css::chart2::data::XDataSource>& xSource,
+ bool bUseXValuesIfAvailable );
+
+ /** Same method as above, but uses the given XModel to determine the
+ parameter bUseXValuesIfAvailable in the above function. It is also
+ necessary that the data::XDataSource is an XDataSeries, thus this parameter
+ also changed.
+ */
+ OOO_DLLPUBLIC_CHARTTOOLS void initializeCurveCalculator(
+ const css::uno::Reference<css::chart2::XRegressionCurveCalculator>& xOutCurveCalculator,
+ const rtl::Reference<::chart::DataSeries>& xSeries,
+ const rtl::Reference<::chart::ChartModel>& xModel );
+
+ OOO_DLLPUBLIC_CHARTTOOLS OUString getUINameForRegressionCurve(
+ const css::uno::Reference<css::chart2::XRegressionCurve>& xCurve );
+
+ OOO_DLLPUBLIC_CHARTTOOLS OUString getRegressionCurveName(
+ const css::uno::Reference<css::chart2::XRegressionCurve>& xCurve );
+
+ OOO_DLLPUBLIC_CHARTTOOLS OUString getRegressionCurveGenericName(
+ const css::uno::Reference<css::chart2::XRegressionCurve>& xCurve );
+
+ OOO_DLLPUBLIC_CHARTTOOLS OUString getRegressionCurveSpecificName(
+ const css::uno::Reference<css::chart2::XRegressionCurve>& xCurve );
+
+ OOO_DLLPUBLIC_CHARTTOOLS void resetEquationPosition(
+ const css::uno::Reference<css::chart2::XRegressionCurve>& xCurve );
+
+ /// @return the index of the given curve in the given container. -1 if not contained
+ OOO_DLLPUBLIC_CHARTTOOLS sal_Int32 getRegressionCurveIndex(
+ const rtl::Reference<::chart::DataSeries>& xContainer,
+ const rtl::Reference<::chart::RegressionCurveModel>& xCurve );
+
+ OOO_DLLPUBLIC_CHARTTOOLS bool hasEquation(const css::uno::Reference<css::chart2::XRegressionCurve>& xCurve );
+ OOO_DLLPUBLIC_CHARTTOOLS bool MayHaveCorrelationCoefficient(const css::uno::Reference<css::chart2::XRegressionCurve>& xCurve );
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/RegressionCurveModel.hxx b/chart2/source/inc/RegressionCurveModel.hxx
new file mode 100644
index 0000000000..ddd75a8391
--- /dev/null
+++ b/chart2/source/inc/RegressionCurveModel.hxx
@@ -0,0 +1,242 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "OPropertySet.hxx"
+
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <sal/types.h>
+
+#include <com/sun/star/chart2/XRegressionCurve.hpp>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include "ModifyListenerHelper.hxx"
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::lang::XServiceInfo,
+ css::lang::XServiceName,
+ css::chart2::XRegressionCurve,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ RegressionCurveModel_Base;
+}
+
+class SAL_DLLPUBLIC_RTTI RegressionCurveModel :
+ public impl::RegressionCurveModel_Base,
+ public ::property::OPropertySet
+{
+public:
+ enum tCurveType
+ {
+ CURVE_TYPE_MEAN_VALUE,
+ CURVE_TYPE_LINEAR,
+ CURVE_TYPE_LOGARITHM,
+ CURVE_TYPE_EXPONENTIAL,
+ CURVE_TYPE_POWER,
+ CURVE_TYPE_POLYNOMIAL,
+ CURVE_TYPE_MOVING_AVERAGE
+ };
+
+ RegressionCurveModel( tCurveType eCurveType );
+ RegressionCurveModel( const RegressionCurveModel & rOther );
+ virtual ~RegressionCurveModel() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+protected:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+public:
+ // ____ XRegressionCurve ____
+ virtual css::uno::Reference< css::chart2::XRegressionCurveCalculator > SAL_CALL getCalculator() override;
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getEquationProperties() override;
+ virtual void SAL_CALL setEquationProperties(
+ const css::uno::Reference< css::beans::XPropertySet >& xEquationProperties ) override;
+
+ // ____ XServiceName ____
+ virtual OUString SAL_CALL getServiceName() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+protected:
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ using ::cppu::OPropertySetHelper::disposing;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+
+ void fireModifyEvent();
+
+private:
+ const tCurveType m_eRegressionCurveType;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+ css::uno::Reference< css::beans::XPropertySet > m_xEquationProperties;
+ void setPropertyMayHaveR2();
+};
+
+// implementations for factory instantiation
+
+class MeanValueRegressionCurve : public RegressionCurveModel
+{
+public:
+ explicit MeanValueRegressionCurve();
+ explicit MeanValueRegressionCurve(
+ const MeanValueRegressionCurve & rOther );
+ virtual ~MeanValueRegressionCurve() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+class LinearRegressionCurve : public RegressionCurveModel
+{
+public:
+ explicit LinearRegressionCurve();
+ explicit LinearRegressionCurve( const LinearRegressionCurve & rOther );
+ virtual ~LinearRegressionCurve() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+class LogarithmicRegressionCurve : public RegressionCurveModel
+{
+public:
+ explicit LogarithmicRegressionCurve();
+ explicit LogarithmicRegressionCurve( const LogarithmicRegressionCurve & rOther );
+ virtual ~LogarithmicRegressionCurve() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+class ExponentialRegressionCurve : public RegressionCurveModel
+{
+public:
+ explicit ExponentialRegressionCurve();
+ explicit ExponentialRegressionCurve( const ExponentialRegressionCurve & rOther );
+ virtual ~ExponentialRegressionCurve() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+class PotentialRegressionCurve : public RegressionCurveModel
+{
+public:
+ explicit PotentialRegressionCurve();
+ explicit PotentialRegressionCurve( const PotentialRegressionCurve & rOther );
+ virtual ~PotentialRegressionCurve() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+class PolynomialRegressionCurve : public RegressionCurveModel
+{
+public:
+ explicit PolynomialRegressionCurve();
+ explicit PolynomialRegressionCurve( const PolynomialRegressionCurve & rOther );
+ virtual ~PolynomialRegressionCurve() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+class MovingAverageRegressionCurve : public RegressionCurveModel
+{
+public:
+ explicit MovingAverageRegressionCurve();
+ explicit MovingAverageRegressionCurve( const MovingAverageRegressionCurve & rOther );
+ virtual ~MovingAverageRegressionCurve() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/RelativePositionHelper.hxx b/chart2/source/inc/RelativePositionHelper.hxx
new file mode 100644
index 0000000000..5a6bcbbc85
--- /dev/null
+++ b/chart2/source/inc/RelativePositionHelper.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/drawing/Alignment.hpp>
+#include <com/sun/star/awt/Point.hpp>
+#include "charttoolsdllapi.hxx"
+
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::chart2 { struct RelativeSize; }
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS RelativePositionHelper
+{
+public:
+ /** returns the upper left corner of an object that has size aObjectSize and
+ where the point indicated by aAnchor has coordinates indicated by aPoint
+ ( e.g. if aAnchor equals BOTTOM_LEFT, aPoint describes the
+ coordinates of the bottom left corner of an object with size aObjectSize )
+ */
+ static css::awt::Point
+ getUpperLeftCornerOfAnchoredObject(
+ css::awt::Point aPoint,
+ css::awt::Size aObjectSize,
+ css::drawing::Alignment aAnchor );
+
+ /** returns the center of an object that has size aObjectSize and
+ where the point indicated by aAnchor has coordinates indicated by aPoint
+ ( e.g. if aAnchor equals BOTTOM_LEFT, aPoint describes the
+ coordinates of the bottom left corner of an object with size aObjectSize )
+ */
+ static css::awt::Point
+ getCenterOfAnchoredObject(
+ css::awt::Point aPoint,
+ css::awt::Size aUnrotatedObjectSize,
+ css::drawing::Alignment aAnchor,
+ double fAnglePi );
+
+ /** Returns a relative position that is the same point after the anchor has
+ been changed to the given one. The passed object size is taken into
+ account for shifting the position.
+ */
+ SAL_DLLPRIVATE static css::chart2::RelativePosition
+ getReanchoredPosition(
+ const css::chart2::RelativePosition & rPosition,
+ const css::chart2::RelativeSize & rObjectSize,
+ css::drawing::Alignment aNewAnchor );
+
+ /** grows a relative size about the given amount and shifts the given
+ position such that the resize is relative to the former rectangle's
+ center.
+
+ The resize is only done, if after
+ transformation, the position and size are within the bounds [0,1].
+
+ @return </sal_True>, if changes were applied.
+
+ <p>That means, if the position's alignment is center, the position will
+ not change at all.</p>
+ */
+ static bool centerGrow(
+ css::chart2::RelativePosition & rInOutPosition,
+ css::chart2::RelativeSize & rInOutSize,
+ double fAmountX, double fAmountY );
+
+ /** shifts a relative position about the given amount
+
+ The shift is only done, if after
+ transformation, the object represented by the position
+ rInOutPosition and its size rObjectSize the position and size are
+ within the bounds [0,1].
+
+ @return </sal_True>, if changes were applied.
+ */
+ static bool moveObject(
+ css::chart2::RelativePosition & rInOutPosition,
+ const css::chart2::RelativeSize & rObjectSize,
+ double fAmountX, double fAmountY );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/RelativeSizeHelper.hxx b/chart2/source/inc/RelativeSizeHelper.hxx
new file mode 100644
index 0000000000..b07876bb67
--- /dev/null
+++ b/chart2/source/inc/RelativeSizeHelper.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "charttoolsdllapi.hxx"
+
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::uno { template <class interface_type> class Reference; }
+class SvxShapeText;
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS RelativeSizeHelper
+{
+public:
+ static double calculate(
+ double fValue,
+ const css::awt::Size & rOldReferenceSize,
+ const css::awt::Size & rNewReferenceSize );
+
+ static void adaptFontSizes(
+ const css::uno::Reference<
+ css::beans::XPropertySet > & xTargetProperties,
+ const css::awt::Size & rOldReferenceSize,
+ const css::awt::Size & rNewReferenceSize );
+
+ static void adaptFontSizes(
+ SvxShapeText& xTargetProperties,
+ const css::awt::Size & rOldReferenceSize,
+ const css::awt::Size & rNewReferenceSize );
+
+private:
+ RelativeSizeHelper() = delete;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ResId.hxx b/chart2/source/inc/ResId.hxx
new file mode 100644
index 0000000000..48baf852ab
--- /dev/null
+++ b/chart2/source/inc/ResId.hxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include "charttoolsdllapi.hxx"
+#include <unotools/resmgr.hxx>
+
+namespace chart
+{
+OUString OOO_DLLPUBLIC_CHARTTOOLS SchResId(TranslateId aId);
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/Scaling.hxx b/chart2/source/inc/Scaling.hxx
new file mode 100644
index 0000000000..6f6310933d
--- /dev/null
+++ b/chart2/source/inc/Scaling.hxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/chart2/XScaling.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <cppuhelper/implbase.hxx>
+
+namespace chart
+{
+
+class LogarithmicScaling final :
+ public ::cppu::WeakImplHelper<
+ css::chart2::XScaling,
+ css::lang::XServiceName,
+ css::lang::XServiceInfo
+ >
+{
+public:
+ /// base is 10.0
+ explicit LogarithmicScaling();
+ LogarithmicScaling( double fBase );
+ virtual ~LogarithmicScaling() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XScaling ____
+ virtual double SAL_CALL doScaling( double value ) override;
+
+ virtual css::uno::Reference<
+ css::chart2::XScaling > SAL_CALL
+ getInverseScaling() override;
+
+ // ____ XServiceName ____
+ virtual OUString SAL_CALL getServiceName() override;
+
+private:
+ const double m_fBase;
+ const double m_fLogOfBase;
+};
+
+class ExponentialScaling final :
+ public ::cppu::WeakImplHelper<
+ css::chart2::XScaling,
+ css::lang::XServiceName,
+ css::lang::XServiceInfo
+ >
+{
+public:
+ /// base is 10.0
+ explicit ExponentialScaling();
+ explicit ExponentialScaling( double fBase );
+ virtual ~ExponentialScaling() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XScaling ____
+ virtual double SAL_CALL
+ doScaling( double value ) override;
+
+ virtual css::uno::Reference< css::chart2::XScaling > SAL_CALL
+ getInverseScaling() override;
+
+ // ____ XServiceName ____
+ virtual OUString SAL_CALL getServiceName() override;
+
+private:
+ const double m_fBase;
+};
+
+class LinearScaling final : public ::cppu::WeakImplHelper<
+ css::chart2::XScaling,
+ css::lang::XServiceName,
+ css::lang::XServiceInfo
+ >
+{
+public:
+ /// y(x) = x
+ explicit LinearScaling();
+ /// y(x) = fSlope * x + fOffset
+ LinearScaling( double fSlope, double fOffset );
+ virtual ~LinearScaling() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XScaling ____
+ virtual double SAL_CALL doScaling( double value ) override;
+
+ virtual css::uno::Reference< css::chart2::XScaling > SAL_CALL
+ getInverseScaling() override;
+
+ // ____ XServiceName ____
+ virtual OUString SAL_CALL getServiceName() override;
+
+private:
+ const double m_fSlope;
+ const double m_fOffset;
+};
+
+class PowerScaling final : public ::cppu::WeakImplHelper<
+ css::chart2::XScaling,
+ css::lang::XServiceName,
+ css::lang::XServiceInfo
+ >
+{
+public:
+ /// exponent 10.0
+ explicit PowerScaling();
+ explicit PowerScaling( double fExponent );
+ virtual ~PowerScaling() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XScaling ____
+ virtual double SAL_CALL
+ doScaling( double value ) override;
+
+ virtual css::uno::Reference< css::chart2::XScaling > SAL_CALL
+ getInverseScaling() override;
+
+ // ____ XServiceName ____
+ virtual OUString SAL_CALL getServiceName() override;
+
+private:
+ const double m_fExponent;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/SceneProperties.hxx b/chart2/source/inc/SceneProperties.hxx
new file mode 100644
index 0000000000..ab7d89711a
--- /dev/null
+++ b/chart2/source/inc/SceneProperties.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "PropertyHelper.hxx"
+#include "FastPropertyIdRanges.hxx"
+#include "charttoolsdllapi.hxx"
+
+#include <vector>
+
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart
+{
+
+// implements service SceneProperties
+namespace SceneProperties
+{
+ // FastProperty Ids for properties
+ enum
+ {
+ // "com.sun.star.drawing.SceneProperties" (does not exist)
+ PROP_SCENE_TRANSF_MATRIX = FAST_PROPERTY_ID_START_SCENE_PROP,
+ PROP_SCENE_DISTANCE,
+ PROP_SCENE_FOCAL_LENGTH,
+ PROP_SCENE_SHADOW_SLANT,
+ PROP_SCENE_SHADE_MODE,
+ PROP_SCENE_AMBIENT_COLOR,
+ PROP_SCENE_TWO_SIDED_LIGHTING,
+ PROP_SCENE_CAMERA_GEOMETRY,
+ PROP_SCENE_PERSPECTIVE,
+ PROP_SCENE_LIGHT_COLOR_1,
+ PROP_SCENE_LIGHT_DIRECTION_1,
+ PROP_SCENE_LIGHT_ON_1,
+ PROP_SCENE_LIGHT_COLOR_2,
+ PROP_SCENE_LIGHT_DIRECTION_2,
+ PROP_SCENE_LIGHT_ON_2,
+ PROP_SCENE_LIGHT_COLOR_3,
+ PROP_SCENE_LIGHT_DIRECTION_3,
+ PROP_SCENE_LIGHT_ON_3,
+ PROP_SCENE_LIGHT_COLOR_4,
+ PROP_SCENE_LIGHT_DIRECTION_4,
+ PROP_SCENE_LIGHT_ON_4,
+ PROP_SCENE_LIGHT_COLOR_5,
+ PROP_SCENE_LIGHT_DIRECTION_5,
+ PROP_SCENE_LIGHT_ON_5,
+ PROP_SCENE_LIGHT_COLOR_6,
+ PROP_SCENE_LIGHT_DIRECTION_6,
+ PROP_SCENE_LIGHT_ON_6,
+ PROP_SCENE_LIGHT_COLOR_7,
+ PROP_SCENE_LIGHT_DIRECTION_7,
+ PROP_SCENE_LIGHT_ON_7,
+ PROP_SCENE_LIGHT_COLOR_8,
+ PROP_SCENE_LIGHT_DIRECTION_8,
+ PROP_SCENE_LIGHT_ON_8
+ };
+
+ OOO_DLLPUBLIC_CHARTTOOLS void AddPropertiesToVector(
+ std::vector< css::beans::Property > & rOutProperties );
+
+ OOO_DLLPUBLIC_CHARTTOOLS void AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/StackMode.hxx b/chart2/source/inc/StackMode.hxx
new file mode 100644
index 0000000000..718befc4e5
--- /dev/null
+++ b/chart2/source/inc/StackMode.hxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+namespace chart
+{
+// needed for chart type templates
+
+enum class StackMode
+{
+ NONE,
+ YStacked,
+ YStackedPercent,
+ ZStacked
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/StatisticsHelper.hxx b/chart2/source/inc/StatisticsHelper.hxx
new file mode 100644
index 0000000000..e700802002
--- /dev/null
+++ b/chart2/source/inc/StatisticsHelper.hxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+#include "charttoolsdllapi.hxx"
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2::data { class XDataProvider; }
+namespace com::sun::star::chart2::data { class XDataSequence; }
+namespace com::sun::star::chart2::data { class XDataSource; }
+namespace com::sun::star::chart2::data { class XLabeledDataSequence; }
+namespace com::sun::star::uno { template <typename > class Sequence; }
+namespace chart { class LabeledDataSequence; }
+namespace chart { class DataSeries; }
+
+namespace chart::StatisticsHelper
+{
+ /** Calculates 1/n * sum (x_i - x_mean)^2.
+
+ @see http://mathworld.wolfram.com/Variance.html
+ */
+ OOO_DLLPUBLIC_CHARTTOOLS double getVariance( const css::uno::Sequence< double > & rData );
+
+ // square root of the variance
+ OOO_DLLPUBLIC_CHARTTOOLS double getStandardDeviation( const css::uno::Sequence< double > & rData );
+
+ // also called "Standard deviation of the mean (SDOM)"
+ OOO_DLLPUBLIC_CHARTTOOLS double getStandardError( const css::uno::Sequence< double > & rData );
+
+ OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference< css::chart2::data::XLabeledDataSequence >
+ getErrorLabeledDataSequenceFromDataSource(
+ const css::uno::Reference< css::chart2::data::XDataSource > & xDataSource,
+ bool bPositiveValue,
+ bool bYError = true );
+
+ OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference< css::chart2::data::XDataSequence >
+ getErrorDataSequenceFromDataSource(
+ const css::uno::Reference< css::chart2::data::XDataSource > & xDataSource,
+ bool bPositiveValue,
+ bool bYError = true );
+
+ OOO_DLLPUBLIC_CHARTTOOLS double getErrorFromDataSource(
+ const css::uno::Reference< css::chart2::data::XDataSource > & xDataSource,
+ sal_Int32 nIndex,
+ bool bPositiveValue,
+ bool bYError = true );
+
+ OOO_DLLPUBLIC_CHARTTOOLS void setErrorDataSequence(
+ const css::uno::Reference< css::chart2::data::XDataSource > & xDataSource,
+ const css::uno::Reference< css::chart2::data::XDataProvider > & xDataProvider,
+ const OUString & rNewRange,
+ bool bPositiveValue,
+ bool bYError = true,
+ OUString const * pXMLRange = nullptr );
+
+ /// @return the newly created or existing error bar object
+ OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference< css::beans::XPropertySet >
+ addErrorBars(
+ const rtl::Reference< ::chart::DataSeries > & xDataSeries,
+ sal_Int32 nStyle,
+ bool bYError = true );
+
+ OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference< css::beans::XPropertySet >
+ getErrorBars(
+ const rtl::Reference< ::chart::DataSeries > & xDataSeries,
+ bool bYError = true );
+
+ OOO_DLLPUBLIC_CHARTTOOLS bool hasErrorBars(
+ const rtl::Reference< ::chart::DataSeries > & xDataSeries,
+ bool bYError = true );
+
+ OOO_DLLPUBLIC_CHARTTOOLS void removeErrorBars(
+ const rtl::Reference< ::chart::DataSeries > & xDataSeries,
+ bool bYError = true );
+
+ OOO_DLLPUBLIC_CHARTTOOLS bool usesErrorBarRanges(
+ const rtl::Reference< ::chart::DataSeries > & xDataSeries,
+ bool bYError = true );
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/ThreeDHelper.hxx b/chart2/source/inc/ThreeDHelper.hxx
new file mode 100644
index 0000000000..a8fc1d63fb
--- /dev/null
+++ b/chart2/source/inc/ThreeDHelper.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/drawing/CameraGeometry.hpp>
+#include <rtl/ref.hxx>
+#include "charttoolsdllapi.hxx"
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XDiagram; }
+
+namespace chart
+{
+class Diagram;
+
+enum class ThreeDLookScheme
+{
+ ThreeDLookScheme_Simple,
+ ThreeDLookScheme_Realistic,
+ ThreeDLookScheme_Unknown
+};
+
+enum CuboidPlanePosition
+{
+ CuboidPlanePosition_Left,
+ CuboidPlanePosition_Right,
+ CuboidPlanePosition_Top,
+ CuboidPlanePosition_Bottom,
+ CuboidPlanePosition_Front,
+ CuboidPlanePosition_Back
+};
+
+class OOO_DLLPUBLIC_CHARTTOOLS ThreeDHelper
+{
+public:
+
+ /** Returns the default camera geometry that is set in the Diagram CTOR.
+ This is not the property default!
+
+ @todo deprecate the hard set camera geometry and use the property
+ default
+ */
+ static css::drawing::CameraGeometry getDefaultCameraGeometry( bool bPie=false );
+
+ static void adaptRadAnglesForRightAngledAxes( double& rfXAngleRad, double& rfYAngleRad );
+ static double getXDegreeAngleLimitForRightAngledAxes() { return 90.0; }
+ static double getYDegreeAngleLimitForRightAngledAxes() { return 45.0; }
+
+ static double getValueClippedToRange( double fValue, const double& fPositivLimit );
+
+ static void convertElevationRotationDegToXYZAngleRad(
+ sal_Int32 nElevationDeg, sal_Int32 nRotationDeg
+ , double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad );
+
+ SAL_DLLPRIVATE static void convertXYZAngleRadToElevationRotationDeg(
+ sal_Int32& rnElevationDeg, sal_Int32& rnRotationDeg
+ , double fXRad, double fYRad, double fZRad );
+
+ SAL_DLLPRIVATE static void ensureCameraDistanceRange( double& rfCameraDistance );
+ SAL_DLLPRIVATE static void getCameraDistanceRange( double& rfMinimumDistance, double& rfMaximumDistance );
+
+ static double CameraDistanceToPerspective( double fCameraDistance );
+ static double PerspectiveToCameraDistance( double fPerspective );
+
+ static CuboidPlanePosition getAutomaticCuboidPlanePositionForStandardLeftWall( const rtl::Reference<
+ ::chart::Diagram >& xDiagram );
+ static CuboidPlanePosition getAutomaticCuboidPlanePositionForStandardBackWall(const rtl::Reference<
+ ::chart::Diagram >& xDiagram );
+ static CuboidPlanePosition getAutomaticCuboidPlanePositionForStandardBottom(const rtl::Reference<
+ ::chart::Diagram >& xDiagram );
+
+ //sal_Int32 nRoundedEdges: <0 or >100 -> mixed state
+ //sal_Int32 nObjectLines: 0->no lines; 1->all lines on; other->mixed state
+
+ static void getRoundedEdgesAndObjectLines( const rtl::Reference< ::chart::Diagram >& xDiagram
+ , sal_Int32& rnRoundedEdges, sal_Int32& rnObjectLines );
+ static void setRoundedEdgesAndObjectLines( const rtl::Reference< ::chart::Diagram >& xDiagram
+ , sal_Int32 nRoundedEdges, sal_Int32 nObjectLines );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/Title.hxx b/chart2/source/inc/Title.hxx
new file mode 100644
index 0000000000..2f21b60402
--- /dev/null
+++ b/chart2/source/inc/Title.hxx
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "OPropertySet.hxx"
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <com/sun/star/chart2/XTitle.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include "ModifyListenerHelper.hxx"
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::chart2::XTitle,
+ css::lang::XServiceInfo,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ Title_Base;
+}
+
+class OOO_DLLPUBLIC_CHARTTOOLS Title final :
+ public impl::Title_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit Title();
+ virtual ~Title() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+ explicit Title( const Title & rOther );
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XTitle ____
+ virtual css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > > SAL_CALL getText() override;
+ virtual void SAL_CALL setText( const css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& Strings ) override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+private:
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ void fireModifyEvent();
+
+ css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > > m_aStrings;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/TitleHelper.hxx b/chart2/source/inc/TitleHelper.hxx
new file mode 100644
index 0000000000..ac9f961879
--- /dev/null
+++ b/chart2/source/inc/TitleHelper.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include "charttoolsdllapi.hxx"
+#include "Title.hxx"
+
+namespace chart { class ChartModel; }
+namespace chart { class ReferenceSizeProvider; }
+namespace com::sun::star::chart2 { class XTitle; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS TitleHelper
+{
+public:
+ enum eTitleType
+ {
+ TITLE_BEGIN = 0,
+ MAIN_TITLE = 0,
+ SUB_TITLE,
+ X_AXIS_TITLE,
+ Y_AXIS_TITLE,
+ Z_AXIS_TITLE,
+ SECONDARY_X_AXIS_TITLE,
+ SECONDARY_Y_AXIS_TITLE,
+ NORMAL_TITLE_END,
+
+ //it is intended that this both types are after NORMAL_TITLE_END
+ TITLE_AT_STANDARD_X_AXIS_POSITION, //equals the Y_AXIS_TITLE for barchart
+ TITLE_AT_STANDARD_Y_AXIS_POSITION //equals the X_AXIS_TITLE for barchart
+ };
+
+ static rtl::Reference< ::chart::Title >
+ getTitle( eTitleType nTitleIndex
+ , ChartModel& rModel );
+
+ static rtl::Reference< ::chart::Title >
+ getTitle( eTitleType nTitleIndex
+ , const rtl::Reference< ::chart::ChartModel >& xModel );
+
+ static rtl::Reference< ::chart::Title >
+ createTitle( eTitleType nTitleIndex
+ , const OUString& rTitleText
+ , const rtl::Reference< ::chart::ChartModel >& xModel
+ , const css::uno::Reference< css::uno::XComponentContext > & xContext
+ , ReferenceSizeProvider * pRefSizeProvider = nullptr );
+ static rtl::Reference< ::chart::Title >
+ createOrShowTitle( eTitleType nTitleIndex
+ , const OUString& rTitleText
+ , const rtl::Reference< ::chart::ChartModel >& xModel
+ , const css::uno::Reference< css::uno::XComponentContext > & xContex );
+
+ static void removeTitle( eTitleType nTitleIndex
+ , const rtl::Reference< ::chart::ChartModel >& xModel );
+
+ static OUString getCompleteString( const rtl::Reference< ::chart::Title >& xTitle );
+ static void setCompleteString( const OUString& rNewText
+ , const rtl::Reference< ::chart::Title >& xTitle
+ , const css::uno::Reference< css::uno::XComponentContext > & xContext
+ , const float * pDefaultCharHeight = nullptr );
+
+ static bool getTitleType( eTitleType& rType
+ , const rtl::Reference< ::chart::Title >& xTitle
+ , const rtl::Reference< ::chart::ChartModel >& xModel );
+ static void hideTitle( eTitleType nTitleIndex,
+ const rtl::Reference< ::chart::ChartModel > & xModel);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/UncachedDataSequence.hxx b/chart2/source/inc/UncachedDataSequence.hxx
new file mode 100644
index 0000000000..ca32af236d
--- /dev/null
+++ b/chart2/source/inc/UncachedDataSequence.hxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+// helper classes
+#include <cppuhelper/compbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <rtl/ref.hxx>
+
+// interfaces and types
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/chart2/data/XDataSequence.hpp>
+#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+
+namespace com::sun::star::beans { class XPropertySetInfo; }
+namespace com::sun::star::chart2 { class XInternalDataProvider; }
+
+namespace chart
+{
+class InternalDataProvider;
+class ModifyEventForwarder;
+
+namespace impl
+{
+typedef ::cppu::WeakComponentImplHelper<
+ css::chart2::data::XDataSequence,
+ css::chart2::data::XNumericalDataSequence,
+ css::chart2::data::XTextualDataSequence,
+ css::util::XCloneable,
+ css::util::XModifiable, // contains util::XModifyBroadcaster
+ css::container::XIndexReplace,
+ css::container::XNamed, // for setting a new range representation
+ css::lang::XServiceInfo >
+ UncachedDataSequence_Base;
+}
+
+/**
+ * This sequence object does NOT store actual sequence data. Instead, it
+ * references a column inside the internal data table (represented by class
+ * InternalData) via range representation string. The range representation
+ * string ends with a numeric value that indicates the column index within
+ * the internal data table.
+ *
+ * <p>A range representation can be either '0', '1', '2', ..., or 'label 1',
+ * 'label 2', ...</p>
+ */
+class UncachedDataSequence final :
+ public ::comphelper::OMutexAndBroadcastHelper,
+ public ::comphelper::OPropertyContainer,
+ public ::comphelper::OPropertyArrayUsageHelper< UncachedDataSequence >,
+ public impl::UncachedDataSequence_Base
+{
+public:
+ /** The referring data provider is held as uno reference to ensure its
+ lifetime is at least as long as the one of this object.
+ */
+ UncachedDataSequence(
+ rtl::Reference< InternalDataProvider > xIntDataProv,
+ OUString aRangeRepresentation );
+ UncachedDataSequence(
+ rtl::Reference< InternalDataProvider > xIntDataProv,
+ OUString aRangeRepresentation,
+ const OUString & rRole );
+ UncachedDataSequence( const UncachedDataSequence & rSource );
+ virtual ~UncachedDataSequence() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+private:
+ // ____ XPropertySet ____
+ /// @see css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+ /// @see ::comphelper::OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ /// @see ::comphelper::OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+
+ // ____ XDataSequence ____
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getData() override;
+ virtual OUString SAL_CALL getSourceRangeRepresentation() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL generateLabel(
+ css::chart2::data::LabelOrigin nLabelOrigin ) override;
+ virtual ::sal_Int32 SAL_CALL getNumberFormatKeyByIndex( ::sal_Int32 nIndex ) override;
+
+ // ____ XNumericalDataSequence ____
+ /// @see css::chart::data::XNumericalDataSequence
+ virtual css::uno::Sequence< double > SAL_CALL getNumericalData() override;
+
+ // ____ XTextualDataSequence ____
+ /// @see css::chart::data::XTextualDataSequence
+ virtual css::uno::Sequence< OUString > SAL_CALL getTextualData() override;
+
+ // ____ XIndexReplace ____
+ virtual void SAL_CALL replaceByIndex( ::sal_Int32 Index, const css::uno::Any& Element ) override;
+
+ // ____ XIndexAccess (base of XIndexReplace) ____
+ virtual ::sal_Int32 SAL_CALL getCount() override;
+ virtual css::uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override;
+
+ // ____ XElementAccess (base of XIndexAccess) ____
+ virtual css::uno::Type SAL_CALL getElementType() override;
+ virtual sal_Bool SAL_CALL hasElements() override;
+
+ // ____ XNamed (for setting a new range representation) ____
+ virtual OUString SAL_CALL getName() override;
+ virtual void SAL_CALL setName( const OUString& aName ) override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifiable ____
+ virtual sal_Bool SAL_CALL isModified() override;
+ virtual void SAL_CALL setModified( sal_Bool bModified ) override;
+
+ // ____ XModifyBroadcaster (base of XModifiable) ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ void fireModifyEvent();
+
+ // <properties>
+ sal_Int32 m_nNumberFormatKey;
+ OUString m_sRole;
+ OUString m_aXMLRange;
+ // </properties>
+
+ /** This method registers all properties. It should be called by all
+ constructors.
+ */
+ void registerProperties();
+
+ rtl::Reference< InternalDataProvider > m_xDataProvider;
+ OUString m_aSourceRepresentation;
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/UserDefinedProperties.hxx b/chart2/source/inc/UserDefinedProperties.hxx
new file mode 100644
index 0000000000..07ab7b5bbc
--- /dev/null
+++ b/chart2/source/inc/UserDefinedProperties.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "FastPropertyIdRanges.hxx"
+#include "charttoolsdllapi.hxx"
+
+#include <vector>
+
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart
+{
+
+// implements service com.sun.star.xml.UserDefinedAttributesSupplier
+namespace UserDefinedProperties
+{
+ // FastProperty Ids for properties
+ enum
+ {
+ // UserDefined attributes in the chart-properties
+ PROP_XML_USERDEF_CHART = FAST_PROPERTY_ID_START_USERDEF_PROP,
+ PROP_XML_USERDEF_TEXT,
+ PROP_XML_USERDEF_PARA,
+ // com.sun.star.xml.UserDefinedAttributesSupplier
+ // UserDefined attributes in the other properties-sections. (as long as
+ // there is no reliable mechanism, properties may move between the
+ // sections)
+ PROP_XML_USERDEF
+ };
+
+ OOO_DLLPUBLIC_CHARTTOOLS void AddPropertiesToVector(
+ std::vector< css::beans::Property > & rOutProperties );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/WeakListenerAdapter.hxx b/chart2/source/inc/WeakListenerAdapter.hxx
new file mode 100644
index 0000000000..f300f1aa03
--- /dev/null
+++ b/chart2/source/inc/WeakListenerAdapter.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+#include <cppuhelper/weakref.hxx>
+#include <cppuhelper/implbase.hxx>
+
+namespace chart
+{
+
+/** Adapter that enables adding listeners as weak UNO references. Thus, adding
+ an object as listener to a broadcaster does not increase its reference
+ count.
+
+ <p>The helper class, of course, is held as hard reference at the
+ broadcaster, but this should never be a problem as the adapter's life time
+ depends on no other object.</p>
+
+ <p>Note that in order to remove an object as listener, you have to remove
+ the same wrapper that you added, i.e., you should store the adapter as a
+ member in the adapted class for later use.</p>
+ */
+template< class Listener >
+ class WeakListenerAdapter : public
+ ::cppu::WeakImplHelper< Listener >
+{
+public:
+ explicit WeakListenerAdapter( const css::uno::Reference< Listener > & xListener ) :
+ m_xListener( xListener )
+ {}
+
+protected:
+ // ____ XEventListener (base of all listeners) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override
+ {
+ css::uno::Reference< css::lang::XEventListener > xEventListener(
+ css::uno::Reference< Listener >( m_xListener), css::uno::UNO_QUERY );
+ if( xEventListener.is())
+ xEventListener->disposing( Source );
+ }
+
+ css::uno::Reference< Listener > getListener() const
+ {
+ return m_xListener;
+ }
+
+private:
+ css::uno::WeakReference< Listener > m_xListener;
+};
+
+class WeakSelectionChangeListenerAdapter final :
+ public WeakListenerAdapter< css::view::XSelectionChangeListener >
+{
+public:
+ explicit WeakSelectionChangeListenerAdapter(
+ const css::uno::Reference< css::view::XSelectionChangeListener > & xListener );
+ virtual ~WeakSelectionChangeListenerAdapter() override;
+
+protected:
+ // ____ XSelectionChangeListener ____
+ virtual void SAL_CALL selectionChanged(
+ const css::lang::EventObject& aEvent ) override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/WrappedDefaultProperty.hxx b/chart2/source/inc/WrappedDefaultProperty.hxx
new file mode 100644
index 0000000000..757eef248b
--- /dev/null
+++ b/chart2/source/inc/WrappedDefaultProperty.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "WrappedProperty.hxx"
+#include "charttoolsdllapi.hxx"
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS WrappedDefaultProperty : public WrappedProperty
+{
+public:
+ explicit WrappedDefaultProperty(
+ const OUString& rOuterName, const OUString& rInnerName,
+ css::uno::Any aNewOuterDefault );
+ virtual ~WrappedDefaultProperty() override;
+
+ virtual void setPropertyToDefault(
+ const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+ virtual css::uno::Any getPropertyDefault(
+ const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+ virtual css::beans::PropertyState getPropertyState(
+ const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+private:
+ css::uno::Any m_aOuterDefaultValue;
+};
+
+} // namespace chart
+
+// CHART2_WRAPPEDPROPERTYNEWDEFAULT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/WrappedDirectStateProperty.hxx b/chart2/source/inc/WrappedDirectStateProperty.hxx
new file mode 100644
index 0000000000..28398efd81
--- /dev/null
+++ b/chart2/source/inc/WrappedDirectStateProperty.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "WrappedProperty.hxx"
+#include "charttoolsdllapi.hxx"
+
+namespace chart
+{
+class OOO_DLLPUBLIC_CHARTTOOLS WrappedDirectStateProperty : public WrappedProperty
+{
+public:
+ explicit WrappedDirectStateProperty(const OUString& rOuterName, const OUString& rInnerName);
+ virtual ~WrappedDirectStateProperty() override;
+
+ virtual css::beans::PropertyState getPropertyState(
+ const css::uno::Reference<css::beans::XPropertyState>& xInnerPropertyState) const override;
+};
+
+} // namespace chart
+
+// CHART2_WRAPPEDPROPERTYNEWDEFAULT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/WrappedIgnoreProperty.hxx b/chart2/source/inc/WrappedIgnoreProperty.hxx
new file mode 100644
index 0000000000..a031097bda
--- /dev/null
+++ b/chart2/source/inc/WrappedIgnoreProperty.hxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "WrappedProperty.hxx"
+#include "charttoolsdllapi.hxx"
+
+#include <vector>
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS WrappedIgnoreProperty final : public WrappedProperty
+{
+public:
+ WrappedIgnoreProperty( const OUString& rOuterName, const css::uno::Any& rDefaultValue );
+ virtual ~WrappedIgnoreProperty() override;
+
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const override;
+
+SAL_DLLPRIVATE virtual void setPropertyToDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+SAL_DLLPRIVATE virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+SAL_DLLPRIVATE virtual css::beans::PropertyState getPropertyState( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const override;
+
+private:
+ css::uno::Any m_aDefaultValue;
+ mutable css::uno::Any m_aCurrentValue;
+};
+
+class OOO_DLLPUBLIC_CHARTTOOLS WrappedIgnoreProperties
+{
+public:
+ static void addIgnoreLineProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList );
+
+ static void addIgnoreFillProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList );
+ SAL_DLLPRIVATE static void addIgnoreFillProperties_without_BitmapProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList );
+ SAL_DLLPRIVATE static void addIgnoreFillProperties_only_BitmapProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/WrappedProperty.hxx b/chart2/source/inc/WrappedProperty.hxx
new file mode 100644
index 0000000000..1ec91f71f9
--- /dev/null
+++ b/chart2/source/inc/WrappedProperty.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <rtl/ustring.hxx>
+#include "charttoolsdllapi.hxx"
+
+#include <map>
+#include <memory>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::beans { class XPropertyState; }
+namespace com::sun::star::uno { template <class interface_type> class Reference; }
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS WrappedProperty
+{
+ /** The property visible to the outer PropertySet in the PropertySetWrapper may have a different name, type and value than
+ a corresponding property of the inner PropertySet. Use this class to do the conversion between the two.
+ */
+public:
+ WrappedProperty( OUString aOuterName, OUString aInnerName );
+ virtual ~WrappedProperty();
+
+ const OUString& getOuterName() const { return m_aOuterName;}
+ virtual OUString getInnerName() const;
+
+ /// @throws css::beans::UnknownPropertyException
+ /// @throws css::beans::PropertyVetoException
+ /// @throws css::lang::IllegalArgumentException
+ /// @throws css::lang::WrappedTargetException
+ /// @throws css::uno::RuntimeException
+ virtual void setPropertyValue( const css::uno::Any& rOuterValue, const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const;
+
+ /// @throws css::beans::UnknownPropertyException
+ /// @throws css::lang::WrappedTargetException
+ /// @throws css::uno::RuntimeException
+ virtual css::uno::Any getPropertyValue( const css::uno::Reference< css::beans::XPropertySet >& xInnerPropertySet ) const;
+
+ /// @throws css::beans::UnknownPropertyException
+ /// @throws css::uno::RuntimeException
+ virtual void setPropertyToDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const;
+
+ /// @throws css::beans::UnknownPropertyException
+ /// @throws css::lang::WrappedTargetException
+ /// @throws css::uno::RuntimeException
+ virtual css::uno::Any getPropertyDefault( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const;
+
+ /// @throws css::beans::UnknownPropertyException
+ /// @throws css::uno::RuntimeException
+ virtual css::beans::PropertyState getPropertyState( const css::uno::Reference< css::beans::XPropertyState >& xInnerPropertyState ) const;
+
+protected:
+ virtual css::uno::Any convertInnerToOuterValue( const css::uno::Any& rInnerValue ) const;
+ virtual css::uno::Any convertOuterToInnerValue( const css::uno::Any& rOuterValue ) const;
+
+protected:
+ OUString m_aOuterName;
+ OUString m_aInnerName;
+};
+
+typedef std::map< sal_Int32, std::unique_ptr<const WrappedProperty> > tWrappedPropertyMap;
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/WrappedPropertySet.hxx b/chart2/source/inc/WrappedPropertySet.hxx
new file mode 100644
index 0000000000..ec3d43632c
--- /dev/null
+++ b/chart2/source/inc/WrappedPropertySet.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "WrappedProperty.hxx"
+#include "charttoolsdllapi.hxx"
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertyStates.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <memory>
+#include <mutex>
+#include <vector>
+
+namespace cppu { class IPropertyArrayHelper; }
+namespace cppu { class OPropertyArrayHelper; }
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTTOOLS WrappedPropertySet :
+ public ::cppu::WeakImplHelper
+ < css::beans::XPropertySet
+ , css::beans::XMultiPropertySet
+ , css::beans::XPropertyState
+ , css::beans::XMultiPropertyStates
+ >
+{
+public:
+ WrappedPropertySet();
+ virtual ~WrappedPropertySet() override;
+
+ void clearWrappedPropertySet();
+
+public:
+ //XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override;
+ virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override;
+
+ //XMultiPropertySet
+ //getPropertySetInfo() already declared in XPropertySet
+ virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ virtual void SAL_CALL addPropertiesChangeListener( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener ) override;
+ virtual void SAL_CALL removePropertiesChangeListener( const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener ) override;
+ virtual void SAL_CALL firePropertiesChangeEvent( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener ) override;
+
+ //XPropertyState
+ virtual css::beans::PropertyState SAL_CALL getPropertyState( const OUString& PropertyName ) override;
+ virtual css::uno::Sequence< css::beans::PropertyState > SAL_CALL getPropertyStates( const css::uno::Sequence< OUString >& aPropertyName ) override;
+ virtual void SAL_CALL setPropertyToDefault( const OUString& PropertyName ) override;
+ virtual css::uno::Any SAL_CALL getPropertyDefault( const OUString& aPropertyName ) override;
+
+ //XMultiPropertyStates
+ //getPropertyStates() already declared in XPropertyState
+ virtual void SAL_CALL setAllPropertiesToDefault( ) override;
+ virtual void SAL_CALL setPropertiesToDefault( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPropertyDefaults( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+
+protected: //methods
+ /** give all the properties that should be visible to the outer side
+ */
+ virtual const css::uno::Sequence< css::beans::Property >& getPropertySequence()=0;
+ /** give a list of all properties that need a special treatment;
+ properties that are not in this list will be wrapped identical.
+ The base class 'WrappedPropertySet' will take ownership on the contained pointer.
+ It is not allowed to have duplicate entries in this list.
+ */
+ virtual std::vector< std::unique_ptr<WrappedProperty> > createWrappedProperties()=0;
+
+ virtual css::uno::Reference< css::beans::XPropertySet > getInnerPropertySet() = 0;
+ SAL_DLLPRIVATE css::uno::Reference< css::beans::XPropertyState > getInnerPropertyState();
+
+ ::cppu::IPropertyArrayHelper& getInfoHelper();
+ SAL_DLLPRIVATE tWrappedPropertyMap& getWrappedPropertyMap();
+
+ const WrappedProperty* getWrappedProperty( const OUString& rOuterName );
+ const WrappedProperty* getWrappedProperty( sal_Int32 nHandle );
+
+ std::mutex m_aMutex;
+
+private:
+ css::uno::Reference< css::beans::XPropertySetInfo > m_xInfo;//outer PropertySetInfo
+
+ std::unique_ptr<::cppu::OPropertyArrayHelper> m_pPropertyArrayHelper;//holds all possible outer properties
+
+ std::unique_ptr<tWrappedPropertyMap> m_pWrappedPropertyMap;//holds all wrapped properties (containing the special mapping from inner to outer properties)
+
+ //Container for the XPropertyChangedListener. The listeners are inserted by handle.
+ //OMultiTypeInterfaceContainerHelperInt32 m_aBoundListenerContainer;
+
+ //Container for the XPropertyVetoableListener. The listeners are inserted by handle.
+ //OMultiTypeInterfaceContainerHelperInt32 m_aVetoableListenerContainer;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/XMLRangeHelper.hxx b/chart2/source/inc/XMLRangeHelper.hxx
new file mode 100644
index 0000000000..519c9b7722
--- /dev/null
+++ b/chart2/source/inc/XMLRangeHelper.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include "charttoolsdllapi.hxx"
+
+namespace chart::XMLRangeHelper
+{
+
+struct OOO_DLLPUBLIC_CHARTTOOLS Cell
+{
+ sal_Int32 nColumn;
+ sal_Int32 nRow;
+ bool bRelativeColumn;
+ bool bRelativeRow;
+ bool bIsEmpty;
+
+ Cell() :
+ nColumn(0),
+ nRow(0),
+ bRelativeColumn(false),
+ bRelativeRow(false),
+ bIsEmpty(true)
+ {}
+
+ bool empty() const { return bIsEmpty; }
+};
+
+struct OOO_DLLPUBLIC_CHARTTOOLS CellRange
+{
+ Cell aUpperLeft;
+ Cell aLowerRight;
+ OUString aTableName;
+};
+
+CellRange getCellRangeFromXMLString( const OUString & rXMLString );
+
+OUString getXMLStringFromCellRange( const CellRange & rRange );
+
+} // namespace chart::XMLRangeHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/charttoolsdllapi.hxx b/chart2/source/inc/charttoolsdllapi.hxx
new file mode 100644
index 0000000000..96336e1012
--- /dev/null
+++ b/chart2/source/inc/charttoolsdllapi.hxx
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <sal/types.h>
+
+#if defined OOO_DLLIMPLEMENTATION_CHARTTOOLS
+#define OOO_DLLPUBLIC_CHARTTOOLS SAL_DLLPUBLIC_EXPORT
+#else
+#define OOO_DLLPUBLIC_CHARTTOOLS SAL_DLLPUBLIC_IMPORT
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/chartview/ChartSfxItemIds.hxx b/chart2/source/inc/chartview/ChartSfxItemIds.hxx
new file mode 100644
index 0000000000..a5099cc0c3
--- /dev/null
+++ b/chart2/source/inc/chartview/ChartSfxItemIds.hxx
@@ -0,0 +1,236 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svl/typedwhich.hxx>
+
+class SvxSizeItem;
+class SfxIntegerListItem;
+class SfxBoolItem;
+class SfxStringItem;
+class SfxInt32Item;
+class SfxUInt32Item;
+class SvxChartIndicateItem;
+class SvxDoubleItem;
+class SvxBrushItem;
+class SvxChartKindErrorItem;
+class SvxChartTextOrderItem;
+class SvxChartRegressItem;
+class SdrAngleItem;
+
+// SCHATTR
+
+// can't this be changed to 0?
+constexpr sal_uInt16 SCHATTR_START = 1;
+
+constexpr sal_uInt16 SCHATTR_DATADESCR_START (SCHATTR_START);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATADESCR_SHOW_NUMBER (SCHATTR_DATADESCR_START);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATADESCR_SHOW_PERCENTAGE (SCHATTR_DATADESCR_START + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATADESCR_SHOW_CATEGORY (SCHATTR_DATADESCR_START + 2);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATADESCR_SHOW_SYMBOL (SCHATTR_DATADESCR_START + 3);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATADESCR_WRAP_TEXT (SCHATTR_DATADESCR_START + 4);
+constexpr TypedWhichId<SfxStringItem> SCHATTR_DATADESCR_SEPARATOR (SCHATTR_DATADESCR_START + 5);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_DATADESCR_PLACEMENT (SCHATTR_DATADESCR_START + 6);
+constexpr TypedWhichId<SfxIntegerListItem> SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS (SCHATTR_DATADESCR_START + 7);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATADESCR_NO_PERCENTVALUE (SCHATTR_DATADESCR_START + 8); //percentage values should not be offered
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATADESCR_CUSTOM_LEADER_LINES (SCHATTR_DATADESCR_START + 9);
+constexpr TypedWhichId<SfxUInt32Item> SCHATTR_PERCENT_NUMBERFORMAT_VALUE (SCHATTR_DATADESCR_START + 10);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_PERCENT_NUMBERFORMAT_SOURCE (SCHATTR_DATADESCR_START + 11);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME (SCHATTR_DATADESCR_START + 12);
+constexpr sal_uInt16 SCHATTR_DATADESCR_END (SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME);
+
+//legend
+constexpr sal_uInt16 SCHATTR_LEGEND_START (SCHATTR_DATADESCR_END + 1);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_LEGEND_POS (SCHATTR_LEGEND_START);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_LEGEND_SHOW (SCHATTR_LEGEND_START + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_LEGEND_NO_OVERLAY (SCHATTR_LEGEND_START + 2);
+constexpr sal_uInt16 SCHATTR_LEGEND_END (SCHATTR_LEGEND_NO_OVERLAY);
+
+//text
+constexpr sal_uInt16 SCHATTR_TEXT_START (SCHATTR_LEGEND_END + 1);
+constexpr TypedWhichId<SdrAngleItem> SCHATTR_TEXT_DEGREES (SCHATTR_TEXT_START);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_TEXT_STACKED (SCHATTR_TEXT_START + 1);
+constexpr sal_uInt16 SCHATTR_TEXT_END (SCHATTR_TEXT_STACKED);
+
+// statistic
+constexpr sal_uInt16 SCHATTR_STAT_START (SCHATTR_TEXT_END + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_STAT_AVERAGE (SCHATTR_STAT_START);
+constexpr TypedWhichId<SvxChartKindErrorItem> SCHATTR_STAT_KIND_ERROR (SCHATTR_STAT_START + 1);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_STAT_PERCENT (SCHATTR_STAT_START + 2);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_STAT_BIGERROR (SCHATTR_STAT_START + 3);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_STAT_CONSTPLUS (SCHATTR_STAT_START + 4);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_STAT_CONSTMINUS (SCHATTR_STAT_START + 5);
+constexpr TypedWhichId<SvxChartIndicateItem> SCHATTR_STAT_INDICATE (SCHATTR_STAT_START + 6);
+constexpr TypedWhichId<SfxStringItem> SCHATTR_STAT_RANGE_POS (SCHATTR_STAT_START + 7);
+constexpr TypedWhichId<SfxStringItem> SCHATTR_STAT_RANGE_NEG (SCHATTR_STAT_START + 8);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_STAT_ERRORBAR_TYPE (SCHATTR_STAT_START + 9);
+constexpr sal_uInt16 SCHATTR_STAT_END (SCHATTR_STAT_ERRORBAR_TYPE);
+
+// these attributes are for replacement of enum eChartStyle
+
+constexpr sal_uInt16 SCHATTR_STYLE_START (SCHATTR_STAT_END + 1);
+
+// for whole chart
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_STYLE_DEEP (SCHATTR_STYLE_START );
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_STYLE_3D (SCHATTR_STYLE_START + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_STYLE_VERTICAL (SCHATTR_STYLE_START + 2);
+
+// also for series
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_STYLE_BASETYPE (SCHATTR_STYLE_START + 3);// Line,Area,...,Pie
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_STYLE_LINES (SCHATTR_STYLE_START + 4);// draw line
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_STYLE_PERCENT (SCHATTR_STYLE_START + 5);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_STYLE_STACKED (SCHATTR_STYLE_START + 6);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_STYLE_SPLINES (SCHATTR_STYLE_START + 7);
+
+// also for data point
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_STYLE_SYMBOL (SCHATTR_STYLE_START + 8);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_STYLE_SHAPE (SCHATTR_STYLE_START + 9);
+constexpr sal_uInt16 SCHATTR_STYLE_END (SCHATTR_STYLE_SHAPE );
+
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS (SCHATTR_STYLE_END + 1); // see chtmodel.hxx defines CHART_AXIS_PRIMARY_X, etc.
+//Re-mapped:
+constexpr sal_uInt16 SCHATTR_AXIS_START (SCHATTR_AXIS + 1);
+//axis scale
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXISTYPE (SCHATTR_AXIS_START);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_REVERSE (SCHATTR_AXIS_START + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_AUTO_MIN (SCHATTR_AXIS_START + 2);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_AXIS_MIN (SCHATTR_AXIS_START + 3);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_AUTO_MAX (SCHATTR_AXIS_START + 4);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_AXIS_MAX (SCHATTR_AXIS_START + 5);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_AUTO_STEP_MAIN (SCHATTR_AXIS_START + 6);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_AXIS_STEP_MAIN (SCHATTR_AXIS_START + 7);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS_MAIN_TIME_UNIT (SCHATTR_AXIS_START + 8);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_AUTO_STEP_HELP (SCHATTR_AXIS_START + 9);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS_STEP_HELP (SCHATTR_AXIS_START + 10);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS_HELP_TIME_UNIT (SCHATTR_AXIS_START + 11);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_AUTO_TIME_RESOLUTION (SCHATTR_AXIS_START + 12);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS_TIME_RESOLUTION (SCHATTR_AXIS_START + 13);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_LOGARITHM (SCHATTR_AXIS_START + 14);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_AUTO_DATEAXIS (SCHATTR_AXIS_START + 15);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_ALLOW_DATEAXIS (SCHATTR_AXIS_START + 16);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_AUTO_ORIGIN (SCHATTR_AXIS_START + 17);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_AXIS_ORIGIN (SCHATTR_AXIS_START + 18);
+//axis position
+constexpr sal_uInt16 SCHATTR_AXIS_POSITION_START (SCHATTR_AXIS_ORIGIN + 1);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS_TICKS (SCHATTR_AXIS_POSITION_START);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS_HELPTICKS (SCHATTR_AXIS_POSITION_START + 1);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS_POSITION (SCHATTR_AXIS_POSITION_START + 2);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_AXIS_POSITION_VALUE (SCHATTR_AXIS_POSITION_START + 3);
+constexpr TypedWhichId<SfxUInt32Item> SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT (SCHATTR_AXIS_POSITION_START + 4);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION (SCHATTR_AXIS_POSITION_START + 5);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS_LABEL_POSITION (SCHATTR_AXIS_POSITION_START + 6);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS_MARK_POSITION (SCHATTR_AXIS_POSITION_START + 7);
+//axis label
+constexpr sal_uInt16 SCHATTR_AXIS_LABEL_START (SCHATTR_AXIS_MARK_POSITION + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_SHOWDESCR (SCHATTR_AXIS_LABEL_START);
+constexpr TypedWhichId<SvxChartTextOrderItem> SCHATTR_AXIS_LABEL_ORDER (SCHATTR_AXIS_LABEL_START + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_LABEL_OVERLAP (SCHATTR_AXIS_LABEL_START + 2);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_AXIS_LABEL_BREAK (SCHATTR_AXIS_LABEL_START + 3);
+constexpr sal_uInt16 SCHATTR_AXIS_LABEL_END (SCHATTR_AXIS_LABEL_BREAK);
+
+constexpr sal_uInt16 SCHATTR_AXIS_END (SCHATTR_AXIS_LABEL_END);
+
+constexpr TypedWhichId<SvxBrushItem> SCHATTR_SYMBOL_BRUSH (SCHATTR_AXIS_END + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_STOCK_VOLUME (SCHATTR_AXIS_END + 2);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_STOCK_UPDOWN (SCHATTR_AXIS_END + 3);
+constexpr TypedWhichId<SvxSizeItem> SCHATTR_SYMBOL_SIZE (SCHATTR_AXIS_END + 4);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY (SCHATTR_AXIS_END + 5);
+
+// non persistent items (binary format)
+constexpr sal_uInt16 SCHATTR_CHARTTYPE_START (SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY + 1);
+
+// new from New Chart
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_BAR_OVERLAP (SCHATTR_CHARTTYPE_START );
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_BAR_GAPWIDTH (SCHATTR_CHARTTYPE_START + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_BAR_CONNECT (SCHATTR_CHARTTYPE_START + 2);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_NUM_OF_LINES_FOR_BAR (SCHATTR_CHARTTYPE_START + 3);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_SPLINE_ORDER (SCHATTR_CHARTTYPE_START + 4);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_SPLINE_RESOLUTION (SCHATTR_CHARTTYPE_START + 5);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_GROUP_BARS_PER_AXIS (SCHATTR_CHARTTYPE_START + 6);
+constexpr TypedWhichId<SdrAngleItem> SCHATTR_STARTING_ANGLE (SCHATTR_CHARTTYPE_START + 7);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_CLOCKWISE (SCHATTR_CHARTTYPE_START + 8);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_MISSING_VALUE_TREATMENT (SCHATTR_CHARTTYPE_START + 9);
+constexpr TypedWhichId<SfxIntegerListItem> SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS (SCHATTR_CHARTTYPE_START + 10);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_INCLUDE_HIDDEN_CELLS (SCHATTR_CHARTTYPE_START + 11);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_HIDE_LEGEND_ENTRY (SCHATTR_CHARTTYPE_START + 12);
+
+constexpr sal_uInt16 SCHATTR_CHARTTYPE_END (SCHATTR_HIDE_LEGEND_ENTRY);
+
+// items for transporting information to dialogs
+constexpr sal_uInt16 SCHATTR_MISC_START (SCHATTR_CHARTTYPE_END + 1);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_AXIS_FOR_ALL_SERIES (SCHATTR_MISC_START);
+constexpr sal_uInt16 SCHATTR_MISC_END (SCHATTR_AXIS_FOR_ALL_SERIES);
+
+// regression curve
+constexpr sal_uInt16 SCHATTR_REGRESSION_START (SCHATTR_MISC_END + 1);
+constexpr TypedWhichId<SvxChartRegressItem> SCHATTR_REGRESSION_TYPE (SCHATTR_REGRESSION_START);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_REGRESSION_SHOW_EQUATION (SCHATTR_REGRESSION_START + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_REGRESSION_SHOW_COEFF (SCHATTR_REGRESSION_START + 2);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_REGRESSION_DEGREE (SCHATTR_REGRESSION_START + 3);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_REGRESSION_PERIOD (SCHATTR_REGRESSION_START + 4);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD (SCHATTR_REGRESSION_START + 5);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD (SCHATTR_REGRESSION_START + 6);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_REGRESSION_SET_INTERCEPT (SCHATTR_REGRESSION_START + 7);
+constexpr TypedWhichId<SvxDoubleItem> SCHATTR_REGRESSION_INTERCEPT_VALUE (SCHATTR_REGRESSION_START + 8);
+constexpr TypedWhichId<SfxStringItem> SCHATTR_REGRESSION_CURVE_NAME (SCHATTR_REGRESSION_START + 9);
+constexpr TypedWhichId<SfxStringItem> SCHATTR_REGRESSION_XNAME (SCHATTR_REGRESSION_START + 10);
+constexpr TypedWhichId<SfxStringItem> SCHATTR_REGRESSION_YNAME (SCHATTR_REGRESSION_START + 11);
+constexpr TypedWhichId<SfxInt32Item> SCHATTR_REGRESSION_MOVING_TYPE (SCHATTR_REGRESSION_START + 12);
+constexpr sal_uInt16 SCHATTR_REGRESSION_END (SCHATTR_REGRESSION_MOVING_TYPE);
+
+constexpr sal_uInt16 SCHATTR_DATA_TABLE_START (SCHATTR_REGRESSION_END + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATA_TABLE_HORIZONTAL_BORDER (SCHATTR_DATA_TABLE_START + 0);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATA_TABLE_VERTICAL_BORDER (SCHATTR_DATA_TABLE_START + 1);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATA_TABLE_OUTLINE (SCHATTR_DATA_TABLE_START + 2);
+constexpr TypedWhichId<SfxBoolItem> SCHATTR_DATA_TABLE_KEYS (SCHATTR_DATA_TABLE_START + 3);
+constexpr sal_uInt16 SCHATTR_DATA_TABLE_END (SCHATTR_DATA_TABLE_KEYS);
+
+constexpr sal_uInt16 SCHATTR_END (SCHATTR_DATA_TABLE_END);
+
+// values for Items
+
+// values for SCHATTR_AXIS_TICKS and SCHATTR_AXIS_HELPTICKS items
+#define CHAXIS_MARK_BOTH 3
+#define CHAXIS_MARK_OUTER 2
+#define CHAXIS_MARK_INNER 1
+#define CHAXIS_MARK_NONE 0
+
+// values for SCHATTR_AXISTYPE items
+#define CHART_AXIS_REALNUMBER 0
+#define CHART_AXIS_PERCENT 1
+#define CHART_AXIS_CATEGORY 2
+#define CHART_AXIS_SERIES 3
+#define CHART_AXIS_DATE 4
+
+// values for SCHATTR_STYLE_SHAPE items
+#define CHART_SHAPE3D_IGNORE -2 //internal! (GetChartShapeStyle()!)
+#define CHART_SHAPE3D_SQUARE 0
+#define CHART_SHAPE3D_CYLINDER 1
+#define CHART_SHAPE3D_CONE 2
+#define CHART_SHAPE3D_PYRAMID 3 //reserved
+#define CHART_SHAPE3D_HANOI 4
+
+// values for SCHATTR_AXIS items
+#define CHART_AXIS_PRIMARY_X 1
+#define CHART_AXIS_PRIMARY_Y 2
+#define CHART_AXIS_PRIMARY_Z 3
+#define CHART_AXIS_SECONDARY_Y 4
+#define CHART_AXIS_SECONDARY_X 5
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/chartview/DataPointSymbolSupplier.hxx b/chart2/source/inc/chartview/DataPointSymbolSupplier.hxx
new file mode 100644
index 0000000000..58d8a9ff2e
--- /dev/null
+++ b/chart2/source/inc/chartview/DataPointSymbolSupplier.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <chartview/chartviewdllapi.hxx>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::drawing { struct Direction3D; }
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTVIEW DataPointSymbolSupplier
+{
+public:
+ static rtl::Reference< SvxShapeGroup >
+ create2DSymbolList( const rtl::Reference<SvxDrawPage>& xTarget
+ , const css::drawing::Direction3D& rSize );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/chartview/DrawModelWrapper.hxx b/chart2/source/inc/chartview/DrawModelWrapper.hxx
new file mode 100644
index 0000000000..080587e7ec
--- /dev/null
+++ b/chart2/source/inc/chartview/DrawModelWrapper.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <svx/svdmodel.hxx>
+#include <svx/unopage.hxx>
+#include <svx/unoshape.hxx>
+#include <chartview/chartviewdllapi.hxx>
+
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace com::sun::star::frame { class XModel; }
+namespace com::sun::star::drawing { class XDrawPage; }
+namespace com::sun::star::drawing { class XShape; }
+namespace com::sun::star::drawing { class XShapes; }
+
+class SdrObjList;
+class SdrObject;
+
+namespace chart
+{
+
+class OOO_DLLPUBLIC_CHARTVIEW DrawModelWrapper final : private SdrModel
+{
+private:
+ rtl::Reference<SvxDrawPage> m_xMainDrawPage;
+ rtl::Reference<SvxDrawPage> m_xHiddenDrawPage;
+ rtl::Reference<SfxItemPool> m_xChartItemPool;
+ VclPtr<OutputDevice> m_pRefDevice;
+
+public:
+ SAL_DLLPRIVATE DrawModelWrapper();
+ SAL_DLLPRIVATE virtual ~DrawModelWrapper() override;
+
+ css::uno::Reference< css::lang::XMultiServiceFactory > getShapeFactory();
+
+ // the main page will contain the normal view objects
+ const rtl::Reference<SvxDrawPage> & getMainDrawPage();
+ SAL_DLLPRIVATE void clearMainDrawPage();
+
+ // the extra page is not visible, but contains some extras like the symbols for data points
+ const rtl::Reference<SvxDrawPage> & getHiddenDrawPage();
+
+ static rtl::Reference<SvxShapeGroupAnyD>
+ getChartRootShape( const rtl::Reference<SvxDrawPage>& xPage );
+
+ SAL_DLLPRIVATE void lockControllers();
+ SAL_DLLPRIVATE void unlockControllers();
+
+ OutputDevice* getReferenceDevice() const;
+
+ SfxItemPool& GetItemPool();
+
+ SAL_DLLPRIVATE virtual css::uno::Reference< css::frame::XModel >
+ createUnoModel() override;
+ SAL_DLLPRIVATE css::uno::Reference< css::frame::XModel >
+ getUnoModel();
+ SdrModel& getSdrModel();
+
+ XColorListRef GetColorList() const;
+ XDashListRef GetDashList() const;
+ XLineEndListRef GetLineEndList() const;
+ XGradientListRef GetGradientList() const;
+ XHatchListRef GetHatchList() const;
+ XBitmapListRef GetBitmapList() const;
+ XPatternListRef GetPatternList() const;
+
+ SdrObject* getNamedSdrObject( const OUString& rName );
+ static SdrObject* getNamedSdrObject( const OUString& rName, SdrObjList const * pObjList );
+
+ static bool removeShape( const rtl::Reference<SvxShape>& xShape );
+
+ void dumpAsXml(xmlTextWriterPtr pWriter) const override;
+};
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/chartview/ExplicitScaleValues.hxx b/chart2/source/inc/chartview/ExplicitScaleValues.hxx
new file mode 100644
index 0000000000..a49dddeb66
--- /dev/null
+++ b/chart2/source/inc/chartview/ExplicitScaleValues.hxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <chartview/chartviewdllapi.hxx>
+#include <com/sun/star/chart/TimeInterval.hpp>
+#include <com/sun/star/chart2/AxisOrientation.hpp>
+#include <com/sun/star/chart2/XScaling.hpp>
+#include <tools/date.hxx>
+#include <vector>
+
+namespace com::sun::star::chart2
+{
+class XScaling;
+}
+
+namespace chart
+{
+/** This structure contains the explicit values for a scale like Minimum and Maximum.
+ See also css::chart2::ScaleData.
+*/
+struct OOO_DLLPUBLIC_CHARTVIEW ExplicitScaleData
+{
+ ExplicitScaleData();
+
+ double Minimum;
+ double Maximum;
+ double Origin;
+
+ css::chart2::AxisOrientation Orientation;
+
+ css::uno::Reference<css::chart2::XScaling> Scaling;
+
+ sal_Int32 AxisType; //see css::chart2::AxisType
+ bool m_bShiftedCategoryPosition;
+ sal_Int32 TimeResolution; //constant of type <type>css::chart::TimeUnit</type>
+ Date NullDate;
+};
+
+struct ExplicitSubIncrement
+{
+ ExplicitSubIncrement();
+
+ /** Numbers of intervals between two superior ticks. For an axis
+ this usually means, that <code>IntervalCount - 1</code>
+ sub-tick-marks are displayed between two superior ticks.
+
+ */
+ sal_Int32 IntervalCount;
+
+ /** If <TRUE/>, the distance between two sub-tick-marks on the
+ screen is always the same. If <FALSE/>, the distances may
+ differ depending on the <type>XScaling</type>.
+ */
+ bool PostEquidistant;
+};
+
+/** describes how tickmarks are positioned on the scale of an axis.
+*/
+struct OOO_DLLPUBLIC_CHARTVIEW ExplicitIncrementData
+{
+ ExplicitIncrementData();
+
+ /** the following two members are only for date-time axis
+ */
+ css::chart::TimeInterval MajorTimeInterval;
+ css::chart::TimeInterval MinorTimeInterval;
+
+ /** the other members are for *not* date-time axis
+ */
+
+ /** <member>Distance</member> describes the distance between two
+ neighboring main tickmarks on a <type>Scale</type> of an axis.
+ All neighboring main tickmarks have the same constant distance.
+
+ <p>If the Scale has a <type>XScaling</type> the <member>Distance</member>
+ may be measured in two different ways - that is - before or after the
+ scaling is applied.</p>
+
+ <p>On a logarithmic scale for example the distance between two main
+ tickmarks is typically measured after the scaling is applied:
+ Distance = log(tick2)-log(tick1)
+ ( log(1000)-log(100)==log(100)-log(10)==log(10)-log(1)==1==Distance ).
+ The resulting tickmarks will always look equidistant on the screen.
+ The other possibility is to have a Distance = tick2-tick1 measured constant
+ before a scaling is applied, which may lead to non equidistant tickmarks
+ on the screen.</p>
+
+ <p><member>PostEquidistant</member> rules whether the <member>Distance</member>
+ is meant to be a value before or after scaling.</p>
+ */
+ double Distance;
+
+ /**
+ <member>PostEquidistant</member> rules whether the member <member>Distance</member>
+ describes a distance before or after the scaling is applied.
+
+ <p>If <member>PostEquidistant</member> equals <TRUE/> <member>Distance</member>
+ is given in values after <type>XScaling</type> is applied, thus resulting
+ main tickmarks will always look equidistant on the screen.
+ If <member>PostEquidistant</member> equals <FALSE/> <member>Distance</member>
+ is given in values before <type>XScaling</type> is applied.</p>
+ */
+ bool PostEquidistant;
+
+ /** The <member>BaseValue</member> gives a starting point on the scale
+ to which all further main tickmarks are relatively positioned.
+
+ <p>The <member>BaseValue</member> is always a value on the scale before
+ a possible scaling is applied. If the given value is not valid in the
+ associated scaling the minimum of the scaling is assumed,
+ if there is no minimum any other obvious value will be assumed.</p>
+
+ <p>E.g.: assume a scale from 0 to 6 with identical scaling.
+ Further assume this Increment to have Distance==2 and PostEquidistant==false.
+ Setting BaseValue=0 would lead to main tickmarks 0; 2; 4; 6;
+ Setting BaseValue=1,3 would lead to main tickmarks 1,3; 3,3; 5,3;
+ Setting BaseValue=-0,7 would also lead to main tickmarks 1,3; 3,3; 5,3;
+ And setting BaseValue to 2, -2, 4, -4 etc. in this example
+ leads to the same result as BaseValue=0.</p>
+ */
+ double BaseValue;
+
+ /** <member>SubIncrements</member> describes the positioning of further
+ sub tickmarks on the scale of an axis.
+
+ <p>The first SubIncrement in this sequence determines how the
+ distance between two neighboring main tickmarks is divided for positioning
+ of further sub tickmarks. Every following SubIncrement determines the
+ positions of subsequent tickmarks in relation to their parent tickmarks
+ given by the preceding SubIncrement.</p>
+ */
+ std::vector<ExplicitSubIncrement> SubIncrements;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/chartview/ExplicitValueProvider.hxx b/chart2/source/inc/chartview/ExplicitValueProvider.hxx
new file mode 100644
index 0000000000..4370e38cf1
--- /dev/null
+++ b/chart2/source/inc/chartview/ExplicitValueProvider.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/types.h>
+#include <chartview/chartviewdllapi.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+
+#include <memory>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XAxis; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::chart2 { class XCoordinateSystem; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::drawing { class XShape; }
+namespace com::sun::star::uno { class XInterface; }
+namespace com::sun::star::uno { template <typename > class Reference; }
+namespace com::sun::star::uno { template <typename > class Sequence; }
+namespace com::sun::star::util { class XNumberFormatsSupplier; }
+namespace com::sun::star::awt { struct Rectangle; }
+class SvxShape;
+
+namespace chart
+{
+class Axis;
+class BaseCoordinateSystem;
+class DrawModelWrapper;
+class ChartModel;
+struct ExplicitIncrementData;
+struct ExplicitScaleData;
+
+class OOO_DLLPUBLIC_CHARTVIEW SAL_LOPLUGIN_ANNOTATE("crosscast") ExplicitValueProvider
+{
+public:
+ /** Gives calculated scale and increment values for a given xAxis in the current view.
+ In contrast to the model data these explicit values are always complete as missing auto properties are calculated.
+ If the given Axis could not be found or for another reason no correct output can be given false is returned.
+ */
+ virtual bool getExplicitValuesForAxis(
+ rtl::Reference< ::chart::Axis > xAxis
+ , ExplicitScaleData& rExplicitScale
+ , ExplicitIncrementData& rExplicitIncrement )=0;
+
+ /** for rotated objects the shape size and position differs from the visible rectangle
+ if bSnapRect is set to true you get the resulting visible position (left-top) and size
+ */
+ virtual css::awt::Rectangle
+ getRectangleOfObject( const OUString& rObjectCID, bool bSnapRect=false )=0;
+
+ virtual css::awt::Rectangle getDiagramRectangleExcludingAxes()=0;
+
+ virtual rtl::Reference< SvxShape >
+ getShapeForCID( const OUString& rObjectCID )=0;
+
+ virtual std::shared_ptr< DrawModelWrapper > getDrawModelWrapper() = 0;
+
+ static css::awt::Rectangle
+ AddSubtractAxisTitleSizes(
+ ChartModel& rModel
+ , ExplicitValueProvider* pChartView
+ , const css::awt::Rectangle& rPositionAndSize, bool bSubtract );
+
+ static sal_Int32 getExplicitNumberFormatKeyForAxis(
+ const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference< ::chart::BaseCoordinateSystem > & xCorrespondingCoordinateSystem
+ , const rtl::Reference<::chart::ChartModel>& xChartDoc);
+
+ static sal_Int32 getExplicitNumberFormatKeyForDataLabel(
+ const css::uno::Reference< css::beans::XPropertySet >& xSeriesOrPointProp );
+
+ static sal_Int32 getExplicitPercentageNumberFormatKeyForDataLabel(
+ const css::uno::Reference< css::beans::XPropertySet >& xSeriesOrPointProp
+ , const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier );
+
+protected:
+ ~ExplicitValueProvider() = default;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/chartview/chartviewdllapi.hxx b/chart2/source/inc/chartview/chartviewdllapi.hxx
new file mode 100644
index 0000000000..533a5cb833
--- /dev/null
+++ b/chart2/source/inc/chartview/chartviewdllapi.hxx
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <sal/types.h>
+
+#if defined OOO_DLLIMPLEMENTATION_CHARTVIEW
+#define OOO_DLLPUBLIC_CHARTVIEW SAL_DLLPUBLIC_EXPORT
+#else
+#define OOO_DLLPUBLIC_CHARTVIEW SAL_DLLPUBLIC_IMPORT
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/defines.hxx b/chart2/source/inc/defines.hxx
new file mode 100644
index 0000000000..1eb464bc20
--- /dev/null
+++ b/chart2/source/inc/defines.hxx
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+constexpr double FIXED_SIZE_FOR_3D_CHART_VOLUME = 10000.0;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/res_BarGeometry.hxx b/chart2/source/inc/res_BarGeometry.hxx
new file mode 100644
index 0000000000..9e0c01870f
--- /dev/null
+++ b/chart2/source/inc/res_BarGeometry.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+
+namespace chart
+{
+class BarGeometryResources
+{
+public:
+ explicit BarGeometryResources(weld::Builder* pParent);
+
+ void set_visible(bool bShow);
+ void set_sensitive(bool bEnable);
+
+ sal_Int32 get_selected_index() const;
+ void select(sal_Int32 nPos);
+
+ void connect_changed(const Link<weld::TreeView&, void>& rLink);
+
+private:
+ std::unique_ptr<weld::Label> m_xFT_Geometry;
+ std::unique_ptr<weld::TreeView> m_xLB_Geometry;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/servicenames.hxx b/chart2/source/inc/servicenames.hxx
new file mode 100644
index 0000000000..0f5cbe2b40
--- /dev/null
+++ b/chart2/source/inc/servicenames.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+inline constexpr OUString CHART_MODEL_SERVICE_IMPLEMENTATION_NAME
+ = u"com.sun.star.comp.chart2.ChartModel"_ustr;
+inline constexpr OUString CHART_MODEL_SERVICE_NAME = u"com.sun.star.chart2.ChartDocument"_ustr;
+//@todo create your own service containing the service com.sun.star.document.OfficeDocument
+
+inline constexpr OUString CHART_VIEW_SERVICE_IMPLEMENTATION_NAME
+ = u"com.sun.star.comp.chart2.ChartView"_ustr;
+inline constexpr OUString CHART_VIEW_SERVICE_NAME = u"com.sun.star.chart2.ChartView"_ustr;
+
+inline constexpr OUString CHART_FRAMELOADER_SERVICE_IMPLEMENTATION_NAME
+ = u"com.sun.star.comp.chart2.ChartFrameLoader"_ustr;
+inline constexpr OUString CHART_FRAMELOADER_SERVICE_NAME
+ = u"com.sun.star.frame.SynchronousFrameLoader"_ustr;
+
+inline constexpr OUString CHART_WIZARD_DIALOG_SERVICE_IMPLEMENTATION_NAME
+ = u"com.sun.star.comp.chart2.WizardDialog"_ustr;
+inline constexpr OUString CHART_WIZARD_DIALOG_SERVICE_NAME
+ = u"com.sun.star.chart2.WizardDialog"_ustr;
+
+inline constexpr OUString CHART_TYPE_DIALOG_SERVICE_IMPLEMENTATION_NAME
+ = u"com.sun.star.comp.chart2.ChartTypeDialog"_ustr;
+inline constexpr OUString CHART_TYPE_DIALOG_SERVICE_NAME
+ = u"com.sun.star.chart2.ChartTypeDialog"_ustr;
+
+// wrapper for old UNO API (com.sun.star.chart)
+inline constexpr OUString CHART_CHARTAPIWRAPPER_IMPLEMENTATION_NAME
+ = u"com.sun.star.comp.chart2.ChartDocumentWrapper"_ustr;
+inline constexpr OUString CHART_CHARTAPIWRAPPER_SERVICE_NAME
+ = u"com.sun.star.chart2.ChartDocumentWrapper"_ustr;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/servicenames_charttypes.hxx b/chart2/source/inc/servicenames_charttypes.hxx
new file mode 100644
index 0000000000..5ab2dcbf49
--- /dev/null
+++ b/chart2/source/inc/servicenames_charttypes.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_AREA
+ = u"com.sun.star.chart2.AreaChartType"_ustr;
+inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_BAR
+ = u"com.sun.star.chart2.BarChartType"_ustr;
+inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_COLUMN
+ = u"com.sun.star.chart2.ColumnChartType"_ustr;
+inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_LINE
+ = u"com.sun.star.chart2.LineChartType"_ustr;
+inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_SCATTER
+ = u"com.sun.star.chart2.ScatterChartType"_ustr;
+inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_PIE
+ = u"com.sun.star.chart2.PieChartType"_ustr;
+inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_NET
+ = u"com.sun.star.chart2.NetChartType"_ustr;
+inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET
+ = u"com.sun.star.chart2.FilledNetChartType"_ustr;
+inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK
+ = u"com.sun.star.chart2.CandleStickChartType"_ustr;
+inline constexpr OUString CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE
+ = u"com.sun.star.chart2.BubbleChartType"_ustr;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/inc/servicenames_coosystems.hxx b/chart2/source/inc/servicenames_coosystems.hxx
new file mode 100644
index 0000000000..065155a8bb
--- /dev/null
+++ b/chart2/source/inc/servicenames_coosystems.hxx
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+inline constexpr OUString CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME = u"com.sun.star.chart2.CoordinateSystems.CartesianView"_ustr;
+inline constexpr OUString CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME = u"com.sun.star.chart2.CoordinateSystems.PolarView"_ustr;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/filter/XMLFilter.cxx b/chart2/source/model/filter/XMLFilter.cxx
new file mode 100644
index 0000000000..f1001f3333
--- /dev/null
+++ b/chart2/source/model/filter/XMLFilter.cxx
@@ -0,0 +1,761 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <XMLFilter.hxx>
+#include <MediaDescriptorHelper.hxx>
+
+#include <officecfg/Office/Common.hxx>
+#include <svtools/sfxecode.hxx>
+#include <comphelper/genericpropertyset.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/documentconstants.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <osl/diagnose.h>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/StorageFactory.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/XFastParser.hpp>
+#include <com/sun/star/packages/zip/ZipIOException.hpp>
+#include <com/sun/star/document/GraphicStorageHandler.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::osl::MutexGuard;
+
+namespace
+{
+constexpr OUString sXML_metaStreamName = u"meta.xml"_ustr;
+constexpr OUString sXML_styleStreamName = u"styles.xml"_ustr;
+constexpr OUString sXML_contentStreamName = u"content.xml"_ustr;
+
+
+uno::Reference< embed::XStorage > lcl_getWriteStorage(
+ const Sequence< beans::PropertyValue >& rMediaDescriptor,
+ const uno::Reference< uno::XComponentContext >& xContext,const OUString& _sMediaType)
+{
+ uno::Reference< embed::XStorage > xStorage;
+ try
+ {
+ apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor );
+ if( aMDHelper.ISSET_Storage )
+ {
+ xStorage = aMDHelper.Storage;
+ }
+ else
+ {
+ Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create( xContext ) );
+
+ std::vector< beans::PropertyValue > aPropertiesForStorage;
+
+ for( sal_Int32 i=rMediaDescriptor.getLength(); i--; )
+ {
+ // properties understood by storage factory
+ // (see package/source/xstor/xfactory.cxx for details)
+ if ( rMediaDescriptor[i].Name == "InteractionHandler" || rMediaDescriptor[i].Name == "Password" || rMediaDescriptor[i].Name == "RepairPackage" )
+ {
+ aPropertiesForStorage.push_back( rMediaDescriptor[i] );
+ }
+ }
+
+ if( aMDHelper.ISSET_Storage )
+ xStorage.set( aMDHelper.Storage );
+ else
+ {
+ Sequence< uno::Any > aStorageArgs{
+ aMDHelper.ISSET_OutputStream ? uno::Any(aMDHelper.OutputStream)
+ : uno::Any(aMDHelper.URL),
+ uno::Any(embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE),
+ uno::Any(comphelper::containerToSequence( aPropertiesForStorage ))
+ };
+
+ xStorage.set(
+ xStorageFact->createInstanceWithArguments( aStorageArgs ),
+ uno::UNO_QUERY_THROW );
+ }
+ }
+
+ // set correct media type at storage
+ uno::Reference<beans::XPropertySet> xProp(xStorage,uno::UNO_QUERY);
+ OUString aMediaType;
+ if ( ! xProp.is() ||
+ ! ( xProp->getPropertyValue( "MediaType") >>= aMediaType ) ||
+ ( aMediaType.isEmpty() ))
+ {
+ xProp->setPropertyValue( "MediaType", uno::Any( _sMediaType ));
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return xStorage;
+}
+
+uno::Reference< embed::XStorage > lcl_getReadStorage(
+ const Sequence< beans::PropertyValue >& rMediaDescriptor,
+ const uno::Reference< uno::XComponentContext >& xContext)
+{
+ uno::Reference< embed::XStorage > xStorage;
+
+ try
+ {
+ apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor );
+ if( aMDHelper.ISSET_Storage )
+ {
+ xStorage = aMDHelper.Storage;
+ }
+ else
+ {
+ // get XStream from MediaDescriptor
+ uno::Reference< io::XInputStream > xStream;
+ std::vector< beans::PropertyValue > aPropertiesForStorage;
+ for( sal_Int32 i=rMediaDescriptor.getLength(); i--; )
+ {
+ if( rMediaDescriptor[i].Name == "InputStream" )
+ xStream.set( rMediaDescriptor[i].Value, uno::UNO_QUERY );
+
+ // properties understood by storage factory
+ // (see package/source/xstor/xfactory.cxx for details)
+ if ( rMediaDescriptor[i].Name == "InteractionHandler" || rMediaDescriptor[i].Name == "Password" || rMediaDescriptor[i].Name == "RepairPackage" )
+ {
+ aPropertiesForStorage.push_back( rMediaDescriptor[i] );
+ }
+ }
+ OSL_ENSURE( xStream.is(), "No Stream" );
+ if( ! xStream.is())
+ return xStorage;
+
+ // convert XInputStream to XStorage via the storage factory
+ Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create( xContext ) );
+ Sequence< uno::Any > aStorageArgs{
+ uno::Any(xStream),
+ uno::Any(embed::ElementModes::READ | embed::ElementModes::NOCREATE),
+ uno::Any(comphelper::containerToSequence( aPropertiesForStorage ))
+ };
+ xStorage.set(
+ xStorageFact->createInstanceWithArguments( aStorageArgs ), uno::UNO_QUERY_THROW );
+ }
+
+ OSL_ENSURE( xStorage.is(), "No Storage" );
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xStorage;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+XMLFilter::XMLFilter( Reference< uno::XComponentContext > const & xContext ) :
+ m_xContext( xContext )
+{}
+
+XMLFilter::~XMLFilter()
+{}
+
+// ____ XFilter ____
+sal_Bool SAL_CALL XMLFilter::filter(
+ const Sequence< beans::PropertyValue >& aDescriptor )
+{
+ bool bResult = false;
+
+ MutexGuard aGuard( m_aMutex );
+
+ if( m_xSourceDoc.is())
+ {
+ OSL_ENSURE( ! m_xTargetDoc.is(), "source doc is set -> target document should not be set" );
+ if( impl_Export( m_xSourceDoc,
+ aDescriptor ) == ERRCODE_NONE )
+ {
+ m_xSourceDoc = nullptr;
+ bResult = true;
+ }
+ }
+ else if( m_xTargetDoc.is())
+ {
+ if( impl_Import( m_xTargetDoc,
+ aDescriptor ) == ERRCODE_NONE )
+ {
+ m_xTargetDoc = nullptr;
+ bResult = true;
+ }
+ }
+ else
+ {
+ OSL_FAIL( "filter() called with no document set" );
+ }
+
+ return bResult;
+}
+
+void SAL_CALL XMLFilter::cancel()
+{
+}
+
+// ____ XImporter ____
+void SAL_CALL XMLFilter::setTargetDocument(
+ const Reference< lang::XComponent >& Document )
+{
+ MutexGuard aGuard( m_aMutex );
+ OSL_ENSURE( ! m_xSourceDoc.is(), "Setting target doc while source doc is set" );
+
+ m_xTargetDoc = Document;
+}
+
+// ____ XExporter ____
+void SAL_CALL XMLFilter::setSourceDocument(
+ const Reference< lang::XComponent >& Document )
+{
+ MutexGuard aGuard( m_aMutex );
+ OSL_ENSURE( ! m_xTargetDoc.is(), "Setting source doc while target doc is set" );
+
+ m_xSourceDoc = Document;
+}
+
+ErrCode XMLFilter::impl_Import(
+ const Reference< lang::XComponent > & xDocumentComp,
+ const Sequence< beans::PropertyValue > & rMediaDescriptor )
+{
+ ErrCode nWarning = ERRCODE_NONE;
+
+ OSL_ENSURE( xDocumentComp.is(), "Import: No Model" );
+ OSL_ENSURE( m_xContext.is(), "Import: No ComponentContext" );
+
+ if( ! (xDocumentComp.is() &&
+ m_xContext.is()))
+ return nWarning;
+
+ try
+ {
+ Reference< lang::XServiceInfo > xServInfo( xDocumentComp, uno::UNO_QUERY_THROW );
+ if( ! xServInfo->supportsService( "com.sun.star.chart2.ChartDocument"))
+ {
+ OSL_FAIL( "Import: No ChartDocument" );
+ return ERRCODE_SFX_GENERAL;
+ }
+
+ Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager());
+ OSL_ENSURE( xFactory.is(), "Import: No Factory" );
+ if( ! xFactory.is())
+ return ERRCODE_SFX_GENERAL;
+
+ bool bOasis = true;
+ isOasisFormat( rMediaDescriptor, bOasis );
+ Reference< embed::XStorage > xStorage( lcl_getReadStorage( rMediaDescriptor, m_xContext));
+ if( ! xStorage.is())
+ return ERRCODE_SFX_GENERAL;
+
+ uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
+ uno::Reference<lang::XMultiServiceFactory> xServiceFactory(xFactory, uno::UNO_QUERY);
+ if (xServiceFactory.is())
+ {
+ uno::Sequence<uno::Any> aArgs{ uno::Any(xStorage) };
+ xGraphicStorageHandler.set(
+ xServiceFactory->createInstanceWithArguments(
+ "com.sun.star.comp.Svx.GraphicImportHelper", aArgs), uno::UNO_QUERY);
+ }
+
+ // create XPropertySet with extra information for the filter
+ /** property map for import info set */
+ static comphelper::PropertyMapEntry const aImportInfoMap[] =
+ {
+ // necessary properties for XML progress bar at load time
+ { OUString("ProgressRange"), 0, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("ProgressMax"), 0, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("ProgressCurrent"), 0, cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("PrivateData"), 0, cppu::UnoType<XInterface>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("BaseURI"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamRelPath"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamName"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("BuildId"), 0, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ };
+ uno::Reference< beans::XPropertySet > xImportInfo(
+ comphelper::GenericPropertySet_CreateInstance(
+ new comphelper::PropertySetInfo( aImportInfoMap ) ) );
+
+ // Set base URI and Hierarchical Name
+ OUString aHierarchName, aBaseUri;
+ // why retrieve this from the model when it's available as rMediaDescriptor?
+ uno::Reference<frame::XModel> const xModel(m_xTargetDoc, uno::UNO_QUERY);
+ if( xModel.is() )
+ {
+ const uno::Sequence< beans::PropertyValue > aModProps = xModel->getArgs();
+ for( beans::PropertyValue const & prop : aModProps )
+ {
+ if( prop.Name == "HierarchicalDocumentName" )
+ {
+ // Actually this argument only has meaning for embedded documents
+ prop.Value >>= aHierarchName;
+ }
+ else if( prop.Name == "DocumentBaseURL" )
+ {
+ prop.Value >>= aBaseUri;
+ }
+ }
+ }
+
+ // needed for relative URLs, but in clipboard copy/paste there may be none
+ SAL_INFO_IF(aBaseUri.isEmpty(), "chart2", "chart::XMLFilter: no base URL");
+ if( !aBaseUri.isEmpty() )
+ xImportInfo->setPropertyValue( "BaseURI", uno::Any( aBaseUri ) );
+
+ if( !aHierarchName.isEmpty() )
+ xImportInfo->setPropertyValue( "StreamRelPath", uno::Any( aHierarchName ) );
+
+ // import meta information
+ if( bOasis )
+ nWarning = impl_ImportStream(
+ sXML_metaStreamName,
+ "com.sun.star.comp.Chart.XMLOasisMetaImporter",
+ xStorage, xFactory, xGraphicStorageHandler, xImportInfo );
+
+ // import styles
+ ErrCode nTmpErr = impl_ImportStream(
+ sXML_styleStreamName,
+ bOasis
+ ? OUString("com.sun.star.comp.Chart.XMLOasisStylesImporter")
+ : OUString("com.sun.star.comp.Chart.XMLStylesImporter"),
+ xStorage, xFactory, xGraphicStorageHandler, xImportInfo );
+ nWarning = nWarning != ERRCODE_NONE ? nWarning : nTmpErr;
+
+ // import content
+ ErrCode nContentWarning = impl_ImportStream(
+ sXML_contentStreamName,
+ bOasis
+ ? OUString("com.sun.star.comp.Chart.XMLOasisContentImporter")
+ : OUString("com.sun.star.comp.Chart.XMLContentImporter"),
+ xStorage, xFactory, xGraphicStorageHandler, xImportInfo );
+ nWarning = nWarning != ERRCODE_NONE ? nWarning : nContentWarning;
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+
+ // something went awry
+ nWarning = ERRCODE_SFX_GENERAL;
+ }
+
+ return nWarning;
+}
+
+ErrCode XMLFilter::impl_ImportStream(
+ const OUString & rStreamName,
+ const OUString & rServiceName,
+ const Reference< embed::XStorage > & xStorage,
+ const Reference< lang::XMultiComponentFactory > & xFactory,
+ const Reference< document::XGraphicStorageHandler > & xGraphicStorageHandler,
+ uno::Reference< beans::XPropertySet > const & xImportInfo )
+{
+ ErrCode nWarning = ERRCODE_SFX_GENERAL;
+
+ if( ! (xStorage.is() &&
+ xStorage->hasByName( rStreamName )))
+ return ERRCODE_NONE;
+
+ if( xImportInfo.is() )
+ xImportInfo->setPropertyValue( "StreamName", uno::Any( rStreamName ) );
+
+ if( xStorage.is() &&
+ xStorage->isStreamElement( rStreamName ) )
+ {
+ try
+ {
+ auto xInputStream =
+ xStorage->openStreamElement(
+ rStreamName,
+ embed::ElementModes::READ | embed::ElementModes::NOCREATE );
+
+ // todo: encryption
+
+ if( xInputStream.is())
+ {
+ sal_Int32 nArgs = 0;
+ if( xGraphicStorageHandler.is())
+ nArgs++;
+ if( xImportInfo.is())
+ nArgs++;
+
+ uno::Sequence< uno::Any > aFilterCompArgs( nArgs );
+ auto aFilterCompArgsRange = asNonConstRange(aFilterCompArgs);
+
+ nArgs = 0;
+ if( xGraphicStorageHandler.is())
+ aFilterCompArgsRange[nArgs++] <<= xGraphicStorageHandler;
+ if( xImportInfo.is())
+ aFilterCompArgsRange[ nArgs++ ] <<= xImportInfo;
+
+ // the underlying SvXMLImport implements XFastParser, XImporter, XFastDocumentHandler
+ Reference< XInterface > xFilter =
+ xFactory->createInstanceWithArgumentsAndContext( rServiceName, aFilterCompArgs, m_xContext );
+ assert(xFilter);
+ Reference< document::XImporter > xImporter( xFilter, uno::UNO_QUERY );
+ assert(xImporter);
+ xImporter->setTargetDocument( Reference< lang::XComponent >( m_xTargetDoc, uno::UNO_SET_THROW ));
+
+ if ( !m_sDocumentHandler.isEmpty() )
+ {
+ try
+ {
+ uno::Sequence< uno::Any > aArgs{
+ uno::Any(beans::NamedValue("DocumentHandler", uno::Any(xFilter))),
+ uno::Any(beans::NamedValue("Model", uno::Any(m_xTargetDoc)))
+ };
+
+ xFilter = xFactory->createInstanceWithArgumentsAndContext(m_sDocumentHandler,aArgs,m_xContext);
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "failed to instantiate " << m_sDocumentHandler);
+ }
+ }
+ xml::sax::InputSource aParserInput;
+ aParserInput.aInputStream.set(xInputStream, uno::UNO_QUERY_THROW);
+
+ // the underlying SvXMLImport implements XFastParser, XImporter, XFastDocumentHandler
+ Reference< xml::sax::XFastParser > xFastParser(xFilter, uno::UNO_QUERY);
+ if (xFastParser.is())
+ xFastParser->parseStream(aParserInput);
+ else
+ {
+ Reference<xml::sax::XParser> xParser = xml::sax::Parser::create(m_xContext);
+ xParser->setDocumentHandler( uno::Reference<xml::sax::XDocumentHandler>(xFilter, uno::UNO_QUERY_THROW) );
+ xParser->parseStream(aParserInput);
+ }
+ }
+
+ // load was successful
+ nWarning = ERRCODE_NONE;
+ }
+ catch (const xml::sax::SAXParseException&)
+ {
+ // todo: if encrypted: ERRCODE_SFX_WRONGPASSWORD
+ }
+ catch (const xml::sax::SAXException&)
+ {
+ // todo: if encrypted: ERRCODE_SFX_WRONGPASSWORD
+ }
+ catch (const packages::zip::ZipIOException&)
+ {
+ nWarning = ERRCODE_IO_BROKENPACKAGE;
+ }
+ catch (const io::IOException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return nWarning;
+}
+
+ErrCode XMLFilter::impl_Export(
+ const Reference< lang::XComponent > & xDocumentComp,
+ const Sequence< beans::PropertyValue > & rMediaDescriptor )
+{
+ m_aMediaDescriptor = rMediaDescriptor;
+ //save
+
+ ErrCode nWarning = ERRCODE_NONE;
+
+ OSL_ENSURE( xDocumentComp.is(), "Export: No Model" );
+ OSL_ENSURE( m_xContext.is(), "Export: No ComponentContext" );
+
+ if( !xDocumentComp.is() || !m_xContext.is() )
+ return nWarning;
+
+ try
+ {
+ Reference< lang::XServiceInfo > xServInfo( xDocumentComp, uno::UNO_QUERY_THROW );
+ if( ! xServInfo->supportsService( "com.sun.star.chart2.ChartDocument"))
+ {
+ OSL_FAIL( "Export: No ChartDocument" );
+ return ERRCODE_SFX_GENERAL;
+ }
+
+ Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager());
+ OSL_ENSURE( xFactory.is(), "Export: No Factory" );
+ if( ! xFactory.is())
+ return ERRCODE_SFX_GENERAL;
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory( m_xContext->getServiceManager(), uno::UNO_QUERY);
+ if( ! xServiceFactory.is())
+ return ERRCODE_SFX_GENERAL;
+
+ uno::Reference< xml::sax::XWriter > xSaxWriter = xml::sax::Writer::create(m_xContext);
+
+ bool bOasis = true;
+ isOasisFormat( rMediaDescriptor, bOasis );
+
+ uno::Reference< embed::XStorage > xStorage( lcl_getWriteStorage( rMediaDescriptor, m_xContext, getMediaType(bOasis) ) );
+ OSL_ENSURE( xStorage.is(), "No Storage" );
+ if( ! xStorage.is())
+ return ERRCODE_SFX_GENERAL;
+
+ uno::Reference< xml::sax::XDocumentHandler> xDocHandler = xSaxWriter;
+
+ if ( !m_sDocumentHandler.isEmpty() )
+ {
+ try
+ {
+ uno::Sequence< uno::Any > aArgs{
+ uno::Any(beans::NamedValue("DocumentHandler", uno::Any(xDocHandler))),
+ uno::Any(beans::NamedValue("Model", uno::Any(xDocumentComp)))
+ };
+
+ xDocHandler.set(xServiceFactory->createInstanceWithArguments(m_sDocumentHandler,aArgs), uno::UNO_QUERY );
+ xSaxWriter.set(xDocHandler,uno::UNO_QUERY);
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "chart2", "Exception caught!");
+ }
+ }
+
+ Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
+ xGraphicStorageHandler.set(document::GraphicStorageHandler::createWithStorage(m_xContext, xStorage));
+
+ // property map for export info set
+ static comphelper::PropertyMapEntry const aExportInfoMap[] =
+ {
+ { OUString("UsePrettyPrinting"), 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("ExportTableNumberList"), 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::MAYBEVOID, 0 },
+ };
+
+ uno::Reference< beans::XPropertySet > xInfoSet =
+ comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) );
+
+ bool bUsePrettyPrinting( officecfg::Office::Common::Save::Document::PrettyPrinting::get() );
+ xInfoSet->setPropertyValue( "UsePrettyPrinting", uno::Any( bUsePrettyPrinting ) );
+ if( ! bOasis )
+ xInfoSet->setPropertyValue( "ExportTableNumberList", uno::Any( true ));
+
+ sal_Int32 nArgs = 2;
+ if( xGraphicStorageHandler.is())
+ nArgs++;
+
+ uno::Sequence< uno::Any > aFilterProperties( nArgs );
+ {
+ auto pFilterProperties = aFilterProperties.getArray();
+ nArgs = 0;
+ pFilterProperties[ nArgs++ ] <<= xInfoSet;
+ pFilterProperties[ nArgs++ ] <<= xDocHandler;
+ if( xGraphicStorageHandler.is())
+ pFilterProperties[ nArgs++ ] <<= xGraphicStorageHandler;
+ }
+
+ // export meta information
+ if( bOasis )
+ nWarning = impl_ExportStream(
+ sXML_metaStreamName,
+ "com.sun.star.comp.Chart.XMLOasisMetaExporter",
+ xStorage, xSaxWriter, xServiceFactory, aFilterProperties );
+
+ // export styles
+ ErrCode nTmp = impl_ExportStream(
+ sXML_styleStreamName,
+ bOasis
+ ? OUString("com.sun.star.comp.Chart.XMLOasisStylesExporter")
+ : OUString("com.sun.star.comp.Chart.XMLStylesExporter"), // soffice 6/7
+ xStorage, xSaxWriter, xServiceFactory, aFilterProperties );
+ nWarning = nWarning != ERRCODE_NONE ? nWarning : nTmp;
+
+ // export content
+ ErrCode nContentWarning = impl_ExportStream(
+ sXML_contentStreamName,
+ bOasis
+ ? OUString("com.sun.star.comp.Chart.XMLOasisContentExporter")
+ : OUString("com.sun.star.comp.Chart.XMLContentExporter"),
+ xStorage, xSaxWriter, xServiceFactory, aFilterProperties );
+ nWarning = nWarning != ERRCODE_NONE ? nWarning : nContentWarning;
+
+ Reference< lang::XComponent > xComp(xGraphicStorageHandler, uno::UNO_QUERY);
+ if (xComp.is())
+ xComp->dispose();
+
+ uno::Reference<embed::XTransactedObject> xTransact( xStorage ,uno::UNO_QUERY);
+ if ( xTransact.is() )
+ xTransact->commit();
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+
+ // something went awry
+ nWarning = ERRCODE_SFX_GENERAL;
+ }
+
+ return nWarning;
+}
+
+ErrCode XMLFilter::impl_ExportStream(
+ const OUString & rStreamName,
+ const OUString & rServiceName,
+ const Reference< embed::XStorage > & xStorage,
+ const uno::Reference< xml::sax::XWriter >& xActiveDataSource,
+ const Reference< lang::XMultiServiceFactory >& xServiceFactory,
+ const Sequence< uno::Any > & rFilterProperties )
+{
+ try
+ {
+ if( !xServiceFactory.is() )
+ return ERRCODE_SFX_GENERAL;
+ if( !xStorage.is() )
+ return ERRCODE_SFX_GENERAL;
+ if ( !xActiveDataSource.is() )
+ return ERRCODE_SFX_GENERAL;
+
+ uno::Reference< io::XStream > xStream( xStorage->openStreamElement(
+ rStreamName, embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ) );
+ if ( !xStream.is() )
+ return ERRCODE_SFX_GENERAL;
+ uno::Reference< io::XOutputStream > xOutputStream( xStream->getOutputStream() );
+ if ( !xOutputStream.is() )
+ return ERRCODE_SFX_GENERAL;
+
+ uno::Reference< beans::XPropertySet > xStreamProp( xOutputStream, uno::UNO_QUERY );
+ if(xStreamProp.is()) try
+ {
+ xStreamProp->setPropertyValue( "MediaType", uno::Any( OUString("text/xml") ) );
+ xStreamProp->setPropertyValue( "Compressed", uno::Any( true ) );//@todo?
+ xStreamProp->setPropertyValue( "UseCommonStoragePasswordEncryption", uno::Any( true ) );
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ xActiveDataSource->setOutputStream(xOutputStream);
+
+ // set Base URL
+ {
+ uno::Reference< beans::XPropertySet > xInfoSet;
+ if( rFilterProperties.hasElements() )
+ rFilterProperties.getConstArray()[0] >>= xInfoSet;
+ OSL_ENSURE( xInfoSet.is(), "missing infoset for export" );
+ if( xInfoSet.is() )
+ xInfoSet->setPropertyValue( "StreamName", uno::Any( rStreamName ) );
+ }
+
+ Reference< XExporter > xExporter( xServiceFactory->createInstanceWithArguments(
+ rServiceName, rFilterProperties ), uno::UNO_QUERY);
+ if ( !xExporter.is() )
+ return ERRCODE_SFX_GENERAL;
+
+ xExporter->setSourceDocument( m_xSourceDoc );
+
+ uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY );
+ if ( !xFilter.is() )
+ return ERRCODE_SFX_GENERAL;
+
+ xFilter->filter(m_aMediaDescriptor);
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return ERRCODE_NONE;
+}
+
+void XMLFilter::isOasisFormat(const Sequence< beans::PropertyValue >& _rMediaDescriptor, bool & rOutOASIS )
+{
+ apphelper::MediaDescriptorHelper aMDHelper( _rMediaDescriptor );
+ if( aMDHelper.ISSET_FilterName )
+ rOutOASIS = aMDHelper.FilterName == "chart8";
+}
+OUString XMLFilter::getMediaType(bool _bOasis)
+{
+ return _bOasis ? MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII : MIMETYPE_VND_SUN_XML_CHART_ASCII;
+}
+
+OUString SAL_CALL XMLFilter::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.XMLFilter";
+}
+
+sal_Bool SAL_CALL XMLFilter::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL XMLFilter::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.document.ImportFilter",
+ "com.sun.star.document.ExportFilter"
+ };
+ // todo: services are incomplete. Missing:
+ // XInitialization, XNamed
+}
+
+void XMLReportFilterHelper::isOasisFormat(const Sequence< beans::PropertyValue >& _rMediaDescriptor, bool & rOutOASIS )
+{
+ apphelper::MediaDescriptorHelper aMDHelper( _rMediaDescriptor );
+ if( aMDHelper.ISSET_FilterName )
+ rOutOASIS = aMDHelper.FilterName == "StarOffice XML (Base) Report Chart";
+}
+OUString XMLReportFilterHelper::getMediaType(bool )
+{
+ return MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART_ASCII;
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_XMLFilter_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::XMLFilter(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_report_XMLFilter_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::XMLReportFilterHelper(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/inc/CartesianCoordinateSystem.hxx b/chart2/source/model/inc/CartesianCoordinateSystem.hxx
new file mode 100644
index 0000000000..d84f53bf57
--- /dev/null
+++ b/chart2/source/model/inc/CartesianCoordinateSystem.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <BaseCoordinateSystem.hxx>
+
+namespace chart
+{
+class CartesianCoordinateSystem : public BaseCoordinateSystem
+{
+public:
+ explicit CartesianCoordinateSystem(sal_Int32 nDimensionCount);
+ explicit CartesianCoordinateSystem(const CartesianCoordinateSystem& rSource);
+ virtual ~CartesianCoordinateSystem() override;
+
+ // ____ XCoordinateSystem ____
+ virtual OUString SAL_CALL getCoordinateSystemType() override;
+ virtual OUString SAL_CALL getViewServiceName() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone() override;
+
+ // ____ XServiceInfo ____
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+class CartesianCoordinateSystem2d final : public CartesianCoordinateSystem
+{
+public:
+ explicit CartesianCoordinateSystem2d();
+ virtual ~CartesianCoordinateSystem2d() override;
+
+ // ____ XServiceInfo ____
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+class CartesianCoordinateSystem3d final : public CartesianCoordinateSystem
+{
+public:
+ explicit CartesianCoordinateSystem3d();
+ virtual ~CartesianCoordinateSystem3d() override;
+
+ // ____ XServiceInfo ____
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/inc/PolarCoordinateSystem.hxx b/chart2/source/model/inc/PolarCoordinateSystem.hxx
new file mode 100644
index 0000000000..43eaefa5b0
--- /dev/null
+++ b/chart2/source/model/inc/PolarCoordinateSystem.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <BaseCoordinateSystem.hxx>
+
+namespace chart
+{
+class PolarCoordinateSystem : public BaseCoordinateSystem
+{
+public:
+ explicit PolarCoordinateSystem(sal_Int32 nDimensionCount);
+ explicit PolarCoordinateSystem(const PolarCoordinateSystem& rSource);
+ virtual ~PolarCoordinateSystem() override;
+
+ // ____ XCoordinateSystem ____
+ virtual OUString SAL_CALL getCoordinateSystemType() override;
+ virtual OUString SAL_CALL getViewServiceName() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone() override;
+
+ // ____ XServiceInfo ____
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+class PolarCoordinateSystem2d final : public PolarCoordinateSystem
+{
+public:
+ explicit PolarCoordinateSystem2d();
+ virtual ~PolarCoordinateSystem2d() override;
+
+ // ____ XServiceInfo ____
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+class PolarCoordinateSystem3d final : public PolarCoordinateSystem
+{
+public:
+ explicit PolarCoordinateSystem3d();
+ virtual ~PolarCoordinateSystem3d() override;
+
+ // ____ XServiceInfo ____
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/inc/StockBar.hxx b/chart2/source/model/inc/StockBar.hxx
new file mode 100644
index 0000000000..38f5c2629b
--- /dev/null
+++ b/chart2/source/model/inc/StockBar.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/util/XCloneable.hpp>
+#include <OPropertySet.hxx>
+
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <ModifyListenerHelper.hxx>
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ StockBar_Base;
+}
+
+class StockBar final :
+ public impl::StockBar_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit StockBar( bool bRisingCourse );
+ virtual ~StockBar() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+
+private:
+ explicit StockBar( const StockBar & rOther );
+
+ // ____ XTypeProvider ____
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/inc/XMLFilter.hxx b/chart2/source/model/inc/XMLFilter.hxx
new file mode 100644
index 0000000000..12c28ad40e
--- /dev/null
+++ b/chart2/source/model/inc/XMLFilter.hxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <osl/mutex.hxx>
+#include <comphelper/errcode.hxx>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::xml::sax { class XWriter; }
+namespace com::sun::star::lang { class XMultiComponentFactory; }
+
+namespace com::sun::star {
+ namespace embed {
+ class XStorage;
+ }
+ namespace xml::sax {
+ class XFastParser;
+ }
+ namespace document {
+ class XGraphicStorageHandler;
+ }
+}
+
+namespace chart
+{
+
+class XMLFilter : public
+ ::cppu::WeakImplHelper<
+ css::document::XFilter,
+ css::document::XExporter,
+ css::document::XImporter,
+ css::lang::XServiceInfo >
+{
+public:
+ explicit XMLFilter( css::uno::Reference< css::uno::XComponentContext > const & xContext );
+ virtual ~XMLFilter() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+protected:
+ // ____ XFilter ____
+ virtual sal_Bool SAL_CALL filter(
+ const css::uno::Sequence< css::beans::PropertyValue >& aDescriptor ) override;
+ virtual void SAL_CALL cancel() override;
+
+ // ____ XImporter ____
+ virtual void SAL_CALL setTargetDocument(
+ const css::uno::Reference< css::lang::XComponent >& Document ) override;
+
+ // ____ XExporter ____
+ virtual void SAL_CALL setSourceDocument(
+ const css::uno::Reference< css::lang::XComponent >& Document ) override;
+
+ void setDocumentHandler(const OUString& _sDocumentHandler) { m_sDocumentHandler = _sDocumentHandler; }
+
+ virtual OUString getMediaType(bool _bOasis);
+
+ /** fills the oasis flag only when a filtername was set
+ *
+ * \param _rMediaDescriptor
+ * \param _rOutOASIS
+ */
+ virtual void isOasisFormat(const css::uno::Sequence< css::beans::PropertyValue >& _rMediaDescriptor, bool & _rOutOASIS );
+
+private:
+ // methods
+
+ /// @return a warning code, or 0 for successful operation
+ ErrCode impl_Import( const css::uno::Reference< css::lang::XComponent > & xDocumentComp,
+ const css::uno::Sequence< css::beans::PropertyValue > & aMediaDescriptor );
+ /// @return a warning code, or 0 for successful operation
+ ErrCode impl_ImportStream(
+ const OUString & rStreamName,
+ const OUString & rServiceName,
+ const css::uno::Reference< css::embed::XStorage > & xStorage,
+ const css::uno::Reference< css::lang::XMultiComponentFactory > & xFactory,
+ const css::uno::Reference<css::document::XGraphicStorageHandler> & xGraphicStorageHandler,
+ css::uno::Reference< css::beans::XPropertySet > const & xPropSet );
+
+ /// @return a warning code, or 0 for successful operation
+ ErrCode impl_Export( const css::uno::Reference< css::lang::XComponent > & xDocumentComp,
+ const css::uno::Sequence< css::beans::PropertyValue > & aMediaDescriptor );
+ /// @return a warning code, or 0 for successful operation
+ ErrCode impl_ExportStream(
+ const OUString & rStreamName,
+ const OUString & rServiceName,
+ const css::uno::Reference< css::embed::XStorage > & xStorage,
+ const css::uno::Reference< css::xml::sax::XWriter >& xActiveDataSource,
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & xFactory,
+ const css::uno::Sequence< css::uno::Any > & rFilterProperties );
+
+ // members
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ css::uno::Reference< css::lang::XComponent > m_xTargetDoc;
+ css::uno::Reference< css::lang::XComponent > m_xSourceDoc;
+
+ css::uno::Sequence<css::beans::PropertyValue> m_aMediaDescriptor;
+
+ OUString m_sDocumentHandler; // when set it will be set as doc handler
+ ::osl::Mutex m_aMutex;
+};
+
+class XMLReportFilterHelper final : public XMLFilter
+{
+ virtual void isOasisFormat(const css::uno::Sequence< css::beans::PropertyValue >& _rMediaDescriptor,
+ bool & _rOutOASIS ) override;
+public:
+ explicit XMLReportFilterHelper( css::uno::Reference< css::uno::XComponentContext > const & _xContext )
+ :XMLFilter(_xContext)
+ {}
+protected:
+ virtual OUString SAL_CALL
+ getImplementationName() override
+ {
+ return "com.sun.star.comp.chart2.report.XMLFilter";
+ }
+ // ____ XImporter ____
+ virtual void SAL_CALL setTargetDocument(
+ const css::uno::Reference< css::lang::XComponent >& Document ) override
+ {
+ setDocumentHandler( "com.sun.star.comp.report.ImportDocumentHandler" );
+ XMLFilter::setTargetDocument(Document);
+ }
+
+ // ____ XExporter ____
+ virtual void SAL_CALL setSourceDocument(
+ const css::uno::Reference< css::lang::XComponent >& Document ) override
+ {
+ setDocumentHandler( "com.sun.star.comp.report.ExportDocumentHandler" );
+ XMLFilter::setSourceDocument(Document);
+ }
+
+ virtual OUString getMediaType(bool _bOasis) override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/Axis.cxx b/chart2/source/model/main/Axis.cxx
new file mode 100644
index 0000000000..26a6d48368
--- /dev/null
+++ b/chart2/source/model/main/Axis.cxx
@@ -0,0 +1,601 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <Axis.hxx>
+#include <GridProperties.hxx>
+#include <CharacterProperties.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <UserDefinedProperties.hxx>
+#include <PropertyHelper.hxx>
+#include <CloneHelper.hxx>
+#include <AxisHelper.hxx>
+#include <EventListenerHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <Title.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
+#include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
+#include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <rtl/ref.hxx>
+
+#include <vector>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans::PropertyAttribute;
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::beans::Property;
+using ::osl::MutexGuard;
+
+namespace
+{
+
+enum
+{
+ PROP_AXIS_SHOW,
+ PROP_AXIS_CROSSOVER_POSITION,
+ PROP_AXIS_CROSSOVER_VALUE,
+ PROP_AXIS_DISPLAY_LABELS,
+ PROP_AXIS_NUMBERFORMAT,
+ PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE,
+ PROP_AXIS_LABEL_POSITION,
+ PROP_AXIS_TEXT_ROTATION,
+ PROP_AXIS_TEXT_BREAK,
+ PROP_AXIS_TEXT_OVERLAP,
+ PROP_AXIS_TEXT_STACKED,
+ PROP_AXIS_TEXT_ARRANGE_ORDER,
+ PROP_AXIS_REFERENCE_DIAGRAM_SIZE,
+
+ PROP_AXIS_MAJOR_TICKMARKS,
+ PROP_AXIS_MINOR_TICKMARKS,
+ PROP_AXIS_MARK_POSITION,
+
+ PROP_AXIS_DISPLAY_UNITS,
+ PROP_AXIS_BUILTINUNIT,
+
+ PROP_AXIS_TRY_STAGGERING_FIRST,
+ PROP_AXIS_MAJOR_ORIGIN
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "Show",
+ PROP_AXIS_SHOW,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "CrossoverPosition",
+ PROP_AXIS_CROSSOVER_POSITION,
+ cppu::UnoType<css::chart::ChartAxisPosition>::get(),
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "CrossoverValue",
+ PROP_AXIS_CROSSOVER_VALUE,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "DisplayLabels",
+ PROP_AXIS_DISPLAY_LABELS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_NUMFMT,
+ PROP_AXIS_NUMBERFORMAT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LINK_TO_SRC_NUMFMT,
+ PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "LabelPosition",
+ PROP_AXIS_LABEL_POSITION,
+ cppu::UnoType<css::chart::ChartAxisLabelPosition>::get(),
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "TextRotation",
+ PROP_AXIS_TEXT_ROTATION,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "TextBreak",
+ PROP_AXIS_TEXT_BREAK,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "TextOverlap",
+ PROP_AXIS_TEXT_OVERLAP,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "StackCharacters",
+ PROP_AXIS_TEXT_STACKED,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ArrangeOrder",
+ PROP_AXIS_TEXT_ARRANGE_ORDER,
+ cppu::UnoType<css::chart::ChartAxisArrangeOrderType>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ReferencePageSize",
+ PROP_AXIS_REFERENCE_DIAGRAM_SIZE,
+ cppu::UnoType<awt::Size>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "MajorTickmarks",
+ PROP_AXIS_MAJOR_TICKMARKS,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "MinorTickmarks",
+ PROP_AXIS_MINOR_TICKMARKS,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "MarkPosition",
+ PROP_AXIS_MARK_POSITION,
+ cppu::UnoType<css::chart::ChartAxisMarkPosition>::get(),
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //Properties for display units:
+ rOutProperties.emplace_back( "DisplayUnits",
+ PROP_AXIS_DISPLAY_UNITS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //Properties for labels:
+ rOutProperties.emplace_back( "BuiltInUnit",
+ PROP_AXIS_BUILTINUNIT,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // Compatibility option: starting from LibreOffice 5.1 the rotated
+ // layout is preferred to staggering for axis labels.
+ rOutProperties.emplace_back( "TryStaggeringFirst",
+ PROP_AXIS_TRY_STAGGERING_FIRST,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "MajorOrigin",
+ PROP_AXIS_MAJOR_ORIGIN,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+}
+} // namespace
+
+namespace chart
+{
+const ::chart::tPropertyValueMap & StaticAxisDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::CharacterProperties::AddDefaultsToMap( aMap );
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aMap );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_SHOW, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_CROSSOVER_POSITION, css::chart::ChartAxisPosition_ZERO );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_DISPLAY_LABELS, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_LINK_NUMBERFORMAT_TO_SOURCE, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_LABEL_POSITION, css::chart::ChartAxisLabelPosition_NEAR_AXIS );
+ ::chart::PropertyHelper::setPropertyValueDefault< double >( aMap, PROP_AXIS_TEXT_ROTATION, 0.0 );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_TEXT_BREAK, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_TEXT_OVERLAP, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_TEXT_STACKED, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_TEXT_ARRANGE_ORDER, css::chart::ChartAxisArrangeOrderType_AUTO );
+
+ float fDefaultCharHeight = 10.0;
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight );
+
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aMap, PROP_AXIS_MAJOR_TICKMARKS, 2 /* CHAXIS_MARK_OUTER */ );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aMap, PROP_AXIS_MINOR_TICKMARKS, 0 /* CHAXIS_MARK_NONE */ );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_MARK_POSITION, css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_DISPLAY_UNITS, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_AXIS_TRY_STAGGERING_FIRST, false );
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+} // namespace chart
+
+namespace
+{
+::cppu::OPropertyArrayHelper& StaticAxisInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+std::vector< rtl::Reference< ::chart::GridProperties > > lcl_CloneSubGrids(
+ const std::vector< rtl::Reference< ::chart::GridProperties > > & rSource )
+{
+ std::vector< rtl::Reference< ::chart::GridProperties > > aDestination;
+ aDestination.reserve( rSource.size());
+ for( rtl::Reference< ::chart::GridProperties > const & i : rSource )
+ {
+ aDestination.push_back(new ::chart::GridProperties(*i));
+ }
+ return aDestination;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+Axis::Axis() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_aScaleData( AxisHelper::createDefaultScale() ),
+ m_xGrid( new GridProperties() )
+{
+ osl_atomic_increment(&m_refCount);
+ setFastPropertyValue_NoBroadcast(
+ ::chart::LinePropertiesHelper::PROP_LINE_COLOR, uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30
+
+ if( m_xGrid.is())
+ ModifyListenerHelper::addListener( m_xGrid, m_xModifyEventForwarder );
+ if( m_aScaleData.Categories.is())
+ ModifyListenerHelper::addListener( m_aScaleData.Categories, m_xModifyEventForwarder );
+
+ AllocateSubGrids();
+ osl_atomic_decrement(&m_refCount);
+}
+
+Axis::Axis( const Axis & rOther ) :
+ impl::Axis_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_aScaleData( rOther.m_aScaleData )
+{
+ if (rOther.m_xGrid)
+ m_xGrid = new ::chart::GridProperties(*rOther.m_xGrid);
+ if( m_xGrid.is())
+ ModifyListenerHelper::addListener( m_xGrid, m_xModifyEventForwarder );
+
+ if( m_aScaleData.Categories.is())
+ ModifyListenerHelper::addListener( m_aScaleData.Categories, m_xModifyEventForwarder );
+
+ if( !rOther.m_aSubGridProperties.empty() )
+ m_aSubGridProperties = lcl_CloneSubGrids( rOther.m_aSubGridProperties );
+ ModifyListenerHelper::addListenerToAllElements( m_aSubGridProperties, m_xModifyEventForwarder );
+
+ if ( rOther.m_xTitle )
+ m_xTitle = new Title( *rOther.m_xTitle );
+ if( m_xTitle.is())
+ ModifyListenerHelper::addListener( m_xTitle, m_xModifyEventForwarder );
+}
+
+// late initialization to call after copy-constructing
+void Axis::Init()
+{
+ if( m_aScaleData.Categories.is())
+ EventListenerHelper::addListener( m_aScaleData.Categories, this );
+}
+
+Axis::~Axis()
+{
+ try
+ {
+ ModifyListenerHelper::removeListener( m_xGrid, m_xModifyEventForwarder );
+ ModifyListenerHelper::removeListenerFromAllElements( m_aSubGridProperties, m_xModifyEventForwarder );
+ ModifyListenerHelper::removeListener( m_xTitle, m_xModifyEventForwarder );
+ if( m_aScaleData.Categories.is())
+ {
+ ModifyListenerHelper::removeListener( m_aScaleData.Categories, m_xModifyEventForwarder );
+ m_aScaleData.Categories.clear();
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ m_aSubGridProperties.clear();
+ m_xGrid = nullptr;
+ m_xTitle = nullptr;
+}
+
+void Axis::AllocateSubGrids()
+{
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ Reference< lang::XEventListener > xEventListener;
+ std::vector< rtl::Reference< GridProperties > > aOldBroadcasters;
+ std::vector< rtl::Reference< GridProperties > > aNewBroadcasters;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ xEventListener = this;
+
+ sal_Int32 nNewSubIncCount = m_aScaleData.IncrementData.SubIncrements.getLength();
+ sal_Int32 nOldSubIncCount = m_aSubGridProperties.size();
+
+ if( nOldSubIncCount > nNewSubIncCount )
+ {
+ // remove superfluous entries
+ for( sal_Int32 i = nNewSubIncCount; i < nOldSubIncCount; ++i )
+ aOldBroadcasters.push_back( m_aSubGridProperties[ i ] );
+ m_aSubGridProperties.resize( nNewSubIncCount );
+ }
+ else if( nOldSubIncCount < nNewSubIncCount )
+ {
+ m_aSubGridProperties.resize( nNewSubIncCount );
+
+ // allocate new entries
+ for( sal_Int32 i = nOldSubIncCount; i < nNewSubIncCount; ++i )
+ {
+ m_aSubGridProperties[ i ] = new GridProperties();
+ LinePropertiesHelper::SetLineInvisible( m_aSubGridProperties[ i ] );
+ LinePropertiesHelper::SetLineColor( m_aSubGridProperties[ i ], static_cast<sal_Int32>(0xdddddd) ); //gray2
+ aNewBroadcasters.push_back( m_aSubGridProperties[ i ] );
+ }
+ }
+ }
+ //don't keep the mutex locked while calling out
+ for (auto const& oldBroadcaster : aOldBroadcasters)
+ ModifyListenerHelper::removeListener(oldBroadcaster, xModifyEventForwarder );
+ for (auto const& newBroadcaster : aNewBroadcasters)
+ ModifyListenerHelper::addListener( newBroadcaster, xModifyEventForwarder );
+}
+
+// ____ XAxis ____
+void SAL_CALL Axis::setScaleData( const chart2::ScaleData& rScaleData )
+{
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ Reference< lang::XEventListener > xEventListener;
+ Reference< chart2::data::XLabeledDataSequence > xOldCategories;
+ Reference< chart2::data::XLabeledDataSequence > xNewCategories = rScaleData.Categories;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ xEventListener = this;
+ xOldCategories = m_aScaleData.Categories;
+ m_aScaleData = rScaleData;
+ }
+ AllocateSubGrids();
+
+ //don't keep the mutex locked while calling out
+ if( xOldCategories.is() && xOldCategories != xNewCategories )
+ {
+ ModifyListenerHelper::removeListener( xOldCategories, xModifyEventForwarder );
+ EventListenerHelper::removeListener( xOldCategories, xEventListener );
+ }
+ if( xNewCategories.is() && xOldCategories != xNewCategories )
+ {
+ ModifyListenerHelper::addListener( xNewCategories, m_xModifyEventForwarder );
+ EventListenerHelper::addListener( xNewCategories, xEventListener );
+ }
+ fireModifyEvent();
+}
+
+chart2::ScaleData SAL_CALL Axis::getScaleData()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_aScaleData;
+}
+
+Reference< beans::XPropertySet > SAL_CALL Axis::getGridProperties()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xGrid;
+}
+rtl::Reference< ::chart::GridProperties > Axis::getGridProperties2()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xGrid;
+}
+Sequence< Reference< beans::XPropertySet > > SAL_CALL Axis::getSubGridProperties()
+{
+ MutexGuard aGuard( m_aMutex );
+ return comphelper::containerToSequence<Reference< beans::XPropertySet >>(m_aSubGridProperties);
+}
+
+std::vector< rtl::Reference< GridProperties > > Axis::getSubGridProperties2()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_aSubGridProperties;
+}
+
+Sequence< Reference< beans::XPropertySet > > SAL_CALL Axis::getSubTickProperties()
+{
+ OSL_FAIL( "Not implemented yet" );
+ return Sequence< Reference< beans::XPropertySet > >();
+}
+
+// ____ XTitled ____
+Reference< chart2::XTitle > SAL_CALL Axis::getTitleObject()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xTitle;
+}
+
+rtl::Reference< Title > Axis::getTitleObject2() const
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xTitle;
+}
+
+void SAL_CALL Axis::setTitleObject( const Reference< chart2::XTitle >& xNewTitle )
+{
+ rtl::Reference<Title> xTitle = dynamic_cast<Title*>(xNewTitle.get());
+ assert(!xNewTitle || xTitle);
+ setTitleObject(xTitle);
+}
+
+void Axis::setTitleObject( const rtl::Reference< Title >& xNewTitle )
+{
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ rtl::Reference< Title > xOldTitle;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xOldTitle = m_xTitle;
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ m_xTitle = xNewTitle;
+ }
+
+ //don't keep the mutex locked while calling out
+ if( xOldTitle.is() && xOldTitle != xNewTitle )
+ ModifyListenerHelper::removeListener( xOldTitle, xModifyEventForwarder );
+ if( xNewTitle.is() && xOldTitle != xNewTitle )
+ ModifyListenerHelper::addListener( xNewTitle, xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+// ____ XCloneable ____
+Reference< util::XCloneable > SAL_CALL Axis::createClone()
+{
+ rtl::Reference<Axis> pNewAxis( new Axis( *this ));
+ // do initialization that uses uno references to the clone
+ pNewAxis->Init();
+ return pNewAxis;
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL Axis::addModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL Axis::removeModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL Axis::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL Axis::disposing( const lang::EventObject& Source )
+{
+ if( Source.Source == m_aScaleData.Categories )
+ m_aScaleData.Categories = nullptr;
+}
+
+// ____ OPropertySet ____
+void Axis::firePropertyChangeEvent()
+{
+ fireModifyEvent();
+}
+
+void Axis::fireModifyEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+// ____ OPropertySet ____
+void Axis::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticAxisDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL Axis::getInfoHelper()
+{
+ return StaticAxisInfoHelper();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL Axis::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticAxisInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+using impl::Axis_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( Axis, Axis_Base, ::property::OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( Axis, Axis_Base, ::property::OPropertySet )
+
+// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
+OUString SAL_CALL Axis::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.Axis";
+}
+
+sal_Bool SAL_CALL Axis::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL Axis::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart2.Axis",
+ "com.sun.star.beans.PropertySet" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_Axis_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::Axis);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/BaseCoordinateSystem.cxx b/chart2/source/model/main/BaseCoordinateSystem.cxx
new file mode 100644
index 0000000000..8af32fa096
--- /dev/null
+++ b/chart2/source/model/main/BaseCoordinateSystem.cxx
@@ -0,0 +1,387 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <BaseCoordinateSystem.hxx>
+#include <PropertyHelper.hxx>
+#include <UserDefinedProperties.hxx>
+#include <CloneHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <Axis.hxx>
+#include <ChartType.hxx>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <o3tl/safeint.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+enum
+{
+ PROP_COORDINATESYSTEM_SWAPXANDYAXIS
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "SwapXAndYAxis",
+ PROP_COORDINATESYSTEM_SWAPXANDYAXIS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+}
+
+const ::chart::tPropertyValueMap & StaticCooSysDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_COORDINATESYSTEM_SWAPXANDYAXIS, false );
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& StaticCooSysInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+BaseCoordinateSystem::BaseCoordinateSystem(
+ sal_Int32 nDimensionCount /* = 2 */ ) :
+ m_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_nDimensionCount( nDimensionCount )
+ {
+ m_aAllAxis.resize( m_nDimensionCount );
+ for( sal_Int32 nN=0; nN<m_nDimensionCount; nN++ )
+ {
+ m_aAllAxis[nN].resize( 1 );
+ rtl::Reference< Axis > xAxis( new Axis );
+ m_aAllAxis[nN][0] = xAxis;
+
+ ModifyListenerHelper::addListenerToAllElements( m_aAllAxis[nN], m_xModifyEventForwarder );
+ chart2::ScaleData aScaleData( xAxis->getScaleData() );
+ if(nN==0)
+ {
+ aScaleData.AxisType = chart2::AxisType::CATEGORY;
+ }
+ else if( nN==1)
+ {
+ aScaleData.AxisType = chart2::AxisType::REALNUMBER;
+ }
+ else if( nN==2)
+ {
+ aScaleData.AxisType = chart2::AxisType::SERIES;
+ }
+ xAxis->setScaleData( aScaleData );
+ }
+
+ setFastPropertyValue_NoBroadcast( PROP_COORDINATESYSTEM_SWAPXANDYAXIS, uno::Any( false ));
+}
+
+// explicit
+BaseCoordinateSystem::BaseCoordinateSystem(
+ const BaseCoordinateSystem & rSource ) :
+ impl::BaseCoordinateSystem_Base(rSource),
+ ::property::OPropertySet( rSource ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_nDimensionCount( rSource.m_nDimensionCount )
+{
+ m_aAllAxis.resize(rSource.m_aAllAxis.size());
+ tAxisVecVecType::size_type nN=0;
+ for( nN=0; nN<m_aAllAxis.size(); nN++ )
+ CloneHelper::CloneRefVector( rSource.m_aAllAxis[nN], m_aAllAxis[nN] );
+ for (const auto & rxChartType : rSource.m_aChartTypes)
+ m_aChartTypes.push_back(rxChartType->cloneChartType());
+
+ for( nN=0; nN<m_aAllAxis.size(); nN++ )
+ ModifyListenerHelper::addListenerToAllElements( m_aAllAxis[nN], m_xModifyEventForwarder );
+ for (const auto & rxChartType : m_aChartTypes)
+ rxChartType->addModifyListener( m_xModifyEventForwarder );
+}
+
+BaseCoordinateSystem::~BaseCoordinateSystem()
+{
+ try
+ {
+ for(const tAxisVecVecType::value_type & i : m_aAllAxis)
+ ModifyListenerHelper::removeListenerFromAllElements( i, m_xModifyEventForwarder );
+ for (const auto & rxChartType : m_aChartTypes)
+ rxChartType->removeModifyListener( m_xModifyEventForwarder );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+}
+
+// ____ XCoordinateSystem ____
+sal_Int32 SAL_CALL BaseCoordinateSystem::getDimension()
+{
+ return m_nDimensionCount;
+}
+
+void SAL_CALL BaseCoordinateSystem::setAxisByDimension(
+ sal_Int32 nDimensionIndex,
+ const Reference< chart2::XAxis >& xAxis,
+ sal_Int32 nIndex )
+{
+ if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
+ throw lang::IndexOutOfBoundsException();
+
+ if( nIndex < 0 )
+ throw lang::IndexOutOfBoundsException();
+
+ assert(!xAxis || dynamic_cast<Axis*>(xAxis.get()));
+
+ if( m_aAllAxis[ nDimensionIndex ].size() < o3tl::make_unsigned( nIndex+1 ))
+ {
+ m_aAllAxis[ nDimensionIndex ].resize( nIndex+1 );
+ m_aAllAxis[ nDimensionIndex ][nIndex] = nullptr;
+ }
+
+ rtl::Reference< Axis > xOldAxis( m_aAllAxis[ nDimensionIndex ][nIndex] );
+ if( xOldAxis.is())
+ ModifyListenerHelper::removeListener( xOldAxis, m_xModifyEventForwarder );
+ m_aAllAxis[ nDimensionIndex ][nIndex] = dynamic_cast<Axis*>(xAxis.get());
+ if( xAxis.is())
+ ModifyListenerHelper::addListener( xAxis, m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+void BaseCoordinateSystem::setAxisByDimension(
+ sal_Int32 nDimensionIndex,
+ const rtl::Reference< Axis >& xAxis,
+ sal_Int32 nIndex )
+{
+ if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
+ throw lang::IndexOutOfBoundsException();
+
+ if( nIndex < 0 )
+ throw lang::IndexOutOfBoundsException();
+
+ if( m_aAllAxis[ nDimensionIndex ].size() < o3tl::make_unsigned( nIndex+1 ))
+ {
+ m_aAllAxis[ nDimensionIndex ].resize( nIndex+1 );
+ m_aAllAxis[ nDimensionIndex ][nIndex] = nullptr;
+ }
+
+ rtl::Reference< Axis > xOldAxis( m_aAllAxis[ nDimensionIndex ][nIndex] );
+ if( xOldAxis.is())
+ ModifyListenerHelper::removeListener( xOldAxis, m_xModifyEventForwarder );
+ m_aAllAxis[ nDimensionIndex ][nIndex] = xAxis;
+ if( xAxis.is())
+ ModifyListenerHelper::addListener( xAxis, m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+Reference< chart2::XAxis > SAL_CALL BaseCoordinateSystem::getAxisByDimension(
+ sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
+ throw lang::IndexOutOfBoundsException();
+
+ OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( getDimension()));
+
+ if( nAxisIndex < 0 || nAxisIndex > getMaximumAxisIndexByDimension(nDimensionIndex) )
+ throw lang::IndexOutOfBoundsException();
+
+ return m_aAllAxis[ nDimensionIndex ][nAxisIndex];
+}
+
+const rtl::Reference< Axis > & BaseCoordinateSystem::getAxisByDimension2(
+ sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ if( nDimensionIndex < 0 || nDimensionIndex >= m_nDimensionCount )
+ throw lang::IndexOutOfBoundsException();
+
+ OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( m_nDimensionCount));
+
+ if( nAxisIndex < 0 || o3tl::make_unsigned(nAxisIndex) > m_aAllAxis[ nDimensionIndex ].size() )
+ throw lang::IndexOutOfBoundsException();
+
+ return m_aAllAxis[ nDimensionIndex ][nAxisIndex];
+}
+
+sal_Int32 SAL_CALL BaseCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex )
+{
+ if( nDimensionIndex < 0 || nDimensionIndex >= getDimension() )
+ throw lang::IndexOutOfBoundsException();
+
+ OSL_ASSERT( m_aAllAxis.size() == static_cast< size_t >( getDimension()));
+
+ sal_Int32 nRet = m_aAllAxis[ nDimensionIndex ].size();
+ if(nRet)
+ nRet-=1;
+
+ return nRet;
+}
+
+// ____ XChartTypeContainer ____
+void SAL_CALL BaseCoordinateSystem::addChartType( const Reference< chart2::XChartType >& aChartType )
+{
+ auto pChartType = dynamic_cast<ChartType*>(aChartType.get());
+ assert(pChartType);
+
+ if( std::find( m_aChartTypes.begin(), m_aChartTypes.end(), pChartType )
+ != m_aChartTypes.end())
+ throw lang::IllegalArgumentException("type not found", static_cast<cppu::OWeakObject*>(this), 1);
+
+ m_aChartTypes.push_back( pChartType );
+ ModifyListenerHelper::addListener( aChartType, m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+void SAL_CALL BaseCoordinateSystem::removeChartType( const Reference< chart2::XChartType >& aChartType )
+{
+ auto pChartType = dynamic_cast<ChartType*>(aChartType.get());
+ assert(pChartType);
+ auto aIt( std::find( m_aChartTypes.begin(), m_aChartTypes.end(), pChartType ));
+ if( aIt == m_aChartTypes.end())
+ throw container::NoSuchElementException(
+ "The given chart type is no element of the container",
+ static_cast< uno::XWeak * >( this ));
+
+ m_aChartTypes.erase( aIt );
+ ModifyListenerHelper::removeListener( aChartType, m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+Sequence< Reference< chart2::XChartType > > SAL_CALL BaseCoordinateSystem::getChartTypes()
+{
+ return comphelper::containerToSequence< Reference< chart2::XChartType > >( m_aChartTypes );
+}
+
+void SAL_CALL BaseCoordinateSystem::setChartTypes( const Sequence< Reference< chart2::XChartType > >& aChartTypes )
+{
+ for (auto const & aChartType : m_aChartTypes)
+ aChartType->removeModifyListener( m_xModifyEventForwarder );
+ m_aChartTypes.clear();
+ for (auto const & aChartType : aChartTypes)
+ {
+ auto pChartType = dynamic_cast<ChartType*>(aChartType.get());
+ assert(pChartType);
+ m_aChartTypes.push_back(pChartType);
+ pChartType->addModifyListener( m_xModifyEventForwarder );
+ }
+ fireModifyEvent();
+}
+
+void BaseCoordinateSystem::setChartTypes( const std::vector< rtl::Reference< ChartType > >& aChartTypes )
+{
+ for (auto const & aChartType : m_aChartTypes)
+ aChartType->removeModifyListener( m_xModifyEventForwarder );
+ m_aChartTypes = aChartTypes;
+ for (auto const & aChartType : m_aChartTypes)
+ aChartType->addModifyListener( m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL BaseCoordinateSystem::addModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL BaseCoordinateSystem::removeModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL BaseCoordinateSystem::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL BaseCoordinateSystem::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void BaseCoordinateSystem::firePropertyChangeEvent()
+{
+ fireModifyEvent();
+}
+
+void BaseCoordinateSystem::fireModifyEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+// ____ OPropertySet ____
+void BaseCoordinateSystem::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticCooSysDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+// ____ OPropertySet ____
+::cppu::IPropertyArrayHelper & SAL_CALL BaseCoordinateSystem::getInfoHelper()
+{
+ return StaticCooSysInfoHelper();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL BaseCoordinateSystem::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticCooSysInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+using impl::BaseCoordinateSystem_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( BaseCoordinateSystem, BaseCoordinateSystem_Base, ::property::OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( BaseCoordinateSystem, BaseCoordinateSystem_Base, ::property::OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/CartesianCoordinateSystem.cxx b/chart2/source/model/main/CartesianCoordinateSystem.cxx
new file mode 100644
index 0000000000..1f1320d8ae
--- /dev/null
+++ b/chart2/source/model/main/CartesianCoordinateSystem.cxx
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <CartesianCoordinateSystem.hxx>
+#include <servicenames_coosystems.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace
+{
+
+constexpr OUString CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME = u"com.sun.star.chart2.CoordinateSystems.Cartesian"_ustr;
+
+}
+
+namespace chart
+{
+
+// explicit
+CartesianCoordinateSystem::CartesianCoordinateSystem(
+ sal_Int32 nDimensionCount /* = 2 */ ) :
+ BaseCoordinateSystem( nDimensionCount )
+{}
+
+CartesianCoordinateSystem::CartesianCoordinateSystem(
+ const CartesianCoordinateSystem & rSource ) :
+ BaseCoordinateSystem( rSource )
+{}
+
+CartesianCoordinateSystem::~CartesianCoordinateSystem()
+{}
+
+// ____ XCoordinateSystem ____
+OUString SAL_CALL CartesianCoordinateSystem::getCoordinateSystemType()
+{
+ return CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME;
+}
+
+OUString SAL_CALL CartesianCoordinateSystem::getViewServiceName()
+{
+ return CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME;
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL CartesianCoordinateSystem::createClone()
+{
+ return Reference< util::XCloneable >( new CartesianCoordinateSystem( *this ));
+}
+
+// ____ XServiceInfo ____
+OUString SAL_CALL CartesianCoordinateSystem::getImplementationName()
+{
+ return "com.sun.star.comp.chart.CartesianCoordinateSystem";
+}
+
+sal_Bool SAL_CALL CartesianCoordinateSystem::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL CartesianCoordinateSystem::getSupportedServiceNames()
+{
+ return { CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME };
+}
+
+// ==== CartesianCoordinateSystem2d ====
+
+CartesianCoordinateSystem2d::CartesianCoordinateSystem2d() :
+ CartesianCoordinateSystem( 2 )
+{}
+
+CartesianCoordinateSystem2d::~CartesianCoordinateSystem2d()
+{}
+
+// ____ XServiceInfo ____
+OUString SAL_CALL CartesianCoordinateSystem2d::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.CartesianCoordinateSystem2d";
+}
+
+sal_Bool SAL_CALL CartesianCoordinateSystem2d::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL CartesianCoordinateSystem2d::getSupportedServiceNames()
+{
+ return {
+ CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME,
+ "com.sun.star.chart2.CartesianCoordinateSystem2d"
+ };
+}
+
+// ==== CartesianCoordinateSystem3d ====
+
+CartesianCoordinateSystem3d::CartesianCoordinateSystem3d() :
+ CartesianCoordinateSystem( 3 )
+{}
+
+CartesianCoordinateSystem3d::~CartesianCoordinateSystem3d()
+{}
+
+// ____ XServiceInfo ____
+OUString SAL_CALL CartesianCoordinateSystem3d::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.CartesianCoordinateSystem3d";
+}
+
+sal_Bool SAL_CALL CartesianCoordinateSystem3d::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL CartesianCoordinateSystem3d::getSupportedServiceNames()
+{
+ return {
+ CHART2_COOSYSTEM_CARTESIAN_SERVICE_NAME,
+ "com.sun.star.chart2.CartesianCoordinateSystem3d"
+ };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_CartesianCoordinateSystem2d_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::CartesianCoordinateSystem2d);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_CartesianCoordinateSystem3d_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::CartesianCoordinateSystem3d);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/ChartModel.cxx b/chart2/source/model/main/ChartModel.cxx
new file mode 100644
index 0000000000..19fccff373
--- /dev/null
+++ b/chart2/source/model/main/ChartModel.cxx
@@ -0,0 +1,1339 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartModel.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <servicenames.hxx>
+#include <DataSource.hxx>
+#include <DataSourceHelper.hxx>
+#include <ChartModelHelper.hxx>
+#include <DisposeHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <InternalDataProvider.hxx>
+#include <ObjectIdentifier.hxx>
+#include "PageBackground.hxx"
+#include <CloneHelper.hxx>
+#include <NameContainer.hxx>
+#include "UndoManager.hxx"
+#include <ChartView.hxx>
+#include <PopupRequest.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <RangeHighlighter.hxx>
+#include <Diagram.hxx>
+#include <comphelper/dumpxmltostring.hxx>
+
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <svl/numformat.hxx>
+#include <svl/numuno.hxx>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/embed/EmbedMapUnits.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/document/DocumentProperties.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+
+#include <sal/log.hxx>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+#include <libxml/xmlwriter.h>
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::osl::MutexGuard;
+
+using namespace ::com::sun::star;
+using namespace ::apphelper;
+using namespace ::chart::CloneHelper;
+
+namespace
+{
+constexpr OUString lcl_aGDIMetaFileMIMEType(
+ u"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""_ustr);
+constexpr OUString lcl_aGDIMetaFileMIMETypeHighContrast(
+ u"application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\""_ustr);
+
+} // anonymous namespace
+
+// ChartModel Constructor and Destructor
+
+namespace chart
+{
+
+ChartModel::ChartModel(uno::Reference<uno::XComponentContext > xContext)
+ : m_aLifeTimeManager( this, this )
+ , m_bReadOnly( false )
+ , m_bModified( false )
+ , m_nInLoad(0)
+ , m_bUpdateNotificationsPending(false)
+ , mbTimeBased(false)
+ , m_aControllers( m_aModelMutex )
+ , m_nControllerLockCount(0)
+ , m_xContext(std::move( xContext ))
+ , m_aVisualAreaSize( ChartModelHelper::getDefaultPageSize() )
+ , m_xPageBackground( new PageBackground )
+ , m_xXMLNamespaceMap( new NameContainer() )
+ , mnStart(0)
+ , mnEnd(0)
+{
+ osl_atomic_increment(&m_refCount);
+ {
+ m_xOldModelAgg.set(
+ m_xContext->getServiceManager()->createInstanceWithContext(
+ CHART_CHARTAPIWRAPPER_SERVICE_NAME,
+ m_xContext ), uno::UNO_QUERY_THROW );
+ m_xOldModelAgg->setDelegator( *this );
+ }
+
+ {
+ m_xPageBackground->addModifyListener( this );
+ m_xChartTypeManager = new ::chart::ChartTypeManager( m_xContext );
+ }
+ osl_atomic_decrement(&m_refCount);
+}
+
+ChartModel::ChartModel( const ChartModel & rOther )
+ : impl::ChartModel_Base(rOther)
+ , m_aLifeTimeManager( this, this )
+ , m_bReadOnly( rOther.m_bReadOnly )
+ , m_bModified( rOther.m_bModified )
+ , m_nInLoad(0)
+ , m_bUpdateNotificationsPending(false)
+ , mbTimeBased(rOther.mbTimeBased)
+ , m_aResource( rOther.m_aResource )
+ , m_aMediaDescriptor( rOther.m_aMediaDescriptor )
+ , m_aControllers( m_aModelMutex )
+ , m_nControllerLockCount(0)
+ , m_xContext( rOther.m_xContext )
+ // @note: the old model aggregate must not be shared with other models if it
+ // is, you get mutex deadlocks
+ //, m_xOldModelAgg( nullptr ) //rOther.m_xOldModelAgg )
+ // m_xStorage( nullptr ) //rOther.m_xStorage )
+ , m_aVisualAreaSize( rOther.m_aVisualAreaSize )
+ , m_aGraphicObjectVector( rOther.m_aGraphicObjectVector )
+ , m_xDataProvider( rOther.m_xDataProvider )
+ , m_xInternalDataProvider( rOther.m_xInternalDataProvider )
+ , mnStart(rOther.mnStart)
+ , mnEnd(rOther.mnEnd)
+{
+ osl_atomic_increment(&m_refCount);
+ {
+ m_xOldModelAgg.set(
+ m_xContext->getServiceManager()->createInstanceWithContext(
+ CHART_CHARTAPIWRAPPER_SERVICE_NAME,
+ m_xContext ), uno::UNO_QUERY_THROW );
+ m_xOldModelAgg->setDelegator( *this );
+
+ Reference< util::XModifyListener > xListener;
+ rtl::Reference< Title > xNewTitle;
+ if ( rOther.m_xTitle )
+ xNewTitle = new Title(*rOther.m_xTitle);
+ rtl::Reference< ::chart::Diagram > xNewDiagram;
+ if (rOther.m_xDiagram.is())
+ xNewDiagram = new ::chart::Diagram( *rOther.m_xDiagram );
+ rtl::Reference< ::chart::PageBackground > xNewPageBackground = new PageBackground( *rOther.m_xPageBackground );
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager; // does not implement XCloneable
+ rtl::Reference< ::chart::NameContainer > xXMLNamespaceMap = new NameContainer( *rOther.m_xXMLNamespaceMap );
+
+ {
+ MutexGuard aGuard( m_aModelMutex );
+ xListener = this;
+ m_xTitle = xNewTitle;
+ m_xDiagram = xNewDiagram;
+ m_xPageBackground = xNewPageBackground;
+ m_xChartTypeManager = xChartTypeManager;
+ m_xXMLNamespaceMap = xXMLNamespaceMap;
+ }
+
+ ModifyListenerHelper::addListener( xNewTitle, xListener );
+ if( xNewDiagram && xListener)
+ xNewDiagram->addModifyListener( xListener );
+ if( xNewPageBackground && xListener)
+ xNewPageBackground->addModifyListener( xListener );
+ xListener.clear();
+ }
+ osl_atomic_decrement(&m_refCount);
+}
+
+ChartModel::~ChartModel()
+{
+ if( m_xOldModelAgg.is())
+ m_xOldModelAgg->setDelegator( nullptr );
+}
+
+void SAL_CALL ChartModel::initialize( const Sequence< Any >& /*rArguments*/ )
+{
+ //#i113722# avoid duplicate creation
+
+ //maybe additional todo?:
+ //support argument "EmbeddedObject"?
+ //support argument "EmbeddedScriptSupport"?
+ //support argument "DocumentRecoverySupport"?
+}
+
+ChartView* ChartModel::getChartView() const
+{
+ return mxChartView.get();
+}
+
+// private methods
+
+OUString ChartModel::impl_g_getLocation()
+{
+
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ return OUString(); //behave passive if already disposed or closed or throw exception @todo?
+ //mutex is acquired
+ return m_aResource;
+}
+
+bool ChartModel::impl_isControllerConnected( const uno::Reference< frame::XController >& xController )
+{
+ try
+ {
+ std::vector< uno::Reference<uno::XInterface> > aSeq = m_aControllers.getElements();
+ for( const auto & r : aSeq )
+ {
+ if( r == xController )
+ return true;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ return false;
+}
+
+uno::Reference< frame::XController > ChartModel::impl_getCurrentController()
+{
+ //@todo? hold only weak references to controllers
+
+ // get the last active controller of this model
+ if( m_xCurrentController.is() )
+ return m_xCurrentController;
+
+ // get the first controller of this model
+ if( m_aControllers.getLength() )
+ {
+ uno::Reference<uno::XInterface> xI = m_aControllers.getInterface(0);
+ return uno::Reference<frame::XController>( xI, uno::UNO_QUERY );
+ }
+
+ //return nothing if no controllers are connected at all
+ return uno::Reference< frame::XController > ();
+}
+
+void ChartModel::impl_notifyCloseListeners()
+{
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ if( m_aLifeTimeManager.m_aCloseListeners.getLength(aGuard) )
+ {
+ lang::EventObject aEvent( static_cast< lang::XComponent*>(this) );
+ m_aLifeTimeManager.m_aCloseListeners.notifyEach(aGuard, &util::XCloseListener::notifyClosing, aEvent);
+ }
+}
+
+void ChartModel::impl_adjustAdditionalShapesPositionAndSize( const awt::Size& aVisualAreaSize )
+{
+ uno::Reference< beans::XPropertySet > xProperties( static_cast< ::cppu::OWeakObject* >( this ), uno::UNO_QUERY );
+ if ( !xProperties.is() )
+ return;
+
+ uno::Reference< drawing::XShapes > xShapes;
+ xProperties->getPropertyValue( "AdditionalShapes" ) >>= xShapes;
+ if ( !xShapes.is() )
+ return;
+
+ sal_Int32 nCount = xShapes->getCount();
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ Reference< drawing::XShape > xShape;
+ if ( xShapes->getByIndex( i ) >>= xShape )
+ {
+ if ( xShape.is() )
+ {
+ awt::Point aPos( xShape->getPosition() );
+ awt::Size aSize( xShape->getSize() );
+
+ double fWidth = static_cast< double >( aVisualAreaSize.Width ) / m_aVisualAreaSize.Width;
+ double fHeight = static_cast< double >( aVisualAreaSize.Height ) / m_aVisualAreaSize.Height;
+
+ aPos.X = static_cast< tools::Long >( aPos.X * fWidth );
+ aPos.Y = static_cast< tools::Long >( aPos.Y * fHeight );
+ aSize.Width = static_cast< tools::Long >( aSize.Width * fWidth );
+ aSize.Height = static_cast< tools::Long >( aSize.Height * fHeight );
+
+ xShape->setPosition( aPos );
+ xShape->setSize( aSize );
+ }
+ }
+ }
+}
+
+// lang::XServiceInfo
+
+OUString SAL_CALL ChartModel::getImplementationName()
+{
+ return CHART_MODEL_SERVICE_IMPLEMENTATION_NAME;
+}
+
+sal_Bool SAL_CALL ChartModel::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ChartModel::getSupportedServiceNames()
+{
+ return {
+ CHART_MODEL_SERVICE_NAME,
+ "com.sun.star.document.OfficeDocument",
+ "com.sun.star.chart.ChartDocument"
+ };
+}
+
+// frame::XModel (required interface)
+
+sal_Bool SAL_CALL ChartModel::attachResource( const OUString& rURL
+ , const uno::Sequence< beans::PropertyValue >& rMediaDescriptor )
+{
+ /*
+ The method attachResource() is used by the frame loader implementations
+ to inform the model about its URL and MediaDescriptor.
+ */
+
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ return false; //behave passive if already disposed or closed or throw exception @todo?
+ //mutex is acquired
+
+ if(!m_aResource.isEmpty())//we have a resource already //@todo? or is setting a new resource allowed?
+ return false;
+ m_aResource = rURL;
+ m_aMediaDescriptor = rMediaDescriptor;
+
+ //@todo ? check rURL ??
+ //@todo ? evaluate m_aMediaDescriptor;
+ //@todo ? ... ??? --> nothing, this method is only for setting information
+
+ return true;
+}
+
+OUString SAL_CALL ChartModel::getURL()
+{
+ return impl_g_getLocation();
+}
+
+uno::Sequence< beans::PropertyValue > SAL_CALL ChartModel::getArgs()
+{
+ /*
+ The method getArgs() returns a sequence of property values
+ that report the resource description according to com.sun.star.document.MediaDescriptor,
+ specified on loading or saving with storeAsURL.
+ */
+
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ return uno::Sequence< beans::PropertyValue >(); //behave passive if already disposed or closed or throw exception @todo?
+ //mutex is acquired
+
+ return m_aMediaDescriptor;
+}
+
+void SAL_CALL ChartModel::connectController( const uno::Reference< frame::XController >& xController )
+{
+ //@todo? this method is declared as oneway -> ...?
+
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ return ; //behave passive if already disposed or closed
+ //mutex is acquired
+
+ //--add controller
+ m_aControllers.addInterface(xController);
+}
+
+void SAL_CALL ChartModel::disconnectController( const uno::Reference< frame::XController >& xController )
+{
+ //@todo? this method is declared as oneway -> ...?
+
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ return; //behave passive if already disposed or closed
+
+ //--remove controller
+ m_aControllers.removeInterface(xController);
+
+ //case: current controller is disconnected:
+ if( m_xCurrentController == xController )
+ m_xCurrentController.clear();
+
+ if (m_xRangeHighlighter)
+ {
+ m_xRangeHighlighter->dispose();
+ m_xRangeHighlighter.clear();
+ }
+ DisposeHelper::DisposeAndClear(m_xPopupRequest);
+}
+
+void SAL_CALL ChartModel::lockControllers()
+{
+ /*
+ suspends some notifications to the controllers which are used for display updates.
+
+ The calls to lockControllers() and unlockControllers() may be nested
+ and even overlapping, but they must be in pairs. While there is at least one lock
+ remaining, some notifications for display updates are not broadcasted.
+ */
+
+ //@todo? this method is declared as oneway -> ...?
+
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ return; //behave passive if already disposed or closed or throw exception @todo?
+ ++m_nControllerLockCount;
+}
+
+void SAL_CALL ChartModel::unlockControllers()
+{
+ /*
+ resumes the notifications which were suspended by lockControllers() .
+
+ The calls to lockControllers() and unlockControllers() may be nested
+ and even overlapping, but they must be in pairs. While there is at least one lock
+ remaining, some notifications for display updates are not broadcasted.
+ */
+
+ //@todo? this method is declared as oneway -> ...?
+
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ return; //behave passive if already disposed or closed or throw exception @todo?
+ if( m_nControllerLockCount == 0 )
+ {
+ SAL_WARN("chart2", "ChartModel: unlockControllers called with m_nControllerLockCount == 0" );
+ return;
+ }
+ --m_nControllerLockCount;
+ if( m_nControllerLockCount == 0 && m_bUpdateNotificationsPending )
+ {
+ aGuard.clear();
+ impl_notifyModifiedListeners();
+ }
+}
+
+sal_Bool SAL_CALL ChartModel::hasControllersLocked()
+{
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ return false; //behave passive if already disposed or closed or throw exception @todo?
+ return ( m_nControllerLockCount != 0 ) ;
+}
+
+uno::Reference< frame::XController > SAL_CALL ChartModel::getCurrentController()
+{
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ throw lang::DisposedException(
+ "getCurrentController was called on an already disposed or closed model",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ return impl_getCurrentController();
+}
+
+void SAL_CALL ChartModel::setCurrentController( const uno::Reference< frame::XController >& xController )
+{
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ throw lang::DisposedException(
+ "setCurrentController was called on an already disposed or closed model",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ //OSL_ENSURE( impl_isControllerConnected(xController), "setCurrentController is called with a Controller which is not connected" );
+ if(!impl_isControllerConnected(xController))
+ throw container::NoSuchElementException(
+ "setCurrentController is called with a Controller which is not connected",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ m_xCurrentController = xController;
+
+ if (m_xRangeHighlighter)
+ {
+ m_xRangeHighlighter->dispose();
+ m_xRangeHighlighter.clear();
+ }
+ DisposeHelper::DisposeAndClear(m_xPopupRequest);
+}
+
+uno::Reference< uno::XInterface > SAL_CALL ChartModel::getCurrentSelection()
+{
+ LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())
+ throw lang::DisposedException(
+ "getCurrentSelection was called on an already disposed or closed model",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ uno::Reference< uno::XInterface > xReturn;
+ uno::Reference< frame::XController > xController = impl_getCurrentController();
+
+ aGuard.clear();
+ if( xController.is() )
+ {
+ uno::Reference< view::XSelectionSupplier > xSelectionSupl( xController, uno::UNO_QUERY );
+ if ( xSelectionSupl.is() )
+ {
+ uno::Any aSel = xSelectionSupl->getSelection();
+ OUString aObjectCID;
+ if( aSel >>= aObjectCID )
+ xReturn.set( ObjectIdentifier::getObjectPropertySet( aObjectCID, this));
+ }
+ }
+ return xReturn;
+}
+
+// lang::XComponent (base of XModel)
+void SAL_CALL ChartModel::dispose()
+{
+ Reference< XInterface > xKeepAlive( *this );
+
+ //This object should release all resources and references in the
+ //easiest possible manner
+ //This object must notify all registered listeners using the method
+ //<member>XEventListener::disposing</member>
+
+ //hold no mutex
+ if( !m_aLifeTimeManager.dispose() )
+ return;
+
+ //--release all resources and references
+ //// @todo
+
+ if ( m_xDiagram.is() )
+ m_xDiagram->removeModifyListener( this );
+
+ if ( m_xDataProvider.is() )
+ {
+ Reference<util::XModifyBroadcaster> xModifyBroadcaster( m_xDataProvider, uno::UNO_QUERY );
+ if ( xModifyBroadcaster.is() )
+ xModifyBroadcaster->removeModifyListener( this );
+ }
+
+ m_xDataProvider.clear();
+ m_xInternalDataProvider.clear();
+ m_xNumberFormatsSupplier.clear();
+ m_xOwnNumberFormatsSupplier.clear();
+ m_xChartTypeManager.clear();
+ m_xDiagram.clear();
+ m_xTitle.clear();
+ m_xPageBackground.clear();
+ m_xXMLNamespaceMap.clear();
+
+ m_xStorage.clear();
+ // just clear, don't dispose - we're not the owner
+
+ if ( m_pUndoManager.is() )
+ m_pUndoManager->disposing();
+ m_pUndoManager.clear();
+ // that's important, since the UndoManager implementation delegates its ref counting to ourself.
+
+ if( m_xOldModelAgg.is()) // #i120828#, to release cyclic reference to ChartModel object
+ m_xOldModelAgg->setDelegator( nullptr );
+
+ m_aControllers.disposeAndClear( lang::EventObject( static_cast< cppu::OWeakObject * >( this )));
+ m_xCurrentController.clear();
+
+ if (m_xRangeHighlighter)
+ {
+ m_xRangeHighlighter->dispose();
+ m_xRangeHighlighter.clear();
+ }
+ DisposeHelper::DisposeAndClear(m_xPopupRequest);
+
+ if( m_xOldModelAgg.is())
+ m_xOldModelAgg->setDelegator( nullptr );
+}
+
+void SAL_CALL ChartModel::addEventListener( const uno::Reference< lang::XEventListener > & xListener )
+{
+ if( m_aLifeTimeManager.impl_isDisposedOrClosed() )
+ return; //behave passive if already disposed or closed
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aEventListeners.addInterface( aGuard, xListener );
+}
+
+void SAL_CALL ChartModel::removeEventListener( const uno::Reference< lang::XEventListener > & xListener )
+{
+ if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
+ return; //behave passive if already disposed or closed
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aEventListeners.removeInterface( aGuard, xListener );
+}
+
+// util::XCloseBroadcaster (base of XCloseable)
+void SAL_CALL ChartModel::addCloseListener( const uno::Reference< util::XCloseListener > & xListener )
+{
+ m_aLifeTimeManager.g_addCloseListener( xListener );
+}
+
+void SAL_CALL ChartModel::removeCloseListener( const uno::Reference< util::XCloseListener > & xListener )
+{
+ if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
+ return; //behave passive if already disposed or closed
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aCloseListeners.removeInterface( aGuard, xListener );
+}
+
+// util::XCloseable
+void SAL_CALL ChartModel::close( sal_Bool bDeliverOwnership )
+{
+ //hold no mutex
+
+ if( !m_aLifeTimeManager.g_close_startTryClose( bDeliverOwnership ) )
+ return;
+ //no mutex is acquired
+
+ // At the end of this method may we must dispose ourself ...
+ // and may nobody from outside hold a reference to us ...
+ // then it's a good idea to do that by ourself.
+ uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) );
+
+ //the listeners have had no veto
+ //check whether we self can close
+ {
+ util::CloseVetoException aVetoException(
+ "the model itself could not be closed",
+ static_cast< ::cppu::OWeakObject* >(this) );
+
+ m_aLifeTimeManager.g_close_isNeedToCancelLongLastingCalls( bDeliverOwnership, aVetoException );
+ }
+ m_aLifeTimeManager.g_close_endTryClose_doClose();
+
+ // BM @todo: is it ok to call the listeners here?
+ impl_notifyCloseListeners();
+}
+
+// lang::XTypeProvider
+uno::Sequence< uno::Type > SAL_CALL ChartModel::getTypes()
+{
+ uno::Reference< lang::XTypeProvider > xAggTypeProvider;
+ if( (m_xOldModelAgg->queryAggregation( cppu::UnoType<decltype(xAggTypeProvider)>::get()) >>= xAggTypeProvider)
+ && xAggTypeProvider.is())
+ {
+ return comphelper::concatSequences(
+ impl::ChartModel_Base::getTypes(),
+ xAggTypeProvider->getTypes());
+ }
+
+ return impl::ChartModel_Base::getTypes();
+}
+
+// document::XDocumentPropertiesSupplier
+uno::Reference< document::XDocumentProperties > SAL_CALL
+ ChartModel::getDocumentProperties()
+{
+ ::osl::MutexGuard aGuard( m_aModelMutex );
+ if ( !m_xDocumentProperties.is() )
+ {
+ m_xDocumentProperties.set( document::DocumentProperties::create( ::comphelper::getProcessComponentContext() ) );
+ }
+ return m_xDocumentProperties;
+}
+
+// document::XDocumentPropertiesSupplier
+Reference< document::XUndoManager > SAL_CALL ChartModel::getUndoManager( )
+{
+ ::osl::MutexGuard aGuard( m_aModelMutex );
+ if ( !m_pUndoManager.is() )
+ m_pUndoManager.set( new UndoManager( *this, m_aModelMutex ) );
+ return m_pUndoManager;
+}
+
+// chart2::XChartDocument
+
+uno::Reference< chart2::XDiagram > SAL_CALL ChartModel::getFirstDiagram()
+{
+ MutexGuard aGuard( m_aModelMutex );
+ return m_xDiagram;
+}
+
+void SAL_CALL ChartModel::setFirstDiagram( const uno::Reference< chart2::XDiagram >& xDiagram )
+{
+ rtl::Reference< ::chart::Diagram > xOldDiagram;
+ Reference< util::XModifyListener > xListener;
+ {
+ MutexGuard aGuard( m_aModelMutex );
+ if( xDiagram.get() == m_xDiagram.get() )
+ return;
+ xOldDiagram = m_xDiagram;
+ assert(!xDiagram || dynamic_cast<::chart::Diagram*>(xDiagram.get()));
+ m_xDiagram = dynamic_cast<::chart::Diagram*>(xDiagram.get());
+ xListener = this;
+ }
+ //don't keep the mutex locked while calling out
+ if( xOldDiagram && xListener )
+ xOldDiagram->removeModifyListener( xListener );
+ ModifyListenerHelper::addListener( xDiagram, xListener );
+ setModified( true );
+}
+
+Reference< chart2::data::XDataSource > ChartModel::impl_createDefaultData()
+{
+ Reference< chart2::data::XDataSource > xDataSource;
+ if( hasInternalDataProvider() )
+ {
+ //init internal dataprovider
+ {
+ beans::NamedValue aParam( "CreateDefaultData" ,uno::Any(true) );
+ uno::Sequence< uno::Any > aArgs{ uno::Any(aParam) };
+ m_xInternalDataProvider->initialize(aArgs);
+ }
+ //create data
+ uno::Sequence<beans::PropertyValue> aArgs( comphelper::InitPropertySequence({
+ { "CellRangeRepresentation", uno::Any( OUString("all") ) },
+ { "HasCategories", uno::Any( true ) },
+ { "FirstCellAsLabel", uno::Any( true ) },
+ { "DataRowSource", uno::Any( css::chart::ChartDataRowSource_COLUMNS ) }
+ }));
+ xDataSource = m_xInternalDataProvider->createDataSource( aArgs );
+ }
+ return xDataSource;
+}
+
+void SAL_CALL ChartModel::createInternalDataProvider( sal_Bool bCloneExistingData )
+{
+ // don't lock the mutex, because this call calls out to code that tries to
+ // lock the solar mutex. On the other hand, a paint locks the solar mutex
+ // and calls to the model lock the model's mutex => deadlock
+ // @todo: lock a separate mutex in the InternalData class
+ if( !hasInternalDataProvider() )
+ {
+ if( bCloneExistingData )
+ m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( this, true );
+ else
+ m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( nullptr, true );
+ m_xDataProvider.set( m_xInternalDataProvider );
+ }
+ setModified( true );
+}
+
+void ChartModel::removeDataProviders()
+{
+ if (m_xInternalDataProvider.is())
+ m_xInternalDataProvider.clear();
+ if (m_xDataProvider.is())
+ m_xDataProvider.clear();
+}
+
+void ChartModel::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ChartModel"));
+ (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
+
+ if (mxChartView.is())
+ {
+ mxChartView->dumpAsXml(pWriter);
+ }
+
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+sal_Bool SAL_CALL ChartModel::hasInternalDataProvider()
+{
+ return m_xDataProvider.is() && m_xInternalDataProvider.is();
+}
+
+uno::Reference< chart2::data::XDataProvider > SAL_CALL ChartModel::getDataProvider()
+{
+ MutexGuard aGuard( m_aModelMutex );
+ return m_xDataProvider;
+}
+
+// ____ XDataReceiver ____
+
+void SAL_CALL ChartModel::attachDataProvider( const uno::Reference< chart2::data::XDataProvider >& xDataProvider )
+{
+ {
+ MutexGuard aGuard( m_aModelMutex );
+ uno::Reference< beans::XPropertySet > xProp( xDataProvider, uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ try
+ {
+ bool bIncludeHiddenCells = ChartModelHelper::isIncludeHiddenCells( this );
+ xProp->setPropertyValue("IncludeHiddenCells", uno::Any(bIncludeHiddenCells));
+ }
+ catch (const beans::UnknownPropertyException&)
+ {
+ }
+ }
+
+ uno::Reference<util::XModifyBroadcaster> xModifyBroadcaster(xDataProvider, uno::UNO_QUERY);
+ if (xModifyBroadcaster.is())
+ {
+ xModifyBroadcaster->addModifyListener(this);
+ }
+
+ m_xDataProvider.set( xDataProvider );
+ m_xInternalDataProvider.clear();
+
+ //the numberformatter is kept independent of the data provider!
+ }
+ setModified( true );
+}
+
+void SAL_CALL ChartModel::attachNumberFormatsSupplier( const uno::Reference< util::XNumberFormatsSupplier >& xNewSupplier )
+{
+ {
+ MutexGuard aGuard( m_aModelMutex );
+ if( xNewSupplier == m_xNumberFormatsSupplier )
+ return;
+ if( xNewSupplier == uno::Reference<XNumberFormatsSupplier>(m_xOwnNumberFormatsSupplier) )
+ return;
+ if( m_xOwnNumberFormatsSupplier.is() && xNewSupplier.is() )
+ {
+ //@todo
+ //merge missing numberformats from own to new formatter
+ }
+ else if( !xNewSupplier.is() )
+ {
+ if( m_xNumberFormatsSupplier.is() )
+ {
+ //@todo
+ //merge missing numberformats from old numberformatter to own numberformatter
+ //create own numberformatter if necessary
+ }
+ }
+
+ m_xNumberFormatsSupplier.set( xNewSupplier );
+ m_xOwnNumberFormatsSupplier.clear();
+ }
+ setModified( true );
+}
+
+void SAL_CALL ChartModel::setArguments( const Sequence< beans::PropertyValue >& aArguments )
+{
+ {
+ MutexGuard aGuard( m_aModelMutex );
+ if( !m_xDataProvider.is() )
+ return;
+ lockControllers();
+
+ try
+ {
+ Reference< chart2::data::XDataSource > xDataSource( m_xDataProvider->createDataSource( aArguments ) );
+ if( xDataSource.is() )
+ {
+ rtl::Reference< Diagram > xDia = getFirstChartDiagram();
+ if( !xDia.is() )
+ {
+ rtl::Reference< ::chart::ChartTypeTemplate > xTemplate( impl_createDefaultChartTypeTemplate() );
+ if( xTemplate.is())
+ setFirstDiagram( xTemplate->createDiagramByDataSource( xDataSource, aArguments ) );
+ }
+ else
+ xDia->setDiagramData( xDataSource, aArguments );
+ }
+ }
+ catch (const lang::IllegalArgumentException&)
+ {
+ throw;
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ unlockControllers();
+ }
+ setModified( true );
+}
+
+Sequence< OUString > SAL_CALL ChartModel::getUsedRangeRepresentations()
+{
+ return DataSourceHelper::getUsedDataRanges( this );
+}
+
+Reference< chart2::data::XDataSource > SAL_CALL ChartModel::getUsedData()
+{
+ return DataSourceHelper::getUsedData( *this );
+}
+
+Reference< chart2::data::XRangeHighlighter > SAL_CALL ChartModel::getRangeHighlighter()
+{
+ if( ! m_xRangeHighlighter.is())
+ m_xRangeHighlighter = new RangeHighlighter( this );
+ return m_xRangeHighlighter;
+}
+
+Reference<awt::XRequestCallback> SAL_CALL ChartModel::getPopupRequest()
+{
+ if (!m_xPopupRequest.is())
+ m_xPopupRequest.set(new PopupRequest);
+ return m_xPopupRequest;
+}
+
+rtl::Reference< ::chart::ChartTypeTemplate > ChartModel::impl_createDefaultChartTypeTemplate()
+{
+ rtl::Reference< ::chart::ChartTypeTemplate > xTemplate;
+ if( m_xChartTypeManager.is() )
+ xTemplate = m_xChartTypeManager->createTemplate( "com.sun.star.chart2.template.Column" );
+ return xTemplate;
+}
+
+void SAL_CALL ChartModel::setChartTypeManager( const uno::Reference< chart2::XChartTypeManager >& xNewManager )
+{
+ {
+ MutexGuard aGuard( m_aModelMutex );
+ m_xChartTypeManager = dynamic_cast<::chart::ChartTypeManager*>(xNewManager.get());
+ assert(!xNewManager || m_xChartTypeManager);
+ }
+ setModified( true );
+}
+
+uno::Reference< chart2::XChartTypeManager > SAL_CALL ChartModel::getChartTypeManager()
+{
+ MutexGuard aGuard( m_aModelMutex );
+ return m_xChartTypeManager;
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL ChartModel::getPageBackground()
+{
+ MutexGuard aGuard( m_aModelMutex );
+ return m_xPageBackground;
+}
+
+void SAL_CALL ChartModel::createDefaultChart()
+{
+ insertDefaultChart();
+}
+
+// ____ XTitled ____
+uno::Reference< chart2::XTitle > SAL_CALL ChartModel::getTitleObject()
+{
+ MutexGuard aGuard( m_aModelMutex );
+ return m_xTitle;
+}
+
+rtl::Reference< Title > ChartModel::getTitleObject2() const
+{
+ MutexGuard aGuard( m_aModelMutex );
+ return m_xTitle;
+}
+
+void SAL_CALL ChartModel::setTitleObject( const uno::Reference< chart2::XTitle >& xNewTitle )
+{
+ rtl::Reference<Title> xTitle = dynamic_cast<Title*>(xNewTitle.get());
+ assert(!xNewTitle || xTitle);
+ setTitleObject(xTitle);
+}
+
+void ChartModel::setTitleObject( const rtl::Reference< Title >& xTitle )
+{
+ {
+ MutexGuard aGuard( m_aModelMutex );
+ if( m_xTitle.is() )
+ ModifyListenerHelper::removeListener( m_xTitle, this );
+ m_xTitle = xTitle;
+ ModifyListenerHelper::addListener( m_xTitle, this );
+ }
+ setModified( true );
+}
+
+// ____ XInterface (for old API wrapper) ____
+uno::Any SAL_CALL ChartModel::queryInterface( const uno::Type& aType )
+{
+ uno::Any aResult( impl::ChartModel_Base::queryInterface( aType ));
+
+ if( ! aResult.hasValue())
+ {
+ // try old API wrapper
+ try
+ {
+ if( m_xOldModelAgg.is())
+ aResult = m_xOldModelAgg->queryAggregation( aType );
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return aResult;
+}
+
+// ____ XCloneable ____
+Reference< util::XCloneable > SAL_CALL ChartModel::createClone()
+{
+ return Reference< util::XCloneable >( new ChartModel( *this ));
+}
+
+// ____ XVisualObject ____
+void SAL_CALL ChartModel::setVisualAreaSize( ::sal_Int64 nAspect, const awt::Size& aSize )
+{
+ if( nAspect == embed::Aspects::MSOLE_CONTENT )
+ {
+ ControllerLockGuard aLockGuard( *this );
+ bool bChanged =
+ (m_aVisualAreaSize.Width != aSize.Width ||
+ m_aVisualAreaSize.Height != aSize.Height);
+
+ // #i12587# support for shapes in chart
+ if ( bChanged )
+ {
+ impl_adjustAdditionalShapesPositionAndSize( aSize );
+ }
+
+ m_aVisualAreaSize = aSize;
+ if( bChanged )
+ setModified( true );
+ }
+ else
+ {
+ OSL_FAIL( "setVisualAreaSize: Aspect not implemented yet.");
+ }
+}
+
+awt::Size SAL_CALL ChartModel::getVisualAreaSize( ::sal_Int64 nAspect )
+{
+ OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT,
+ "No aspects other than content are supported" );
+ // other possible aspects are MSOLE_THUMBNAIL, MSOLE_ICON and MSOLE_DOCPRINT
+
+ return m_aVisualAreaSize;
+}
+
+embed::VisualRepresentation SAL_CALL ChartModel::getPreferredVisualRepresentation( ::sal_Int64 nAspect )
+{
+ OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT,
+ "No aspects other than content are supported" );
+
+ embed::VisualRepresentation aResult;
+
+ try
+ {
+ Sequence< sal_Int8 > aMetafile;
+
+ //get view from old api wrapper
+ Reference< datatransfer::XTransferable > xTransferable(
+ createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY );
+ if( xTransferable.is() )
+ {
+ datatransfer::DataFlavor aDataFlavor( lcl_aGDIMetaFileMIMEType,
+ "GDIMetaFile",
+ cppu::UnoType<uno::Sequence< sal_Int8 >>::get() );
+
+ uno::Any aData( xTransferable->getTransferData( aDataFlavor ) );
+ aData >>= aMetafile;
+ }
+
+ aResult.Flavor.MimeType = lcl_aGDIMetaFileMIMEType;
+ aResult.Flavor.DataType = cppu::UnoType<decltype(aMetafile)>::get();
+
+ aResult.Data <<= aMetafile;
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return aResult;
+}
+
+::sal_Int32 SAL_CALL ChartModel::getMapUnit( ::sal_Int64 nAspect )
+{
+ OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT,
+ "No aspects other than content are supported" );
+ return embed::EmbedMapUnits::ONE_100TH_MM;
+}
+
+// ____ datatransfer::XTransferable ____
+uno::Any SAL_CALL ChartModel::getTransferData( const datatransfer::DataFlavor& aFlavor )
+{
+ uno::Any aResult;
+ if( !isDataFlavorSupported( aFlavor ) )
+ throw datatransfer::UnsupportedFlavorException(
+ aFlavor.MimeType, static_cast< ::cppu::OWeakObject* >( this ));
+
+ try
+ {
+ //get view from old api wrapper
+ Reference< datatransfer::XTransferable > xTransferable(
+ createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY );
+ if( xTransferable.is() &&
+ xTransferable->isDataFlavorSupported( aFlavor ))
+ {
+ aResult = xTransferable->getTransferData( aFlavor );
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return aResult;
+}
+
+Sequence< datatransfer::DataFlavor > SAL_CALL ChartModel::getTransferDataFlavors()
+{
+ return { datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast,
+ "GDIMetaFile",
+ cppu::UnoType<uno::Sequence< sal_Int8 >>::get() ) };
+}
+
+sal_Bool SAL_CALL ChartModel::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
+{
+ return aFlavor.MimeType == lcl_aGDIMetaFileMIMETypeHighContrast;
+}
+
+namespace
+{
+enum eServiceType
+{
+ SERVICE_DASH_TABLE,
+ SERVICE_GRADIENT_TABLE,
+ SERVICE_HATCH_TABLE,
+ SERVICE_BITMAP_TABLE,
+ SERVICE_TRANSP_GRADIENT_TABLE,
+ SERVICE_MARKER_TABLE,
+ SERVICE_NAMESPACE_MAP
+};
+
+typedef std::map< OUString, enum eServiceType > tServiceNameMap;
+
+tServiceNameMap & lcl_getStaticServiceNameMap()
+{
+ static tServiceNameMap aServiceNameMap{
+ {"com.sun.star.drawing.DashTable", SERVICE_DASH_TABLE},
+ {"com.sun.star.drawing.GradientTable", SERVICE_GRADIENT_TABLE},
+ {"com.sun.star.drawing.HatchTable", SERVICE_HATCH_TABLE},
+ {"com.sun.star.drawing.BitmapTable", SERVICE_BITMAP_TABLE},
+ {"com.sun.star.drawing.TransparencyGradientTable", SERVICE_TRANSP_GRADIENT_TABLE},
+ {"com.sun.star.drawing.MarkerTable", SERVICE_MARKER_TABLE},
+ {"com.sun.star.xml.NamespaceMap", SERVICE_NAMESPACE_MAP}};
+ return aServiceNameMap;
+}
+}
+// ____ XMultiServiceFactory ____
+Reference< uno::XInterface > SAL_CALL ChartModel::createInstance( const OUString& rServiceSpecifier )
+{
+ tServiceNameMap & rMap = lcl_getStaticServiceNameMap();
+
+ tServiceNameMap::const_iterator aIt( rMap.find( rServiceSpecifier ));
+ if( aIt != rMap.end())
+ {
+ switch( (*aIt).second )
+ {
+ case SERVICE_DASH_TABLE:
+ case SERVICE_GRADIENT_TABLE:
+ case SERVICE_HATCH_TABLE:
+ case SERVICE_BITMAP_TABLE:
+ case SERVICE_TRANSP_GRADIENT_TABLE:
+ case SERVICE_MARKER_TABLE:
+ {
+ if(!mxChartView.is())
+ {
+ mxChartView = new ChartView( m_xContext, *this);
+ }
+ return mxChartView->createInstance( rServiceSpecifier );
+ }
+ break;
+ case SERVICE_NAMESPACE_MAP:
+ return static_cast<cppu::OWeakObject*>(m_xXMLNamespaceMap.get());
+ }
+ }
+ else if(rServiceSpecifier == CHART_VIEW_SERVICE_NAME)
+ {
+ if(!mxChartView.is())
+ {
+ mxChartView = new ChartView( m_xContext, *this);
+ }
+
+ return static_cast< ::cppu::OWeakObject* >( mxChartView.get() );
+ }
+ else
+ {
+ if( m_xOldModelAgg.is() )
+ {
+ Any aAny = m_xOldModelAgg->queryAggregation( cppu::UnoType<lang::XMultiServiceFactory>::get());
+ uno::Reference< lang::XMultiServiceFactory > xOldModelFactory;
+ if( (aAny >>= xOldModelFactory) && xOldModelFactory.is() )
+ {
+ return xOldModelFactory->createInstance( rServiceSpecifier );
+ }
+ }
+ }
+ return nullptr;
+}
+
+Reference< uno::XInterface > SAL_CALL ChartModel::createInstanceWithArguments(
+ const OUString& rServiceSpecifier , const Sequence< Any >& Arguments )
+{
+ OSL_ENSURE( Arguments.hasElements(), "createInstanceWithArguments: Warning: Arguments are ignored" );
+ return createInstance( rServiceSpecifier );
+}
+
+Sequence< OUString > SAL_CALL ChartModel::getAvailableServiceNames()
+{
+ uno::Sequence< OUString > aResult;
+
+ if( m_xOldModelAgg.is())
+ {
+ Any aAny = m_xOldModelAgg->queryAggregation( cppu::UnoType<lang::XMultiServiceFactory>::get());
+ uno::Reference< lang::XMultiServiceFactory > xOldModelFactory;
+ if( (aAny >>= xOldModelFactory) && xOldModelFactory.is() )
+ {
+ return xOldModelFactory->getAvailableServiceNames();
+ }
+ }
+ return aResult;
+}
+
+Reference< util::XNumberFormatsSupplier > const & ChartModel::getNumberFormatsSupplier()
+{
+ if( !m_xNumberFormatsSupplier.is() )
+ {
+ if( !m_xOwnNumberFormatsSupplier.is() )
+ {
+ m_apSvNumberFormatter.reset( new SvNumberFormatter( m_xContext, LANGUAGE_SYSTEM ) );
+ m_xOwnNumberFormatsSupplier = new SvNumberFormatsSupplierObj( m_apSvNumberFormatter.get() );
+ //pOwnNumberFormatter->ChangeStandardPrec( 15 ); todo?
+ }
+ m_xNumberFormatsSupplier = m_xOwnNumberFormatsSupplier;
+ }
+ return m_xNumberFormatsSupplier;
+}
+
+// ____ XUnoTunnel ___
+::sal_Int64 SAL_CALL ChartModel::getSomething( const Sequence< ::sal_Int8 >& aIdentifier )
+{
+ if( comphelper::isUnoTunnelId<SvNumberFormatsSupplierObj>(aIdentifier) )
+ {
+ Reference< lang::XUnoTunnel > xTunnel( getNumberFormatsSupplier(), uno::UNO_QUERY );
+ if( xTunnel.is() )
+ return xTunnel->getSomething( aIdentifier );
+ }
+ return 0;
+}
+
+// ____ XNumberFormatsSupplier ____
+uno::Reference< beans::XPropertySet > SAL_CALL ChartModel::getNumberFormatSettings()
+{
+ Reference< util::XNumberFormatsSupplier > xSupplier( getNumberFormatsSupplier() );
+ if( xSupplier.is() )
+ return xSupplier->getNumberFormatSettings();
+ return uno::Reference< beans::XPropertySet >();
+}
+
+uno::Reference< util::XNumberFormats > SAL_CALL ChartModel::getNumberFormats()
+{
+ Reference< util::XNumberFormatsSupplier > xSupplier( getNumberFormatsSupplier() );
+ if( xSupplier.is() )
+ return xSupplier->getNumberFormats();
+ return uno::Reference< util::XNumberFormats >();
+}
+
+// ____ XChild ____
+Reference< uno::XInterface > SAL_CALL ChartModel::getParent()
+{
+ return Reference< uno::XInterface >(m_xParent,uno::UNO_QUERY);
+}
+
+void SAL_CALL ChartModel::setParent( const Reference< uno::XInterface >& Parent )
+{
+ if( Parent != m_xParent )
+ m_xParent.set( Parent, uno::UNO_QUERY );
+}
+
+// ____ XDataSource ____
+uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL ChartModel::getDataSequences()
+{
+ rtl::Reference< DataSource > xSource = DataSourceHelper::getUsedData( *this );
+ if( xSource.is())
+ return xSource->getDataSequences();
+
+ return uno::Sequence< Reference< chart2::data::XLabeledDataSequence > >();
+}
+
+//XDumper
+OUString SAL_CALL ChartModel::dump(OUString const & kind)
+{
+ if (kind.isEmpty()) {
+ return comphelper::dumpXmlToString([this](auto writer) { return dumpAsXml(writer); });
+ }
+
+ // kind == "shapes":
+ uno::Reference< qa::XDumper > xDumper(
+ createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY );
+ if (xDumper.is())
+ return xDumper->dump(kind);
+
+ return OUString();
+}
+
+void ChartModel::setTimeBasedRange(sal_Int32 nStart, sal_Int32 nEnd)
+{
+ mnStart = nStart;
+ mnEnd = nEnd;
+ mbTimeBased = true;
+}
+
+void ChartModel::update()
+{
+ if(!mxChartView.is())
+ {
+ mxChartView = new ChartView( m_xContext, *this);
+ }
+ mxChartView->setViewDirty();
+ mxChartView->update();
+}
+
+bool ChartModel::isDataFromSpreadsheet()
+{
+ return !isDataFromPivotTable() && !hasInternalDataProvider();
+}
+
+bool ChartModel::isDataFromPivotTable() const
+{
+ uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(m_xDataProvider, uno::UNO_QUERY);
+ return xPivotTableDataProvider.is();
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_ChartModel_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::ChartModel(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/ChartModel_Persistence.cxx b/chart2/source/model/main/ChartModel_Persistence.cxx
new file mode 100644
index 0000000000..03824aab5c
--- /dev/null
+++ b/chart2/source/model/main/ChartModel_Persistence.cxx
@@ -0,0 +1,802 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <ChartModel.hxx>
+#include <MediaDescriptorHelper.hxx>
+#include <ChartViewHelper.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <DataSourceHelper.hxx>
+#include <AxisHelper.hxx>
+#include <ThreeDHelper.hxx>
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <Legend.hxx>
+#include <XMLFilter.hxx>
+
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/ProjectionMode.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/StorageFactory.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/io/TempFile.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/ucb/CommandFailedException.hpp>
+#include <com/sun/star/ucb/ContentCreationException.hpp>
+
+#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
+
+#include <ucbhelper/content.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <unotools/tempfile.hxx>
+#include <utility>
+#include <vcl/cvtgrf.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+#include <sfx2/objsh.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::osl::MutexGuard;
+
+namespace
+{
+struct lcl_PropNameEquals
+{
+ explicit lcl_PropNameEquals( OUString aStrToCompareWith ) :
+ m_aStr(std::move( aStrToCompareWith ))
+ {}
+ bool operator() ( const beans::PropertyValue & rProp )
+ {
+ return rProp.Name == m_aStr;
+ }
+private:
+ OUString m_aStr;
+};
+
+template< typename T >
+T lcl_getProperty(
+ const Sequence< beans::PropertyValue > & rMediaDescriptor,
+ const OUString & rPropName )
+{
+ T aResult;
+ if( rMediaDescriptor.hasElements())
+ {
+ const beans::PropertyValue * pIt = rMediaDescriptor.getConstArray();
+ const beans::PropertyValue * pEndIt = pIt + + rMediaDescriptor.getLength();
+ pIt = std::find_if( pIt, pEndIt, lcl_PropNameEquals( rPropName ));
+ if( pIt != pEndIt )
+ (*pIt).Value >>= aResult;
+ }
+ return aResult;
+}
+
+void lcl_addStorageToMediaDescriptor(
+ Sequence< beans::PropertyValue > & rOutMD,
+ const Reference< embed::XStorage > & xStorage )
+{
+ rOutMD.realloc( rOutMD.getLength() + 1 );
+ rOutMD.getArray()[rOutMD.getLength() - 1] = beans::PropertyValue(
+ "Storage", -1, uno::Any( xStorage ), beans::PropertyState_DIRECT_VALUE );
+}
+
+Reference< embed::XStorage > lcl_createStorage(
+ const OUString & rURL,
+ const Reference< uno::XComponentContext > & xContext,
+ const Sequence< beans::PropertyValue > & rMediaDescriptor )
+{
+ // create new storage
+ Reference< embed::XStorage > xStorage;
+ if( !xContext.is())
+ return xStorage;
+
+ try
+ {
+ Reference< io::XStream > xStream(
+ ::ucbhelper::Content( rURL, Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext()).openStream(),
+ uno::UNO_QUERY );
+
+ Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create( xContext ) );
+ Sequence< uno::Any > aStorageArgs{ uno::Any(xStream),
+ uno::Any(embed::ElementModes::READWRITE),
+ uno::Any(rMediaDescriptor) };
+ xStorage.set(
+ xStorageFact->createInstanceWithArguments( aStorageArgs ), uno::UNO_QUERY_THROW );
+ }
+ catch(const css::ucb::ContentCreationException&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ catch(const css::ucb::CommandFailedException&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xStorage;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+Reference< document::XFilter > ChartModel::impl_createFilter(
+ const Sequence< beans::PropertyValue > & rMediaDescriptor )
+{
+ Reference< document::XFilter > xFilter;
+
+ // find FilterName in MediaDescriptor
+ OUString aFilterName(
+ lcl_getProperty< OUString >( rMediaDescriptor, "FilterName" ) );
+
+ // if FilterName was found, get Filter from factory
+ if( !aFilterName.isEmpty() )
+ {
+ try
+ {
+ Reference< container::XNameAccess > xFilterFact(
+ m_xContext->getServiceManager()->createInstanceWithContext(
+ "com.sun.star.document.FilterFactory", m_xContext ),
+ uno::UNO_QUERY_THROW );
+ uno::Any aFilterProps( xFilterFact->getByName( aFilterName ));
+ Sequence< beans::PropertyValue > aProps;
+
+ if( aFilterProps.hasValue() &&
+ (aFilterProps >>= aProps))
+ {
+ OUString aFilterServiceName(
+ lcl_getProperty< OUString >( aProps, "FilterService" ) );
+
+ if( !aFilterServiceName.isEmpty())
+ {
+ xFilter.set(
+ m_xContext->getServiceManager()->createInstanceWithContext(
+ aFilterServiceName, m_xContext ), uno::UNO_QUERY_THROW );
+ SAL_INFO("chart2", "Filter found for service " << aFilterServiceName );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ OSL_ENSURE( xFilter.is(), "Filter not found via factory" );
+ }
+
+ // fall-back: create XML-Filter
+ if( ! xFilter.is())
+ {
+ SAL_WARN("chart2", "No FilterName passed in MediaDescriptor" );
+ xFilter = new XMLFilter(m_xContext);
+ }
+
+ return xFilter;
+}
+
+// frame::XStorable2
+
+void SAL_CALL ChartModel::storeSelf( const Sequence< beans::PropertyValue >& rMediaDescriptor )
+{
+ // only some parameters are allowed (see also SfxBaseModel)
+ // "VersionComment", "Author", "InteractionHandler", "StatusIndicator"
+ // However, they are ignored here. They would become interesting when
+ // charts support a standalone format again.
+ impl_store( rMediaDescriptor, m_xStorage );
+}
+
+// frame::XStorable (base of XStorable2)
+sal_Bool SAL_CALL ChartModel::hasLocation()
+{
+ //@todo guard
+ return !m_aResource.isEmpty();
+}
+
+OUString SAL_CALL ChartModel::getLocation()
+{
+ return impl_g_getLocation();
+}
+
+sal_Bool SAL_CALL ChartModel::isReadonly()
+{
+ //@todo guard
+ return m_bReadOnly;
+}
+
+void SAL_CALL ChartModel::store()
+{
+ apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall(true)) //start LongLastingCall
+ return; //behave passive if already disposed or closed or throw exception @todo?
+
+ OUString aLocation = m_aResource;
+
+ if( aLocation.isEmpty() )
+ throw io::IOException( "no location specified", static_cast< ::cppu::OWeakObject* >(this));
+ //@todo check whether aLocation is something like private:factory...
+ if( m_bReadOnly )
+ throw io::IOException( "document is read only", static_cast< ::cppu::OWeakObject* >(this));
+
+ aGuard.clear();
+
+ // store
+ impl_store( m_aMediaDescriptor, m_xStorage );
+}
+
+void SAL_CALL ChartModel::storeAsURL(
+ const OUString& rURL,
+ const uno::Sequence< beans::PropertyValue >& rMediaDescriptor )
+{
+ apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall(true)) //start LongLastingCall
+ return; //behave passive if already disposed or closed or throw exception @todo?
+
+ apphelper::MediaDescriptorHelper aMediaDescriptorHelper(rMediaDescriptor);
+ uno::Sequence< beans::PropertyValue > aReducedMediaDescriptor(
+ aMediaDescriptorHelper.getReducedForModel() );
+
+ m_bReadOnly = false;
+ aGuard.clear();
+
+ // create new storage
+ Reference< embed::XStorage > xStorage( lcl_createStorage( rURL, m_xContext, aReducedMediaDescriptor ));
+
+ if( xStorage.is())
+ {
+ impl_store( aReducedMediaDescriptor, xStorage );
+ attachResource( rURL, aReducedMediaDescriptor );
+ }
+}
+
+void SAL_CALL ChartModel::storeToURL(
+ const OUString& rURL,
+ const uno::Sequence< beans::PropertyValue >& rMediaDescriptor )
+{
+ apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall(true)) //start LongLastingCall
+ return; //behave passive if already disposed or closed or throw exception @todo?
+ //do not change the internal state of the document here
+
+ aGuard.clear();
+
+ apphelper::MediaDescriptorHelper aMediaDescriptorHelper(rMediaDescriptor);
+ uno::Sequence< beans::PropertyValue > aReducedMediaDescriptor(
+ aMediaDescriptorHelper.getReducedForModel() );
+
+ if ( rURL == "private:stream" )
+ {
+ try
+ {
+ if( m_xContext.is() && aMediaDescriptorHelper.ISSET_OutputStream )
+ {
+ rtl::Reference< utl::TempFileFastService > xStream = new utl::TempFileFastService;
+ Reference< io::XInputStream > xInputStream( xStream->getInputStream());
+
+ Reference< embed::XStorage > xStorage(
+ ::comphelper::OStorageHelper::GetStorageFromStream( xStream, embed::ElementModes::READWRITE, m_xContext ));
+ if( xStorage.is())
+ {
+ impl_store( aReducedMediaDescriptor, xStorage );
+
+ xStream->seek( 0 );
+ ::comphelper::OStorageHelper::CopyInputToOutput( xInputStream, aMediaDescriptorHelper.OutputStream );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ else
+ {
+ // create new storage
+ Reference< embed::XStorage > xStorage( lcl_createStorage( rURL, m_xContext, aReducedMediaDescriptor ));
+
+ if( xStorage.is())
+ impl_store( aReducedMediaDescriptor, xStorage );
+ }
+}
+
+void ChartModel::impl_store(
+ const Sequence< beans::PropertyValue >& rMediaDescriptor,
+ const Reference< embed::XStorage > & xStorage )
+{
+ Reference< document::XFilter > xFilter( impl_createFilter( rMediaDescriptor));
+ if( xFilter.is() && xStorage.is())
+ {
+ Sequence< beans::PropertyValue > aMD( rMediaDescriptor );
+ lcl_addStorageToMediaDescriptor( aMD, xStorage );
+ try
+ {
+ Reference< document::XExporter > xExporter( xFilter, uno::UNO_QUERY_THROW );
+ xExporter->setSourceDocument( Reference< lang::XComponent >( this ));
+ xFilter->filter( aMD );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ else
+ {
+ OSL_FAIL( "No filter" );
+ }
+
+ setModified( false );
+
+ //#i66865#
+ //for data change notification during chart is not loaded:
+ //notify parent data provider after saving thus the parent document can store
+ //the ranges for which a load and update of the chart will be necessary
+ Reference< beans::XPropertySet > xPropSet( m_xParent, uno::UNO_QUERY );
+ if ( hasInternalDataProvider() || !xPropSet.is() )
+ return;
+
+ apphelper::MediaDescriptorHelper aMDHelper(rMediaDescriptor);
+ try
+ {
+ xPropSet->setPropertyValue(
+ "SavedObject",
+ uno::Any( aMDHelper.HierarchicalDocumentName ) );
+ }
+ catch ( const uno::Exception& )
+ {
+ }
+}
+
+void ChartModel::insertDefaultChart()
+{
+ lockControllers();
+ createInternalDataProvider( false );
+ try
+ {
+ // create default chart
+ rtl::Reference< ::chart::ChartTypeTemplate > xTemplate( impl_createDefaultChartTypeTemplate() );
+ if( xTemplate.is())
+ {
+ try
+ {
+ Reference< chart2::data::XDataSource > xDataSource( impl_createDefaultData() );
+ Sequence< beans::PropertyValue > aParam;
+
+ bool bSupportsCategories = xTemplate->supportsCategories();
+ if( bSupportsCategories )
+ {
+ aParam = { beans::PropertyValue( "HasCategories", -1, uno::Any( true ),
+ beans::PropertyState_DIRECT_VALUE ) };
+ }
+
+ rtl::Reference< Diagram > xDiagram( xTemplate->createDiagramByDataSource2( xDataSource, aParam ) );
+
+ setFirstDiagram( xDiagram );
+
+ bool bIsRTL = AllSettings::GetMathLayoutRTL();
+ //reverse x axis for rtl charts
+ if( bIsRTL )
+ AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) );
+
+ // create and attach legend
+ rtl::Reference< Legend > xLegend = new Legend();
+ xLegend->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_NONE ));
+ xLegend->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE ));
+ xLegend->setPropertyValue( "LineColor", uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) )); // gray30
+ xLegend->setPropertyValue( "FillColor", uno::Any( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10
+
+ if( bIsRTL )
+ xLegend->setPropertyValue( "AnchorPosition", uno::Any( chart2::LegendPosition_LINE_START ));
+ if(xDiagram.is())
+ xDiagram->setLegend( xLegend );
+
+ // set simple 3D look
+ if( xDiagram.is() )
+ {
+ xDiagram->setPropertyValue( "RightAngledAxes", uno::Any( true ));
+ xDiagram->setPropertyValue( "D3DScenePerspective", uno::Any( drawing::ProjectionMode_PARALLEL ));
+ xDiagram->setScheme( ThreeDLookScheme::ThreeDLookScheme_Realistic );
+ }
+
+ //set some new 'defaults' for wall and floor
+ if( xDiagram.is() )
+ {
+ Reference< beans::XPropertySet > xWall( xDiagram->getWall() );
+ if( xWall.is() )
+ {
+ xWall->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_SOLID ) );
+ xWall->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_NONE ) );
+ xWall->setPropertyValue( "LineColor", uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30
+ xWall->setPropertyValue( "FillColor", uno::Any( static_cast< sal_Int32 >( 0xe6e6e6 ) ) ); // gray10
+ }
+ Reference< beans::XPropertySet > xFloor( xDiagram->getFloor() );
+ if( xFloor.is() )
+ {
+ xFloor->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE ) );
+ xFloor->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_SOLID ) );
+ xFloor->setPropertyValue( "LineColor", uno::Any( static_cast< sal_Int32 >( 0xb3b3b3 ) ) ); // gray30
+ xFloor->setPropertyValue( "FillColor", uno::Any( static_cast< sal_Int32 >( 0xcccccc ) ) ); // gray20
+ }
+
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ ChartModelHelper::setIncludeHiddenCells( false, *this );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ setModified( false );
+ unlockControllers();
+}
+
+// frame::XLoadable
+void SAL_CALL ChartModel::initNew()
+{
+}
+
+void SAL_CALL ChartModel::load(
+ const Sequence< beans::PropertyValue >& rMediaDescriptor )
+{
+ Reference< embed::XStorage > xStorage;
+ OUString aURL;
+ try
+ {
+ apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor );
+ if( aMDHelper.ISSET_Storage )
+ {
+ xStorage = aMDHelper.Storage;
+ }
+ else if( aMDHelper.ISSET_Stream ||
+ aMDHelper.ISSET_InputStream )
+ {
+ if( aMDHelper.ISSET_FilterName &&
+ (aMDHelper.FilterName == "StarChart 5.0" ||
+ aMDHelper.FilterName == "StarChart 4.0" ||
+ aMDHelper.FilterName == "StarChart 3.0" ))
+ {
+ attachResource( aMDHelper.URL, rMediaDescriptor );
+ impl_load( rMediaDescriptor, nullptr ); // cannot create a storage from binary streams, but I do not need the storage here anyhow
+ m_bReadOnly = true;
+ return;
+ }
+
+ Reference< lang::XSingleServiceFactory > xStorageFact( embed::StorageFactory::create(m_xContext) );
+
+ if( aMDHelper.ISSET_Stream )
+ {
+ // convert XStream to XStorage via the storage factory
+ Sequence< uno::Any > aStorageArgs{ uno::Any(aMDHelper.Stream),
+ // todo: check if stream is read-only
+ uno::Any(embed::ElementModes::READ) }; //WRITE | embed::ElementModes::NOCREATE);
+
+ xStorage.set( xStorageFact->createInstanceWithArguments( aStorageArgs ),
+ uno::UNO_QUERY_THROW );
+ }
+ else
+ {
+ OSL_ASSERT( aMDHelper.ISSET_InputStream );
+ // convert XInputStream to XStorage via the storage factory
+ Sequence< uno::Any > aStorageArgs{ uno::Any(aMDHelper.InputStream),
+ uno::Any(embed::ElementModes::READ) };
+
+ xStorage.set( xStorageFact->createInstanceWithArguments( aStorageArgs ),
+ uno::UNO_QUERY_THROW );
+ }
+ }
+
+ if( aMDHelper.ISSET_URL )
+ aURL = aMDHelper.URL;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ if( xStorage.is())
+ {
+ attachResource( aURL, rMediaDescriptor );
+ impl_load( rMediaDescriptor, xStorage );
+ }
+}
+
+void ChartModel::impl_load(
+ const Sequence< beans::PropertyValue >& rMediaDescriptor,
+ const Reference< embed::XStorage >& xStorage )
+{
+ {
+ MutexGuard aGuard( m_aModelMutex );
+ m_nInLoad++;
+ }
+
+ Reference< document::XFilter > xFilter( impl_createFilter( rMediaDescriptor ));
+
+ if( xFilter.is())
+ {
+ Reference< document::XImporter > xImporter( xFilter, uno::UNO_QUERY_THROW );
+ xImporter->setTargetDocument( this );
+ Sequence< beans::PropertyValue > aMD( rMediaDescriptor );
+ lcl_addStorageToMediaDescriptor( aMD, xStorage );
+
+ xFilter->filter( aMD );
+ xFilter.clear();
+ }
+ else
+ {
+ OSL_FAIL( "loadFromStorage cannot create filter" );
+ }
+
+ if( xStorage.is() )
+ impl_loadGraphics( xStorage );
+
+ setModified( false );
+
+ // switchToStorage without notifying listeners (which shouldn't exist at
+ // this time, anyway)
+ m_xStorage = xStorage;
+
+ {
+ MutexGuard aGuard( m_aModelMutex );
+ m_nInLoad--;
+ }
+}
+
+void ChartModel::impl_loadGraphics(
+ const Reference< embed::XStorage >& xStorage )
+{
+ try
+ {
+ const Reference< embed::XStorage >& xGraphicsStorage(
+ xStorage->openStorageElement( "Pictures",
+ embed::ElementModes::READ ) );
+
+ if( xGraphicsStorage.is() )
+ {
+ const uno::Sequence< OUString > aElementNames(
+ xGraphicsStorage->getElementNames() );
+
+ for( OUString const & streamName : aElementNames )
+ {
+ if( xGraphicsStorage->isStreamElement( streamName ) )
+ {
+ uno::Reference< io::XStream > xElementStream(
+ xGraphicsStorage->openStreamElement(
+ streamName,
+ embed::ElementModes::READ ) );
+
+ if( xElementStream.is() )
+ {
+ std::unique_ptr< SvStream > apIStm(
+ ::utl::UcbStreamHelper::CreateStream(
+ xElementStream, true ) );
+
+ if (apIStm)
+ {
+ SolarMutexGuard aGuard;
+ Graphic aGraphic;
+ if (!GraphicConverter::Import(*apIStm, aGraphic))
+ {
+ m_aGraphicObjectVector.emplace_back(aGraphic );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch ( const uno::Exception& )
+ {
+ }
+}
+
+// util::XModifiable
+void ChartModel::impl_notifyModifiedListeners()
+{
+ {
+ MutexGuard aGuard( m_aModelMutex );
+ m_bUpdateNotificationsPending = false;
+ }
+
+ //always notify the view first!
+ ChartViewHelper::setViewToDirtyState( this );
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ if( m_aLifeTimeManager.m_aModifyListeners.getLength(aGuard) )
+ {
+ lang::EventObject aEvent( static_cast< lang::XComponent*>(this) );
+ m_aLifeTimeManager.m_aModifyListeners.notifyEach(aGuard, &util::XModifyListener::modified, aEvent);
+ }
+}
+
+sal_Bool SAL_CALL ChartModel::isModified()
+{
+ //@todo guard
+ return m_bModified;
+}
+
+void SAL_CALL ChartModel::setModified( sal_Bool bModified )
+{
+ // tdf#141914: allow to set *unmodified* when parent does not allow to set modified
+ if (bModified)
+ {
+ // tdf#77007: honor parent's IsEnableSetModified
+ // Check it before LifeTimeGuard, to avoid deadlocking solar mutex and this guard
+ if (auto pParentShell = SfxObjectShell::GetShellFromComponent(getParent());
+ pParentShell && !pParentShell->IsEnableSetModified())
+ return;
+ }
+
+ apphelper::LifeTimeGuard aGuard(m_aLifeTimeManager);
+ if(!aGuard.startApiCall())//@todo ? is this a long lasting call??
+ return; //behave passive if already disposed or closed or throw exception @todo?
+ m_bModified = bModified;
+
+ if( m_nControllerLockCount > 0 )
+ {
+ if (bModified)
+ m_bUpdateNotificationsPending = true; // Maybe !bModified should reset it?
+ return;//don't call listeners if controllers are locked
+ }
+ aGuard.clear();
+
+ if(bModified)
+ impl_notifyModifiedListeners();
+}
+
+// util::XModifyBroadcaster (base of XModifiable)
+void SAL_CALL ChartModel::addModifyListener(
+ const uno::Reference< util::XModifyListener >& xListener )
+{
+ if( m_aLifeTimeManager.impl_isDisposedOrClosed() )
+ return; //behave passive if already disposed or closed
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aModifyListeners.addInterface( aGuard, xListener );
+}
+
+void SAL_CALL ChartModel::removeModifyListener(
+ const uno::Reference< util::XModifyListener >& xListener )
+{
+ if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
+ return; //behave passive if already disposed or closed
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aModifyListeners.removeInterface( aGuard, xListener );
+}
+
+// util::XModifyListener
+void SAL_CALL ChartModel::modified( const lang::EventObject& rEvenObject)
+{
+ uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(rEvenObject.Source, uno::UNO_QUERY);
+ if (xPivotTableDataProvider.is())
+ {
+ lockControllers();
+ uno::Reference<chart2::data::XDataProvider> xDataProvider(xPivotTableDataProvider, uno::UNO_QUERY);
+ try
+ {
+ uno::Sequence<beans::PropertyValue> aArguments =
+ DataSourceHelper::createArguments("PivotChart", uno::Sequence<sal_Int32>(), true, true, true);
+
+ Reference<chart2::data::XDataSource> xDataSource(xDataProvider->createDataSource(aArguments));
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = getTypeManager();
+ rtl::Reference<Diagram> xDiagram(getFirstChartDiagram());
+
+ Diagram::tTemplateWithServiceName aTemplateAndService = xDiagram->getTemplate(xChartTypeManager);
+ aTemplateAndService.xChartTypeTemplate->changeDiagramData(xDiagram, xDataSource, aArguments);
+ }
+ catch (const uno::Exception &)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ unlockControllers();
+ }
+
+ if (m_nInLoad == 0)
+ setModified(true);
+}
+
+// lang::XEventListener (base of util::XModifyListener)
+void SAL_CALL ChartModel::disposing( const lang::EventObject& )
+{
+ // child was disposed -- should not happen from outside
+}
+
+// document::XStorageBasedDocument
+void SAL_CALL ChartModel::loadFromStorage(
+ const Reference< embed::XStorage >& xStorage,
+ const Sequence< beans::PropertyValue >& rMediaDescriptor )
+{
+ attachResource( OUString(), rMediaDescriptor );
+ impl_load( rMediaDescriptor, xStorage );
+}
+
+void SAL_CALL ChartModel::storeToStorage(
+ const Reference< embed::XStorage >& xStorage,
+ const Sequence< beans::PropertyValue >& rMediaDescriptor )
+{
+ impl_store( rMediaDescriptor, xStorage );
+}
+
+void SAL_CALL ChartModel::switchToStorage( const Reference< embed::XStorage >& xStorage )
+{
+ m_xStorage = xStorage;
+ impl_notifyStorageChangeListeners();
+}
+
+Reference< embed::XStorage > SAL_CALL ChartModel::getDocumentStorage()
+{
+ return m_xStorage;
+}
+
+void ChartModel::impl_notifyStorageChangeListeners()
+{
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ if( m_aLifeTimeManager.m_aStorageChangeListeners.getLength(aGuard) )
+ {
+ m_aLifeTimeManager.m_aStorageChangeListeners.forEach(aGuard,
+ [this](const uno::Reference<document::XStorageChangeListener>& l)
+ {
+ l->notifyStorageChange( static_cast< ::cppu::OWeakObject* >( this ), m_xStorage );
+ });
+ }
+}
+
+void SAL_CALL ChartModel::addStorageChangeListener( const Reference< document::XStorageChangeListener >& xListener )
+{
+ if( m_aLifeTimeManager.impl_isDisposedOrClosed() )
+ return; //behave passive if already disposed or closed
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aStorageChangeListeners.addInterface( aGuard, xListener );
+}
+
+void SAL_CALL ChartModel::removeStorageChangeListener( const Reference< document::XStorageChangeListener >& xListener )
+{
+ if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
+ return; //behave passive if already disposed or closed
+
+ std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
+ m_aLifeTimeManager.m_aStorageChangeListeners.removeInterface(aGuard, xListener );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/DataPoint.cxx b/chart2/source/model/main/DataPoint.cxx
new file mode 100644
index 0000000000..d6c8a9e2ac
--- /dev/null
+++ b/chart2/source/model/main/DataPoint.cxx
@@ -0,0 +1,255 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DataPoint.hxx"
+#include "DataPointProperties.hxx"
+#include <CharacterProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include <PropertyHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper& StaticDataPointInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ ::chart::DataPointProperties::AddPropertiesToVector( aProperties );
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+DataPoint::DataPoint( const uno::Reference< beans::XPropertySet > & rParentProperties ) :
+ m_xParentProperties( rParentProperties ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_bNoParentPropAllowed( false )
+{
+ SetNewValuesExplicitlyEvenIfTheyEqualDefault();
+}
+
+DataPoint::DataPoint( const DataPoint & rOther ) :
+ impl::DataPoint_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_bNoParentPropAllowed( true )
+{
+ SetNewValuesExplicitlyEvenIfTheyEqualDefault();
+
+ // m_xParentProperties has to be set from outside, like in the method
+ // DataSeries::createClone
+
+ // add as listener to XPropertySet properties
+ Reference< beans::XPropertySet > xPropertySet;
+ uno::Any aValue;
+
+ getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder );
+
+ getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder );
+
+ m_bNoParentPropAllowed = false;
+}
+
+DataPoint::~DataPoint()
+{
+ try
+ {
+ // remove listener from XPropertySet properties
+ Reference< beans::XPropertySet > xPropertySet;
+ uno::Any aValue;
+
+ getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder );
+
+ getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL DataPoint::createClone()
+{
+ return uno::Reference< util::XCloneable >( new DataPoint( *this ));
+}
+
+// ____ XChild ____
+Reference< uno::XInterface > SAL_CALL DataPoint::getParent()
+{
+ return Reference< uno::XInterface >( m_xParentProperties.get(), uno::UNO_QUERY );
+}
+
+void SAL_CALL DataPoint::setParent(
+ const Reference< uno::XInterface >& Parent )
+{
+ m_xParentProperties = Reference< beans::XPropertySet >( Parent, uno::UNO_QUERY );
+}
+
+// ____ OPropertySet ____
+void DataPoint::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ // the value set at the data series is the default
+ uno::Reference< beans::XFastPropertySet > xFast( m_xParentProperties.get(), uno::UNO_QUERY );
+ if( !xFast.is())
+ {
+ OSL_ENSURE( m_bNoParentPropAllowed, "data point needs a parent property set to provide values correctly" );
+ rAny.clear();
+ return;
+ }
+
+ rAny = xFast->getFastPropertyValue( nHandle );
+}
+
+void SAL_CALL DataPoint::setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle, const uno::Any& rValue )
+{
+ if( nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
+ || nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X )
+ {
+ uno::Any aOldValue;
+ Reference< util::XModifyBroadcaster > xBroadcaster;
+ getFastPropertyValue( aOldValue, nHandle );
+ if( aOldValue.hasValue() &&
+ (aOldValue >>= xBroadcaster) &&
+ xBroadcaster.is())
+ {
+ ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder );
+ }
+
+ OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE );
+ if( rValue.hasValue() &&
+ (rValue >>= xBroadcaster) &&
+ xBroadcaster.is())
+ {
+ ModifyListenerHelper::addListener( xBroadcaster, m_xModifyEventForwarder );
+ }
+ }
+
+ ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL DataPoint::getInfoHelper()
+{
+ return StaticDataPointInfoHelper();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL DataPoint::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataPointInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL DataPoint::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL DataPoint::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL DataPoint::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL DataPoint::disposing( const lang::EventObject& )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void DataPoint::firePropertyChangeEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+// needed by MSC compiler
+using impl::DataPoint_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( DataPoint, DataPoint_Base, ::property::OPropertySet )
+
+// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
+OUString SAL_CALL DataPoint::getImplementationName()
+{
+ return "com.sun.star.comp.chart.DataPoint" ;
+}
+
+sal_Bool SAL_CALL DataPoint::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL DataPoint::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.drawing.FillProperties",
+ "com.sun.star.chart2.DataPoint",
+ "com.sun.star.chart2.DataPointProperties",
+ "com.sun.star.beans.PropertySet"
+ };
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/DataPoint.hxx b/chart2/source/model/main/DataPoint.hxx
new file mode 100644
index 0000000000..ba94449fff
--- /dev/null
+++ b/chart2/source/model/main/DataPoint.hxx
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <comphelper/uno3.hxx>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <OPropertySet.hxx>
+#include <ModifyListenerHelper.hxx>
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::container::XChild,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener,
+ css::lang::XServiceInfo >
+ DataPoint_Base;
+}
+
+class DataPoint final :
+ public impl::DataPoint_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit DataPoint( const css::uno::Reference< css::beans::XPropertySet > & rParentProperties );
+ virtual ~DataPoint() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+private:
+ explicit DataPoint( const DataPoint & rOther );
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast
+ ( sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ // Note: m_xParentProperties are not cloned!
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XChild ____
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent() override;
+ virtual void SAL_CALL setParent(
+ const css::uno::Reference< css::uno::XInterface >& Parent ) override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ css::uno::WeakReference< css::beans::XPropertySet > m_xParentProperties;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+ bool m_bNoParentPropAllowed;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/DataPointProperties.cxx b/chart2/source/model/main/DataPointProperties.cxx
new file mode 100644
index 0000000000..819336edd9
--- /dev/null
+++ b/chart2/source/model/main/DataPointProperties.cxx
@@ -0,0 +1,544 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DataPointProperties.hxx"
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/drawing/LineCap.hpp>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <com/sun/star/drawing/RectanglePoint.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
+#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+
+#include <tools/color.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+
+namespace chart
+{
+
+void DataPointProperties::AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ // DataPointProperties
+
+ // Common
+
+ rOutProperties.emplace_back( "Color",
+ PROP_DATAPOINT_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID // "maybe auto"
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillColor",
+ PROP_DATAPOINT_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID // "maybe auto"
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "Transparency",
+ PROP_DATAPOINT_TRANSPARENCY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillTransparence",
+ PROP_DATAPOINT_TRANSPARENCY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // Fill Properties
+ rOutProperties.emplace_back( "FillStyle",
+ PROP_DATAPOINT_FILL_STYLE,
+ cppu::UnoType<drawing::FillStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "TransparencyGradientName",
+ PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "FillTransparenceGradientName",
+ PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "GradientName",
+ PROP_DATAPOINT_GRADIENT_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "FillGradientName",
+ PROP_DATAPOINT_GRADIENT_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "GradientStepCount",
+ PROP_DATAPOINT_GRADIENT_STEPCOUNT,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "FillGradientStepCount",
+ PROP_DATAPOINT_GRADIENT_STEPCOUNT,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "HatchName",
+ PROP_DATAPOINT_HATCH_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "FillHatchName",
+ PROP_DATAPOINT_HATCH_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "FillBitmapName",
+ PROP_DATAPOINT_FILL_BITMAP_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "FillBackground",
+ PROP_DATAPOINT_FILL_BACKGROUND,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ // border for filled objects
+ rOutProperties.emplace_back( "BorderColor",
+ PROP_DATAPOINT_BORDER_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID // "maybe auto"
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "BorderStyle",
+ PROP_DATAPOINT_BORDER_STYLE,
+ cppu::UnoType<drawing::LineStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "BorderWidth",
+ PROP_DATAPOINT_BORDER_WIDTH,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "BorderDashName",
+ PROP_DATAPOINT_BORDER_DASH_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "BorderTransparency",
+ PROP_DATAPOINT_BORDER_TRANSPARENCY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ // Line Properties
+
+ rOutProperties.emplace_back( "LineColor",
+ PROP_DATAPOINT_BORDER_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "LineStyle",
+ LinePropertiesHelper::PROP_LINE_STYLE,
+ cppu::UnoType<drawing::LineStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "LineWidth",
+ LinePropertiesHelper::PROP_LINE_WIDTH,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "LineDash",
+ LinePropertiesHelper::PROP_LINE_DASH,
+ cppu::UnoType<drawing::LineDash>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "LineDashName",
+ LinePropertiesHelper::PROP_LINE_DASH_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "LineTransparence",
+ PROP_DATAPOINT_BORDER_TRANSPARENCY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "LineCap",
+ ::chart::LinePropertiesHelper::PROP_LINE_CAP,
+ cppu::UnoType<drawing::LineCap>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // FillProperties
+ // bitmap properties
+ rOutProperties.emplace_back( "FillBitmapOffsetX",
+ FillProperties::PROP_FILL_BITMAP_OFFSETX,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapOffsetY",
+ FillProperties::PROP_FILL_BITMAP_OFFSETY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapPositionOffsetX",
+ FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapPositionOffsetY",
+ FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapRectanglePoint",
+ FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT,
+ cppu::UnoType<drawing::RectanglePoint>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapLogicalSize",
+ FillProperties::PROP_FILL_BITMAP_LOGICALSIZE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapSizeX",
+ FillProperties::PROP_FILL_BITMAP_SIZEX,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapSizeY",
+ FillProperties::PROP_FILL_BITMAP_SIZEY,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapMode",
+ FillProperties::PROP_FILL_BITMAP_MODE,
+ cppu::UnoType<drawing::BitmapMode>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // others
+ rOutProperties.emplace_back( "Symbol",
+ PROP_DATAPOINT_SYMBOL_PROP,
+ cppu::UnoType<chart2::Symbol>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "Offset",
+ PROP_DATAPOINT_OFFSET,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "Geometry3D",
+ PROP_DATAPOINT_GEOMETRY3D,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_NUMFMT,
+ PROP_DATAPOINT_NUMBER_FORMAT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LINK_TO_SRC_NUMFMT,
+ PROP_DATAPOINT_LINK_NUMBERFORMAT_TO_SOURCE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //additional 'PercentageNumberFormat'
+ rOutProperties.emplace_back( "PercentageNumberFormat",
+ PROP_DATAPOINT_PERCENTAGE_NUMBER_FORMAT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "LabelPlacement",
+ PROP_DATAPOINT_LABEL_PLACEMENT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "ReferencePageSize",
+ PROP_DATAPOINT_REFERENCE_DIAGRAM_SIZE,
+ cppu::UnoType<awt::Size>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "TextRotation",
+ PROP_DATAPOINT_TEXT_ROTATION,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // statistics
+ rOutProperties.emplace_back( CHART_UNONAME_ERRORBAR_X,
+ PROP_DATAPOINT_ERROR_BAR_X,
+ // XPropertySet supporting service ErrorBar
+ cppu::UnoType<beans::XPropertySet>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( CHART_UNONAME_ERRORBAR_Y,
+ PROP_DATAPOINT_ERROR_BAR_Y,
+ // XPropertySet supporting service ErrorBar
+ cppu::UnoType<beans::XPropertySet>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "ShowErrorBox",
+ PROP_DATAPOINT_SHOW_ERROR_BOX,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "PercentDiagonal",
+ PROP_DATAPOINT_PERCENT_DIAGONAL,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ // Properties specific to data label.
+
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL,
+ PROP_DATAPOINT_LABEL,
+ cppu::UnoType<chart2::DataPointLabel>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "TextWordWrap",
+ PROP_DATAPOINT_TEXT_WORD_WRAP,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_SEP,
+ PROP_DATAPOINT_LABEL_SEPARATOR,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_STYLE,
+ PROP_DATAPOINT_LABEL_BORDER_STYLE,
+ cppu::UnoType<drawing::LineStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_COLOR,
+ PROP_DATAPOINT_LABEL_BORDER_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID // "maybe auto"
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_STYLE,
+ PROP_DATAPOINT_LABEL_FILL_STYLE,
+ cppu::UnoType<drawing::FillStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_COLOR,
+ PROP_DATAPOINT_LABEL_FILL_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_BACKGROUND,
+ PROP_DATAPOINT_LABEL_FILL_BACKGROUND,
+ cppu::UnoType<sal_Bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_FILL_HATCH_NAME,
+ PROP_DATAPOINT_LABEL_FILL_HATCH_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_WIDTH,
+ PROP_DATAPOINT_LABEL_BORDER_WIDTH,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_DASH,
+ PROP_DATAPOINT_LABEL_BORDER_DASH,
+ cppu::UnoType<drawing::LineDash>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_DASHNAME,
+ PROP_DATAPOINT_LABEL_BORDER_DASH_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( CHART_UNONAME_LABEL_BORDER_TRANS,
+ PROP_DATAPOINT_LABEL_BORDER_TRANS,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_CUSTOM_LABEL_FIELDS,
+ PROP_DATAPOINT_CUSTOM_LABEL_FIELDS,
+ cppu::UnoType<uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>>>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT);
+
+ rOutProperties.emplace_back( "CustomLabelPosition",
+ PROP_DATAPOINT_LABEL_CUSTOM_POS,
+ cppu::UnoType<chart2::RelativePosition>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+}
+
+void DataPointProperties::AddDefaultsToMap(
+ ::chart::tPropertyValueMap & rOutMap )
+{
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_COLOR, Color(0x99, 0xcc, 0xff) ); // blue 8
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_TRANSPARENCY, sal_Int16(0) );
+
+ //fill
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_FILL_STYLE, drawing::FillStyle_SOLID );
+ PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME );
+ PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_GRADIENT_NAME );
+ PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_HATCH_NAME );
+ PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_FILL_BITMAP_NAME );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_FILL_BACKGROUND, false );
+
+ //border
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_COLOR, COL_BLACK );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_STYLE, drawing::LineStyle_SOLID ); // drawing::LineStyle_NONE
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_WIDTH, sal_Int32(0) );
+ PropertyHelper::setEmptyPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_DASH_NAME );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_BORDER_TRANSPARENCY, sal_Int16(0) );
+
+ //line
+ PropertyHelper::setPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_SOLID );
+ PropertyHelper::setPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_WIDTH, sal_Int32(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_DASH, drawing::LineDash());
+ PropertyHelper::setEmptyPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_DASH_NAME );
+ PropertyHelper::setPropertyValueDefault( rOutMap, LinePropertiesHelper::PROP_LINE_CAP, drawing::LineCap_BUTT);
+
+ //fill bitmap
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETX, sal_Int16(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETY, sal_Int16(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, sal_Int16(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, sal_Int16(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT, drawing::RectanglePoint_MIDDLE_MIDDLE );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_LOGICALSIZE, true );
+
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEX, sal_Int32(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEY, sal_Int32(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_MODE, drawing::BitmapMode_REPEAT );
+
+ //others
+ chart2::Symbol aSymbProp;
+ aSymbProp.Style = chart2::SymbolStyle_NONE;
+ aSymbProp.StandardSymbol = 0;
+ aSymbProp.Size = awt::Size( 250, 250 ); // ca. 7pt x 7pt (7pt=246.94)
+ aSymbProp.BorderColor = sal_Int32(COL_BLACK);
+ aSymbProp.FillColor = 0xee4000; // OrangeRed2
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_SYMBOL_PROP, aSymbProp );
+
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_OFFSET, 0.0 );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_GEOMETRY3D, chart2::DataPointGeometry3D::CUBOID );
+
+ //@todo maybe choose a different one here -> should be dynamically that of the attached axis
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_ERROR_BAR_X, uno::Reference< beans::XPropertySet >());
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_ERROR_BAR_Y, uno::Reference< beans::XPropertySet >());
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_PERCENT_DIAGONAL, sal_Int16(0) );
+
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_TEXT_ROTATION, 0.0 );
+
+ PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LINK_NUMBERFORMAT_TO_SOURCE, true);
+
+ // data label
+ PropertyHelper::setPropertyValueDefault(
+ rOutMap, PROP_DATAPOINT_LABEL,
+ chart2::DataPointLabel(
+ false, // ShowNumber
+ false, // ShowNumberInPercent
+ false, // ShowCategoryName
+ false, // ShowLegendSymbol
+ false, // ShowCustomLabel
+ false // ShowSeriesName
+ ));
+
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_TEXT_WORD_WRAP, false );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATAPOINT_LABEL_SEPARATOR, OUString(" ") );
+ PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_STYLE, drawing::LineStyle_NONE);
+ PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_COLOR);
+ PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_FILL_STYLE);
+ PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_FILL_COLOR);
+ PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_FILL_BACKGROUND);
+ PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_FILL_HATCH_NAME);
+ PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_WIDTH, sal_Int32(0));
+ PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_DASH, drawing::LineDash());
+ PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_DASH_NAME);
+ PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_TRANS, sal_Int16(0));
+
+ uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields(0);
+ PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_CUSTOM_LABEL_FIELDS, aFields);
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/DataPointProperties.hxx b/chart2/source/model/main/DataPointProperties.hxx
new file mode 100644
index 0000000000..ada7907b88
--- /dev/null
+++ b/chart2/source/model/main/DataPointProperties.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <PropertyHelper.hxx>
+#include <FastPropertyIdRanges.hxx>
+
+#include <vector>
+
+namespace com::sun::star::beans { struct Property; }
+
+namespace chart
+{
+
+// implements service DataPointProperties
+namespace DataPointProperties
+{
+ // FastProperty Ids for properties
+ enum
+ {
+ PROP_DATAPOINT_LABEL_FILL_STYLE,
+ PROP_DATAPOINT_LABEL_FILL_COLOR,
+ PROP_DATAPOINT_LABEL_FILL_BACKGROUND,
+ PROP_DATAPOINT_LABEL_FILL_HATCH_NAME,
+
+ // common
+ PROP_DATAPOINT_COLOR = FAST_PROPERTY_ID_START_DATA_POINT,
+ PROP_DATAPOINT_TRANSPARENCY,
+
+ // fill
+ PROP_DATAPOINT_FILL_STYLE,
+ PROP_DATAPOINT_TRANSPARENCY_GRADIENT_NAME,
+ PROP_DATAPOINT_GRADIENT_NAME,
+ PROP_DATAPOINT_GRADIENT_STEPCOUNT,
+ PROP_DATAPOINT_HATCH_NAME,
+ PROP_DATAPOINT_FILL_BITMAP_NAME,
+ PROP_DATAPOINT_FILL_BACKGROUND,
+
+ // border (of filled objects)
+ PROP_DATAPOINT_BORDER_COLOR,
+ PROP_DATAPOINT_BORDER_STYLE,
+ PROP_DATAPOINT_BORDER_WIDTH,
+ PROP_DATAPOINT_BORDER_DASH_NAME,
+ PROP_DATAPOINT_BORDER_TRANSPARENCY,
+
+ // others
+ PROP_DATAPOINT_SYMBOL_PROP,
+ PROP_DATAPOINT_OFFSET,
+ PROP_DATAPOINT_GEOMETRY3D,
+ PROP_DATAPOINT_NUMBER_FORMAT,
+ PROP_DATAPOINT_LINK_NUMBERFORMAT_TO_SOURCE,
+ PROP_DATAPOINT_PERCENTAGE_NUMBER_FORMAT,
+ PROP_DATAPOINT_LABEL_PLACEMENT,
+ PROP_DATAPOINT_REFERENCE_DIAGRAM_SIZE,
+ PROP_DATAPOINT_TEXT_ROTATION,
+
+ // statistics
+ PROP_DATAPOINT_ERROR_BAR_X,
+ PROP_DATAPOINT_ERROR_BAR_Y,
+ PROP_DATAPOINT_SHOW_ERROR_BOX,
+ PROP_DATAPOINT_PERCENT_DIAGONAL,
+
+ // label
+ PROP_DATAPOINT_LABEL,
+ PROP_DATAPOINT_LABEL_SEPARATOR,
+ PROP_DATAPOINT_TEXT_WORD_WRAP,
+ PROP_DATAPOINT_LABEL_BORDER_STYLE,
+ PROP_DATAPOINT_LABEL_BORDER_COLOR,
+ PROP_DATAPOINT_LABEL_BORDER_WIDTH,
+ PROP_DATAPOINT_LABEL_BORDER_DASH,
+ PROP_DATAPOINT_LABEL_BORDER_DASH_NAME,
+ PROP_DATAPOINT_LABEL_BORDER_TRANS,
+ PROP_DATAPOINT_CUSTOM_LABEL_FIELDS,
+ PROP_DATAPOINT_LABEL_CUSTOM_POS
+
+ // additionally some properties from ::chart::LineProperties
+ };
+
+ void AddPropertiesToVector(
+ std::vector< css::beans::Property > & rOutProperties );
+
+ void AddDefaultsToMap( ::chart::tPropertyValueMap & rOutMap );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/DataSeries.cxx b/chart2/source/model/main/DataSeries.cxx
new file mode 100644
index 0000000000..38f2c474b4
--- /dev/null
+++ b/chart2/source/model/main/DataSeries.cxx
@@ -0,0 +1,733 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DataSeries.hxx>
+#include <DataSeriesProperties.hxx>
+#include "DataPointProperties.hxx"
+#include <CharacterProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include "DataPoint.hxx"
+#include <DataSeriesHelper.hxx>
+#include <CloneHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <algorithm>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::osl::MutexGuard;
+
+namespace chart
+{
+const ::chart::tPropertyValueMap & StaticDataSeriesDefaults()
+{
+ static const ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::DataSeriesProperties::AddDefaultsToMap( aMap );
+ ::chart::CharacterProperties::AddDefaultsToMap( aMap );
+ float fDefaultCharHeight = 10.0;
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight );
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+} // namespace chart
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper& StaticDataSeriesInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper oHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ ::chart::DataSeriesProperties::AddPropertiesToVector( aProperties );
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return oHelper;
+};
+
+void lcl_SetParent(
+ const uno::Reference< uno::XInterface > & xChildInterface,
+ const uno::Reference< uno::XInterface > & xParentInterface )
+{
+ uno::Reference< container::XChild > xChild( xChildInterface, uno::UNO_QUERY );
+ if( xChild.is())
+ xChild->setParent( xParentInterface );
+}
+
+typedef std::map< sal_Int32, css::uno::Reference< css::beans::XPropertySet > >
+ lcl_tDataPointMap;
+
+void lcl_CloneAttributedDataPoints(
+ const lcl_tDataPointMap & rSource, lcl_tDataPointMap & rDestination,
+ const uno::Reference< uno::XInterface > & xSeries )
+{
+ for (auto const& elem : rSource)
+ {
+ Reference< beans::XPropertySet > xPoint( elem.second );
+ if( xPoint.is())
+ {
+ Reference< util::XCloneable > xCloneable( xPoint, uno::UNO_QUERY );
+ if( xCloneable.is())
+ {
+ xPoint.set( xCloneable->createClone(), uno::UNO_QUERY );
+ if( xPoint.is())
+ {
+ lcl_SetParent( xPoint, xSeries );
+ rDestination.emplace( elem.first, xPoint );
+ }
+ }
+ }
+ }
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+DataSeries::DataSeries() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+}
+
+DataSeries::DataSeries( const DataSeries & rOther ) :
+ impl::DataSeries_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ if( ! rOther.m_aDataSequences.empty())
+ {
+ CloneHelper::CloneRefVector(rOther.m_aDataSequences, m_aDataSequences );
+ ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder );
+ }
+
+ CloneHelper::CloneRefVector( rOther.m_aRegressionCurves, m_aRegressionCurves );
+ ModifyListenerHelper::addListenerToAllElements( m_aRegressionCurves, m_xModifyEventForwarder );
+
+ // add as listener to XPropertySet properties
+ Reference< beans::XPropertySet > xPropertySet;
+ uno::Any aValue;
+
+ getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder );
+
+ getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder );
+}
+
+// late initialization to call after copy-constructing
+void DataSeries::Init( const DataSeries & rOther )
+{
+ Reference< uno::XInterface > xThisInterface( static_cast< ::cppu::OWeakObject * >( this ));
+ if( ! rOther.m_aAttributedDataPoints.empty())
+ {
+ lcl_CloneAttributedDataPoints(
+ rOther.m_aAttributedDataPoints, m_aAttributedDataPoints, xThisInterface );
+ ModifyListenerHelper::addListenerToAllMapElements( m_aAttributedDataPoints, m_xModifyEventForwarder );
+ }
+
+ // add as parent to error bars
+ Reference< beans::XPropertySet > xPropertySet;
+ uno::Any aValue;
+
+ getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ lcl_SetParent( xPropertySet, xThisInterface );
+
+ getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ lcl_SetParent( xPropertySet, xThisInterface );
+}
+
+DataSeries::~DataSeries()
+{
+ try
+ {
+ ModifyListenerHelper::removeListenerFromAllMapElements( m_aAttributedDataPoints, m_xModifyEventForwarder );
+ ModifyListenerHelper::removeListenerFromAllElements( m_aRegressionCurves, m_xModifyEventForwarder );
+ ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences, m_xModifyEventForwarder );
+
+ // remove listener from XPropertySet properties
+ Reference< beans::XPropertySet > xPropertySet;
+ uno::Any aValue;
+
+ getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder );
+
+ getFastPropertyValue( aValue, DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL DataSeries::createClone()
+{
+ rtl::Reference<DataSeries> pNewSeries( new DataSeries( *this ));
+ // do initialization that uses uno references to the clone
+ pNewSeries->Init( *this );
+
+ return pNewSeries;
+}
+
+// ____ OPropertySet ____
+void DataSeries::GetDefaultValue( sal_Int32 nHandle, uno::Any& rDest ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticDataSeriesDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rDest.clear();
+ else
+ rDest = (*aFound).second;
+}
+
+// ____ OPropertySet ____
+::cppu::IPropertyArrayHelper & SAL_CALL DataSeries::getInfoHelper()
+{
+ return StaticDataSeriesInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL DataSeries::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropSetInfo =
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataSeriesInfoHelper() );
+ return xPropSetInfo;
+}
+
+void SAL_CALL DataSeries::getFastPropertyValue
+ ( uno::Any& rValue,
+ sal_Int32 nHandle ) const
+{
+ // special handling for get. set is not possible for this property
+ if( nHandle == DataSeriesProperties::PROP_DATASERIES_ATTRIBUTED_DATA_POINTS )
+ {
+ // TODO: only add those property sets that are really modified
+
+ rValue <<= comphelper::mapKeysToSequence(m_aAttributedDataPoints);
+ }
+ else
+ OPropertySet::getFastPropertyValue( rValue, nHandle );
+}
+
+void SAL_CALL DataSeries::setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle, const uno::Any& rValue )
+{
+ if( nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_Y
+ || nHandle == DataPointProperties::PROP_DATAPOINT_ERROR_BAR_X )
+ {
+ uno::Any aOldValue;
+ Reference< util::XModifyBroadcaster > xBroadcaster;
+ getFastPropertyValue( aOldValue, nHandle );
+ if( aOldValue.hasValue() &&
+ (aOldValue >>= xBroadcaster) &&
+ xBroadcaster.is())
+ {
+ ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder );
+ }
+
+ OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE );
+ if( rValue.hasValue() &&
+ (rValue >>= xBroadcaster) &&
+ xBroadcaster.is())
+ {
+ ModifyListenerHelper::addListener( xBroadcaster, m_xModifyEventForwarder );
+ }
+ }
+
+ ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+}
+
+Reference< beans::XPropertySet >
+ SAL_CALL DataSeries::getDataPointByIndex( sal_Int32 nIndex )
+{
+ Reference< beans::XPropertySet > xResult;
+
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences;
+ {
+ MutexGuard aGuard( m_aMutex );
+ aSequences = m_aDataSequences;
+ }
+
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aValuesSeries(
+ DataSeriesHelper::getAllDataSequencesByRole( aSequences , "values" ) );
+
+ if (aValuesSeries.empty())
+ throw lang::IndexOutOfBoundsException();
+
+ Reference< chart2::data::XDataSequence > xSeq( aValuesSeries.front()->getValues() );
+ if( 0 <= nIndex && nIndex < xSeq->getData().getLength() )
+ {
+ {
+ MutexGuard aGuard( m_aMutex );
+ tDataPointAttributeContainer::iterator aIt( m_aAttributedDataPoints.find( nIndex ) );
+ if( aIt != m_aAttributedDataPoints.end() )
+ xResult = (*aIt).second;
+ }
+ if( !xResult.is() )
+ {
+ Reference< beans::XPropertySet > xParentProperties;
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xParentProperties = this;
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ }
+
+ // create a new XPropertySet for this data point
+ xResult.set( new DataPoint( xParentProperties ) );
+ {
+ MutexGuard aGuard( m_aMutex );
+ m_aAttributedDataPoints[ nIndex ] = xResult;
+ }
+ ModifyListenerHelper::addListener( xResult, xModifyEventForwarder );
+ }
+ }
+
+ return xResult;
+}
+
+void SAL_CALL DataSeries::resetDataPoint( sal_Int32 nIndex )
+{
+ Reference< beans::XPropertySet > xDataPointProp;
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ tDataPointAttributeContainer::iterator aIt( m_aAttributedDataPoints.find( nIndex ));
+ if( aIt != m_aAttributedDataPoints.end())
+ {
+ xDataPointProp = (*aIt).second;
+ m_aAttributedDataPoints.erase(aIt);
+ }
+
+ }
+ if( xDataPointProp.is() )
+ {
+ Reference< util::XModifyBroadcaster > xBroadcaster( xDataPointProp, uno::UNO_QUERY );
+ if( xBroadcaster.is() && xModifyEventForwarder.is())
+ xBroadcaster->removeModifyListener( xModifyEventForwarder );
+ fireModifyEvent();
+ }
+}
+
+void SAL_CALL DataSeries::resetAllDataPoints()
+{
+ tDataPointAttributeContainer aOldAttributedDataPoints;
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ std::swap( aOldAttributedDataPoints, m_aAttributedDataPoints );
+ }
+ ModifyListenerHelper::removeListenerFromAllMapElements( aOldAttributedDataPoints, xModifyEventForwarder );
+ aOldAttributedDataPoints.clear();
+ fireModifyEvent();
+}
+
+// ____ XDataSink ____
+void SAL_CALL DataSeries::setData( const uno::Sequence< Reference< chart2::data::XLabeledDataSequence > >& aData )
+{
+ tDataSequenceContainer aOldDataSequences;
+ tDataSequenceContainer aNewDataSequences;
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ std::swap( aOldDataSequences, m_aDataSequences );
+ for (const auto & i : aData)
+ {
+ aNewDataSequences.push_back(i);
+ }
+ m_aDataSequences = aNewDataSequences;
+ }
+ ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences, xModifyEventForwarder );
+ ModifyListenerHelper::addListenerToAllElements( aNewDataSequences, xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+void DataSeries::setData( const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > >& aData )
+{
+ tDataSequenceContainer aOldDataSequences;
+ tDataSequenceContainer aNewDataSequences;
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ std::swap( aOldDataSequences, m_aDataSequences );
+ aNewDataSequences = aData;
+ m_aDataSequences = aNewDataSequences;
+ }
+ ModifyListenerHelper::removeListenerFromAllElements( aOldDataSequences, xModifyEventForwarder );
+ ModifyListenerHelper::addListenerToAllElements( aNewDataSequences, xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+// ____ XDataSource ____
+Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL DataSeries::getDataSequences()
+{
+ MutexGuard aGuard( m_aMutex );
+ return comphelper::containerToSequence<Reference< chart2::data::XLabeledDataSequence >>( m_aDataSequences );
+}
+
+// ____ XRegressionCurveContainer ____
+void SAL_CALL DataSeries::addRegressionCurve(
+ const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve )
+{
+ auto pRegressionCurve = dynamic_cast<RegressionCurveModel*>(xRegressionCurve.get());
+ assert(pRegressionCurve);
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ if( std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), pRegressionCurve )
+ != m_aRegressionCurves.end())
+ throw lang::IllegalArgumentException("curve not found", static_cast<cppu::OWeakObject*>(this), 1);
+ m_aRegressionCurves.push_back( pRegressionCurve );
+ }
+ ModifyListenerHelper::addListener( rtl::Reference<RegressionCurveModel>(pRegressionCurve), xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+void SAL_CALL DataSeries::removeRegressionCurve(
+ const uno::Reference< chart2::XRegressionCurve >& xRegressionCurve )
+{
+ if( !xRegressionCurve.is() )
+ throw container::NoSuchElementException();
+ auto pRegressionCurve = dynamic_cast<RegressionCurveModel*>(xRegressionCurve.get());
+ assert(pRegressionCurve);
+
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ tRegressionCurveContainerType::iterator aIt(
+ std::find( m_aRegressionCurves.begin(), m_aRegressionCurves.end(), pRegressionCurve ) );
+ if( aIt == m_aRegressionCurves.end())
+ throw container::NoSuchElementException(
+ "The given regression curve is no element of this series",
+ static_cast< uno::XWeak * >( this ));
+ m_aRegressionCurves.erase( aIt );
+ }
+
+ ModifyListenerHelper::removeListener( rtl::Reference<RegressionCurveModel>(pRegressionCurve), xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+uno::Sequence< uno::Reference< chart2::XRegressionCurve > > SAL_CALL DataSeries::getRegressionCurves()
+{
+ MutexGuard aGuard( m_aMutex );
+ return comphelper::containerToSequence<uno::Reference< chart2::XRegressionCurve >>( m_aRegressionCurves );
+}
+
+void SAL_CALL DataSeries::setRegressionCurves(
+ const Sequence< Reference< chart2::XRegressionCurve > >& aRegressionCurves )
+{
+ tRegressionCurveContainerType aOldCurves;
+ tRegressionCurveContainerType aNewCurves;
+ for (const auto & i : aRegressionCurves)
+ {
+ auto pRegressionCurve = dynamic_cast<RegressionCurveModel*>(i.get());
+ assert(pRegressionCurve);
+ aNewCurves.push_back(pRegressionCurve);
+ }
+ Reference< util::XModifyListener > xModifyEventForwarder;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xModifyEventForwarder = m_xModifyEventForwarder;
+ std::swap( aOldCurves, m_aRegressionCurves );
+ m_aRegressionCurves = aNewCurves;
+ }
+ ModifyListenerHelper::removeListenerFromAllElements( aOldCurves, xModifyEventForwarder );
+ ModifyListenerHelper::addListenerToAllElements( aNewCurves, xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL DataSeries::addModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL DataSeries::removeModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL DataSeries::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL DataSeries::disposing( const lang::EventObject& )
+{
+}
+
+// ____ OPropertySet ____
+void DataSeries::firePropertyChangeEvent()
+{
+ fireModifyEvent();
+}
+
+void DataSeries::fireModifyEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+using impl::DataSeries_Base;
+using ::property::OPropertySet;
+
+IMPLEMENT_FORWARD_XINTERFACE2( DataSeries, DataSeries_Base, OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataSeries, DataSeries_Base, OPropertySet )
+
+// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
+OUString SAL_CALL DataSeries::getImplementationName()
+{
+ return "com.sun.star.comp.chart.DataSeries";
+}
+
+sal_Bool SAL_CALL DataSeries::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL DataSeries::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart2.DataSeries",
+ "com.sun.star.chart2.DataPointProperties",
+ "com.sun.star.beans.PropertySet" };
+}
+
+static Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
+ const Sequence< Reference< chart2::data::XLabeledDataSequence > > & rDataSequences )
+{
+ Reference< chart2::data::XLabeledDataSequence > xResult;
+
+ for( auto const & labeledData : rDataSequences )
+ {
+ OSL_ENSURE( labeledData.is(), "empty LabeledDataSequence" );
+ // no values are set but a label exists
+ if( labeledData.is() &&
+ ( ! labeledData->getValues().is() &&
+ labeledData->getLabel().is()))
+ {
+ xResult.set( labeledData );
+ break;
+ }
+ }
+
+ return xResult;
+}
+
+static OUString lcl_getDataSequenceLabel( const Reference< chart2::data::XDataSequence > & xSequence )
+{
+ OUString aResult;
+
+ Reference< chart2::data::XTextualDataSequence > xTextSeq( xSequence, uno::UNO_QUERY );
+ if( xTextSeq.is())
+ {
+ Sequence< OUString > aSeq( xTextSeq->getTextualData());
+
+ const sal_Int32 nMax = aSeq.getLength() - 1;
+ OUStringBuffer aBuf;
+
+ for( sal_Int32 i = 0; i <= nMax; ++i )
+ {
+ aBuf.append( aSeq[i] );
+ if( i < nMax )
+ aBuf.append( ' ');
+ }
+ aResult = aBuf.makeStringAndClear();
+ }
+ else if( xSequence.is())
+ {
+ Sequence< uno::Any > aSeq( xSequence->getData());
+
+ const sal_Int32 nMax = aSeq.getLength() - 1;
+ OUString aVal;
+ OUStringBuffer aBuf;
+ double fNum = 0;
+
+ for( sal_Int32 i = 0; i <= nMax; ++i )
+ {
+ if( aSeq[i] >>= aVal )
+ {
+ aBuf.append( aVal );
+ if( i < nMax )
+ aBuf.append( ' ');
+ }
+ else if( aSeq[ i ] >>= fNum )
+ {
+ aBuf.append( fNum );
+ if( i < nMax )
+ aBuf.append( ' ');
+ }
+ }
+ aResult = aBuf.makeStringAndClear();
+ }
+
+ return aResult;
+}
+
+static OUString getLabelForLabeledDataSequence(
+ const Reference< chart2::data::XLabeledDataSequence > & xLabeledSeq )
+{
+ OUString aResult;
+ if( xLabeledSeq.is())
+ {
+ Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
+ if( xSeq.is() )
+ aResult = lcl_getDataSequenceLabel( xSeq );
+ if( !xSeq.is() || aResult.isEmpty() )
+ {
+ // no label set or label content is empty -> use auto-generated one
+ Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
+ if( xValueSeq.is() )
+ {
+ Sequence< OUString > aLabels( xValueSeq->generateLabel(
+ chart2::data::LabelOrigin_SHORT_SIDE ) );
+ // no labels returned is interpreted as: auto-generation not
+ // supported by sequence
+ if( aLabels.hasElements() )
+ aResult=aLabels[0];
+ else
+ {
+ //todo?: maybe use the index of the series as name
+ //but as the index may change it would be better to have such a name persistent
+ //what is not possible at the moment
+ //--> maybe use the identifier as part of the name ...
+ aResult = lcl_getDataSequenceLabel( xValueSeq );
+ }
+ }
+ }
+ }
+ return aResult;
+}
+
+OUString DataSeries::getLabelForRole( const OUString & rLabelSequenceRole )
+{
+ OUString aResult;
+
+ Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
+ ::chart::DataSeriesHelper::getDataSequenceByRole( this, rLabelSequenceRole ));
+ if( xLabeledSeq.is())
+ aResult = getLabelForLabeledDataSequence( xLabeledSeq );
+ else
+ {
+ // special case: labeled data series with only a label and no values may
+ // serve as label
+ xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( getDataSequences() ));
+ if( xLabeledSeq.is())
+ {
+ Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getLabel());
+ if( xSeq.is())
+ aResult = lcl_getDataSequenceLabel( xSeq );
+ }
+ }
+
+ return aResult;
+}
+
+static bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
+{
+ if (!xDataSequence.is())
+ return false;
+ uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ uno::Sequence< sal_Int32 > aHiddenValues;
+ try
+ {
+ xProp->getPropertyValue( "HiddenValues" ) >>= aHiddenValues;
+ if( !aHiddenValues.hasElements() )
+ return true;
+ }
+ catch( const uno::Exception& )
+ {
+ return true;
+ }
+ }
+ return xDataSequence->getData().hasElements();
+}
+
+bool DataSeries::hasUnhiddenData()
+{
+ MutexGuard aGuard( m_aMutex );
+
+ for(uno::Reference< chart2::data::XLabeledDataSequence > const & rDataSequence : m_aDataSequences)
+ {
+ if( !rDataSequence.is() )
+ continue;
+ if( lcl_SequenceHasUnhiddenData( rDataSequence->getValues() ) )
+ return true;
+ }
+ return false;
+}
+
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_DataSeries_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::DataSeries );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/DataSeriesProperties.cxx b/chart2/source/model/main/DataSeriesProperties.cxx
new file mode 100644
index 0000000000..e6d40feb5a
--- /dev/null
+++ b/chart2/source/model/main/DataSeriesProperties.cxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DataSeriesProperties.hxx>
+#include "DataPointProperties.hxx"
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+
+namespace chart
+{
+
+void DataSeriesProperties::AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "AttributedDataPoints",
+ PROP_DATASERIES_ATTRIBUTED_DATA_POINTS,
+ cppu::UnoType<uno::Sequence< sal_Int32 >>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "StackingDirection",
+ PROP_DATASERIES_STACKING_DIRECTION,
+ cppu::UnoType<chart2::StackingDirection>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "VaryColorsByPoint",
+ PROP_DATASERIES_VARY_COLORS_BY_POINT,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "AttachedAxisIndex",
+ PROP_DATASERIES_ATTACHED_AXIS_INDEX,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ShowLegendEntry",
+ PROP_DATASERIES_SHOW_LEGEND_ENTRY,
+ cppu::UnoType<sal_Bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "DeletedLegendEntries",
+ PROP_DATASERIES_DELETED_LEGEND_ENTRIES,
+ cppu::UnoType<uno::Sequence<sal_Int32>>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "ShowCustomLeaderLines",
+ PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES,
+ cppu::UnoType<sal_Bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // add properties of service DataPointProperties
+ DataPointProperties::AddPropertiesToVector( rOutProperties );
+}
+
+void DataSeriesProperties::AddDefaultsToMap(
+ tPropertyValueMap & rOutMap )
+{
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_STACKING_DIRECTION, chart2::StackingDirection_NO_STACKING );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_VARY_COLORS_BY_POINT, false );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_ATTACHED_AXIS_INDEX, sal_Int32(0) );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_SHOW_LEGEND_ENTRY, true );
+ PropertyHelper::setPropertyValueDefault( rOutMap, PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES, true );
+
+ // PROP_DATASERIES_ATTRIBUTED_DATA_POINTS has no default
+
+ // add properties of service DataPointProperties
+ DataPointProperties::AddDefaultsToMap( rOutMap );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/DataTable.cxx b/chart2/source/model/main/DataTable.cxx
new file mode 100644
index 0000000000..6cec190615
--- /dev/null
+++ b/chart2/source/model/main/DataTable.cxx
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <DataTable.hxx>
+
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <CharacterProperties.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+
+#include <algorithm>
+
+using namespace css;
+
+namespace
+{
+/** DataTable Properties */
+enum
+{
+ DataTableProperty_HorizontalBorder,
+ DataTableProperty_VerticalBorder,
+ DataTableProperty_Outilne,
+ DataTableProperty_Keys,
+};
+
+void lcl_AddPropertiesToVector(std::vector<beans::Property>& rProps)
+{
+ auto const nBound = beans::PropertyAttribute::BOUND;
+ auto const nMaybeDefault = beans::PropertyAttribute::MAYBEDEFAULT;
+
+ rProps.emplace_back("HBorder", DataTableProperty_HorizontalBorder, cppu::UnoType<bool>::get(),
+ nBound | nMaybeDefault);
+ rProps.emplace_back("VBorder", DataTableProperty_VerticalBorder, cppu::UnoType<bool>::get(),
+ nBound | nMaybeDefault);
+ rProps.emplace_back("Outline", DataTableProperty_Outilne, cppu::UnoType<bool>::get(),
+ nBound | nMaybeDefault);
+ rProps.emplace_back("Keys", DataTableProperty_Keys, cppu::UnoType<bool>::get(),
+ nBound | nMaybeDefault);
+}
+
+const ::chart::tPropertyValueMap& StaticDataTableDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []() {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap(aMap);
+ ::chart::FillProperties::AddDefaultsToMap(aMap);
+ ::chart::CharacterProperties::AddDefaultsToMap(aMap);
+
+ ::chart::PropertyHelper::setPropertyValueDefault(aMap, DataTableProperty_HorizontalBorder,
+ false);
+ ::chart::PropertyHelper::setPropertyValueDefault(aMap, DataTableProperty_VerticalBorder,
+ false);
+ ::chart::PropertyHelper::setPropertyValueDefault(aMap, DataTableProperty_Outilne, false);
+ ::chart::PropertyHelper::setPropertyValueDefault(aMap, DataTableProperty_Keys, false);
+
+ ::chart::PropertyHelper::setPropertyValue(
+ aMap, ::chart::LinePropertiesHelper::PROP_LINE_WIDTH, uno::Any(sal_Int32(1)));
+
+ ::chart::PropertyHelper::setPropertyValueDefault(
+ aMap, ::chart::FillProperties::PROP_FILL_STYLE, drawing::FillStyle_NONE);
+
+ float fDefaultCharHeight = 10.0;
+ ::chart::PropertyHelper::setPropertyValue(
+ aMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight);
+ ::chart::PropertyHelper::setPropertyValue(
+ aMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight);
+ ::chart::PropertyHelper::setPropertyValue(
+ aMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight);
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+
+cppu::OPropertyArrayHelper& StaticDataTableInfoHelper()
+{
+ static cppu::OPropertyArrayHelper aPropHelper = []() {
+ std::vector<beans::Property> aProperties;
+ lcl_AddPropertiesToVector(aProperties);
+ ::chart::LinePropertiesHelper::AddPropertiesToVector(aProperties);
+ ::chart::FillProperties::AddPropertiesToVector(aProperties);
+ ::chart::CharacterProperties::AddPropertiesToVector(aProperties);
+ std::sort(aProperties.begin(), aProperties.end(), ::chart::PropertyNameLess());
+
+ return comphelper::containerToSequence(aProperties);
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+DataTable::DataTable()
+ : m_xModifyEventForwarder(new ModifyEventForwarder())
+{
+}
+
+DataTable::DataTable(const DataTable& rOther)
+ : DataTable_Base(rOther)
+ , ::property::OPropertySet(rOther)
+ , m_xModifyEventForwarder(new ModifyEventForwarder())
+{
+}
+
+DataTable::~DataTable() = default;
+
+// ____ XCloneable ____
+uno::Reference<util::XCloneable> SAL_CALL DataTable::createClone()
+{
+ return uno::Reference<util::XCloneable>(new DataTable(*this));
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL DataTable::addModifyListener(const uno::Reference<util::XModifyListener>& aListener)
+{
+ m_xModifyEventForwarder->addModifyListener(aListener);
+}
+
+void SAL_CALL
+DataTable::removeModifyListener(const uno::Reference<util::XModifyListener>& aListener)
+{
+ m_xModifyEventForwarder->removeModifyListener(aListener);
+}
+
+// ____ XModifyListener ____
+void SAL_CALL DataTable::modified(const lang::EventObject& aEvent)
+{
+ m_xModifyEventForwarder->modified(aEvent);
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL DataTable::disposing(const lang::EventObject& /* Source */)
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void DataTable::firePropertyChangeEvent()
+{
+ m_xModifyEventForwarder->modified(lang::EventObject(static_cast<uno::XWeak*>(this)));
+}
+
+// ____ OPropertySet ____
+void DataTable::GetDefaultValue(sal_Int32 nHandle, uno::Any& rAny) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticDataTableDefaults();
+ auto aFound = rStaticDefaults.find(nHandle);
+ if (aFound == rStaticDefaults.end())
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper& SAL_CALL DataTable::getInfoHelper()
+{
+ return StaticDataTableInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference<beans::XPropertySetInfo> SAL_CALL DataTable::getPropertySetInfo()
+{
+ static uno::Reference<beans::XPropertySetInfo> xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDataTableInfoHelper()));
+ return xPropertySetInfo;
+}
+
+// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
+OUString SAL_CALL DataTable::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.DataTable";
+}
+
+sal_Bool SAL_CALL DataTable::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL DataTable::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.DataTable", "com.sun.star.beans.PropertySet",
+ "com.sun.star.drawing.FillProperties", "com.sun.star.drawing.LineProperties",
+ "com.sun.star.style.CharacterProperties" };
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2(DataTable, DataTable_Base, ::property::OPropertySet)
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(DataTable, DataTable_Base, ::property::OPropertySet)
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_comp_chart2_DataTable_get_implementation(
+ css::uno::XComponentContext* /*pComponentContext*/, uno::Sequence<uno::Any> const& /*rAny*/)
+{
+ return cppu::acquire(new ::chart::DataTable);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/Diagram.cxx b/chart2/source/model/main/Diagram.cxx
new file mode 100644
index 0000000000..db7be686b0
--- /dev/null
+++ b/chart2/source/model/main/Diagram.cxx
@@ -0,0 +1,2288 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <Diagram.hxx>
+#include <AxisHelper.hxx>
+#include <BaseGFXHelper.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <ChartType.hxx>
+#include <DataSeriesHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include "Wall.hxx"
+#include <ModifyListenerHelper.hxx>
+#include <UserDefinedProperties.hxx>
+#include <ConfigColorScheme.hxx>
+#include <DiagramHelper.hxx>
+#include <ThreeDHelper.hxx>
+#include <CloneHelper.hxx>
+#include <SceneProperties.hxx>
+#include <unonames.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <Legend.hxx>
+#include <Axis.hxx>
+#include <DataTable.hxx>
+#include <servicenames_charttypes.hxx>
+#include <defines.hxx>
+
+#include <basegfx/numeric/ftools.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <editeng/unoprnms.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/math.hxx>
+#include <tools/helpers.hxx>
+
+#include <algorithm>
+#include <utility>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans::PropertyAttribute;
+using namespace ::chart::SceneProperties;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::osl::MutexGuard;
+
+namespace
+{
+
+enum
+{
+ PROP_DIAGRAM_REL_POS,
+ PROP_DIAGRAM_REL_SIZE,
+ PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS,
+ PROP_DIAGRAM_SORT_BY_X_VALUES,
+ PROP_DIAGRAM_CONNECT_BARS,
+ PROP_DIAGRAM_GROUP_BARS_PER_AXIS,
+ PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS,
+ PROP_DIAGRAM_STARTING_ANGLE,
+ PROP_DIAGRAM_RIGHT_ANGLED_AXES,
+ PROP_DIAGRAM_PERSPECTIVE,
+ PROP_DIAGRAM_ROTATION_HORIZONTAL,
+ PROP_DIAGRAM_ROTATION_VERTICAL,
+ PROP_DIAGRAM_MISSING_VALUE_TREATMENT,
+ PROP_DIAGRAM_3DRELATIVEHEIGHT,
+ PROP_DIAGRAM_DATATABLEHBORDER,
+ PROP_DIAGRAM_DATATABLEVBORDER,
+ PROP_DIAGRAM_DATATABLEOUTLINE,
+ PROP_DIAGRAM_EXTERNALDATA
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "RelativePosition",
+ PROP_DIAGRAM_REL_POS,
+ cppu::UnoType<chart2::RelativePosition>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "RelativeSize",
+ PROP_DIAGRAM_REL_SIZE,
+ cppu::UnoType<chart2::RelativeSize>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "PosSizeExcludeAxes",
+ PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( CHART_UNONAME_SORT_BY_XVALUES,
+ PROP_DIAGRAM_SORT_BY_X_VALUES,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ConnectBars",
+ PROP_DIAGRAM_CONNECT_BARS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "GroupBarsPerAxis",
+ PROP_DIAGRAM_GROUP_BARS_PER_AXIS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "IncludeHiddenCells",
+ PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "StartingAngle",
+ PROP_DIAGRAM_STARTING_ANGLE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "RightAngledAxes",
+ PROP_DIAGRAM_RIGHT_ANGLED_AXES,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "Perspective",
+ PROP_DIAGRAM_PERSPECTIVE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "RotationHorizontal",
+ PROP_DIAGRAM_ROTATION_HORIZONTAL,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "RotationVertical",
+ PROP_DIAGRAM_ROTATION_VERTICAL,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "MissingValueTreatment",
+ PROP_DIAGRAM_MISSING_VALUE_TREATMENT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "3DRelativeHeight",
+ PROP_DIAGRAM_3DRELATIVEHEIGHT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "ExternalData",
+ PROP_DIAGRAM_EXTERNALDATA,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID );
+}
+
+const ::chart::tPropertyValueMap& StaticDiagramDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_SORT_BY_X_VALUES, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_CONNECT_BARS, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_GROUP_BARS_PER_AXIS, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_INCLUDE_HIDDEN_CELLS, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aMap, PROP_DIAGRAM_RIGHT_ANGLED_AXES, false );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aMap, PROP_DIAGRAM_STARTING_ANGLE, 90 );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aMap, PROP_DIAGRAM_3DRELATIVEHEIGHT, 100 );
+ ::chart::SceneProperties::AddDefaultsToMap( aMap );
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& StaticDiagramInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::SceneProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return ::cppu::OPropertyArrayHelper( aProperties.data(), aProperties.size() );
+ }();
+ return aPropHelper;
+};
+
+const uno::Reference< beans::XPropertySetInfo >& StaticDiagramInfo()
+{
+ static const uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticDiagramInfoHelper() ) );
+ return xPropertySetInfo;
+};
+
+void lcl_CloneCoordinateSystems(
+ const ::chart::Diagram::tCoordinateSystemContainerType & rSource,
+ ::chart::Diagram::tCoordinateSystemContainerType & rDestination )
+{
+ for( rtl::Reference< ::chart::BaseCoordinateSystem > const & i : rSource )
+ {
+ auto xClone = i->createClone();
+ ::chart::BaseCoordinateSystem* pClone = dynamic_cast<::chart::BaseCoordinateSystem*>(xClone.get());
+ assert(pClone);
+ rDestination.push_back( pClone );
+ }
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+Diagram::Diagram( uno::Reference< uno::XComponentContext > xContext ) :
+ m_xContext(std::move( xContext )),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ // Set camera position to a default position (that should be set hard, so
+ // that it will be exported. The property default is a camera looking
+ // straight ono the scene). These defaults have been acquired from the old
+ // chart implementation.
+ setFastPropertyValue_NoBroadcast(
+ PROP_SCENE_CAMERA_GEOMETRY, uno::Any(
+ ThreeDHelper::getDefaultCameraGeometry()));
+}
+
+Diagram::Diagram( const Diagram & rOther ) :
+ impl::Diagram_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xContext( rOther.m_xContext ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ lcl_CloneCoordinateSystems( rOther.m_aCoordSystems, m_aCoordSystems );
+ for (auto & xSystem : m_aCoordSystems)
+ xSystem->addModifyListener(m_xModifyEventForwarder);
+
+ if ( rOther.m_xWall )
+ m_xWall = new Wall( *rOther.m_xWall );
+ if ( rOther.m_xFloor )
+ m_xFloor = new Wall( *rOther.m_xFloor );
+ m_xTitle.set( CloneHelper::CreateRefClone< chart2::XTitle >()( rOther.m_xTitle ));
+ if (rOther.m_xLegend)
+ m_xLegend = new Legend(*rOther.m_xLegend);
+ if (rOther.m_xDataTable)
+ m_xDataTable = new DataTable(*rOther.m_xDataTable);
+
+ if ( m_xWall )
+ m_xWall->addModifyListener( m_xModifyEventForwarder );
+ if ( m_xFloor )
+ m_xFloor->addModifyListener( m_xModifyEventForwarder );
+ ModifyListenerHelper::addListener( m_xTitle, m_xModifyEventForwarder );
+ ModifyListenerHelper::addListener( m_xLegend, m_xModifyEventForwarder );
+}
+
+Diagram::~Diagram()
+{
+ try
+ {
+ for (auto & xSystem : m_aCoordSystems)
+ xSystem->removeModifyListener(m_xModifyEventForwarder);
+
+ if ( m_xWall )
+ m_xWall->removeModifyListener( m_xModifyEventForwarder );
+ if ( m_xFloor )
+ m_xFloor->removeModifyListener( m_xModifyEventForwarder );
+ ModifyListenerHelper::removeListener( m_xTitle, m_xModifyEventForwarder );
+ ModifyListenerHelper::removeListener( m_xLegend, m_xModifyEventForwarder );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// ____ XDiagram ____
+uno::Reference< beans::XPropertySet > SAL_CALL Diagram::getWall()
+{
+ rtl::Reference< Wall > xRet;
+ bool bAddListener = false;
+ {
+ MutexGuard aGuard( m_aMutex );
+ if( !m_xWall.is() )
+ {
+ m_xWall.set( new Wall() );
+ bAddListener = true;
+ }
+ xRet = m_xWall;
+ }
+ if(bAddListener)
+ xRet->addModifyListener( m_xModifyEventForwarder );
+ return xRet;
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL Diagram::getFloor()
+{
+ rtl::Reference< Wall > xRet;
+ bool bAddListener = false;
+ {
+ MutexGuard aGuard( m_aMutex );
+ if( !m_xFloor.is() )
+ {
+ m_xFloor.set( new Wall() );
+ bAddListener = true;
+ }
+ xRet = m_xFloor;
+ }
+ if(bAddListener)
+ xRet->addModifyListener( m_xModifyEventForwarder );
+ return xRet;
+}
+
+uno::Reference< chart2::XLegend > SAL_CALL Diagram::getLegend()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xLegend;
+}
+
+rtl::Reference< ::chart::Legend > Diagram::getLegend2() const
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xLegend;
+}
+
+void SAL_CALL Diagram::setLegend( const uno::Reference< chart2::XLegend >& xNewLegend )
+{
+ auto pLegend = dynamic_cast<Legend*>(xNewLegend.get());
+ assert(!xNewLegend || pLegend);
+ setLegend(rtl::Reference< Legend >(pLegend));
+}
+
+void Diagram::setLegend( const rtl::Reference< Legend >& xNewLegend )
+{
+ rtl::Reference< Legend > xOldLegend;
+ {
+ MutexGuard aGuard( m_aMutex );
+ if( m_xLegend == xNewLegend )
+ return;
+ xOldLegend = m_xLegend;
+ m_xLegend = xNewLegend;
+ }
+ if( xOldLegend.is())
+ ModifyListenerHelper::removeListener( xOldLegend, m_xModifyEventForwarder );
+ if( xNewLegend.is())
+ ModifyListenerHelper::addListener( xNewLegend, m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+Reference< chart2::XColorScheme > SAL_CALL Diagram::getDefaultColorScheme()
+{
+ Reference< chart2::XColorScheme > xRet;
+ {
+ MutexGuard aGuard( m_aMutex );
+ xRet = m_xColorScheme;
+ }
+
+ if( !xRet.is())
+ {
+ xRet.set( createConfigColorScheme( m_xContext ));
+ MutexGuard aGuard( m_aMutex );
+ m_xColorScheme = xRet;
+ }
+ return xRet;
+}
+
+void SAL_CALL Diagram::setDefaultColorScheme( const Reference< chart2::XColorScheme >& xColorScheme )
+{
+ {
+ MutexGuard aGuard( m_aMutex );
+ m_xColorScheme.set( xColorScheme );
+ }
+ fireModifyEvent();
+}
+
+void SAL_CALL Diagram::setDiagramData(
+ const Reference< chart2::data::XDataSource >& xDataSource,
+ const Sequence< beans::PropertyValue >& aArguments )
+{
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = new ::chart::ChartTypeManager( m_xContext );
+ Diagram::tTemplateWithServiceName aTemplateAndService = getTemplate( xChartTypeManager );
+ rtl::Reference< ::chart::ChartTypeTemplate > xTemplate( aTemplateAndService.xChartTypeTemplate );
+ if( !xTemplate.is() )
+ xTemplate = xChartTypeManager->createTemplate( "com.sun.star.chart2.template.Column" );
+ if(!xTemplate.is())
+ return;
+ xTemplate->changeDiagramData( rtl::Reference< ::chart::Diagram >(this), xDataSource, aArguments );
+}
+
+// ____ XTitled ____
+uno::Reference< chart2::XTitle > SAL_CALL Diagram::getTitleObject()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xTitle;
+}
+
+void SAL_CALL Diagram::setTitleObject( const uno::Reference< chart2::XTitle >& xNewTitle )
+{
+ Reference< chart2::XTitle > xOldTitle;
+ {
+ MutexGuard aGuard( m_aMutex );
+ if( m_xTitle == xNewTitle )
+ return;
+ xOldTitle = m_xTitle;
+ m_xTitle = xNewTitle;
+ }
+ if( xOldTitle.is())
+ ModifyListenerHelper::removeListener( xOldTitle, m_xModifyEventForwarder );
+ if( xNewTitle.is())
+ ModifyListenerHelper::addListener( xNewTitle, m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+// ____ X3DDefaultSetter ____
+void SAL_CALL Diagram::set3DSettingsToDefault()
+{
+ setPropertyToDefault( "D3DSceneDistance");
+ setPropertyToDefault( "D3DSceneFocalLength");
+ setDefaultRotation();
+ setDefaultIllumination();
+}
+
+void SAL_CALL Diagram::setDefaultRotation()
+{
+ bool bPieOrDonut( isPieOrDonutChart() );
+ setDefaultRotation( bPieOrDonut );
+}
+
+static ::basegfx::B3DHomMatrix lcl_getCompleteRotationMatrix( Diagram& rDiagram )
+{
+ ::basegfx::B3DHomMatrix aCompleteRotation;
+ double fXAngleRad=0.0;
+ double fYAngleRad=0.0;
+ double fZAngleRad=0.0;
+ rDiagram.getRotationAngle( fXAngleRad, fYAngleRad, fZAngleRad );
+ aCompleteRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
+ return aCompleteRotation;
+}
+static void lcl_RotateLightSource( Diagram& rDiagram
+ , int nLightSourceDirectionProp
+ , int nLightSourceOnProp
+ , const ::basegfx::B3DHomMatrix& rRotationMatrix )
+{
+ bool bLightOn = false;
+ if( !(rDiagram.getFastPropertyValue( nLightSourceOnProp ) >>= bLightOn) )
+ return;
+
+ if( bLightOn )
+ {
+ drawing::Direction3D aLight;
+ if( rDiagram.getFastPropertyValue( nLightSourceDirectionProp ) >>= aLight )
+ {
+ ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aLight ) );
+ aLightVector = rRotationMatrix*aLightVector;
+
+ rDiagram.setFastPropertyValue( nLightSourceDirectionProp
+ , uno::Any( BaseGFXHelper::B3DVectorToDirection3D( aLightVector ) ) );
+ }
+ }
+}
+
+static void lcl_setLightsForScheme( Diagram& rDiagram, const ThreeDLookScheme& rScheme )
+{
+ if( rScheme == ThreeDLookScheme::ThreeDLookScheme_Unknown)
+ return;
+
+ // "D3DSceneLightOn2" / UNO_NAME_3D_SCENE_LIGHTON_2
+ rDiagram.setFastPropertyValue( PROP_SCENE_LIGHT_ON_2, uno::Any( true ) );
+
+ rtl::Reference< ChartType > xChartType( rDiagram.getChartTypeByIndex( 0 ) );
+ uno::Any aADirection( rScheme == ThreeDLookScheme::ThreeDLookScheme_Simple
+ ? ChartTypeHelper::getDefaultSimpleLightDirection(xChartType)
+ : ChartTypeHelper::getDefaultRealisticLightDirection(xChartType) );
+
+ // "D3DSceneLightDirection2" / UNO_NAME_3D_SCENE_LIGHTDIRECTION_2
+ rDiagram.setFastPropertyValue( PROP_SCENE_LIGHT_DIRECTION_2, aADirection );
+ //rotate light direction when right angled axes are off but supported
+ {
+ bool bRightAngledAxes = false;
+ rDiagram.getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES ) >>= bRightAngledAxes; // "RightAngledAxes"
+ if(!bRightAngledAxes)
+ {
+ if( ChartTypeHelper::isSupportingRightAngledAxes( xChartType ) )
+ {
+ ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( rDiagram ) );
+ BaseGFXHelper::ReduceToRotationMatrix( aRotation );
+ // "D3DSceneLightDirection2", "D3DSceneLightOn2"
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_2, PROP_SCENE_LIGHT_ON_2, aRotation );
+ }
+ }
+ }
+
+ sal_Int32 nColor = ::chart::ChartTypeHelper::getDefaultDirectLightColor(
+ rScheme == ThreeDLookScheme::ThreeDLookScheme_Simple, xChartType);
+ // "D3DSceneLightColor2" / UNO_NAME_3D_SCENE_LIGHTCOLOR_2
+ rDiagram.setFastPropertyValue( PROP_SCENE_LIGHT_COLOR_2, uno::Any( nColor ) );
+
+ sal_Int32 nAmbientColor = ::chart::ChartTypeHelper::getDefaultAmbientLightColor(
+ rScheme == ThreeDLookScheme::ThreeDLookScheme_Simple, xChartType);
+ // "D3DSceneAmbientColor" / UNO_NAME_3D_SCENE_AMBIENTCOLOR
+ rDiagram.setFastPropertyValue( PROP_SCENE_AMBIENT_COLOR, uno::Any( nAmbientColor ) );
+}
+
+void SAL_CALL Diagram::setDefaultIllumination()
+{
+ drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH );
+ try
+ {
+ // "D3DSceneShadeMode"
+ getFastPropertyValue( PROP_SCENE_SHADE_MODE )>>= aShadeMode;
+ // "D3DSceneLightOn1" / UNO_NAME_3D_SCENE_LIGHTON_1
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_1, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_3, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_4, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_5, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_6, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_7, uno::Any( false ) );
+ setFastPropertyValue( PROP_SCENE_LIGHT_ON_8, uno::Any( false ) );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ ThreeDLookScheme aScheme = (aShadeMode == drawing::ShadeMode_FLAT)
+ ? ThreeDLookScheme::ThreeDLookScheme_Simple
+ : ThreeDLookScheme::ThreeDLookScheme_Realistic;
+ lcl_setLightsForScheme( *this, aScheme );
+}
+
+// ____ XCoordinateSystemContainer ____
+void SAL_CALL Diagram::addCoordinateSystem(
+ const uno::Reference< chart2::XCoordinateSystem >& aCoordSys )
+{
+ ::chart::BaseCoordinateSystem* pCoordSys = dynamic_cast<::chart::BaseCoordinateSystem*>(aCoordSys.get());
+ assert(pCoordSys);
+ {
+ MutexGuard aGuard( m_aMutex );
+ if( std::find( m_aCoordSystems.begin(), m_aCoordSystems.end(), pCoordSys )
+ != m_aCoordSystems.end())
+ throw lang::IllegalArgumentException("coordsys not found", static_cast<cppu::OWeakObject*>(this), 1);
+
+ if( !m_aCoordSystems.empty() )
+ {
+ OSL_FAIL( "more than one coordinatesystem is not supported yet by the fileformat" );
+ return;
+ }
+ m_aCoordSystems.push_back( pCoordSys );
+ }
+ ModifyListenerHelper::addListener( aCoordSys, m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+void SAL_CALL Diagram::removeCoordinateSystem(
+ const uno::Reference< chart2::XCoordinateSystem >& aCoordSys )
+{
+ ::chart::BaseCoordinateSystem* pCoordSys = dynamic_cast<::chart::BaseCoordinateSystem*>(aCoordSys.get());
+ assert(pCoordSys);
+ {
+ MutexGuard aGuard( m_aMutex );
+ auto aIt = std::find( m_aCoordSystems.begin(), m_aCoordSystems.end(), pCoordSys );
+ if( aIt == m_aCoordSystems.end())
+ throw container::NoSuchElementException(
+ "The given coordinate-system is no element of the container",
+ static_cast< uno::XWeak * >( this ));
+ m_aCoordSystems.erase( aIt );
+ }
+ ModifyListenerHelper::removeListener( aCoordSys, m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > SAL_CALL Diagram::getCoordinateSystems()
+{
+ MutexGuard aGuard( m_aMutex );
+ return comphelper::containerToSequence<uno::Reference< chart2::XCoordinateSystem >>( m_aCoordSystems );
+}
+
+Diagram::tCoordinateSystemContainerType Diagram::getBaseCoordinateSystems() const
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_aCoordSystems;
+}
+
+void SAL_CALL Diagram::setCoordinateSystems(
+ const Sequence< Reference< chart2::XCoordinateSystem > >& aCoordinateSystems )
+{
+ tCoordinateSystemContainerType aNew;
+ tCoordinateSystemContainerType aOld;
+ if( aCoordinateSystems.hasElements() )
+ {
+ OSL_ENSURE( aCoordinateSystems.getLength()<=1, "more than one coordinatesystem is not supported yet by the fileformat" );
+ ::chart::BaseCoordinateSystem* pCoordSys = dynamic_cast<::chart::BaseCoordinateSystem*>(aCoordinateSystems[0].get());
+ assert(pCoordSys);
+ aNew.push_back( pCoordSys );
+ }
+ {
+ MutexGuard aGuard( m_aMutex );
+ std::swap( aOld, m_aCoordSystems );
+ m_aCoordSystems = aNew;
+ }
+ for (auto & xSystem : aOld)
+ xSystem->removeModifyListener(m_xModifyEventForwarder);
+ for (auto & xSystem : aNew)
+ xSystem->addModifyListener(m_xModifyEventForwarder);
+ fireModifyEvent();
+}
+
+void Diagram::setCoordinateSystems(
+ const std::vector< rtl::Reference< BaseCoordinateSystem > >& aCoordinateSystems )
+{
+ tCoordinateSystemContainerType aNew;
+ tCoordinateSystemContainerType aOld;
+ if( !aCoordinateSystems.empty() )
+ {
+ OSL_ENSURE( aCoordinateSystems.size()<=1, "more than one coordinatesystem is not supported yet by the fileformat" );
+ aNew.push_back( aCoordinateSystems[0] );
+ }
+ {
+ MutexGuard aGuard( m_aMutex );
+ std::swap( aOld, m_aCoordSystems );
+ m_aCoordSystems = aNew;
+ }
+ for (auto & xSystem : aOld)
+ xSystem->removeModifyListener(m_xModifyEventForwarder);
+ for (auto & xSystem : aNew)
+ xSystem->addModifyListener(m_xModifyEventForwarder);
+ fireModifyEvent();
+}
+
+// ____ XCloneable ____
+Reference< util::XCloneable > SAL_CALL Diagram::createClone()
+{
+ MutexGuard aGuard( m_aMutex );
+ return Reference< util::XCloneable >( new Diagram( *this ));
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL Diagram::addModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL Diagram::removeModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL Diagram::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL Diagram::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void Diagram::firePropertyChangeEvent()
+{
+ fireModifyEvent();
+}
+
+void Diagram::fireModifyEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+// ____ OPropertySet ____
+void Diagram::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticDiagramDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+// ____ OPropertySet ____
+::cppu::IPropertyArrayHelper & SAL_CALL Diagram::getInfoHelper()
+{
+ return StaticDiagramInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL Diagram::getPropertySetInfo()
+{
+ return StaticDiagramInfo();
+}
+
+// ____ XFastPropertySet ____
+void SAL_CALL Diagram::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+{
+ //special treatment for some 3D properties
+ if( nHandle == PROP_DIAGRAM_PERSPECTIVE )
+ {
+ sal_Int32 fPerspective = 20;
+ if( rValue >>=fPerspective )
+ setCameraDistance( ThreeDHelper::PerspectiveToCameraDistance( fPerspective ) );
+ }
+ else if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL
+ || nHandle == PROP_DIAGRAM_ROTATION_VERTICAL )
+ {
+ sal_Int32 nNewAngleDegree = 0;
+ if( rValue >>=nNewAngleDegree )
+ {
+ sal_Int32 nHorizontal, nVertical;
+ getRotation( nHorizontal, nVertical );
+ if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL )
+ nHorizontal = nNewAngleDegree;
+ else
+ nVertical = nNewAngleDegree;
+ setRotation( nHorizontal, nVertical );
+ }
+ }
+ else
+ ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+}
+
+void SAL_CALL Diagram::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ //special treatment for some 3D properties
+ if( nHandle == PROP_DIAGRAM_PERSPECTIVE )
+ {
+ sal_Int32 nPerspective = ::basegfx::fround( ThreeDHelper::CameraDistanceToPerspective(
+ const_cast< Diagram* >( this )->getCameraDistance() ) );
+ rValue <<= nPerspective;
+ }
+ else if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL
+ || nHandle == PROP_DIAGRAM_ROTATION_VERTICAL )
+ {
+ sal_Int32 nHorizontal, nVertical;
+ const_cast< Diagram* >( this )->getRotation( nHorizontal, nVertical );
+ sal_Int32 nAngleDegree = 0;
+ if( nHandle == PROP_DIAGRAM_ROTATION_HORIZONTAL )
+ nAngleDegree = nHorizontal;
+ else
+ nAngleDegree = nVertical;
+ rValue <<= nAngleDegree;
+ }
+ else
+ ::property::OPropertySet::getFastPropertyValue( rValue,nHandle );
+}
+
+uno::Reference<chart2::XDataTable> SAL_CALL Diagram::getDataTable()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xDataTable;
+}
+
+rtl::Reference<::chart::DataTable> Diagram::getDataTableRef() const
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_xDataTable;
+}
+
+void SAL_CALL Diagram::setDataTable(const uno::Reference<chart2::XDataTable>& xDataTable)
+{
+ auto* pDataTable = dynamic_cast<DataTable*>(xDataTable.get());
+ assert(!xDataTable || pDataTable);
+ setDataTable(rtl::Reference<DataTable>(pDataTable));
+}
+
+void Diagram::setDataTable(const rtl::Reference<DataTable>& xNewDataTable)
+{
+ rtl::Reference<DataTable> xOldDataTable;
+ {
+ MutexGuard aGuard(m_aMutex);
+ if (m_xDataTable == xNewDataTable)
+ return;
+ xOldDataTable = m_xDataTable;
+ m_xDataTable = xNewDataTable;
+ }
+ if (xOldDataTable.is())
+ ModifyListenerHelper::removeListener(xOldDataTable, m_xModifyEventForwarder);
+ if (xNewDataTable.is())
+ ModifyListenerHelper::addListener(xNewDataTable, m_xModifyEventForwarder);
+ fireModifyEvent();
+}
+
+using impl::Diagram_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( Diagram, Diagram_Base, ::property::OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( Diagram, Diagram_Base, ::property::OPropertySet )
+
+// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
+OUString SAL_CALL Diagram::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.Diagram";
+}
+
+sal_Bool SAL_CALL Diagram::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL Diagram::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart2.Diagram",
+ "com.sun.star.layout.LayoutElement",
+ "com.sun.star.beans.PropertySet" };
+}
+
+DiagramPositioningMode Diagram::getDiagramPositioningMode()
+{
+ DiagramPositioningMode eMode = DiagramPositioningMode::Auto;
+ chart2::RelativePosition aRelPos;
+ chart2::RelativeSize aRelSize;
+ if( (getFastPropertyValue(PROP_DIAGRAM_REL_POS) >>= aRelPos ) &&
+ (getFastPropertyValue(PROP_DIAGRAM_REL_SIZE) >>= aRelSize ) )
+ {
+ bool bPosSizeExcludeAxes=false;
+ getFastPropertyValue(PROP_DIAGRAM_POSSIZE_EXCLUDE_LABELS) >>= bPosSizeExcludeAxes;
+ if( bPosSizeExcludeAxes )
+ eMode = DiagramPositioningMode::Excluding;
+ else
+ eMode = DiagramPositioningMode::Including;
+ }
+ return eMode;
+}
+
+
+sal_Int32 Diagram::getCorrectedMissingValueTreatment(
+ const rtl::Reference< ChartType >& xChartType )
+{
+ sal_Int32 nResult = css::chart::MissingValueTreatment::LEAVE_GAP;
+ const uno::Sequence < sal_Int32 > aAvailableMissingValueTreatments(
+ ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) );
+
+ if( getFastPropertyValue( PROP_DIAGRAM_MISSING_VALUE_TREATMENT ) >>= nResult )
+ {
+ //ensure that the set value is supported by this charttype
+ for( sal_Int32 n : aAvailableMissingValueTreatments )
+ if( n == nResult )
+ return nResult; //ok
+ }
+
+ //otherwise use the first supported one
+ if( aAvailableMissingValueTreatments.hasElements() )
+ {
+ nResult = aAvailableMissingValueTreatments[0];
+ return nResult;
+ }
+
+ return nResult;
+}
+
+void Diagram::setGeometry3D( sal_Int32 nNewGeometry )
+{
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec =
+ getDataSeries();
+
+ for (auto const& series : aSeriesVec)
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints(
+ series, "Geometry3D", uno::Any( nNewGeometry ));
+ }
+}
+
+sal_Int32 Diagram::getGeometry3D( bool& rbFound, bool& rbAmbiguous )
+{
+ sal_Int32 nCommonGeom( css::chart2::DataPointGeometry3D::CUBOID );
+ rbFound = false;
+ rbAmbiguous = false;
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec = getDataSeries();
+
+ if( aSeriesVec.empty())
+ rbAmbiguous = true;
+
+ for (auto const& series : aSeriesVec)
+ {
+ try
+ {
+ sal_Int32 nGeom = 0;
+ if( series->getPropertyValue( "Geometry3D") >>= nGeom )
+ {
+ if( ! rbFound )
+ {
+ // first series
+ nCommonGeom = nGeom;
+ rbFound = true;
+ }
+ // further series: compare for uniqueness
+ else if( nCommonGeom != nGeom )
+ {
+ rbAmbiguous = true;
+ break;
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return nCommonGeom;
+}
+
+bool Diagram::isPieOrDonutChart()
+{
+ rtl::Reference< ChartType > xChartType = getChartTypeByIndex( 0 );
+
+ if( xChartType .is() )
+ {
+ OUString aChartType = xChartType->getChartType();
+ if( aChartType == CHART2_SERVICE_NAME_CHARTTYPE_PIE )
+ return true;
+ }
+ return false;
+}
+
+bool Diagram::isSupportingFloorAndWall()
+{
+ //pies and donuts currently do not support this because of wrong files from older versions
+ //todo: allow this in future again, if fileversion is available for OLE objects (metastream)
+ //thus the wrong bottom can be removed on import
+
+ const std::vector< rtl::Reference< ChartType > > aTypes = getChartTypes();
+ for( rtl::Reference< ChartType > const & xType : aTypes )
+ {
+ OUString sChartType = xType->getChartType();
+ if( sChartType.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ return false;
+ if( sChartType.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ return false;
+ if( sChartType.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
+ return false;
+ }
+ return true;
+}
+
+ /**
+ * This method implements the logic of checking if a series can be moved
+ * forward/backward. Depending on the "bDoMove" parameter the series will
+ * be moved (bDoMove = true) or the function just will test if the
+ * series can be moved without doing the move (bDoMove = false).
+ *
+ * @param xDiagram
+ * Reference to the diagram that contains the series.
+ *
+ * @param xGivenDataSeries
+ * Reference to the series that should moved or tested for moving.
+ *
+ * @param bForward
+ * Direction in which the series should be moved or tested for moving.
+ *
+ * @param bDoMove
+ * Should this function really move the series (true) or just test if it is
+ * possible (false).
+ *
+ *
+ * @returns
+ * in case of bDoMove == true
+ * - True : if the move was done
+ * - False : the move failed
+ * in case of bDoMove == false
+ * - True : the series can be moved
+ * - False : the series can not be moved
+ *
+ */
+static bool lcl_moveSeriesOrCheckIfMoveIsAllowed(
+ Diagram& rDiagram,
+ const rtl::Reference< DataSeries >& xGivenDataSeries,
+ bool bForward,
+ bool bDoMove )
+{
+ bool bMovedOrMoveAllowed = false;
+
+ try
+ {
+ if( !xGivenDataSeries.is() )
+ return false;
+
+ //find position of series.
+ bool bFound = false;
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysList( rDiagram.getBaseCoordinateSystems() );
+
+ for( std::size_t nCS = 0; !bFound && nCS < aCooSysList.size(); ++nCS )
+ {
+ const rtl::Reference< BaseCoordinateSystem > & xCooSys( aCooSysList[nCS] );
+
+ //iterate through all chart types in the current coordinate system
+ std::vector< rtl::Reference< ChartType > > aChartTypeList( xCooSys->getChartTypes2() );
+ rtl::Reference< ChartType > xFormerChartType;
+
+ for( std::size_t nT = 0; !bFound && nT < aChartTypeList.size(); ++nT )
+ {
+ rtl::Reference< ChartType > xCurrentChartType( aChartTypeList[nT] );
+
+ //iterate through all series in this chart type
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesList = xCurrentChartType->getDataSeries2();
+
+ for( std::size_t nS = 0; !bFound && nS < aSeriesList.size(); ++nS )
+ {
+
+ // We found the series we are interested in!
+ if( xGivenDataSeries==aSeriesList[nS] )
+ {
+ std::size_t nOldSeriesIndex = nS;
+ bFound = true;
+
+ try
+ {
+ sal_Int32 nNewSeriesIndex = nS;
+
+ // tdf#34517 Bringing forward means increasing, backwards means decreasing series position
+ if( !bForward )
+ nNewSeriesIndex--;
+ else
+ nNewSeriesIndex++;
+
+ if( nNewSeriesIndex >= 0 && o3tl::make_unsigned(nNewSeriesIndex) < aSeriesList.size() )
+ {
+ //move series in the same charttype
+ bMovedOrMoveAllowed = true;
+ if( bDoMove )
+ {
+ aSeriesList[ nOldSeriesIndex ] = aSeriesList[ nNewSeriesIndex ];
+ aSeriesList[ nNewSeriesIndex ] = xGivenDataSeries;
+ xCurrentChartType->setDataSeries( aSeriesList );
+ }
+ }
+ else if( nNewSeriesIndex<0 )
+ {
+ //exchange series with former charttype
+ if( xFormerChartType.is() && DiagramHelper::areChartTypesCompatible( xFormerChartType, xCurrentChartType ) )
+ {
+ bMovedOrMoveAllowed = true;
+ if( bDoMove )
+ {
+ std::vector< rtl::Reference< DataSeries > > aOtherSeriesList = xFormerChartType->getDataSeries2();
+ sal_Int32 nOtherSeriesIndex = aOtherSeriesList.size()-1;
+ if( nOtherSeriesIndex >= 0 && o3tl::make_unsigned(nOtherSeriesIndex) < aOtherSeriesList.size() )
+ {
+ rtl::Reference< DataSeries > xExchangeSeries( aOtherSeriesList[nOtherSeriesIndex] );
+ aOtherSeriesList[nOtherSeriesIndex] = xGivenDataSeries;
+ xFormerChartType->setDataSeries(aOtherSeriesList);
+
+ aSeriesList[nOldSeriesIndex]=xExchangeSeries;
+ xCurrentChartType->setDataSeries(aSeriesList);
+ }
+ }
+ }
+ }
+ else if( nT+1 < aChartTypeList.size() )
+ {
+ //exchange series with next charttype
+ rtl::Reference< ChartType > xOtherChartType( aChartTypeList[nT+1] );
+ if( xOtherChartType.is() && DiagramHelper::areChartTypesCompatible( xOtherChartType, xCurrentChartType ) )
+ {
+ bMovedOrMoveAllowed = true;
+ if( bDoMove )
+ {
+ std::vector< rtl::Reference< DataSeries > > aOtherSeriesList = xOtherChartType->getDataSeries2();
+ if( !aOtherSeriesList.empty() )
+ {
+ rtl::Reference< DataSeries > xExchangeSeries( aOtherSeriesList[0] );
+ aOtherSeriesList[0] = xGivenDataSeries;
+ xOtherChartType->setDataSeries(aOtherSeriesList);
+
+ aSeriesList[nOldSeriesIndex]=xExchangeSeries;
+ xCurrentChartType->setDataSeries(aSeriesList);
+ }
+ }
+ }
+ }
+ }
+ catch( const util::CloseVetoException& )
+ {
+ }
+ catch( const uno::RuntimeException& )
+ {
+ }
+ }
+ }
+ xFormerChartType = xCurrentChartType;
+ }
+ }
+ }
+ catch( const util::CloseVetoException& )
+ {
+ }
+ catch( const uno::RuntimeException& )
+ {
+ }
+ return bMovedOrMoveAllowed;
+}
+
+bool Diagram::isSeriesMoveable(
+ const rtl::Reference< DataSeries >& xGivenDataSeries,
+ bool bForward )
+{
+ const bool bDoMove = false;
+
+ bool bIsMoveable = lcl_moveSeriesOrCheckIfMoveIsAllowed(
+ *this, xGivenDataSeries, bForward, bDoMove );
+
+ return bIsMoveable;
+}
+
+bool Diagram::moveSeries( const rtl::Reference< DataSeries >& xGivenDataSeries, bool bForward )
+{
+ const bool bDoMove = true;
+
+ bool bMoved = lcl_moveSeriesOrCheckIfMoveIsAllowed(
+ *this, xGivenDataSeries, bForward, bDoMove );
+
+ return bMoved;
+}
+
+std::vector< rtl::Reference< ChartType > > Diagram::getChartTypes()
+{
+ std::vector< rtl::Reference< ChartType > > aResult;
+ try
+ {
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : getBaseCoordinateSystems() )
+ {
+ const std::vector< rtl::Reference< ChartType > > & aChartTypeSeq( coords->getChartTypes2());
+ aResult.insert( aResult.end(), aChartTypeSeq.begin(), aChartTypeSeq.end() );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return aResult;
+}
+
+rtl::Reference< ChartType > Diagram::getChartTypeByIndex( sal_Int32 nIndex )
+{
+ rtl::Reference< ChartType > xChartType;
+
+ //iterate through all coordinate systems
+ sal_Int32 nTypesSoFar = 0;
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : getBaseCoordinateSystems() )
+ {
+ const std::vector< rtl::Reference< ChartType > > & aChartTypeList( coords->getChartTypes2() );
+ if( nIndex >= 0 && o3tl::make_unsigned(nIndex) < nTypesSoFar + aChartTypeList.size() )
+ {
+ xChartType = aChartTypeList[nIndex - nTypesSoFar];
+ break;
+ }
+ nTypesSoFar += aChartTypeList.size();
+ }
+
+ return xChartType;
+}
+
+bool Diagram::isSupportingDateAxis()
+{
+ return ::chart::ChartTypeHelper::isSupportingDateAxis( getChartTypeByIndex( 0 ), 0 );
+}
+
+static std::vector< rtl::Reference< Axis > > lcl_getAxisHoldingCategoriesFromDiagram(
+ Diagram& rDiagram )
+{
+ std::vector< rtl::Reference< Axis > > aRet;
+
+ // return first x-axis as fall-back
+ rtl::Reference< Axis > xFallBack;
+ try
+ {
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : rDiagram.getBaseCoordinateSystems() )
+ {
+ OSL_ASSERT( xCooSys.is());
+ for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
+ {
+ const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
+ for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( nN,nI );
+ OSL_ASSERT( xAxis.is());
+ if( xAxis.is())
+ {
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ if( aScaleData.Categories.is() || (aScaleData.AxisType == chart2::AxisType::CATEGORY) )
+ {
+ aRet.push_back(xAxis);
+ }
+ if( (nN == 0) && !xFallBack.is())
+ xFallBack = xAxis;
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+
+ if( aRet.empty() )
+ aRet.push_back(xFallBack);
+
+ return aRet;
+}
+
+uno::Reference< chart2::data::XLabeledDataSequence > Diagram::getCategories()
+{
+ uno::Reference< chart2::data::XLabeledDataSequence > xResult;
+
+ try
+ {
+ std::vector< rtl::Reference< Axis > > aCatAxes(
+ lcl_getAxisHoldingCategoriesFromDiagram( *this ));
+ //search for first categories
+ if (aCatAxes.empty())
+ return xResult;
+
+ rtl::Reference< Axis > xCatAxis(aCatAxes[0]);
+ if( !xCatAxis.is())
+ return xResult;
+
+ chart2::ScaleData aScaleData( xCatAxis->getScaleData());
+ if( !aScaleData.Categories.is() )
+ return xResult;
+
+ xResult = aScaleData.Categories;
+ uno::Reference<beans::XPropertySet> xProp(xResult->getValues(), uno::UNO_QUERY );
+ if( xProp.is() )
+ {
+ try
+ {
+ xProp->setPropertyValue( "Role", uno::Any( OUString("categories") ) );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+void Diagram::setCategories(
+ const uno::Reference< chart2::data::XLabeledDataSequence >& xCategories,
+ bool bSetAxisType /* = false */,
+ bool bCategoryAxis /* = true */ )
+{
+ std::vector< rtl::Reference< Axis > > aCatAxes(
+ lcl_getAxisHoldingCategoriesFromDiagram( *this ));
+
+ for (const rtl::Reference< Axis >& xCatAxis : aCatAxes)
+ {
+ if( xCatAxis.is())
+ {
+ chart2::ScaleData aScaleData( xCatAxis->getScaleData());
+ aScaleData.Categories = xCategories;
+ if( bSetAxisType )
+ {
+ if( bCategoryAxis )
+ aScaleData.AxisType = chart2::AxisType::CATEGORY;
+ else if( aScaleData.AxisType == chart2::AxisType::CATEGORY || aScaleData.AxisType == chart2::AxisType::DATE )
+ aScaleData.AxisType = chart2::AxisType::REALNUMBER;
+ }
+ xCatAxis->setScaleData( aScaleData );
+ }
+ }
+}
+
+bool Diagram::isCategory()
+{
+ try
+ {
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
+ {
+ const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
+ for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( nN,nI );
+ OSL_ASSERT( xAxis.is());
+ if( xAxis.is())
+ {
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ if( aScaleData.AxisType == chart2::AxisType::CATEGORY || aScaleData.AxisType == chart2::AxisType::DATE )
+ return true;
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return false;
+}
+
+std::vector< std::vector< rtl::Reference< DataSeries > > >
+Diagram::getDataSeriesGroups()
+{
+ std::vector< std::vector< rtl::Reference< DataSeries > > > aResult;
+
+ //iterate through all coordinate systems
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : getBaseCoordinateSystems() )
+ {
+ //iterate through all chart types in the current coordinate system
+ for( rtl::Reference< ChartType > const & chartType : coords->getChartTypes2() )
+ {
+ aResult.push_back( chartType->getDataSeries2() );
+ }
+ }
+ return aResult;
+}
+
+std::vector< rtl::Reference< ::chart::DataSeries > >
+ Diagram::getDataSeries()
+{
+ std::vector< rtl::Reference< DataSeries > > aResult;
+ try
+ {
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : getBaseCoordinateSystems() )
+ {
+ for( rtl::Reference< ChartType> const & chartType : coords->getChartTypes2() )
+ {
+ const std::vector< rtl::Reference< DataSeries > > aSeriesSeq( chartType->getDataSeries2() );
+ aResult.insert( aResult.end(), aSeriesSeq.begin(), aSeriesSeq.end() );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return aResult;
+}
+
+rtl::Reference< ChartType > Diagram::getChartTypeOfSeries(
+ const rtl::Reference< DataSeries >& xGivenDataSeries )
+{
+ if( !xGivenDataSeries.is() )
+ return nullptr;
+
+ //iterate through the model to find the given xSeries
+ //the found parent indicates the charttype
+
+ //iterate through all coordinate systems
+
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ //iterate through all chart types in the current coordinate system
+ const std::vector< rtl::Reference< ChartType > > & aChartTypeList( xCooSys->getChartTypes2() );
+ for( rtl::Reference< ChartType > const & xChartType : aChartTypeList )
+ {
+ //iterate through all series in this chart type
+ for( rtl::Reference< DataSeries > const & dataSeries : xChartType->getDataSeries2() )
+ {
+ if( xGivenDataSeries==dataSeries )
+ return xChartType;
+ }
+ }
+ }
+ return nullptr;
+}
+
+rtl::Reference< Axis > Diagram::getAttachedAxis(
+ const rtl::Reference< DataSeries >& xSeries )
+{
+ return AxisHelper::getAxis( 1, DiagramHelper::isSeriesAttachedToMainAxis( xSeries ), this );
+}
+
+bool Diagram::attachSeriesToAxis( bool bAttachToMainAxis
+ , const rtl::Reference< DataSeries >& xDataSeries
+ , const uno::Reference< uno::XComponentContext > & xContext
+ , bool bAdaptAxes )
+{
+ bool bChanged = false;
+
+ //set property at axis
+
+ sal_Int32 nNewAxisIndex = bAttachToMainAxis ? 0 : 1;
+ sal_Int32 nOldAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
+ rtl::Reference< Axis > xOldAxis = getAttachedAxis( xDataSeries );
+
+ if( nOldAxisIndex != nNewAxisIndex )
+ {
+ try
+ {
+ xDataSeries->setPropertyValue( "AttachedAxisIndex", uno::Any( nNewAxisIndex ) );
+ bChanged = true;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ if( bChanged )
+ {
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( 1, bAttachToMainAxis, this );
+ if(!xAxis.is()) //create an axis if necessary
+ xAxis = AxisHelper::createAxis( 1, bAttachToMainAxis, this, xContext );
+ if( bAdaptAxes )
+ {
+ AxisHelper::makeAxisVisible( xAxis );
+ AxisHelper::hideAxisIfNoDataIsAttached( xOldAxis, this );
+ }
+ }
+
+ return bChanged;
+}
+
+void Diagram::replaceCoordinateSystem(
+ const rtl::Reference< BaseCoordinateSystem > & xCooSysToReplace,
+ const rtl::Reference< BaseCoordinateSystem > & xReplacement )
+{
+ // update the coordinate-system container
+ try
+ {
+ uno::Reference< chart2::data::XLabeledDataSequence > xCategories = getCategories();
+
+ // move chart types of xCooSysToReplace to xReplacement
+ xReplacement->setChartTypes( xCooSysToReplace->getChartTypes());
+
+ removeCoordinateSystem( xCooSysToReplace );
+ addCoordinateSystem( xReplacement );
+
+ if( xCategories.is() )
+ setCategories( xCategories );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+sal_Int32 Diagram::getDimension()
+{
+ // -1: not yet set
+ sal_Int32 nResult = -1;
+
+ try
+ {
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ if(xCooSys.is())
+ {
+ nResult = xCooSys->getDimension();
+ break;
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return nResult;
+}
+
+void Diagram::setDimension( sal_Int32 nNewDimensionCount )
+{
+ if( getDimension() == nNewDimensionCount )
+ return;
+
+ try
+ {
+ bool rbFound = false;
+ bool rbAmbiguous = true;
+ StackMode eStackMode = getStackMode( rbFound, rbAmbiguous );
+ bool bIsSupportingOnlyDeepStackingFor3D=false;
+
+ //change all coordinate systems:
+ auto aCoordSystems = getBaseCoordinateSystems();
+ for( rtl::Reference<BaseCoordinateSystem> const & xOldCooSys : aCoordSystems )
+ {
+ rtl::Reference< BaseCoordinateSystem > xNewCooSys;
+
+ const std::vector< rtl::Reference< ChartType > > aChartTypeList( xOldCooSys->getChartTypes2() );
+ for( rtl::Reference< ChartType > const & xChartType : aChartTypeList )
+ {
+ bIsSupportingOnlyDeepStackingFor3D = ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType );
+ if(!xNewCooSys.is())
+ {
+ xNewCooSys = dynamic_cast<BaseCoordinateSystem*>(xChartType->createCoordinateSystem( nNewDimensionCount ).get());
+ assert(xNewCooSys);
+ break;
+ }
+ //@todo make sure that all following charttypes are also capable of the new dimension
+ //otherwise separate them in a different group
+ //BM: might be done in replaceCoordinateSystem()
+ }
+
+ // replace the old coordinate system at all places where it was used
+ replaceCoordinateSystem( xOldCooSys, xNewCooSys );
+ }
+
+ //correct stack mode if necessary
+ if( nNewDimensionCount==3 && eStackMode != StackMode::ZStacked && bIsSupportingOnlyDeepStackingFor3D )
+ setStackMode( StackMode::ZStacked );
+ else if( nNewDimensionCount==2 && eStackMode == StackMode::ZStacked )
+ setStackMode( StackMode::NONE );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void Diagram::setStackMode( StackMode eStackMode )
+{
+ try
+ {
+ bool bValueFound = false;
+ bool bIsAmbiguous = false;
+ StackMode eOldStackMode = getStackMode( bValueFound, bIsAmbiguous );
+
+ if( eStackMode == eOldStackMode && !bIsAmbiguous )
+ return;
+
+ chart2::StackingDirection eNewDirection = chart2::StackingDirection_NO_STACKING;
+ if( eStackMode == StackMode::YStacked || eStackMode == StackMode::YStackedPercent )
+ eNewDirection = chart2::StackingDirection_Y_STACKING;
+ else if( eStackMode == StackMode::ZStacked )
+ eNewDirection = chart2::StackingDirection_Z_STACKING;
+
+ uno::Any aNewDirection( eNewDirection );
+
+ bool bPercent = false;
+ if( eStackMode == StackMode::YStackedPercent )
+ bPercent = true;
+
+ //iterate through all coordinate systems
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ //set correct percent stacking
+ const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(1);
+ for(sal_Int32 nI=0; nI<=nMaximumScaleIndex; ++nI)
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( 1,nI );
+ if( xAxis.is())
+ {
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ if( (aScaleData.AxisType==chart2::AxisType::PERCENT) != bPercent )
+ {
+ if( bPercent )
+ aScaleData.AxisType = chart2::AxisType::PERCENT;
+ else
+ aScaleData.AxisType = chart2::AxisType::REALNUMBER;
+ xAxis->setScaleData( aScaleData );
+ }
+ }
+ }
+ //iterate through all chart types in the current coordinate system
+ const std::vector< rtl::Reference< ChartType > > & aChartTypeList( xCooSys->getChartTypes2() );
+ if (aChartTypeList.empty())
+ continue;
+
+ rtl::Reference< ChartType > xChartType( aChartTypeList[0] );
+
+ //iterate through all series in this chart type
+ for( rtl::Reference< DataSeries > const & dataSeries : xChartType->getDataSeries2() )
+ {
+ dataSeries->setPropertyValue( "StackingDirection", aNewDirection );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+StackMode Diagram::getStackMode( bool& rbFound, bool& rbAmbiguous )
+{
+ rbFound=false;
+ rbAmbiguous=false;
+
+ StackMode eGlobalStackMode = StackMode::NONE;
+
+ //iterate through all coordinate systems
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ //iterate through all chart types in the current coordinate system
+ std::vector< rtl::Reference< ChartType > > aChartTypeList( xCooSys->getChartTypes2() );
+ for( std::size_t nT = 0; nT < aChartTypeList.size(); ++nT )
+ {
+ rtl::Reference< ChartType > xChartType( aChartTypeList[nT] );
+
+ StackMode eLocalStackMode = DiagramHelper::getStackModeFromChartType(
+ xChartType, rbFound, rbAmbiguous, xCooSys );
+
+ if( rbFound && eLocalStackMode != eGlobalStackMode && nT>0 )
+ {
+ rbAmbiguous = true;
+ return eGlobalStackMode;
+ }
+
+ eGlobalStackMode = eLocalStackMode;
+ }
+ }
+
+ return eGlobalStackMode;
+}
+
+void Diagram::setVertical( bool bVertical /* = true */ )
+{
+ try
+ {
+ uno::Any aValue;
+ aValue <<= bVertical;
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : getBaseCoordinateSystems() )
+ {
+ bool bChanged = false;
+ bool bOldSwap = false;
+ if( !(xCooSys->getPropertyValue("SwapXAndYAxis") >>= bOldSwap)
+ || bVertical != bOldSwap )
+ bChanged = true;
+
+ if( bChanged )
+ xCooSys->setPropertyValue("SwapXAndYAxis", aValue);
+
+ const sal_Int32 nDimensionCount = xCooSys->getDimension();
+ sal_Int32 nDimIndex = 0;
+ for (nDimIndex=0; nDimIndex < nDimensionCount; ++nDimIndex)
+ {
+ const sal_Int32 nMaximumScaleIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
+ for (sal_Int32 nI = 0; nI <= nMaximumScaleIndex; ++nI)
+ {
+ rtl::Reference<Axis> xAxis = xCooSys->getAxisByDimension2(nDimIndex,nI);
+ if (!xAxis.is())
+ continue;
+
+ //adapt title rotation only when axis swapping has changed
+ if (!bChanged)
+ continue;
+
+ Reference< beans::XPropertySet > xTitleProps( xAxis->getTitleObject(), uno::UNO_QUERY );
+ if (!xTitleProps.is())
+ continue;
+
+ double fAngleDegree = 0.0;
+ xTitleProps->getPropertyValue("TextRotation") >>= fAngleDegree;
+ if (fAngleDegree != 0.0 &&
+ !rtl::math::approxEqual(fAngleDegree, 90.0))
+ continue;
+
+ double fNewAngleDegree = 0.0;
+ if( !bVertical && nDimIndex == 1 )
+ fNewAngleDegree = 90.0;
+ else if( bVertical && nDimIndex == 0 )
+ fNewAngleDegree = 90.0;
+
+ xTitleProps->setPropertyValue("TextRotation", uno::Any(fNewAngleDegree));
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+bool Diagram::getVertical( bool& rbFound, bool& rbAmbiguous )
+{
+ bool bValue = false;
+ rbFound = false;
+ rbAmbiguous = false;
+
+ for (rtl::Reference<BaseCoordinateSystem> const & coords : getBaseCoordinateSystems())
+ {
+ bool bCurrent = false;
+ if (coords->getPropertyValue("SwapXAndYAxis") >>= bCurrent)
+ {
+ if (!rbFound)
+ {
+ bValue = bCurrent;
+ rbFound = true;
+ }
+ else if (bCurrent != bValue)
+ {
+ // ambiguous -> choose always first found
+ rbAmbiguous = true;
+ }
+ }
+ }
+ return bValue;
+}
+
+Diagram::tTemplateWithServiceName
+ Diagram::getTemplate(
+ const rtl::Reference< ::chart::ChartTypeManager > & xChartTypeManager )
+{
+ tTemplateWithServiceName aResult;
+
+ if( !xChartTypeManager )
+ return aResult;
+
+ Sequence< OUString > aServiceNames( xChartTypeManager->getAvailableServiceNames());
+ const sal_Int32 nLength = aServiceNames.getLength();
+
+ bool bTemplateFound = false;
+
+ for( sal_Int32 i = 0; ! bTemplateFound && i < nLength; ++i )
+ {
+ try
+ {
+ rtl::Reference< ::chart::ChartTypeTemplate > xTempl =
+ xChartTypeManager->createTemplate( aServiceNames[ i ] );
+
+ if (xTempl.is() && xTempl->matchesTemplate2(this, true))
+ {
+ aResult.xChartTypeTemplate = xTempl;
+ aResult.sServiceName = aServiceNames[ i ];
+ bTemplateFound = true;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return aResult;
+}
+
+std::vector< rtl::Reference< RegressionCurveModel > >
+ Diagram::getAllRegressionCurvesNotMeanValueLine()
+{
+ std::vector< rtl::Reference< RegressionCurveModel > > aResult;
+ std::vector< rtl::Reference< DataSeries > > aSeries( getDataSeries());
+ for (auto const& elem : aSeries)
+ {
+ for( rtl::Reference< RegressionCurveModel > const & curve : elem->getRegressionCurves2() )
+ {
+ if( ! RegressionCurveHelper::isMeanValueLine( curve ))
+ aResult.push_back( curve );
+ }
+ }
+
+ return aResult;
+}
+
+double Diagram::getCameraDistance()
+{
+ double fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME;
+
+ try
+ {
+ drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
+ getFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY ) >>= aCG;
+ ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) );
+ fCameraDistance = aVRP.getLength();
+
+ ThreeDHelper::ensureCameraDistanceRange( fCameraDistance );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return fCameraDistance;
+}
+
+void Diagram::setCameraDistance(double fCameraDistance )
+{
+ try
+ {
+ if( fCameraDistance <= 0 )
+ fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME;
+
+ drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
+ getFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY ) >>= aCG;
+ ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) );
+ if( ::basegfx::fTools::equalZero( aVRP.getLength() ) )
+ aVRP = ::basegfx::B3DVector(0,0,1);
+ aVRP.setLength(fCameraDistance);
+ aCG.vrp = BaseGFXHelper::B3DVectorToPosition3D( aVRP );
+
+ setFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY, uno::Any( aCG ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+static bool lcl_isRightAngledAxesSetAndSupported( Diagram& rDiagram )
+{
+ bool bRightAngledAxes = false;
+ rDiagram.getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES ) >>= bRightAngledAxes; // "RightAngledAxes"
+ if(bRightAngledAxes)
+ {
+ if( ChartTypeHelper::isSupportingRightAngledAxes(
+ rDiagram.getChartTypeByIndex( 0 ) ) )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void Diagram::getRotation( sal_Int32& rnHorizontalAngleDegree, sal_Int32& rnVerticalAngleDegree )
+{
+ double fXAngle, fYAngle, fZAngle;
+ getRotationAngle( fXAngle, fYAngle, fZAngle );
+
+ if( !lcl_isRightAngledAxesSetAndSupported( *this ) )
+ {
+ ThreeDHelper::convertXYZAngleRadToElevationRotationDeg(
+ rnHorizontalAngleDegree, rnVerticalAngleDegree, fXAngle, fYAngle, fZAngle);
+ rnVerticalAngleDegree*=-1;
+ }
+ else
+ {
+ rnHorizontalAngleDegree = basegfx::fround(basegfx::rad2deg(fXAngle));
+ rnVerticalAngleDegree = basegfx::fround(-1.0 * basegfx::rad2deg(fYAngle));
+ // nZRotation = basegfx::fround(-1.0 * basegfx::rad2deg(fZAngle));
+ }
+
+ rnHorizontalAngleDegree = NormAngle180(rnHorizontalAngleDegree);
+ rnVerticalAngleDegree = NormAngle180(rnVerticalAngleDegree);
+}
+
+void Diagram::setRotation( sal_Int32 nHorizontalAngleDegree, sal_Int32 nVerticalYAngleDegree )
+{
+ //todo: x and y is not equal to horz and vert in case of RightAngledAxes==false
+ double fXAngle = basegfx::deg2rad(nHorizontalAngleDegree);
+ double fYAngle = basegfx::deg2rad(-1 * nVerticalYAngleDegree);
+ double fZAngle = 0.0;
+
+ if( !lcl_isRightAngledAxesSetAndSupported( *this ) )
+ ThreeDHelper::convertElevationRotationDegToXYZAngleRad(
+ nHorizontalAngleDegree, -1*nVerticalYAngleDegree, fXAngle, fYAngle, fZAngle );
+
+ setRotationAngle( fXAngle, fYAngle, fZAngle );
+}
+
+static ::basegfx::B3DHomMatrix lcl_getCameraMatrix( Diagram& rDiagram )
+{
+ drawing::HomogenMatrix aCameraMatrix;
+
+ drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
+ rDiagram.getFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY ) >>= aCG; // "D3DCameraGeometry"
+
+ ::basegfx::B3DVector aVPN( BaseGFXHelper::Direction3DToB3DVector( aCG.vpn ) );
+ ::basegfx::B3DVector aVUP( BaseGFXHelper::Direction3DToB3DVector( aCG.vup ) );
+
+ //normalize vectors:
+ aVPN.normalize();
+ aVUP.normalize();
+
+ ::basegfx::B3DVector aCross = ::basegfx::cross( aVUP, aVPN );
+
+ //first line is VUP x VPN
+ aCameraMatrix.Line1.Column1 = aCross[0];
+ aCameraMatrix.Line1.Column2 = aCross[1];
+ aCameraMatrix.Line1.Column3 = aCross[2];
+ aCameraMatrix.Line1.Column4 = 0.0;
+
+ //second line is VUP
+ aCameraMatrix.Line2.Column1 = aVUP[0];
+ aCameraMatrix.Line2.Column2 = aVUP[1];
+ aCameraMatrix.Line2.Column3 = aVUP[2];
+ aCameraMatrix.Line2.Column4 = 0.0;
+
+ //third line is VPN
+ aCameraMatrix.Line3.Column1 = aVPN[0];
+ aCameraMatrix.Line3.Column2 = aVPN[1];
+ aCameraMatrix.Line3.Column3 = aVPN[2];
+ aCameraMatrix.Line3.Column4 = 0.0;
+
+ //fourth line is 0 0 0 1
+ aCameraMatrix.Line4.Column1 = 0.0;
+ aCameraMatrix.Line4.Column2 = 0.0;
+ aCameraMatrix.Line4.Column3 = 0.0;
+ aCameraMatrix.Line4.Column4 = 1.0;
+
+ return BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aCameraMatrix );
+}
+
+static double lcl_shiftAngleToIntervalMinusPiToPi( double fAngleRad )
+{
+ //valid range: ]-Pi,Pi]
+ while( fAngleRad<=-M_PI )
+ fAngleRad+=(2*M_PI);
+ while( fAngleRad>M_PI )
+ fAngleRad-=(2*M_PI);
+ return fAngleRad;
+}
+
+void Diagram::getRotationAngle( double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad )
+{
+ //takes the camera and the transformation matrix into account
+
+ rfXAngleRad = rfYAngleRad = rfZAngleRad = 0.0;
+
+ //get camera rotation
+ ::basegfx::B3DHomMatrix aFixCameraRotationMatrix( lcl_getCameraMatrix( *this ) );
+ BaseGFXHelper::ReduceToRotationMatrix( aFixCameraRotationMatrix );
+
+ //get scene rotation
+ ::basegfx::B3DHomMatrix aSceneRotation;
+ {
+ drawing::HomogenMatrix aHomMatrix;
+ // "D3DTransformMatrix"
+ if( getFastPropertyValue( PROP_SCENE_TRANSF_MATRIX ) >>= aHomMatrix )
+ {
+ aSceneRotation = BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aHomMatrix );
+ BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation );
+ }
+ }
+
+ ::basegfx::B3DHomMatrix aResultRotation = aFixCameraRotationMatrix * aSceneRotation;
+ ::basegfx::B3DTuple aRotation( BaseGFXHelper::GetRotationFromMatrix( aResultRotation ) );
+
+ rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getX());
+ rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getY());
+ rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getZ());
+
+ if(rfZAngleRad<-M_PI_2 || rfZAngleRad>M_PI_2)
+ {
+ rfZAngleRad-=M_PI;
+ rfXAngleRad-=M_PI;
+ rfYAngleRad=(M_PI-rfYAngleRad);
+
+ rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfXAngleRad);
+ rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfYAngleRad);
+ rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfZAngleRad);
+ }
+}
+
+static ::basegfx::B3DHomMatrix lcl_getInverseRotationMatrix( Diagram& rDiagram )
+{
+ ::basegfx::B3DHomMatrix aInverseRotation;
+ double fXAngleRad=0.0;
+ double fYAngleRad=0.0;
+ double fZAngleRad=0.0;
+ rDiagram.getRotationAngle( fXAngleRad, fYAngleRad, fZAngleRad );
+ aInverseRotation.rotate( 0.0, 0.0, -fZAngleRad );
+ aInverseRotation.rotate( 0.0, -fYAngleRad, 0.0 );
+ aInverseRotation.rotate( -fXAngleRad, 0.0, 0.0 );
+ return aInverseRotation;
+}
+
+static void lcl_rotateLights( const ::basegfx::B3DHomMatrix& rLightRotation, Diagram& rDiagram )
+{
+ ::basegfx::B3DHomMatrix aLightRotation( rLightRotation );
+ BaseGFXHelper::ReduceToRotationMatrix( aLightRotation );
+
+ // "D3DSceneLightDirection1","D3DSceneLightOn1",
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_1, PROP_SCENE_LIGHT_ON_1, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_2, PROP_SCENE_LIGHT_ON_2, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_3, PROP_SCENE_LIGHT_ON_3, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_4, PROP_SCENE_LIGHT_ON_4, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_5, PROP_SCENE_LIGHT_ON_5, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_6, PROP_SCENE_LIGHT_ON_6, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_7, PROP_SCENE_LIGHT_ON_7, aLightRotation );
+ lcl_RotateLightSource( rDiagram, PROP_SCENE_LIGHT_DIRECTION_8, PROP_SCENE_LIGHT_ON_8, aLightRotation );
+}
+
+void Diagram::setRotationAngle(
+ double fXAngleRad, double fYAngleRad, double fZAngleRad )
+{
+ //the rotation of the camera is not touched but taken into account
+ //the rotation difference is applied to the transformation matrix
+
+ //the light sources will be adapted also
+
+ try
+ {
+ //remind old rotation for adaptation of light directions
+ ::basegfx::B3DHomMatrix aInverseOldRotation( lcl_getInverseRotationMatrix( *this ) );
+
+ ::basegfx::B3DHomMatrix aInverseCameraRotation;
+ {
+ ::basegfx::B3DTuple aR( BaseGFXHelper::GetRotationFromMatrix(
+ lcl_getCameraMatrix( *this ) ) );
+ aInverseCameraRotation.rotate( 0.0, 0.0, -aR.getZ() );
+ aInverseCameraRotation.rotate( 0.0, -aR.getY(), 0.0 );
+ aInverseCameraRotation.rotate( -aR.getX(), 0.0, 0.0 );
+ }
+
+ ::basegfx::B3DHomMatrix aCumulatedRotation;
+ aCumulatedRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
+
+ //calculate new scene matrix
+ ::basegfx::B3DHomMatrix aSceneRotation = aInverseCameraRotation*aCumulatedRotation;
+ BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation );
+
+ //set new rotation to transformation matrix ("D3DTransformMatrix")
+ setFastPropertyValue(
+ PROP_SCENE_TRANSF_MATRIX, uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation )));
+
+ //rotate lights if RightAngledAxes are not set or not supported
+ bool bRightAngledAxes = false;
+ getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES ) >>= bRightAngledAxes;
+ if(!bRightAngledAxes || !ChartTypeHelper::isSupportingRightAngledAxes(
+ getChartTypeByIndex( 0 ) ) )
+ {
+ ::basegfx::B3DHomMatrix aNewRotation;
+ aNewRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
+ lcl_rotateLights( aNewRotation*aInverseOldRotation, *this );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+static bool lcl_isEqual( const drawing::Direction3D& rA, const drawing::Direction3D& rB )
+{
+ return ::rtl::math::approxEqual(rA.DirectionX, rB.DirectionX)
+ && ::rtl::math::approxEqual(rA.DirectionY, rB.DirectionY)
+ && ::rtl::math::approxEqual(rA.DirectionZ, rB.DirectionZ);
+}
+static bool lcl_isSimpleScheme( drawing::ShadeMode aShadeMode
+ , sal_Int32 nRoundedEdges
+ , sal_Int32 nObjectLines
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ if(aShadeMode!=drawing::ShadeMode_FLAT)
+ return false;
+ if(nRoundedEdges!=0)
+ return false;
+ if(nObjectLines==0)
+ {
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeByIndex( 0 ) );
+ return ChartTypeHelper::noBordersForSimpleScheme( xChartType );
+ }
+ if(nObjectLines!=1)
+ return false;
+ return true;
+}
+static bool lcl_isRealisticScheme( drawing::ShadeMode aShadeMode
+ , sal_Int32 nRoundedEdges
+ , sal_Int32 nObjectLines )
+{
+ if(aShadeMode!=drawing::ShadeMode_SMOOTH)
+ return false;
+ if(nRoundedEdges!=5)
+ return false;
+ if(nObjectLines!=0)
+ return false;
+ return true;
+}
+static bool lcl_isLightScheme( Diagram& rDiagram, bool bRealistic )
+{
+ bool bIsOn = false;
+ // "D3DSceneLightOn2" / UNO_NAME_3D_SCENE_LIGHTON_2
+ rDiagram.getFastPropertyValue( PROP_SCENE_LIGHT_ON_2 ) >>= bIsOn;
+ if(!bIsOn)
+ return false;
+
+ rtl::Reference< ChartType > xChartType( rDiagram.getChartTypeByIndex( 0 ) );
+
+ sal_Int32 nColor = 0;
+ // "D3DSceneLightColor2" / UNO_NAME_3D_SCENE_LIGHTCOLOR_2
+ rDiagram.getFastPropertyValue( PROP_SCENE_LIGHT_COLOR_2 ) >>= nColor;
+ if( nColor != ::chart::ChartTypeHelper::getDefaultDirectLightColor( !bRealistic, xChartType ) )
+ return false;
+
+ sal_Int32 nAmbientColor = 0;
+ // "D3DSceneAmbientColor" / UNO_NAME_3D_SCENE_AMBIENTCOLOR
+ rDiagram.getFastPropertyValue( PROP_SCENE_AMBIENT_COLOR ) >>= nAmbientColor;
+ if( nAmbientColor != ::chart::ChartTypeHelper::getDefaultAmbientLightColor( !bRealistic, xChartType ) )
+ return false;
+
+ drawing::Direction3D aDirection(0,0,0);
+ // "D3DSceneLightDirection2" / UNO_NAME_3D_SCENE_LIGHTDIRECTION_2
+ rDiagram.getFastPropertyValue( PROP_SCENE_LIGHT_DIRECTION_2 ) >>= aDirection;
+
+ drawing::Direction3D aDefaultDirection( bRealistic
+ ? ChartTypeHelper::getDefaultRealisticLightDirection(xChartType)
+ : ChartTypeHelper::getDefaultSimpleLightDirection(xChartType) );
+
+ //rotate default light direction when right angled axes are off but supported
+ {
+ bool bRightAngledAxes = false;
+ rDiagram.getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES ) >>= bRightAngledAxes; // "RightAngledAxes"
+ if(!bRightAngledAxes)
+ {
+ if( ChartTypeHelper::isSupportingRightAngledAxes(
+ rDiagram.getChartTypeByIndex( 0 ) ) )
+ {
+ ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( rDiagram ) );
+ BaseGFXHelper::ReduceToRotationMatrix( aRotation );
+ ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aDefaultDirection ) );
+ aLightVector = aRotation*aLightVector;
+ aDefaultDirection = BaseGFXHelper::B3DVectorToDirection3D( aLightVector );
+ }
+ }
+ }
+
+ return lcl_isEqual( aDirection, aDefaultDirection );
+}
+static bool lcl_isRealisticLightScheme( Diagram& rDiagram )
+{
+ return lcl_isLightScheme( rDiagram, true /*bRealistic*/ );
+}
+static bool lcl_isSimpleLightScheme( Diagram& rDiagram )
+{
+ return lcl_isLightScheme( rDiagram, false /*bRealistic*/ );
+}
+
+ThreeDLookScheme Diagram::detectScheme()
+{
+ ThreeDLookScheme aScheme = ThreeDLookScheme::ThreeDLookScheme_Unknown;
+
+ sal_Int32 nRoundedEdges;
+ sal_Int32 nObjectLines;
+ ThreeDHelper::getRoundedEdgesAndObjectLines( this, nRoundedEdges, nObjectLines );
+
+ //get shade mode and light settings:
+ drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH );
+ try
+ {
+ getFastPropertyValue( PROP_SCENE_SHADE_MODE )>>= aShadeMode; // "D3DSceneShadeMode"
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ if( lcl_isSimpleScheme( aShadeMode, nRoundedEdges, nObjectLines, this ) )
+ {
+ if( lcl_isSimpleLightScheme(*this) )
+ aScheme = ThreeDLookScheme::ThreeDLookScheme_Simple;
+ }
+ else if( lcl_isRealisticScheme( aShadeMode, nRoundedEdges, nObjectLines ) )
+ {
+ if( lcl_isRealisticLightScheme(*this) )
+ aScheme = ThreeDLookScheme::ThreeDLookScheme_Realistic;
+ }
+
+ return aScheme;
+}
+
+static void lcl_setRealisticScheme( drawing::ShadeMode& rShadeMode
+ , sal_Int32& rnRoundedEdges
+ , sal_Int32& rnObjectLines )
+{
+ rShadeMode = drawing::ShadeMode_SMOOTH;
+ rnRoundedEdges = 5;
+ rnObjectLines = 0;
+}
+
+static void lcl_setSimpleScheme( drawing::ShadeMode& rShadeMode
+ , sal_Int32& rnRoundedEdges
+ , sal_Int32& rnObjectLines
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ rShadeMode = drawing::ShadeMode_FLAT;
+ rnRoundedEdges = 0;
+
+ rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeByIndex( 0 ) );
+ rnObjectLines = ChartTypeHelper::noBordersForSimpleScheme( xChartType ) ? 0 : 1;
+}
+void Diagram::setScheme( ThreeDLookScheme aScheme )
+{
+ if( aScheme == ThreeDLookScheme::ThreeDLookScheme_Unknown )
+ return;
+
+ drawing::ShadeMode aShadeMode;
+ sal_Int32 nRoundedEdges;
+ sal_Int32 nObjectLines;
+
+ if( aScheme == ThreeDLookScheme::ThreeDLookScheme_Simple )
+ lcl_setSimpleScheme(aShadeMode,nRoundedEdges,nObjectLines,this);
+ else
+ lcl_setRealisticScheme(aShadeMode,nRoundedEdges,nObjectLines);
+
+ try
+ {
+ ThreeDHelper::setRoundedEdgesAndObjectLines( this, nRoundedEdges, nObjectLines );
+
+ drawing::ShadeMode aOldShadeMode;
+ if( ! (getFastPropertyValue( PROP_SCENE_SHADE_MODE)>>=aOldShadeMode) ||
+ aOldShadeMode != aShadeMode )
+ {
+ setFastPropertyValue( PROP_SCENE_SHADE_MODE, uno::Any( aShadeMode )); // "D3DSceneShadeMode"
+ }
+
+ lcl_setLightsForScheme( *this, aScheme );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+}
+
+void Diagram::setDefaultRotation( bool bPieOrDonut )
+{
+ drawing::CameraGeometry aCameraGeo( ThreeDHelper::getDefaultCameraGeometry( bPieOrDonut ) );
+ // "D3DCameraGeometry"
+ setFastPropertyValue( PROP_SCENE_CAMERA_GEOMETRY, uno::Any( aCameraGeo ));
+
+ ::basegfx::B3DHomMatrix aSceneRotation;
+ if( bPieOrDonut )
+ aSceneRotation.rotate( -M_PI/3.0, 0, 0 );
+ // "D3DTransformMatrix"
+ setFastPropertyValue( PROP_SCENE_TRANSF_MATRIX,
+ uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation )));
+}
+
+void Diagram::switchRightAngledAxes( bool bRightAngledAxes )
+{
+ try
+ {
+ bool bOldRightAngledAxes = false;
+ getFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES ) >>= bOldRightAngledAxes; // "RightAngledAxes"
+ if( bOldRightAngledAxes!=bRightAngledAxes)
+ {
+ setFastPropertyValue( PROP_DIAGRAM_RIGHT_ANGLED_AXES, uno::Any( bRightAngledAxes ));
+ if(bRightAngledAxes)
+ {
+ ::basegfx::B3DHomMatrix aInverseRotation( lcl_getInverseRotationMatrix( *this ) );
+ lcl_rotateLights( aInverseRotation, *this );
+ }
+ else
+ {
+ ::basegfx::B3DHomMatrix aCompleteRotation( lcl_getCompleteRotationMatrix( *this ) );
+ lcl_rotateLights( aCompleteRotation, *this );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_Diagram_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::Diagram(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/FormattedString.cxx b/chart2/source/model/main/FormattedString.cxx
new file mode 100644
index 0000000000..dbd5876b97
--- /dev/null
+++ b/chart2/source/model/main/FormattedString.cxx
@@ -0,0 +1,276 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <FormattedString.hxx>
+
+#include <CharacterProperties.hxx>
+#include <PropertyHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::osl::MutexGuard;
+
+namespace chart
+{
+const ::chart::tPropertyValueMap & StaticFormattedStringDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []
+ {
+ ::chart::tPropertyValueMap aMap;
+ ::chart::CharacterProperties::AddDefaultsToMap( aMap );
+ return aMap;
+ }();
+ return aStaticDefaults;
+};
+} // namespace chart
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper& StaticFormattedStringInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+FormattedString::FormattedString() :
+ m_aType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT),
+ m_bDataLabelsRange(false),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+FormattedString::FormattedString( const FormattedString & rOther ) :
+ impl::FormattedString_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_aString( rOther.m_aString ),
+ m_aType(rOther.m_aType),
+ m_aGuid(rOther.m_aGuid),
+ m_bDataLabelsRange(rOther.m_bDataLabelsRange),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+FormattedString::~FormattedString()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL FormattedString::createClone()
+{
+ return uno::Reference< util::XCloneable >( new FormattedString( *this ));
+}
+
+// ____ XFormattedString ____
+OUString SAL_CALL FormattedString::getString()
+{
+ MutexGuard aGuard( m_aMutex);
+ return m_aString;
+}
+
+void SAL_CALL FormattedString::setString( const OUString& String )
+{
+ {
+ MutexGuard aGuard( m_aMutex);
+ m_aString = String;
+ }
+ //don't keep the mutex locked while calling out
+ fireModifyEvent();
+
+}
+
+// ____ XDataPointCustomLabelField ____
+css::chart2::DataPointCustomLabelFieldType SAL_CALL FormattedString::getFieldType()
+{
+ MutexGuard aGuard(m_aMutex);
+ return m_aType;
+}
+
+void SAL_CALL
+FormattedString::setFieldType(const css::chart2::DataPointCustomLabelFieldType Type)
+{
+ {
+ MutexGuard aGuard(m_aMutex);
+ m_aType = Type;
+ }
+ //don't keep the mutex locked while calling out
+ fireModifyEvent();
+}
+
+OUString SAL_CALL FormattedString::getGuid()
+{
+ MutexGuard aGuard( m_aMutex);
+ return m_aGuid;
+}
+
+void SAL_CALL FormattedString::setGuid( const OUString& guid )
+{
+ {
+ MutexGuard aGuard( m_aMutex);
+ m_aGuid= guid;
+ }
+ //don't keep the mutex locked while calling out
+ fireModifyEvent();
+
+}
+
+sal_Bool SAL_CALL FormattedString::getDataLabelsRange()
+{
+ MutexGuard aGuard( m_aMutex);
+ return m_bDataLabelsRange;
+}
+
+void SAL_CALL FormattedString::setDataLabelsRange( sal_Bool dataLabelsRange )
+{
+ {
+ MutexGuard aGuard( m_aMutex);
+ m_bDataLabelsRange = dataLabelsRange;
+ }
+ //don't keep the mutex locked while calling out
+ fireModifyEvent();
+}
+
+OUString SAL_CALL FormattedString::getCellRange()
+{
+ MutexGuard aGuard( m_aMutex);
+ return m_aCellRange;
+}
+
+void SAL_CALL FormattedString::setCellRange( const OUString& cellRange )
+{
+ {
+ MutexGuard aGuard( m_aMutex);
+ m_aCellRange = cellRange;
+ }
+ //don't keep the mutex locked while calling out
+ fireModifyEvent();
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL FormattedString::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL FormattedString::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL FormattedString::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL FormattedString::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void FormattedString::firePropertyChangeEvent()
+{
+ fireModifyEvent();
+}
+
+void FormattedString::fireModifyEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+// ____ OPropertySet ____
+void FormattedString::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticFormattedStringDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+// ____ OPropertySet ____
+::cppu::IPropertyArrayHelper & SAL_CALL FormattedString::getInfoHelper()
+{
+ return StaticFormattedStringInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL FormattedString::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticFormattedStringInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+using impl::FormattedString_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( FormattedString, FormattedString_Base, ::property::OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( FormattedString, FormattedString_Base, ::property::OPropertySet )
+
+// do this in derived classes!
+
+// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
+OUString SAL_CALL FormattedString::getImplementationName()
+{
+ return "com.sun.star.comp.chart.FormattedString";
+}
+
+sal_Bool SAL_CALL FormattedString::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL FormattedString::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart2.DataPointCustomLabelField",
+ "com.sun.star.chart2.FormattedString",
+ "com.sun.star.beans.PropertySet" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_FormattedString_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::FormattedString);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/GridProperties.cxx b/chart2/source/model/main/GridProperties.cxx
new file mode 100644
index 0000000000..a495f631f7
--- /dev/null
+++ b/chart2/source/model/main/GridProperties.cxx
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <GridProperties.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <UserDefinedProperties.hxx>
+#include <PropertyHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace com::sun::star::beans { class XPropertySetInfo; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+enum
+{
+ PROP_GRID_SHOW
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "Show",
+ PROP_GRID_SHOW,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+const ::chart::tPropertyValueMap & StaticGridDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_GRID_SHOW, false );
+
+ // override other defaults
+ ::chart::PropertyHelper::setPropertyValue< sal_Int32 >(
+ aTmp, ::chart::LinePropertiesHelper::PROP_LINE_COLOR, 0xb3b3b3 ); // gray30
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& StaticGridInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+GridProperties::GridProperties() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+GridProperties::GridProperties( const GridProperties & rOther ) :
+ impl::GridProperties_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+}
+
+GridProperties::~GridProperties()
+{}
+
+// ____ OPropertySet ____
+void GridProperties::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticGridDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL GridProperties::getInfoHelper()
+{
+ return StaticGridInfoHelper();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL GridProperties::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticGridInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL GridProperties::createClone()
+{
+ return uno::Reference< util::XCloneable >( new GridProperties( *this ));
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL GridProperties::addModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL GridProperties::removeModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL GridProperties::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL GridProperties::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void GridProperties::firePropertyChangeEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
+OUString SAL_CALL GridProperties::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.GridProperties";
+}
+
+sal_Bool SAL_CALL GridProperties::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL GridProperties::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart2.GridProperties",
+ "com.sun.star.beans.PropertySet" };
+}
+
+// needed by MSC compiler
+using impl::GridProperties_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( GridProperties, GridProperties_Base, ::property::OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( GridProperties, GridProperties_Base, ::property::OPropertySet )
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_GridProperties_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::GridProperties);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/Legend.cxx b/chart2/source/model/main/Legend.cxx
new file mode 100644
index 0000000000..f72868b58c
--- /dev/null
+++ b/chart2/source/model/main/Legend.cxx
@@ -0,0 +1,275 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <Legend.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <CharacterProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart/ChartLegendExpansion.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <algorithm>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans::PropertyAttribute;
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+enum
+{
+ PROP_LEGEND_ANCHOR_POSITION,
+ PROP_LEGEND_EXPANSION,
+ PROP_LEGEND_SHOW,
+ PROP_LEGEND_OVERLAY,
+ PROP_LEGEND_REF_PAGE_SIZE,
+ PROP_LEGEND_REL_POS,
+ PROP_LEGEND_REL_SIZE
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "AnchorPosition",
+ PROP_LEGEND_ANCHOR_POSITION,
+ cppu::UnoType<chart2::LegendPosition>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "Expansion",
+ PROP_LEGEND_EXPANSION,
+ cppu::UnoType<css::chart::ChartLegendExpansion>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "Show",
+ PROP_LEGEND_SHOW,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "Overlay",
+ PROP_LEGEND_OVERLAY,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ReferencePageSize",
+ PROP_LEGEND_REF_PAGE_SIZE,
+ cppu::UnoType<awt::Size>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "RelativePosition",
+ PROP_LEGEND_REL_POS,
+ cppu::UnoType<chart2::RelativePosition>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "RelativeSize",
+ PROP_LEGEND_REL_SIZE,
+ cppu::UnoType<chart2::RelativeSize>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+}
+
+} // namespace
+
+namespace chart
+{
+const ::chart::tPropertyValueMap& StaticLegendDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+ ::chart::CharacterProperties::AddDefaultsToMap( aTmp );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_LEGEND_ANCHOR_POSITION, chart2::LegendPosition_LINE_END );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_LEGEND_EXPANSION, css::chart::ChartLegendExpansion_HIGH );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_LEGEND_SHOW, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_LEGEND_OVERLAY, false );
+
+ float fDefaultCharHeight = 10.0;
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight );
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+} // namespace chart
+
+namespace
+{
+::cppu::OPropertyArrayHelper& StaticLegendInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+Legend::Legend() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+}
+
+Legend::Legend( const Legend & rOther ) :
+ impl::Legend_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+}
+
+Legend::~Legend()
+{
+}
+
+// ____ XCloneable ____
+Reference< util::XCloneable > SAL_CALL Legend::createClone()
+{
+ return Reference< util::XCloneable >( new Legend( *this ));
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL Legend::addModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL Legend::removeModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL Legend::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL Legend::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void Legend::firePropertyChangeEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+// ____ OPropertySet ____
+void Legend::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticLegendDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL Legend::getInfoHelper()
+{
+ return StaticLegendInfoHelper();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL Legend::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticLegendInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
+OUString SAL_CALL Legend::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.Legend";
+}
+
+sal_Bool SAL_CALL Legend::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL Legend::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart2.Legend",
+ "com.sun.star.beans.PropertySet",
+ "com.sun.star.drawing.FillProperties",
+ "com.sun.star.drawing.LineProperties",
+ "com.sun.star.style.CharacterProperties",
+ "com.sun.star.layout.LayoutElement"
+ };
+}
+
+// needed by MSC compiler
+using impl::Legend_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( Legend, Legend_Base, ::property::OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( Legend, Legend_Base, ::property::OPropertySet )
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_Legend_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::Legend);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/PageBackground.cxx b/chart2/source/model/main/PageBackground.cxx
new file mode 100644
index 0000000000..c866bdbb3f
--- /dev/null
+++ b/chart2/source/model/main/PageBackground.cxx
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "PageBackground.hxx"
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include <PropertyHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <svtools/colorcfg.hxx>
+#include <sfx2/viewsh.hxx>
+
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <vector>
+#include <algorithm>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+const ::chart::tPropertyValueMap& StaticPageBackgroundDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+
+ // override other defaults
+ Color aDocColor = COL_WHITE;
+ if (SfxViewShell::Current()) {
+ aDocColor = SfxViewShell::Current()->GetColorConfigColor(svtools::DOCCOLOR);
+ } else {
+ SAL_WARN("chart2", "SfxViewShell::Current() returned nullptr");
+ }
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::FillProperties::PROP_FILL_COLOR, aDocColor );
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE );
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& StaticPageBackgroundInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+PageBackground::PageBackground() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+PageBackground::PageBackground( const PageBackground & rOther ) :
+ impl::PageBackground_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+PageBackground::~PageBackground()
+{}
+
+// ____ XTypeProvider ____
+uno::Sequence< css::uno::Type > SAL_CALL PageBackground::getTypes()
+{
+ return ::comphelper::concatSequences(
+ impl::PageBackground_Base::getTypes(),
+ ::property::OPropertySet::getTypes());
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL PageBackground::createClone()
+{
+ return uno::Reference< util::XCloneable >( new PageBackground( *this ));
+}
+
+// ____ OPropertySet ____
+void PageBackground::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticPageBackgroundDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL PageBackground::getInfoHelper()
+{
+ return StaticPageBackgroundInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL PageBackground::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticPageBackgroundInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL PageBackground::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL PageBackground::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL PageBackground::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL PageBackground::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void PageBackground::firePropertyChangeEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+OUString SAL_CALL PageBackground::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.PageBackground";
+}
+
+sal_Bool SAL_CALL PageBackground::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL PageBackground::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart2.PageBackground",
+ "com.sun.star.beans.PropertySet" };
+}
+
+using impl::PageBackground_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( PageBackground, PageBackground_Base, ::property::OPropertySet )
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_PageBackground_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::PageBackground );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/PageBackground.hxx b/chart2/source/model/main/PageBackground.hxx
new file mode 100644
index 0000000000..2aef8bd45e
--- /dev/null
+++ b/chart2/source/model/main/PageBackground.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <OPropertySet.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <ModifyListenerHelper.hxx>
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener,
+ css::lang::XServiceInfo >
+ PageBackground_Base;
+}
+
+class PageBackground final :
+ public impl::PageBackground_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit PageBackground();
+ virtual ~PageBackground() override;
+
+ /// XServiceInfo declarations
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+
+ explicit PageBackground( const PageBackground & rOther );
+
+ // ____ XTypeProvider ____
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+private:
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/PolarCoordinateSystem.cxx b/chart2/source/model/main/PolarCoordinateSystem.cxx
new file mode 100644
index 0000000000..0807415dac
--- /dev/null
+++ b/chart2/source/model/main/PolarCoordinateSystem.cxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PolarCoordinateSystem.hxx>
+#include <servicenames_coosystems.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+
+constexpr OUString CHART2_COOSYSTEM_POLAR_SERVICE_NAME
+ = u"com.sun.star.chart2.CoordinateSystems.Polar"_ustr;
+
+}
+
+namespace chart
+{
+
+// explicit
+PolarCoordinateSystem::PolarCoordinateSystem( sal_Int32 nDimensionCount /* = 2 */ ) :
+ BaseCoordinateSystem( nDimensionCount )
+{}
+
+PolarCoordinateSystem::PolarCoordinateSystem(
+ const PolarCoordinateSystem & rSource ) :
+ BaseCoordinateSystem( rSource )
+{}
+
+PolarCoordinateSystem::~PolarCoordinateSystem()
+{}
+
+// ____ XCoordinateSystem ____
+OUString SAL_CALL PolarCoordinateSystem::getCoordinateSystemType()
+{
+ return CHART2_COOSYSTEM_POLAR_SERVICE_NAME;
+}
+
+OUString SAL_CALL PolarCoordinateSystem::getViewServiceName()
+{
+ return CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME;
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL PolarCoordinateSystem::createClone()
+{
+ return Reference< util::XCloneable >( new PolarCoordinateSystem( *this ));
+}
+
+// ____ XServiceInfo ____
+OUString SAL_CALL PolarCoordinateSystem::getImplementationName()
+{
+ return "com.sun.star.comp.chart.PolarCoordinateSystem";
+}
+
+sal_Bool SAL_CALL PolarCoordinateSystem::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL PolarCoordinateSystem::getSupportedServiceNames()
+{
+ return { CHART2_COOSYSTEM_POLAR_SERVICE_NAME };
+}
+
+// ==== PolarCoordinateSystem2d ====
+
+PolarCoordinateSystem2d::PolarCoordinateSystem2d() :
+ PolarCoordinateSystem( 2 )
+{}
+
+PolarCoordinateSystem2d::~PolarCoordinateSystem2d()
+{}
+
+// ____ XServiceInfo ____
+OUString SAL_CALL PolarCoordinateSystem2d::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.PolarCoordinateSystem2d" ;
+}
+
+sal_Bool SAL_CALL PolarCoordinateSystem2d::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL PolarCoordinateSystem2d::getSupportedServiceNames()
+{
+ return {
+ CHART2_COOSYSTEM_POLAR_SERVICE_NAME,
+ "com.sun.star.chart2.PolarCoordinateSystem2d" };
+}
+
+// ==== PolarCoordinateSystem3d ====
+
+PolarCoordinateSystem3d::PolarCoordinateSystem3d() :
+ PolarCoordinateSystem( 3 )
+{}
+
+PolarCoordinateSystem3d::~PolarCoordinateSystem3d()
+{}
+
+// ____ XServiceInfo ____
+OUString SAL_CALL PolarCoordinateSystem3d::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.PolarCoordinateSystem3d";
+}
+
+sal_Bool SAL_CALL PolarCoordinateSystem3d::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL PolarCoordinateSystem3d::getSupportedServiceNames()
+{
+ return {
+ CHART2_COOSYSTEM_POLAR_SERVICE_NAME,
+ "com.sun.star.chart2.PolarCoordinateSystem3d" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_PolarCoordinateSystem2d_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::PolarCoordinateSystem2d);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_PolarCoordinateSystem3d_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::PolarCoordinateSystem3d);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/StockBar.cxx b/chart2/source/model/main/StockBar.cxx
new file mode 100644
index 0000000000..e8c72059bc
--- /dev/null
+++ b/chart2/source/model/main/StockBar.cxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <StockBar.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include <PropertyHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <algorithm>
+
+namespace com::sun::star::beans { class XPropertySetInfo; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper& StaticStockBarInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+const ::chart::tPropertyValueMap & StaticStockBarDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+
+ // override other defaults
+ ::chart::PropertyHelper::setPropertyValue< sal_Int32 >( aTmp, ::chart::FillProperties::PROP_FILL_COLOR, 0xffffff ); // white
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+StockBar::StockBar( bool bRisingCourse ) :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ if( ! bRisingCourse )
+ {
+ setFastPropertyValue_NoBroadcast(
+ ::chart::FillProperties::PROP_FILL_COLOR,
+ uno::Any( sal_Int32( 0x000000 ))); // black
+ setFastPropertyValue_NoBroadcast(
+ ::chart::LinePropertiesHelper::PROP_LINE_COLOR,
+ uno::Any( sal_Int32( 0xb3b3b3 ))); // gray30
+ }
+}
+
+StockBar::StockBar( const StockBar & rOther ) :
+ impl::StockBar_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+StockBar::~StockBar()
+{}
+
+// ____ XTypeProvider ____
+uno::Sequence< css::uno::Type > SAL_CALL StockBar::getTypes()
+{
+ return ::comphelper::concatSequences(
+ impl::StockBar_Base::getTypes(),
+ ::property::OPropertySet::getTypes());
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL StockBar::createClone()
+{
+ return uno::Reference< util::XCloneable >( new StockBar( *this ));
+}
+
+// ____ OPropertySet ____
+void StockBar::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticStockBarDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL StockBar::getInfoHelper()
+{
+ return StaticStockBarInfoHelper();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL StockBar::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticStockBarInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL StockBar::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL StockBar::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL StockBar::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL StockBar::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void StockBar::firePropertyChangeEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+using impl::StockBar_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( StockBar, StockBar_Base, ::property::OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/Title.cxx b/chart2/source/model/main/Title.cxx
new file mode 100644
index 0000000000..6833684e9b
--- /dev/null
+++ b/chart2/source/model/main/Title.cxx
@@ -0,0 +1,343 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <Title.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <CloneHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <vector>
+#include <algorithm>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans::PropertyAttribute;
+
+using ::com::sun::star::beans::Property;
+using ::osl::MutexGuard;
+
+namespace
+{
+
+enum
+{
+ PROP_TITLE_PARA_ADJUST,
+ PROP_TITLE_PARA_LAST_LINE_ADJUST,
+ PROP_TITLE_PARA_LEFT_MARGIN,
+ PROP_TITLE_PARA_RIGHT_MARGIN,
+ PROP_TITLE_PARA_TOP_MARGIN,
+ PROP_TITLE_PARA_BOTTOM_MARGIN,
+ PROP_TITLE_PARA_IS_HYPHENATION,
+ PROP_TITLE_VISIBLE,
+
+ PROP_TITLE_TEXT_ROTATION,
+ PROP_TITLE_TEXT_STACKED,
+ PROP_TITLE_REL_POS,
+
+ PROP_TITLE_REF_PAGE_SIZE
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "ParaAdjust",
+ PROP_TITLE_PARA_ADJUST,
+ cppu::UnoType<css::style::ParagraphAdjust>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ParaLastLineAdjust",
+ PROP_TITLE_PARA_LAST_LINE_ADJUST,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ParaLeftMargin",
+ PROP_TITLE_PARA_LEFT_MARGIN,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ParaRightMargin",
+ PROP_TITLE_PARA_RIGHT_MARGIN,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ParaTopMargin",
+ PROP_TITLE_PARA_TOP_MARGIN,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ParaBottomMargin",
+ PROP_TITLE_PARA_BOTTOM_MARGIN,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ParaIsHyphenation",
+ PROP_TITLE_PARA_IS_HYPHENATION,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+
+ rOutProperties.emplace_back( "Visible",
+ PROP_TITLE_VISIBLE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "TextRotation",
+ PROP_TITLE_TEXT_ROTATION,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "StackCharacters",
+ PROP_TITLE_TEXT_STACKED,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "RelativePosition",
+ PROP_TITLE_REL_POS,
+ cppu::UnoType<chart2::RelativePosition>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "ReferencePageSize",
+ PROP_TITLE_REF_PAGE_SIZE,
+ cppu::UnoType<awt::Size>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+}
+
+const ::chart::tPropertyValueMap& StaticTitleDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+
+ // ParagraphProperties
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_TITLE_PARA_ADJUST,
+ css::style::ParagraphAdjust_CENTER );
+ // PROP_TITLE_PARA_LAST_LINE_ADJUST
+
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aTmp, PROP_TITLE_PARA_LEFT_MARGIN, 0 );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aTmp, PROP_TITLE_PARA_RIGHT_MARGIN, 0 );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aTmp, PROP_TITLE_PARA_TOP_MARGIN, 0 );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aTmp, PROP_TITLE_PARA_BOTTOM_MARGIN, 0 );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_TITLE_PARA_IS_HYPHENATION, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_TITLE_VISIBLE, true );
+
+ // own properties
+ ::chart::PropertyHelper::setPropertyValueDefault< double >( aTmp, PROP_TITLE_TEXT_ROTATION, 0.0 );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_TITLE_TEXT_STACKED, false );
+
+ // override other defaults
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::FillProperties::PROP_FILL_STYLE, drawing::FillStyle_NONE );
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE );
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& StaticTitleInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+Title::Title() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+Title::Title( const Title & rOther ) :
+ impl::Title_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ CloneHelper::CloneRefSequence<chart2::XFormattedString>(
+ rOther.m_aStrings, m_aStrings );
+ ModifyListenerHelper::addListenerToAllElements(
+ comphelper::sequenceToContainer<std::vector<uno::Reference< chart2::XFormattedString > > >( m_aStrings ),
+ m_xModifyEventForwarder );
+}
+
+Title::~Title()
+{
+ ModifyListenerHelper::removeListenerFromAllElements(
+ comphelper::sequenceToContainer<std::vector<uno::Reference< chart2::XFormattedString > > >( m_aStrings ),
+ m_xModifyEventForwarder );
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL Title::createClone()
+{
+ return uno::Reference< util::XCloneable >( new Title( *this ));
+}
+
+// ____ XTitle ____
+uno::Sequence< uno::Reference< chart2::XFormattedString > > SAL_CALL Title::getText()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_aStrings;
+}
+
+void SAL_CALL Title::setText( const uno::Sequence< uno::Reference< chart2::XFormattedString > >& rNewStrings )
+{
+ uno::Sequence< uno::Reference< chart2::XFormattedString > > aOldStrings;
+ {
+ MutexGuard aGuard( m_aMutex );
+ std::swap( m_aStrings, aOldStrings );
+ m_aStrings = rNewStrings;
+ }
+ //don't keep the mutex locked while calling out
+ ModifyListenerHelper::removeListenerFromAllElements(
+ comphelper::sequenceToContainer<std::vector<uno::Reference< chart2::XFormattedString > > >( aOldStrings ),
+ m_xModifyEventForwarder );
+ ModifyListenerHelper::addListenerToAllElements(
+ comphelper::sequenceToContainer<std::vector<uno::Reference< chart2::XFormattedString > > >( rNewStrings ),
+ m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+// ____ OPropertySet ____
+void Title::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticTitleDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL Title::getInfoHelper()
+{
+ return StaticTitleInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL Title::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticTitleInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL Title::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL Title::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL Title::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL Title::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void Title::firePropertyChangeEvent()
+{
+ fireModifyEvent();
+}
+
+void Title::fireModifyEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+OUString SAL_CALL Title::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.Title";
+}
+
+sal_Bool SAL_CALL Title::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL Title::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart2.Title",
+ "com.sun.star.style.ParagraphProperties",
+ "com.sun.star.beans.PropertySet",
+ "com.sun.star.layout.LayoutElement" };
+}
+
+// needed by MSC compiler
+using impl::Title_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( Title, Title_Base, ::property::OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( Title, Title_Base, ::property::OPropertySet )
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_Title_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::Title);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/UndoManager.cxx b/chart2/source/model/main/UndoManager.cxx
new file mode 100644
index 0000000000..a756e7440a
--- /dev/null
+++ b/chart2/source/model/main/UndoManager.cxx
@@ -0,0 +1,350 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "UndoManager.hxx"
+#include <ChartModel.hxx>
+#include <ChartViewHelper.hxx>
+
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <framework/undomanagerhelper.hxx>
+#include <framework/imutex.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <svl/undo.hxx>
+
+namespace chart
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::lang::DisposedException;
+ using ::com::sun::star::document::XUndoManager;
+ using ::com::sun::star::document::XUndoAction;
+ using ::com::sun::star::document::XUndoManagerListener;
+ using ::com::sun::star::lang::NoSupportException;
+ using ::com::sun::star::util::XModifyListener;
+ using ::com::sun::star::frame::XModel;
+
+ namespace impl
+ {
+ class UndoManager_Impl : public ::framework::IUndoManagerImplementation
+ {
+ public:
+ UndoManager_Impl( UndoManager& i_antiImpl, ::chart::ChartModel& i_parent, ::osl::Mutex& i_mutex )
+ :m_rAntiImpl( i_antiImpl )
+ ,m_rParent( i_parent )
+ ,m_rMutex( i_mutex )
+ ,m_bDisposed( false )
+ ,m_aUndoHelper( *this )
+ {
+ m_aUndoManager.SetMaxUndoActionCount(
+ officecfg::Office::Common::Undo::Steps::get());
+ }
+
+ virtual ~UndoManager_Impl()
+ {
+ }
+
+ ::osl::Mutex& getMutex();
+ // IUndoManagerImplementation
+ virtual SfxUndoManager& getImplUndoManager() override;
+ virtual Reference< XUndoManager > getThis() override;
+
+ // attribute access
+ ::chart::ChartModel& getParent() { return m_rParent; }
+ ::framework::UndoManagerHelper& getUndoHelper() { return m_aUndoHelper; }
+
+ // public interface
+
+ /// is called when the owner of the UndoManager is being disposed
+ void disposing();
+
+ /// checks whether we're already disposed, throws a DisposedException if so
+ void checkDisposed_lck();
+
+ private:
+ UndoManager& m_rAntiImpl;
+ ::chart::ChartModel& m_rParent;
+ ::osl::Mutex& m_rMutex;
+ bool m_bDisposed;
+
+ SfxUndoManager m_aUndoManager;
+ ::framework::UndoManagerHelper m_aUndoHelper;
+ };
+
+ ::osl::Mutex& UndoManager_Impl::getMutex()
+ {
+ return m_rMutex;
+ }
+
+ SfxUndoManager& UndoManager_Impl::getImplUndoManager()
+ {
+ return m_aUndoManager;
+ }
+
+ Reference< XUndoManager > UndoManager_Impl::getThis()
+ {
+ return &m_rAntiImpl;
+ }
+
+ void UndoManager_Impl::disposing()
+ {
+ {
+ ::osl::MutexGuard aGuard( m_rMutex );
+ m_bDisposed = true;
+ }
+ m_aUndoHelper.disposing();
+ }
+
+ void UndoManager_Impl::checkDisposed_lck()
+ {
+ if ( m_bDisposed )
+ throw DisposedException( OUString(), getThis() );
+ }
+
+ namespace {
+
+ /** guard for public UNO methods of the UndoManager
+
+ The only purpose of this guard is to check for the instance being disposed already. Everything else,
+ in particular the IMutexGuard functionality required by the UndoManagerHelper class, is a dummy only,
+ as all involved classes (means we ourselves, the UndoManagerHelper, the SfxUndoManager, and the Undo actions
+ we create) are inherently thread-safe, thus need no external lock (in particular no SolarMutex!).
+ */
+ class UndoManagerMethodGuard : public ::framework::IMutexGuard
+ {
+ public:
+ explicit UndoManagerMethodGuard( UndoManager_Impl& i_impl )
+ {
+ ::osl::MutexGuard aGuard( i_impl.getMutex() );
+ // throw if the instance is already disposed
+ i_impl.checkDisposed_lck();
+ }
+ virtual ~UndoManagerMethodGuard()
+ {
+ }
+
+ // IMutexGuard
+ virtual void clear() override;
+ virtual ::framework::IMutex& getGuardedMutex() override;
+ };
+
+ class DummyMutex : public ::framework::IMutex
+ {
+ public:
+ virtual ~DummyMutex() {}
+ virtual void acquire() override { }
+ virtual void release() override { }
+ };
+
+ }
+
+ ::framework::IMutex& UndoManagerMethodGuard::getGuardedMutex()
+ {
+ static DummyMutex s_aDummyMutex;
+ return s_aDummyMutex;
+ }
+
+ void UndoManagerMethodGuard::clear()
+ {
+ // nothing to do. This interface implementation is a dummy.
+ }
+ }
+
+ using impl::UndoManagerMethodGuard;
+
+ UndoManager::UndoManager( ::chart::ChartModel& i_parent, ::osl::Mutex& i_mutex )
+ :m_pImpl( new impl::UndoManager_Impl( *this, i_parent, i_mutex ) )
+ {
+ }
+
+ UndoManager::~UndoManager()
+ {
+ }
+
+ void SAL_CALL UndoManager::acquire() noexcept
+ {
+ m_pImpl->getParent().acquire();
+ }
+
+ void SAL_CALL UndoManager::release() noexcept
+ {
+ m_pImpl->getParent().release();
+ }
+
+ void UndoManager::disposing()
+ {
+ m_pImpl->disposing();
+ }
+
+ void SAL_CALL UndoManager::enterUndoContext( const OUString& i_title )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().enterUndoContext( i_title, aGuard );
+ }
+
+ void SAL_CALL UndoManager::enterHiddenUndoContext( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().enterHiddenUndoContext( aGuard );
+ }
+
+ void SAL_CALL UndoManager::leaveUndoContext( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().leaveUndoContext( aGuard );
+ }
+
+ void SAL_CALL UndoManager::addUndoAction( const Reference< XUndoAction >& i_action )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().addUndoAction( i_action, aGuard );
+ }
+
+ void SAL_CALL UndoManager::undo( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().undo( aGuard );
+
+ ChartViewHelper::setViewToDirtyState( &m_pImpl->getParent() );
+ }
+
+ void SAL_CALL UndoManager::redo( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().redo( aGuard );
+
+ ChartViewHelper::setViewToDirtyState( &m_pImpl->getParent() );
+ }
+
+ sal_Bool SAL_CALL UndoManager::isUndoPossible( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ return m_pImpl->getUndoHelper().isUndoPossible();
+ }
+
+ sal_Bool SAL_CALL UndoManager::isRedoPossible( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ return m_pImpl->getUndoHelper().isRedoPossible();
+ }
+
+ OUString SAL_CALL UndoManager::getCurrentUndoActionTitle( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ return m_pImpl->getUndoHelper().getCurrentUndoActionTitle();
+ }
+
+ OUString SAL_CALL UndoManager::getCurrentRedoActionTitle( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ return m_pImpl->getUndoHelper().getCurrentRedoActionTitle();
+ }
+
+ Sequence< OUString > SAL_CALL UndoManager::getAllUndoActionTitles( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ return m_pImpl->getUndoHelper().getAllUndoActionTitles();
+ }
+
+ Sequence< OUString > SAL_CALL UndoManager::getAllRedoActionTitles( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ return m_pImpl->getUndoHelper().getAllRedoActionTitles();
+ }
+
+ void SAL_CALL UndoManager::clear( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().clear( aGuard );
+ }
+
+ void SAL_CALL UndoManager::clearRedo( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().clearRedo( aGuard );
+ }
+
+ void SAL_CALL UndoManager::reset( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().reset( aGuard );
+ }
+
+ void SAL_CALL UndoManager::addUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().addUndoManagerListener( i_listener );
+ }
+
+ void SAL_CALL UndoManager::removeUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().removeUndoManagerListener( i_listener );
+ }
+
+ void SAL_CALL UndoManager::lock( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().lock();
+ }
+
+ void SAL_CALL UndoManager::unlock( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().unlock();
+ }
+
+ sal_Bool SAL_CALL UndoManager::isLocked( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ return m_pImpl->getUndoHelper().isLocked();
+ }
+
+ Reference< XInterface > SAL_CALL UndoManager::getParent( )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ return m_pImpl->getParent();
+ }
+
+ void SAL_CALL UndoManager::setParent( const Reference< XInterface >& )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ throw NoSupportException( OUString(), m_pImpl->getThis() );
+ }
+
+ void SAL_CALL UndoManager::addModifyListener( const Reference< XModifyListener >& i_listener )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().addModifyListener( i_listener );
+ }
+
+ void SAL_CALL UndoManager::removeModifyListener( const Reference< XModifyListener >& i_listener )
+ {
+ UndoManagerMethodGuard aGuard( *m_pImpl );
+ m_pImpl->getUndoHelper().removeModifyListener( i_listener );
+ }
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/UndoManager.hxx b/chart2/source/model/main/UndoManager.hxx
new file mode 100644
index 0000000000..c20dcef664
--- /dev/null
+++ b/chart2/source/model/main/UndoManager.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/document/XUndoManager.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+
+#include <cppuhelper/implbase2.hxx>
+
+#include <memory>
+
+namespace chart
+{
+class ChartModel;
+
+ namespace impl
+ {
+ class UndoManager_Impl;
+ typedef ::cppu::ImplHelper2 < css::document::XUndoManager
+ , css::util::XModifyBroadcaster
+ > UndoManager_Base;
+ }
+
+ class UndoManager : public impl::UndoManager_Base
+ {
+ public:
+ UndoManager( ::chart::ChartModel& i_parent, ::osl::Mutex& i_mutex );
+ virtual ~UndoManager();
+
+ // XInterface
+ virtual void SAL_CALL acquire( ) noexcept override;
+ virtual void SAL_CALL release( ) noexcept override;
+
+ // XComponent equivalents
+ void disposing();
+
+ // XUndoManager
+ virtual void SAL_CALL enterUndoContext( const OUString& i_title ) override;
+ virtual void SAL_CALL enterHiddenUndoContext( ) override;
+ virtual void SAL_CALL leaveUndoContext( ) override;
+ virtual void SAL_CALL addUndoAction( const css::uno::Reference< css::document::XUndoAction >& i_action ) override;
+ virtual void SAL_CALL undo( ) override;
+ virtual void SAL_CALL redo( ) override;
+ virtual sal_Bool SAL_CALL isUndoPossible( ) override;
+ virtual sal_Bool SAL_CALL isRedoPossible( ) override;
+ virtual OUString SAL_CALL getCurrentUndoActionTitle( ) override;
+ virtual OUString SAL_CALL getCurrentRedoActionTitle( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getAllUndoActionTitles( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getAllRedoActionTitles( ) override;
+ virtual void SAL_CALL clear( ) override;
+ virtual void SAL_CALL clearRedo( ) override;
+ virtual void SAL_CALL reset( ) override;
+ virtual void SAL_CALL addUndoManagerListener( const css::uno::Reference< css::document::XUndoManagerListener >& i_listener ) override;
+ virtual void SAL_CALL removeUndoManagerListener( const css::uno::Reference< css::document::XUndoManagerListener >& i_listener ) override;
+
+ // XLockable (base of XUndoManager)
+ virtual void SAL_CALL lock( ) override;
+ virtual void SAL_CALL unlock( ) override;
+ virtual sal_Bool SAL_CALL isLocked( ) override;
+
+ // XChild (base of XUndoManager)
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent( ) override;
+ virtual void SAL_CALL setParent( const css::uno::Reference< css::uno::XInterface >& Parent ) override;
+
+ // XModifyBroadcaster
+ virtual void SAL_CALL addModifyListener( const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener( const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ private:
+ std::unique_ptr< impl::UndoManager_Impl > m_pImpl;
+ };
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/Wall.cxx b/chart2/source/model/main/Wall.cxx
new file mode 100644
index 0000000000..1bbe133de9
--- /dev/null
+++ b/chart2/source/model/main/Wall.cxx
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Wall.hxx"
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include <PropertyHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <com/sun/star/drawing/LineStyle.hpp>
+
+#include <vector>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper& StaticWallInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+Wall::Wall() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+Wall::Wall( const Wall & rOther ) :
+ impl::Wall_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+Wall::~Wall()
+{}
+
+// ____ XTypeProvider ____
+uno::Sequence< css::uno::Type > SAL_CALL Wall::getTypes()
+{
+ return ::comphelper::concatSequences(
+ impl::Wall_Base::getTypes(),
+ ::property::OPropertySet::getTypes());
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL Wall::createClone()
+{
+ return uno::Reference< util::XCloneable >( new Wall( *this ));
+}
+
+// ____ OPropertySet ____
+void Wall::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ ::chart::FillProperties::AddDefaultsToMap( aTmp );
+
+ // override other defaults
+ ::chart::PropertyHelper::setPropertyValue( aTmp, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE );
+ return aTmp;
+ }();
+ tPropertyValueMap::const_iterator aFound( aStaticDefaults.find( nHandle ) );
+ if( aFound == aStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL Wall::getInfoHelper()
+{
+ return StaticWallInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL Wall::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticWallInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL Wall::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL Wall::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL Wall::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL Wall::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void Wall::firePropertyChangeEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+using impl::Wall_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( Wall, Wall_Base, ::property::OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/main/Wall.hxx b/chart2/source/model/main/Wall.hxx
new file mode 100644
index 0000000000..6cae798959
--- /dev/null
+++ b/chart2/source/model/main/Wall.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/util/XCloneable.hpp>
+#include <OPropertySet.hxx>
+
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <ModifyListenerHelper.hxx>
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener >
+ Wall_Base;
+}
+
+class Wall final :
+ public impl::Wall_Base,
+ public ::property::OPropertySet
+{
+public:
+ Wall();
+ virtual ~Wall() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+
+ explicit Wall( const Wall & rOther );
+
+ // ____ XTypeProvider ____
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+private:
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+ using OPropertySet::disposing;
+
+private:
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/AreaChartType.cxx b/chart2/source/model/template/AreaChartType.cxx
new file mode 100644
index 0000000000..b0581ddc88
--- /dev/null
+++ b/chart2/source/model/template/AreaChartType.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AreaChartType.hxx"
+#include <servicenames_charttypes.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+AreaChartType::AreaChartType()
+{}
+
+AreaChartType::AreaChartType( const AreaChartType & rOther ) :
+ ChartType( rOther )
+{}
+
+AreaChartType::~AreaChartType()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL AreaChartType::createClone()
+{
+ return uno::Reference< util::XCloneable >( new AreaChartType( *this ));
+}
+
+rtl::Reference< ChartType > AreaChartType::cloneChartType() const
+{
+ return new AreaChartType( *this );
+}
+
+// ____ XChartType ____
+OUString SAL_CALL AreaChartType::getChartType()
+{
+ return CHART2_SERVICE_NAME_CHARTTYPE_AREA;
+}
+
+OUString SAL_CALL AreaChartType::getImplementationName()
+{
+ return "com.sun.star.comp.chart.AreaChartType";
+}
+
+sal_Bool SAL_CALL AreaChartType::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL AreaChartType::getSupportedServiceNames()
+{
+ return {
+ CHART2_SERVICE_NAME_CHARTTYPE_AREA,
+ "com.sun.star.chart2.ChartType" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_AreaChartType_get_implementation(css::uno::XComponentContext * /*context*/,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::AreaChartType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/AreaChartType.hxx b/chart2/source/model/template/AreaChartType.hxx
new file mode 100644
index 0000000000..8ca01e1f3a
--- /dev/null
+++ b/chart2/source/model/template/AreaChartType.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartType.hxx>
+
+namespace chart
+{
+
+class AreaChartType final : public ChartType
+{
+public:
+ explicit AreaChartType();
+ virtual ~AreaChartType() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const override;
+
+private:
+ explicit AreaChartType( const AreaChartType & rOther );
+
+ // ____ XChartType ____
+ virtual OUString SAL_CALL getChartType() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/AreaChartTypeTemplate.cxx b/chart2/source/model/template/AreaChartTypeTemplate.cxx
new file mode 100644
index 0000000000..f2ff81a1e8
--- /dev/null
+++ b/chart2/source/model/template/AreaChartTypeTemplate.cxx
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AreaChartTypeTemplate.hxx"
+#include "AreaChartType.hxx"
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+
+enum
+{
+ PROP_AREA_TEMPLATE_DIMENSION
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "Dimension",
+ PROP_AREA_TEMPLATE_DIMENSION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+::cppu::OPropertyArrayHelper& StaticAreaChartTypeTemplateInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+AreaChartTypeTemplate::AreaChartTypeTemplate(
+ uno::Reference<
+ uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StackMode eStackMode,
+ sal_Int32 nDim /* = 2 */ ) :
+ ChartTypeTemplate( xContext, rServiceName ),
+ m_eStackMode( eStackMode )
+{
+ setFastPropertyValue_NoBroadcast( PROP_AREA_TEMPLATE_DIMENSION, uno::Any( nDim ));
+}
+
+AreaChartTypeTemplate::~AreaChartTypeTemplate()
+{}
+
+// ____ OPropertySet ____
+void AreaChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aTmp, PROP_AREA_TEMPLATE_DIMENSION, 2 );
+ return aTmp;
+ }();
+ tPropertyValueMap::const_iterator aFound( aStaticDefaults.find( nHandle ) );
+ if( aFound == aStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL AreaChartTypeTemplate::getInfoHelper()
+{
+ return StaticAreaChartTypeTemplateInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL AreaChartTypeTemplate::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticAreaChartTypeTemplateInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+sal_Int32 AreaChartTypeTemplate::getDimension() const
+{
+ sal_Int32 nDim = 2;
+ try
+ {
+ // note: UNO-methods are never const
+ const_cast< AreaChartTypeTemplate * >( this )->
+ getFastPropertyValue( PROP_AREA_TEMPLATE_DIMENSION ) >>= nDim;
+ }
+ catch( const beans::UnknownPropertyException & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return nDim;
+}
+
+StackMode AreaChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
+{
+ return m_eStackMode;
+}
+
+// ____ ChartTypeTemplate ____
+void AreaChartTypeTemplate::applyStyle2(
+ const rtl::Reference< DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount )
+{
+ ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount );
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) );
+}
+
+void AreaChartTypeTemplate::resetStyles2( const rtl::Reference< ::chart::Diagram >& xDiagram )
+{
+ ChartTypeTemplate::resetStyles2( xDiagram );
+ std::vector< rtl::Reference< ::chart::DataSeries > > aSeriesVec(
+ xDiagram->getDataSeries());
+ uno::Any aLineStyleAny( drawing::LineStyle_NONE );
+ for (auto const& series : aSeriesVec)
+ {
+ if( series->getPropertyValue( "BorderStyle") == aLineStyleAny )
+ {
+ series->setPropertyToDefault( "BorderStyle");
+ }
+ }
+}
+
+rtl::Reference< ChartType > AreaChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ )
+{
+ return new AreaChartType();
+}
+
+rtl::Reference< ChartType > AreaChartTypeTemplate::getChartTypeForNewSeries2(
+ const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes )
+{
+ rtl::Reference< ChartType > xResult( getChartTypeForIndex( 0 ) );
+ ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult );
+ return xResult;
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( AreaChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( AreaChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/AreaChartTypeTemplate.hxx b/chart2/source/model/template/AreaChartTypeTemplate.hxx
new file mode 100644
index 0000000000..76a5bfd4c8
--- /dev/null
+++ b/chart2/source/model/template/AreaChartTypeTemplate.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartTypeTemplate.hxx>
+#include <StackMode.hxx>
+
+#include <OPropertySet.hxx>
+#include <comphelper/uno3.hxx>
+
+namespace chart
+{
+
+class AreaChartTypeTemplate :
+ public ChartTypeTemplate,
+ public ::property::OPropertySet
+{
+public:
+ explicit AreaChartTypeTemplate(
+ css::uno::Reference< css::uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StackMode eStackMode,
+ sal_Int32 nDim = 2 );
+ virtual ~AreaChartTypeTemplate() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+protected:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ ChartTypeTemplate ____
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForNewSeries2( const std::vector<
+ rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override;
+ virtual void applyStyle2(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeGroupIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount ) override;
+ virtual void resetStyles2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram ) override;
+
+ // ____ ChartTypeTemplate ____
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override;
+ virtual sal_Int32 getDimension() const override;
+ virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override;
+
+private:
+ StackMode m_eStackMode;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/BarChartType.cxx b/chart2/source/model/template/BarChartType.cxx
new file mode 100644
index 0000000000..2a94db82ba
--- /dev/null
+++ b/chart2/source/model/template/BarChartType.cxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "BarChartType.hxx"
+#include <servicenames_charttypes.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+BarChartType::BarChartType()
+{}
+
+BarChartType::BarChartType( const BarChartType & rOther ) :
+ ChartType( rOther )
+{
+}
+
+BarChartType::~BarChartType()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL BarChartType::createClone()
+{
+ return uno::Reference< util::XCloneable >( new BarChartType( *this ));
+}
+
+rtl::Reference< ChartType > BarChartType::cloneChartType() const
+{
+ return new BarChartType( *this );
+}
+
+// ____ XChartType ____
+OUString SAL_CALL BarChartType::getChartType()
+{
+ return CHART2_SERVICE_NAME_CHARTTYPE_BAR;
+}
+
+uno::Sequence< OUString > BarChartType::getSupportedPropertyRoles()
+{
+ return { "FillColor", "BorderColor" };
+}
+
+OUString SAL_CALL BarChartType::getImplementationName()
+{
+ return "com.sun.star.comp.chart.BarChartType";
+}
+
+sal_Bool SAL_CALL BarChartType::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL BarChartType::getSupportedServiceNames()
+{
+ return {
+ CHART2_SERVICE_NAME_CHARTTYPE_BAR,
+ "com.sun.star.chart2.ChartType" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_BarChartType_get_implementation(css::uno::XComponentContext * /*context*/,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::BarChartType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/BarChartType.hxx b/chart2/source/model/template/BarChartType.hxx
new file mode 100644
index 0000000000..cceaf05777
--- /dev/null
+++ b/chart2/source/model/template/BarChartType.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartType.hxx>
+
+namespace chart
+{
+
+class BarChartType final : public ChartType
+{
+public:
+ explicit BarChartType();
+ virtual ~BarChartType() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const override;
+
+private:
+ explicit BarChartType( const BarChartType & rOther );
+
+ // ____ XChartType ____
+ virtual OUString SAL_CALL getChartType() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedPropertyRoles() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/BarChartTypeTemplate.cxx b/chart2/source/model/template/BarChartTypeTemplate.cxx
new file mode 100644
index 0000000000..1381e09cc4
--- /dev/null
+++ b/chart2/source/model/template/BarChartTypeTemplate.cxx
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "BarChartTypeTemplate.hxx"
+#include "ColumnChartType.hxx"
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+enum
+{
+ PROP_BAR_TEMPLATE_DIMENSION,
+ PROP_BAR_TEMPLATE_GEOMETRY3D
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "Dimension",
+ PROP_BAR_TEMPLATE_DIMENSION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "Geometry3D",
+ PROP_BAR_TEMPLATE_GEOMETRY3D,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+::cppu::OPropertyArrayHelper& StaticBarChartTypeTemplateInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+BarChartTypeTemplate::BarChartTypeTemplate(
+ Reference<
+ uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StackMode eStackMode,
+ BarDirection eDirection,
+ sal_Int32 nDim /* = 2 */ ) :
+ ChartTypeTemplate( xContext, rServiceName ),
+ m_eStackMode( eStackMode ),
+ m_eBarDirection( eDirection ),
+ m_nDim( nDim )
+{}
+
+BarChartTypeTemplate::~BarChartTypeTemplate()
+{}
+
+sal_Int32 BarChartTypeTemplate::getDimension() const
+{
+ return m_nDim;
+}
+
+StackMode BarChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
+{
+ return m_eStackMode;
+}
+
+bool BarChartTypeTemplate::isSwapXAndY() const
+{
+ return (m_eBarDirection == HORIZONTAL);
+}
+
+// ____ ChartTypeTemplate ____
+bool BarChartTypeTemplate::matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties )
+{
+ bool bResult = ChartTypeTemplate::matchesTemplate2( xDiagram, bAdaptProperties );
+
+ //check BarDirection
+ if( bResult )
+ {
+ bool bFound = false;
+ bool bAmbiguous = false;
+ bool bVertical = xDiagram->getVertical( bFound, bAmbiguous );
+ if( m_eBarDirection == HORIZONTAL )
+ bResult = bVertical;
+ else if( m_eBarDirection == VERTICAL )
+ bResult = !bVertical;
+ }
+
+ // adapt solid-type of template according to values in series
+ if( bAdaptProperties &&
+ bResult &&
+ getDimension() == 3 )
+ {
+
+ bool bGeomFound = false, bGeomAmbiguous = false;
+ sal_Int32 aCommonGeom = xDiagram->getGeometry3D( bGeomFound, bGeomAmbiguous );
+
+ if( !bGeomAmbiguous )
+ {
+ setFastPropertyValue_NoBroadcast(
+ PROP_BAR_TEMPLATE_GEOMETRY3D, uno::Any( aCommonGeom ));
+ }
+ }
+
+ return bResult;
+}
+
+rtl::Reference< ChartType > BarChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ )
+{
+ return new ColumnChartType();
+}
+
+rtl::Reference< ChartType > BarChartTypeTemplate::getChartTypeForNewSeries2(
+ const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes )
+{
+ rtl::Reference< ChartType > xResult( getChartTypeForIndex( 0 ) );
+ ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult );
+ return xResult;
+}
+
+// ____ OPropertySet ____
+void BarChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ static ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aTmp, PROP_BAR_TEMPLATE_DIMENSION, 2 );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_BAR_TEMPLATE_GEOMETRY3D, ::chart2::DataPointGeometry3D::CUBOID );
+ return aTmp;
+ }();
+ tPropertyValueMap::const_iterator aFound( aStaticDefaults.find( nHandle ) );
+ if( aFound == aStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL BarChartTypeTemplate::getInfoHelper()
+{
+ return StaticBarChartTypeTemplateInfoHelper();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL BarChartTypeTemplate::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticBarChartTypeTemplateInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+void BarChartTypeTemplate::applyStyle2(
+ const rtl::Reference< DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount )
+{
+ ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount );
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) );
+ if( getDimension() != 3 )
+ return;
+
+ try
+ {
+ //apply Geometry3D
+ uno::Any aAGeometry3D;
+ getFastPropertyValue( aAGeometry3D, PROP_BAR_TEMPLATE_GEOMETRY3D );
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "Geometry3D", aAGeometry3D );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void BarChartTypeTemplate::resetStyles2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram )
+{
+ ChartTypeTemplate::resetStyles2( xDiagram );
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec(
+ xDiagram->getDataSeries());
+ uno::Any aLineStyleAny( drawing::LineStyle_NONE );
+ for (auto const& series : aSeriesVec)
+ {
+ if( getDimension() == 3 )
+ series->setPropertyToDefault( "Geometry3D");
+ if( series->getPropertyValue( "BorderStyle") == aLineStyleAny )
+ {
+ series->setPropertyToDefault( "BorderStyle");
+ }
+ }
+
+ xDiagram->setVertical( false );
+}
+
+void BarChartTypeTemplate::createCoordinateSystems(
+ const rtl::Reference< ::chart::Diagram > & xDiagram )
+{
+ ChartTypeTemplate::createCoordinateSystems( xDiagram );
+
+ xDiagram->setVertical( m_eBarDirection == HORIZONTAL );
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( BarChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( BarChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/BarChartTypeTemplate.hxx b/chart2/source/model/template/BarChartTypeTemplate.hxx
new file mode 100644
index 0000000000..ab56869e71
--- /dev/null
+++ b/chart2/source/model/template/BarChartTypeTemplate.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <OPropertySet.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <ChartTypeTemplate.hxx>
+#include <StackMode.hxx>
+
+namespace chart
+{
+
+class BarChartTypeTemplate :
+ public ChartTypeTemplate,
+ public ::property::OPropertySet
+{
+public:
+ enum BarDirection
+ {
+ HORIZONTAL,
+ VERTICAL
+ };
+
+ explicit BarChartTypeTemplate(
+ css::uno::Reference< css::uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StackMode eStackMode,
+ BarDirection eDirection,
+ sal_Int32 nDim = 2 );
+ virtual ~BarChartTypeTemplate() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+protected:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ ChartTypeTemplate ____
+ virtual bool matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties ) override;
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForNewSeries2( const std::vector<
+ rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override;
+ virtual void applyStyle2(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeGroupIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount ) override;
+ virtual void resetStyles2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram ) override;
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override;
+ virtual sal_Int32 getDimension() const override;
+ virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override;
+ virtual bool isSwapXAndY() const override;
+
+ virtual void createCoordinateSystems(
+ const rtl::Reference< ::chart::Diagram > & xDiagram ) override;
+
+private:
+ StackMode m_eStackMode;
+ BarDirection m_eBarDirection;
+ sal_Int32 m_nDim;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/BubbleChartType.cxx b/chart2/source/model/template/BubbleChartType.cxx
new file mode 100644
index 0000000000..bd8bf287d9
--- /dev/null
+++ b/chart2/source/model/template/BubbleChartType.cxx
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "BubbleChartType.hxx"
+#include <PropertyHelper.hxx>
+#include <servicenames_charttypes.hxx>
+#include <CartesianCoordinateSystem.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <AxisIndexDefines.hxx>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper& StaticBubbleChartTypeInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+BubbleChartType::BubbleChartType()
+{
+}
+
+BubbleChartType::BubbleChartType( const BubbleChartType & rOther ) :
+ ChartType( rOther )
+{
+}
+
+BubbleChartType::~BubbleChartType()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL BubbleChartType::createClone()
+{
+ return uno::Reference< util::XCloneable >( new BubbleChartType( *this ));
+}
+
+rtl::Reference< ChartType > BubbleChartType::cloneChartType() const
+{
+ return new BubbleChartType( *this );
+}
+
+// ____ XChartType ____
+rtl::Reference< ::chart::BaseCoordinateSystem >
+ BubbleChartType::createCoordinateSystem2( sal_Int32 DimensionCount )
+{
+ rtl::Reference< CartesianCoordinateSystem > xResult =
+ new CartesianCoordinateSystem( DimensionCount );
+
+ for( sal_Int32 i=0; i<DimensionCount; ++i )
+ {
+ rtl::Reference< Axis > xAxis = xResult->getAxisByDimension2( i, MAIN_AXIS_INDEX );
+ if( !xAxis.is() )
+ {
+ OSL_FAIL("a created coordinate system should have an axis for each dimension");
+ continue;
+ }
+
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
+ aScaleData.Scaling = AxisHelper::createLinearScaling();
+
+ if( i == 2 )
+ aScaleData.AxisType = chart2::AxisType::SERIES;
+ else
+ aScaleData.AxisType = chart2::AxisType::REALNUMBER;
+
+ xAxis->setScaleData( aScaleData );
+ }
+
+ return xResult;
+}
+
+OUString SAL_CALL BubbleChartType::getChartType()
+{
+ return CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE;
+}
+
+uno::Sequence< OUString > SAL_CALL BubbleChartType::getSupportedMandatoryRoles()
+{
+ return { "label", "values-x", "values-y", "values-size" };
+}
+
+uno::Sequence< OUString > SAL_CALL BubbleChartType::getSupportedPropertyRoles()
+{
+ return { "FillColor", "BorderColor" };
+}
+
+OUString SAL_CALL BubbleChartType::getRoleOfSequenceForSeriesLabel()
+{
+ return "values-size";
+}
+
+// ____ OPropertySet ____
+void BubbleChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ static ::chart::tPropertyValueMap aStaticDefaults;
+ tPropertyValueMap::const_iterator aFound( aStaticDefaults.find( nHandle ) );
+ if( aFound == aStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+// ____ OPropertySet ____
+::cppu::IPropertyArrayHelper & SAL_CALL BubbleChartType::getInfoHelper()
+{
+ return StaticBubbleChartTypeInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL BubbleChartType::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticBubbleChartTypeInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+OUString SAL_CALL BubbleChartType::getImplementationName()
+{
+ return "com.sun.star.comp.chart.BubbleChartType";
+}
+
+sal_Bool SAL_CALL BubbleChartType::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL BubbleChartType::getSupportedServiceNames()
+{
+ return {
+ CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE,
+ "com.sun.star.chart2.ChartType",
+ "com.sun.star.beans.PropertySet" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_BubbleChartType_get_implementation(css::uno::XComponentContext * /*context*/,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::BubbleChartType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/BubbleChartType.hxx b/chart2/source/model/template/BubbleChartType.hxx
new file mode 100644
index 0000000000..a2afa7e694
--- /dev/null
+++ b/chart2/source/model/template/BubbleChartType.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartType.hxx>
+
+namespace chart
+{
+
+class BubbleChartType final : public ChartType
+{
+public:
+ explicit BubbleChartType();
+ virtual ~BubbleChartType() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const override;
+
+private:
+ explicit BubbleChartType( const BubbleChartType & rOther );
+
+ // ____ XChartType ____
+ virtual OUString SAL_CALL getChartType() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedMandatoryRoles() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedPropertyRoles() override;
+ virtual OUString SAL_CALL getRoleOfSequenceForSeriesLabel() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ virtual rtl::Reference< ::chart::BaseCoordinateSystem >
+ createCoordinateSystem2( sal_Int32 DimensionCount ) override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/BubbleChartTypeTemplate.cxx b/chart2/source/model/template/BubbleChartTypeTemplate.cxx
new file mode 100644
index 0000000000..55f39ef066
--- /dev/null
+++ b/chart2/source/model/template/BubbleChartTypeTemplate.cxx
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "BubbleChartTypeTemplate.hxx"
+#include "BubbleChartType.hxx"
+#include "BubbleDataInterpreter.hxx"
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <PropertyHelper.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper & StaticBubbleChartTypeTemplateInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+BubbleChartTypeTemplate::BubbleChartTypeTemplate(
+ Reference<
+ uno::XComponentContext > const & xContext,
+ const OUString & rServiceName ) :
+ ChartTypeTemplate( xContext, rServiceName )
+{
+}
+
+BubbleChartTypeTemplate::~BubbleChartTypeTemplate()
+{}
+
+// ____ OPropertySet ____
+void BubbleChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ static ::chart::tPropertyValueMap aStaticDefaults;
+ tPropertyValueMap::const_iterator aFound( aStaticDefaults.find( nHandle ) );
+ if( aFound == aStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL BubbleChartTypeTemplate::getInfoHelper()
+{
+ return StaticBubbleChartTypeTemplateInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL BubbleChartTypeTemplate::getPropertySetInfo()
+{
+ static const uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticBubbleChartTypeTemplateInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+sal_Int32 BubbleChartTypeTemplate::getDimension() const
+{
+ return 2;
+}
+
+StackMode BubbleChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
+{
+ return StackMode::NONE;
+}
+
+void BubbleChartTypeTemplate::applyStyle2(
+ const rtl::Reference< DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount )
+{
+ ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount );
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) );
+}
+
+// ____ XChartTypeTemplate ____
+sal_Bool SAL_CALL BubbleChartTypeTemplate::supportsCategories()
+{
+ return false;
+}
+
+rtl::Reference< ChartType > BubbleChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ )
+{
+ return new BubbleChartType();
+}
+
+rtl::Reference< ChartType > BubbleChartTypeTemplate::getChartTypeForNewSeries2(
+ const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes )
+{
+ rtl::Reference< ChartType > xResult;
+
+ try
+ {
+ xResult = new BubbleChartType();
+
+ ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+rtl::Reference< DataInterpreter > BubbleChartTypeTemplate::getDataInterpreter2()
+{
+ if( ! m_xDataInterpreter.is())
+ m_xDataInterpreter.set( new BubbleDataInterpreter );
+
+ return m_xDataInterpreter;
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( BubbleChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( BubbleChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/BubbleChartTypeTemplate.hxx b/chart2/source/model/template/BubbleChartTypeTemplate.hxx
new file mode 100644
index 0000000000..8a59e5e728
--- /dev/null
+++ b/chart2/source/model/template/BubbleChartTypeTemplate.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartTypeTemplate.hxx>
+#include <OPropertySet.hxx>
+#include <comphelper/uno3.hxx>
+
+namespace chart
+{
+
+class BubbleChartTypeTemplate :
+ public ChartTypeTemplate,
+ public ::property::OPropertySet
+{
+public:
+ explicit BubbleChartTypeTemplate(
+ css::uno::Reference< css::uno::XComponentContext > const & xContext,
+ const OUString & rServiceName );
+ virtual ~BubbleChartTypeTemplate() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+protected:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ ChartTypeTemplate ____
+ virtual sal_Bool SAL_CALL supportsCategories() override;
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForNewSeries2( const std::vector<
+ rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override;
+ virtual rtl::Reference< ::chart::DataInterpreter > getDataInterpreter2() override;
+ virtual void applyStyle2(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeGroupIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount ) override;
+
+ // ____ ChartTypeTemplate ____
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override;
+ virtual sal_Int32 getDimension() const override;
+ virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/BubbleDataInterpreter.cxx b/chart2/source/model/template/BubbleDataInterpreter.cxx
new file mode 100644
index 0000000000..bb468fd972
--- /dev/null
+++ b/chart2/source/model/template/BubbleDataInterpreter.cxx
@@ -0,0 +1,277 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cstddef>
+
+#include "BubbleDataInterpreter.hxx"
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <CommonConverters.hxx>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+BubbleDataInterpreter::BubbleDataInterpreter()
+{
+}
+
+BubbleDataInterpreter::~BubbleDataInterpreter()
+{
+}
+
+// ____ XDataInterpreter ____
+InterpretedData BubbleDataInterpreter::interpretDataSource(
+ const Reference< chart2::data::XDataSource >& xSource,
+ const Sequence< beans::PropertyValue >& aArguments,
+ const std::vector< rtl::Reference< DataSeries > >& aSeriesToReUse )
+{
+ if( ! xSource.is())
+ return InterpretedData();
+
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = DataInterpreter::getDataSequences(xSource);
+
+ uno::Reference< chart2::data::XLabeledDataSequence > xValuesX;
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aYValuesVector;
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSizeValuesVector;
+
+ uno::Reference< chart2::data::XLabeledDataSequence > xCategories;
+ bool bHasCategories = HasCategories( aArguments, aData );
+ bool bUseCategoriesAsX = UseCategoriesAsX( aArguments );
+
+ sal_Int32 nDataSeqCount = aData.size();
+
+ bool bSetXValues = bHasCategories ? ( (nDataSeqCount-1) > 2 && (nDataSeqCount-1) % 2 != 0 )
+ :( nDataSeqCount > 2 && nDataSeqCount % 2 != 0 );
+
+ bool bCategoriesUsed = false;
+ bool bNextIsYValues = bHasCategories ? nDataSeqCount>2 : nDataSeqCount>1;
+ for( sal_Int32 nDataIdx = 0; nDataIdx < nDataSeqCount; ++nDataIdx )
+ {
+ try
+ {
+ if( bHasCategories && !bCategoriesUsed )
+ {
+ xCategories = aData[nDataIdx];
+ if( xCategories.is())
+ {
+ SetRole( xCategories->getValues(), "categories");
+ if( bUseCategoriesAsX )
+ {
+ bSetXValues = false;
+ bNextIsYValues = nDataSeqCount > 2;
+ }
+ }
+ bCategoriesUsed = true;
+ }
+ else if( !xValuesX.is() && bSetXValues )
+ {
+ xValuesX = aData[nDataIdx];
+ if( xValuesX.is())
+ SetRole( xValuesX->getValues(), "values-x");
+ }
+ else if( bNextIsYValues )
+ {
+ aYValuesVector.push_back( aData[nDataIdx] );
+ if( aData[nDataIdx].is())
+ SetRole( aData[nDataIdx]->getValues(), "values-y");
+ bNextIsYValues = false;
+ }
+ else if( !bNextIsYValues )
+ {
+ aSizeValuesVector.push_back( aData[nDataIdx] );
+ if( aData[nDataIdx].is())
+ SetRole( aData[nDataIdx]->getValues(), "values-size");
+ bNextIsYValues = (nDataSeqCount-(nDataIdx+1)) >= 2;//two or more left
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ // create DataSeries
+ std::size_t nSeriesIndex = 0;
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec;
+ aSeriesVec.reserve( aSizeValuesVector.size());
+
+ Reference< data::XLabeledDataSequence > xClonedXValues = xValuesX;
+ Reference< util::XCloneable > xCloneableX( xValuesX, uno::UNO_QUERY );
+
+ for( size_t nN = 0; nN < aSizeValuesVector.size(); ++nN, ++nSeriesIndex )
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewData;
+ if( xValuesX.is() )
+ {
+ if( nN > 0 && xCloneableX.is() )
+ xClonedXValues.set( xCloneableX->createClone(), uno::UNO_QUERY );
+ aNewData.push_back( xClonedXValues );
+ }
+ if( aYValuesVector.size() > nN )
+ aNewData.push_back( aYValuesVector[nN] );
+ aNewData.push_back(aSizeValuesVector[nN]);
+
+ rtl::Reference< DataSeries > xSeries;
+ if( nSeriesIndex < aSeriesToReUse.size())
+ xSeries = aSeriesToReUse[nSeriesIndex];
+ else
+ xSeries = new DataSeries;
+ assert( xSeries.is() );
+ xSeries->setData( aNewData );
+
+ aSeriesVec.push_back( xSeries );
+ }
+
+ return { { aSeriesVec }, xCategories };
+}
+
+InterpretedData BubbleDataInterpreter::reinterpretDataSeries(
+ const InterpretedData& aInterpretedData )
+{
+ InterpretedData aResult( aInterpretedData );
+
+ sal_Int32 i=0;
+ std::vector< rtl::Reference< DataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
+ const sal_Int32 nCount = aSeries.size();
+ for( ; i<nCount; ++i )
+ {
+ try
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences;
+
+ uno::Reference< chart2::data::XLabeledDataSequence > xValuesSize(
+ DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-size" ));
+ uno::Reference< chart2::data::XLabeledDataSequence > xValuesY(
+ DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-y" ));
+ uno::Reference< chart2::data::XLabeledDataSequence > xValuesX(
+ DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-x" ));
+
+ if( ! xValuesX.is() ||
+ ! xValuesY.is() ||
+ ! xValuesSize.is() )
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aValueSeqVec(
+ DataSeriesHelper::getAllDataSequencesByRole(
+ aSeries[i]->getDataSequences2(), "values" ));
+ if( xValuesX.is())
+ aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesX ));
+ if( xValuesY.is())
+ aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesY ));
+ if( xValuesSize.is())
+ aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesSize ));
+
+ size_t nIndex = 0;
+
+ if( ! xValuesSize.is() &&
+ aValueSeqVec.size() > nIndex )
+ {
+ xValuesSize = aValueSeqVec[nIndex++];
+ if( xValuesSize.is())
+ SetRole( xValuesSize->getValues(), "values-size");
+ }
+
+ if( ! xValuesY.is() &&
+ aValueSeqVec.size() > nIndex )
+ {
+ xValuesY = aValueSeqVec[nIndex++];
+ if( xValuesY.is())
+ SetRole( xValuesY->getValues(), "values-y");
+ }
+
+ if( ! xValuesX.is() &&
+ aValueSeqVec.size() > nIndex )
+ {
+ xValuesX = aValueSeqVec[nIndex++];
+ if( xValuesX.is())
+ SetRole( xValuesY->getValues(), "values-x");
+ }
+ }
+ if( xValuesSize.is())
+ {
+ if( xValuesY.is() )
+ {
+ if( xValuesX.is() )
+ {
+ aNewSequences = { xValuesX, xValuesY, xValuesSize };
+ }
+ else
+ {
+ aNewSequences = { xValuesY, xValuesSize };
+ }
+ }
+ else
+ {
+ aNewSequences = { xValuesSize };
+ }
+ }
+
+ const std::vector< uno::Reference< data::XLabeledDataSequence > > & aSeqs = aSeries[i]->getDataSequences2();
+ if( aSeqs.size() != aNewSequences.size() )
+ {
+#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ for( auto const & j : aSeqs )
+ {
+ assert( (j == xValuesY || j == xValuesX || j == xValuesSize) && "All sequences should be used" );
+ }
+#endif
+ aSeries[i]->setData( aNewSequences );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return aResult;
+}
+
+bool BubbleDataInterpreter::isDataCompatible(
+ const InterpretedData& aInterpretedData )
+{
+ const std::vector< rtl::Reference< DataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
+ for( rtl::Reference< DataSeries > const & dataSeries : aSeries )
+ {
+ try
+ {
+ if( dataSeries->getDataSequences2().size() != 3 )
+ return false;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return true;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/BubbleDataInterpreter.hxx b/chart2/source/model/template/BubbleDataInterpreter.hxx
new file mode 100644
index 0000000000..ff4b56de61
--- /dev/null
+++ b/chart2/source/model/template/BubbleDataInterpreter.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <DataInterpreter.hxx>
+
+namespace chart
+{
+
+class BubbleDataInterpreter : public DataInterpreter
+{
+public:
+ explicit BubbleDataInterpreter();
+ virtual ~BubbleDataInterpreter() override;
+
+protected:
+ // ____ DataInterpreter ____
+ virtual InterpretedData interpretDataSource(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments,
+ const std::vector< rtl::Reference< ::chart::DataSeries > >& aSeriesToReUse ) override;
+ virtual InterpretedData reinterpretDataSeries(
+ const InterpretedData& aInterpretedData ) override;
+ virtual bool isDataCompatible(
+ const InterpretedData& aInterpretedData ) override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/CandleStickChartType.cxx b/chart2/source/model/template/CandleStickChartType.cxx
new file mode 100644
index 0000000000..247a684068
--- /dev/null
+++ b/chart2/source/model/template/CandleStickChartType.cxx
@@ -0,0 +1,309 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "CandleStickChartType.hxx"
+#include <PropertyHelper.hxx>
+#include <StockBar.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <servicenames_charttypes.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+
+enum
+{
+ PROP_CANDLESTICKCHARTTYPE_JAPANESE,
+ PROP_CANDLESTICKCHARTTYPE_WHITE_DAY,
+ PROP_CANDLESTICKCHARTTYPE_BLACK_DAY,
+
+ PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST,
+ PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "Japanese",
+ PROP_CANDLESTICKCHARTTYPE_JAPANESE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "WhiteDay",
+ PROP_CANDLESTICKCHARTTYPE_WHITE_DAY,
+ cppu::UnoType<beans::XPropertySet>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "BlackDay",
+ PROP_CANDLESTICKCHARTTYPE_BLACK_DAY,
+ cppu::UnoType<beans::XPropertySet>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "ShowFirst",
+ PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "ShowHighLow",
+ PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+::cppu::OPropertyArrayHelper& StaticCandleStickChartTypeInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+CandleStickChartType::CandleStickChartType()
+{
+ Reference< beans::XPropertySet > xWhiteDayProps( new ::chart::StockBar( true ));
+ Reference< beans::XPropertySet > xBlackDayProps( new ::chart::StockBar( false ));
+
+ ModifyListenerHelper::addListener( xWhiteDayProps, m_xModifyEventForwarder );
+ ModifyListenerHelper::addListener( xBlackDayProps, m_xModifyEventForwarder );
+
+ setFastPropertyValue_NoBroadcast(
+ PROP_CANDLESTICKCHARTTYPE_WHITE_DAY, uno::Any( xWhiteDayProps ));
+ setFastPropertyValue_NoBroadcast(
+ PROP_CANDLESTICKCHARTTYPE_BLACK_DAY, uno::Any( xBlackDayProps ));
+}
+
+CandleStickChartType::CandleStickChartType( const CandleStickChartType & rOther ) :
+ ChartType( rOther )
+{
+ Reference< beans::XPropertySet > xPropertySet;
+ uno::Any aValue;
+
+ getFastPropertyValue( aValue, PROP_CANDLESTICKCHARTTYPE_WHITE_DAY );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder );
+
+ getFastPropertyValue( aValue, PROP_CANDLESTICKCHARTTYPE_BLACK_DAY );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::addListener( xPropertySet, m_xModifyEventForwarder );
+}
+
+CandleStickChartType::~CandleStickChartType()
+{
+ try
+ {
+ Reference< beans::XPropertySet > xPropertySet;
+ uno::Any aValue;
+
+ getFastPropertyValue( aValue, PROP_CANDLESTICKCHARTTYPE_WHITE_DAY );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder );
+
+ getFastPropertyValue( aValue, PROP_CANDLESTICKCHARTTYPE_BLACK_DAY );
+ if( ( aValue >>= xPropertySet )
+ && xPropertySet.is())
+ ModifyListenerHelper::removeListener( xPropertySet, m_xModifyEventForwarder );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL CandleStickChartType::createClone()
+{
+ return uno::Reference< util::XCloneable >( new CandleStickChartType( *this ));
+}
+
+rtl::Reference< ChartType > CandleStickChartType::cloneChartType() const
+{
+ return new CandleStickChartType( *this );
+}
+
+// ____ XChartType ____
+OUString SAL_CALL CandleStickChartType::getChartType()
+{
+ return CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK;
+}
+
+uno::Sequence< OUString > SAL_CALL CandleStickChartType::getSupportedMandatoryRoles()
+{
+ bool bShowFirst = true;
+ bool bShowHiLow = false;
+ getFastPropertyValue( PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST ) >>= bShowFirst;
+ getFastPropertyValue( PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW ) >>= bShowHiLow;
+
+ std::vector< OUString > aMandRoles;
+
+ aMandRoles.emplace_back("label");
+ if( bShowFirst )
+ aMandRoles.emplace_back("values-first");
+
+ if( bShowHiLow )
+ {
+ aMandRoles.emplace_back("values-min");
+ aMandRoles.emplace_back("values-max");
+ }
+
+ aMandRoles.emplace_back("values-last");
+
+ return comphelper::containerToSequence( aMandRoles );
+}
+
+Sequence< OUString > SAL_CALL CandleStickChartType::getSupportedOptionalRoles()
+{
+ bool bShowFirst = true;
+ bool bShowHiLow = false;
+ getFastPropertyValue( PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST ) >>= bShowFirst;
+ getFastPropertyValue( PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW ) >>= bShowHiLow;
+
+ std::vector< OUString > aOptRoles;
+
+ if( ! bShowFirst )
+ aOptRoles.emplace_back("values-first");
+
+ if( ! bShowHiLow )
+ {
+ aOptRoles.emplace_back("values-min");
+ aOptRoles.emplace_back("values-max");
+ }
+
+ return comphelper::containerToSequence( aOptRoles );
+}
+
+OUString SAL_CALL CandleStickChartType::getRoleOfSequenceForSeriesLabel()
+{
+ return "values-last";
+}
+
+// ____ OPropertySet ____
+void CandleStickChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ static const ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ // must match default in CTOR!
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_CANDLESTICKCHARTTYPE_JAPANESE, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_CANDLESTICKCHARTTYPE_SHOW_FIRST, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_CANDLESTICKCHARTTYPE_SHOW_HIGH_LOW, true );
+ return aTmp;
+ }();
+ tPropertyValueMap::const_iterator aFound( aStaticDefaults.find( nHandle ) );
+ if( aFound == aStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+// ____ OPropertySet ____
+::cppu::IPropertyArrayHelper & SAL_CALL CandleStickChartType::getInfoHelper()
+{
+ return StaticCandleStickChartTypeInfoHelper();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL CandleStickChartType::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticCandleStickChartTypeInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+void SAL_CALL CandleStickChartType::setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle, const uno::Any& rValue )
+{
+ if( nHandle == PROP_CANDLESTICKCHARTTYPE_WHITE_DAY
+ || nHandle == PROP_CANDLESTICKCHARTTYPE_BLACK_DAY )
+ {
+ uno::Any aOldValue;
+ Reference< util::XModifyBroadcaster > xBroadcaster;
+ getFastPropertyValue( aOldValue, nHandle );
+ if( aOldValue.hasValue() &&
+ (aOldValue >>= xBroadcaster) &&
+ xBroadcaster.is())
+ {
+ ModifyListenerHelper::removeListener( xBroadcaster, m_xModifyEventForwarder );
+ }
+
+ OSL_ASSERT( rValue.getValueType().getTypeClass() == uno::TypeClass_INTERFACE );
+ if( rValue.hasValue() &&
+ (rValue >>= xBroadcaster) &&
+ xBroadcaster.is())
+ {
+ ModifyListenerHelper::addListener( xBroadcaster, m_xModifyEventForwarder );
+ }
+ }
+
+ ::property::OPropertySet::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+}
+
+OUString SAL_CALL CandleStickChartType::getImplementationName()
+{
+ return "com.sun.star.comp.chart.CandleStickChartType" ;
+}
+
+sal_Bool SAL_CALL CandleStickChartType::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL CandleStickChartType::getSupportedServiceNames()
+{
+ return {
+ CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK,
+ "com.sun.star.chart2.ChartType",
+ "com.sun.star.beans.PropertySet" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_CandleStickChartType_get_implementation(css::uno::XComponentContext * /*context*/,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::CandleStickChartType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/CandleStickChartType.hxx b/chart2/source/model/template/CandleStickChartType.hxx
new file mode 100644
index 0000000000..e761075075
--- /dev/null
+++ b/chart2/source/model/template/CandleStickChartType.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartType.hxx>
+
+namespace chart
+{
+
+// see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100797> "[10/11/12 Regression] using
+// declaration causing virtual call with wrongly adjusted this pointer" before restoring 'final'
+class CandleStickChartType /* final */ : public ChartType
+{
+public:
+ explicit CandleStickChartType();
+ virtual ~CandleStickChartType() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const override;
+
+private:
+ explicit CandleStickChartType( const CandleStickChartType & rOther );
+
+ // ____ XChartType ____
+ virtual OUString SAL_CALL getChartType() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedMandatoryRoles() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedOptionalRoles() override;
+ virtual OUString SAL_CALL getRoleOfSequenceForSeriesLabel() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ OPropertySet ____
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast
+ ( sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ChartType.cxx b/chart2/source/model/template/ChartType.cxx
new file mode 100644
index 0000000000..9448a76607
--- /dev/null
+++ b/chart2/source/model/template/ChartType.cxx
@@ -0,0 +1,315 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartType.hxx>
+#include <CartesianCoordinateSystem.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <CloneHelper.hxx>
+#include <AxisIndexDefines.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <DataSeries.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+ChartType::ChartType() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_bNotifyChanges( true )
+{}
+
+ChartType::ChartType( const ChartType & rOther ) :
+ impl::ChartType_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_bNotifyChanges( true )
+{
+ {
+ SolarMutexGuard g; // access to rOther.m_aDataSeries
+ CloneHelper::CloneRefVector(
+ rOther.m_aDataSeries, m_aDataSeries);
+ }
+ ModifyListenerHelper::addListenerToAllElements( m_aDataSeries, m_xModifyEventForwarder );
+}
+
+ChartType::~ChartType()
+{
+ ModifyListenerHelper::removeListenerFromAllElements( m_aDataSeries, m_xModifyEventForwarder );
+ m_aDataSeries.clear();
+}
+
+// ____ XChartType ____
+Reference< chart2::XCoordinateSystem > SAL_CALL
+ ChartType::createCoordinateSystem( ::sal_Int32 DimensionCount )
+{
+ return createCoordinateSystem2(DimensionCount);
+}
+
+rtl::Reference< BaseCoordinateSystem >
+ ChartType::createCoordinateSystem2( ::sal_Int32 DimensionCount )
+{
+ rtl::Reference< CartesianCoordinateSystem > xResult =
+ new CartesianCoordinateSystem( DimensionCount );
+
+ for( sal_Int32 i=0; i<DimensionCount; ++i )
+ {
+ rtl::Reference< Axis > xAxis = xResult->getAxisByDimension2( i, MAIN_AXIS_INDEX );
+ if( !xAxis.is() )
+ {
+ OSL_FAIL("a created coordinate system should have an axis for each dimension");
+ continue;
+ }
+
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
+ aScaleData.Scaling = AxisHelper::createLinearScaling();
+
+ switch( i )
+ {
+ case 0: aScaleData.AxisType = chart2::AxisType::CATEGORY; break;
+ case 2: aScaleData.AxisType = chart2::AxisType::SERIES; break;
+ default: aScaleData.AxisType = chart2::AxisType::REALNUMBER; break;
+ }
+
+ xAxis->setScaleData( aScaleData );
+ }
+
+ return xResult;
+}
+
+Sequence< OUString > SAL_CALL ChartType::getSupportedMandatoryRoles()
+{
+ return { "label", "values-y" };
+}
+
+Sequence< OUString > SAL_CALL ChartType::getSupportedOptionalRoles()
+{
+ return Sequence< OUString >();
+}
+
+Sequence< OUString > SAL_CALL ChartType::getSupportedPropertyRoles()
+{
+ return Sequence< OUString >();
+}
+
+OUString SAL_CALL ChartType::getRoleOfSequenceForSeriesLabel()
+{
+ return "values-y";
+}
+
+void ChartType::impl_addDataSeriesWithoutNotification(
+ const rtl::Reference< DataSeries >& xDataSeries )
+{
+ if( std::find( m_aDataSeries.begin(), m_aDataSeries.end(), xDataSeries )
+ != m_aDataSeries.end())
+ throw lang::IllegalArgumentException("dataseries not found", static_cast<cppu::OWeakObject*>(this), 1);
+
+ m_aDataSeries.push_back( xDataSeries );
+ ModifyListenerHelper::addListener( xDataSeries, m_xModifyEventForwarder );
+}
+
+// ____ XDataSeriesContainer ____
+void SAL_CALL ChartType::addDataSeries( const Reference< chart2::XDataSeries >& xDataSeries )
+{
+ rtl::Reference<DataSeries> xTmp = dynamic_cast<DataSeries*>(xDataSeries.get());
+ assert(xTmp);
+ addDataSeries(xTmp);
+}
+
+void ChartType::addDataSeries( const rtl::Reference< DataSeries >& xDataSeries )
+{
+ SolarMutexGuard g;
+
+ impl_addDataSeriesWithoutNotification( xDataSeries );
+ fireModifyEvent();
+}
+
+void SAL_CALL ChartType::removeDataSeries( const Reference< chart2::XDataSeries >& xDataSeries )
+{
+ rtl::Reference<DataSeries> xTmp = dynamic_cast<DataSeries*>(xDataSeries.get());
+ assert(xTmp);
+ removeDataSeries(xTmp);
+}
+
+void ChartType::removeDataSeries( const rtl::Reference< DataSeries >& xDataSeries )
+{
+ if( !xDataSeries.is())
+ throw container::NoSuchElementException();
+
+ SolarMutexGuard g;
+
+ auto aIt = std::find( m_aDataSeries.begin(), m_aDataSeries.end(), xDataSeries );
+
+ if( aIt == m_aDataSeries.end())
+ throw container::NoSuchElementException(
+ "The given series is no element of this charttype",
+ static_cast< uno::XWeak * >( this ));
+
+ ModifyListenerHelper::removeListener( xDataSeries, m_xModifyEventForwarder );
+ m_aDataSeries.erase( aIt );
+ fireModifyEvent();
+}
+
+Sequence< Reference< chart2::XDataSeries > > SAL_CALL ChartType::getDataSeries()
+{
+ SolarMutexGuard g;
+
+ return comphelper::containerToSequence< Reference< chart2::XDataSeries > >( m_aDataSeries );
+}
+
+void SAL_CALL ChartType::setDataSeries( const Sequence< Reference< chart2::XDataSeries > >& aDataSeries )
+{
+ std::vector< rtl::Reference<DataSeries> > aTmp;
+ for (auto const & i : aDataSeries)
+ {
+ auto p = dynamic_cast<DataSeries*>(i.get());
+ assert(p);
+ aTmp.push_back(p);
+ }
+ setDataSeries(aTmp);
+}
+
+void ChartType::setDataSeries( const std::vector< rtl::Reference< DataSeries > >& aDataSeries )
+{
+ SolarMutexGuard g;
+
+ m_bNotifyChanges = false;
+ try
+ {
+ for( auto const & i : m_aDataSeries )
+ ModifyListenerHelper::removeListener( i, m_xModifyEventForwarder );
+ m_aDataSeries.clear();
+
+ for( auto const & i : aDataSeries )
+ impl_addDataSeriesWithoutNotification( i );
+ }
+ catch( ... )
+ {
+ m_bNotifyChanges = true;
+ throw;
+ }
+ m_bNotifyChanges = true;
+ fireModifyEvent();
+}
+
+// ____ OPropertySet ____
+void ChartType::GetDefaultValue( sal_Int32 /* nHandle */, uno::Any& rAny ) const
+{
+ rAny.clear();
+}
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper& StaticChartTypeInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper( Sequence< beans::Property >{} );
+ return aPropHelper;
+};
+
+}
+
+// ____ OPropertySet ____
+::cppu::IPropertyArrayHelper & SAL_CALL ChartType::getInfoHelper()
+{
+ return StaticChartTypeInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL ChartType::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo( StaticChartTypeInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL ChartType::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ try
+ {
+ m_xModifyEventForwarder->addModifyListener( aListener );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void SAL_CALL ChartType::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ try
+ {
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// ____ XModifyListener ____
+void SAL_CALL ChartType::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL ChartType::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void ChartType::firePropertyChangeEvent()
+{
+ fireModifyEvent();
+}
+
+void ChartType::fireModifyEvent()
+{
+ bool bNotifyChanges;
+
+ {
+ SolarMutexGuard g;
+ bNotifyChanges = m_bNotifyChanges;
+ }
+
+ if (bNotifyChanges)
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+using impl::ChartType_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( ChartType, ChartType_Base, ::property::OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( ChartType, ChartType_Base, ::property::OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ChartTypeManager.cxx b/chart2/source/model/template/ChartTypeManager.cxx
new file mode 100644
index 0000000000..bc6c2fb75a
--- /dev/null
+++ b/chart2/source/model/template/ChartTypeManager.cxx
@@ -0,0 +1,589 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartTypeManager.hxx>
+#include <StackMode.hxx>
+
+#include "LineChartTypeTemplate.hxx"
+#include "BarChartTypeTemplate.hxx"
+#include "ColumnLineChartTypeTemplate.hxx"
+#include "AreaChartTypeTemplate.hxx"
+#include "PieChartTypeTemplate.hxx"
+#include "ScatterChartTypeTemplate.hxx"
+#include "StockChartTypeTemplate.hxx"
+#include "NetChartTypeTemplate.hxx"
+#include "BubbleChartTypeTemplate.hxx"
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <sal/log.hxx>
+
+#include <algorithm>
+#include <iterator>
+#include <o3tl/functional.hxx>
+#include <map>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+
+enum TemplateId
+{
+ TEMPLATE_SYMBOL,
+ TEMPLATE_STACKEDSYMBOL,
+ TEMPLATE_PERCENTSTACKEDSYMBOL,
+ TEMPLATE_LINE,
+ TEMPLATE_STACKEDLINE,
+ TEMPLATE_PERCENTSTACKEDLINE,
+ TEMPLATE_LINESYMBOL,
+ TEMPLATE_STACKEDLINESYMBOL,
+ TEMPLATE_PERCENTSTACKEDLINESYMBOL,
+ TEMPLATE_THREEDLINE,
+ TEMPLATE_STACKEDTHREEDLINE,
+ TEMPLATE_PERCENTSTACKEDTHREEDLINE,
+ TEMPLATE_THREEDLINEDEEP,
+ TEMPLATE_COLUMN,
+ TEMPLATE_STACKEDCOLUMN,
+ TEMPLATE_PERCENTSTACKEDCOLUMN,
+ TEMPLATE_BAR,
+ TEMPLATE_STACKEDBAR,
+ TEMPLATE_PERCENTSTACKEDBAR,
+ TEMPLATE_THREEDCOLUMNDEEP,
+ TEMPLATE_THREEDCOLUMNFLAT,
+ TEMPLATE_STACKEDTHREEDCOLUMNFLAT,
+ TEMPLATE_PERCENTSTACKEDTHREEDCOLUMNFLAT,
+ TEMPLATE_THREEDBARDEEP,
+ TEMPLATE_THREEDBARFLAT,
+ TEMPLATE_STACKEDTHREEDBARFLAT,
+ TEMPLATE_PERCENTSTACKEDTHREEDBARFLAT,
+ TEMPLATE_COLUMNWITHLINE,
+ TEMPLATE_STACKEDCOLUMNWITHLINE,
+ TEMPLATE_AREA,
+ TEMPLATE_STACKEDAREA,
+ TEMPLATE_PERCENTSTACKEDAREA,
+ TEMPLATE_THREEDAREA,
+ TEMPLATE_STACKEDTHREEDAREA,
+ TEMPLATE_PERCENTSTACKEDTHREEDAREA,
+ TEMPLATE_PIE,
+ TEMPLATE_PIEALLEXPLODED,
+ TEMPLATE_DONUT,
+ TEMPLATE_DONUTALLEXPLODED,
+ TEMPLATE_THREEDPIE,
+ TEMPLATE_THREEDPIEALLEXPLODED,
+ TEMPLATE_THREEDDONUT,
+ TEMPLATE_THREEDDONUTALLEXPLODED,
+ TEMPLATE_SCATTERLINESYMBOL,
+ TEMPLATE_SCATTERLINE,
+ TEMPLATE_SCATTERSYMBOL,
+ TEMPLATE_THREEDSCATTER,
+ TEMPLATE_NET,
+ TEMPLATE_NETSYMBOL,
+ TEMPLATE_NETLINE,
+ TEMPLATE_STACKEDNET,
+ TEMPLATE_STACKEDNETSYMBOL,
+ TEMPLATE_STACKEDNETLINE,
+ TEMPLATE_PERCENTSTACKEDNET,
+ TEMPLATE_PERCENTSTACKEDNETSYMBOL,
+ TEMPLATE_PERCENTSTACKEDNETLINE,
+ TEMPLATE_FILLEDNET,
+ TEMPLATE_STACKEDFILLEDNET,
+ TEMPLATE_PERCENTSTACKEDFILLEDNET,
+ TEMPLATE_STOCKLOWHIGHCLOSE,
+ TEMPLATE_STOCKOPENLOWHIGHCLOSE,
+ TEMPLATE_STOCKVOLUMELOWHIGHCLOSE,
+ TEMPLATE_STOCKVOLUMEOPENLOWHIGHCLOSE,
+ TEMPLATE_BUBBLE,
+// TEMPLATE_SURFACE,
+// TEMPLATE_ADDIN,
+ TEMPLATE_NOT_FOUND = 0xffff
+};
+
+typedef std::map< OUString, TemplateId > tTemplateMapType;
+
+const tTemplateMapType & lcl_DefaultChartTypeMap()
+{
+ static const tTemplateMapType aMap{
+ {"com.sun.star.chart2.template.Symbol", TEMPLATE_SYMBOL},
+ {"com.sun.star.chart2.template.StackedSymbol", TEMPLATE_STACKEDSYMBOL},
+ {"com.sun.star.chart2.template.PercentStackedSymbol", TEMPLATE_PERCENTSTACKEDSYMBOL},
+ {"com.sun.star.chart2.template.Line", TEMPLATE_LINE},
+ {"com.sun.star.chart2.template.StackedLine", TEMPLATE_STACKEDLINE},
+ {"com.sun.star.chart2.template.PercentStackedLine", TEMPLATE_PERCENTSTACKEDLINE},
+ {"com.sun.star.chart2.template.LineSymbol", TEMPLATE_LINESYMBOL},
+ {"com.sun.star.chart2.template.StackedLineSymbol", TEMPLATE_STACKEDLINESYMBOL},
+ {"com.sun.star.chart2.template.PercentStackedLineSymbol", TEMPLATE_PERCENTSTACKEDLINESYMBOL},
+ {"com.sun.star.chart2.template.ThreeDLine", TEMPLATE_THREEDLINE},
+ {"com.sun.star.chart2.template.StackedThreeDLine", TEMPLATE_STACKEDTHREEDLINE},
+ {"com.sun.star.chart2.template.PercentStackedThreeDLine", TEMPLATE_PERCENTSTACKEDTHREEDLINE},
+ {"com.sun.star.chart2.template.ThreeDLineDeep", TEMPLATE_THREEDLINEDEEP},
+ {"com.sun.star.chart2.template.Column", TEMPLATE_COLUMN},
+ {"com.sun.star.chart2.template.StackedColumn", TEMPLATE_STACKEDCOLUMN},
+ {"com.sun.star.chart2.template.PercentStackedColumn", TEMPLATE_PERCENTSTACKEDCOLUMN},
+ {"com.sun.star.chart2.template.Bar", TEMPLATE_BAR},
+ {"com.sun.star.chart2.template.StackedBar", TEMPLATE_STACKEDBAR},
+ {"com.sun.star.chart2.template.PercentStackedBar", TEMPLATE_PERCENTSTACKEDBAR},
+ {"com.sun.star.chart2.template.ThreeDColumnDeep", TEMPLATE_THREEDCOLUMNDEEP},
+ {"com.sun.star.chart2.template.ThreeDColumnFlat", TEMPLATE_THREEDCOLUMNFLAT},
+ {"com.sun.star.chart2.template.StackedThreeDColumnFlat", TEMPLATE_STACKEDTHREEDCOLUMNFLAT},
+ {"com.sun.star.chart2.template.PercentStackedThreeDColumnFlat", TEMPLATE_PERCENTSTACKEDTHREEDCOLUMNFLAT},
+ {"com.sun.star.chart2.template.ThreeDBarDeep", TEMPLATE_THREEDBARDEEP},
+ {"com.sun.star.chart2.template.ThreeDBarFlat", TEMPLATE_THREEDBARFLAT},
+ {"com.sun.star.chart2.template.StackedThreeDBarFlat", TEMPLATE_STACKEDTHREEDBARFLAT},
+ {"com.sun.star.chart2.template.PercentStackedThreeDBarFlat", TEMPLATE_PERCENTSTACKEDTHREEDBARFLAT},
+ {"com.sun.star.chart2.template.ColumnWithLine", TEMPLATE_COLUMNWITHLINE},
+ {"com.sun.star.chart2.template.StackedColumnWithLine", TEMPLATE_STACKEDCOLUMNWITHLINE},
+ {"com.sun.star.chart2.template.Area", TEMPLATE_AREA},
+ {"com.sun.star.chart2.template.StackedArea", TEMPLATE_STACKEDAREA},
+ {"com.sun.star.chart2.template.PercentStackedArea", TEMPLATE_PERCENTSTACKEDAREA},
+ {"com.sun.star.chart2.template.ThreeDArea", TEMPLATE_THREEDAREA},
+ {"com.sun.star.chart2.template.StackedThreeDArea", TEMPLATE_STACKEDTHREEDAREA},
+ {"com.sun.star.chart2.template.PercentStackedThreeDArea", TEMPLATE_PERCENTSTACKEDTHREEDAREA},
+ {"com.sun.star.chart2.template.Pie", TEMPLATE_PIE},
+ {"com.sun.star.chart2.template.PieAllExploded", TEMPLATE_PIEALLEXPLODED},
+ {"com.sun.star.chart2.template.Donut", TEMPLATE_DONUT},
+ {"com.sun.star.chart2.template.DonutAllExploded", TEMPLATE_DONUTALLEXPLODED},
+ {"com.sun.star.chart2.template.ThreeDPie", TEMPLATE_THREEDPIE},
+ {"com.sun.star.chart2.template.ThreeDPieAllExploded", TEMPLATE_THREEDPIEALLEXPLODED},
+ {"com.sun.star.chart2.template.ThreeDDonut", TEMPLATE_THREEDDONUT},
+ {"com.sun.star.chart2.template.ThreeDDonutAllExploded", TEMPLATE_THREEDDONUTALLEXPLODED},
+ {"com.sun.star.chart2.template.ScatterLineSymbol", TEMPLATE_SCATTERLINESYMBOL},
+ {"com.sun.star.chart2.template.ScatterLine", TEMPLATE_SCATTERLINE},
+ {"com.sun.star.chart2.template.ScatterSymbol", TEMPLATE_SCATTERSYMBOL},
+ {"com.sun.star.chart2.template.ThreeDScatter", TEMPLATE_THREEDSCATTER},
+ {"com.sun.star.chart2.template.Net", TEMPLATE_NET},
+ {"com.sun.star.chart2.template.NetSymbol", TEMPLATE_NETSYMBOL},
+ {"com.sun.star.chart2.template.NetLine", TEMPLATE_NETLINE},
+ {"com.sun.star.chart2.template.StackedNet", TEMPLATE_STACKEDNET},
+ {"com.sun.star.chart2.template.StackedNetSymbol", TEMPLATE_STACKEDNETSYMBOL},
+ {"com.sun.star.chart2.template.StackedNetLine", TEMPLATE_STACKEDNETLINE},
+ {"com.sun.star.chart2.template.PercentStackedNet", TEMPLATE_PERCENTSTACKEDNET},
+ {"com.sun.star.chart2.template.PercentStackedNetSymbol", TEMPLATE_PERCENTSTACKEDNETSYMBOL},
+ {"com.sun.star.chart2.template.PercentStackedNetLine", TEMPLATE_PERCENTSTACKEDNETLINE},
+ {"com.sun.star.chart2.template.FilledNet", TEMPLATE_FILLEDNET},
+ {"com.sun.star.chart2.template.StackedFilledNet", TEMPLATE_STACKEDFILLEDNET},
+ {"com.sun.star.chart2.template.PercentStackedFilledNet", TEMPLATE_PERCENTSTACKEDFILLEDNET},
+ {"com.sun.star.chart2.template.StockLowHighClose", TEMPLATE_STOCKLOWHIGHCLOSE},
+ {"com.sun.star.chart2.template.StockOpenLowHighClose", TEMPLATE_STOCKOPENLOWHIGHCLOSE},
+ {"com.sun.star.chart2.template.StockVolumeLowHighClose", TEMPLATE_STOCKVOLUMELOWHIGHCLOSE},
+ {"com.sun.star.chart2.template.StockVolumeOpenLowHighClose", TEMPLATE_STOCKVOLUMEOPENLOWHIGHCLOSE},
+ {"com.sun.star.chart2.template.Bubble", TEMPLATE_BUBBLE},
+// {"com.sun.star.chart2.template.Surface", TEMPLATE_SURFACE},
+// {"com.sun.star.chart2.template.Addin", TEMPLATE_ADDIN},
+ };
+ return aMap;
+}
+
+TemplateId lcl_GetTemplateIdForService( const OUString & rServiceName )
+{
+ TemplateId eResult = TEMPLATE_NOT_FOUND;
+ const tTemplateMapType & rMap = lcl_DefaultChartTypeMap();
+ tTemplateMapType::const_iterator aIt( rMap.find( rServiceName ));
+
+ if( aIt != rMap.end())
+ eResult = (*aIt).second;
+
+ return eResult;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+ChartTypeManager::ChartTypeManager(
+ uno::Reference<
+ uno::XComponentContext > xContext ) :
+ m_xContext(std::move( xContext ))
+{}
+
+ChartTypeManager::~ChartTypeManager()
+{}
+
+// ____ XMultiServiceFactory ____
+uno::Reference< uno::XInterface > SAL_CALL ChartTypeManager::createInstance(
+ const OUString& aServiceSpecifier )
+{
+ return static_cast<cppu::OWeakObject*>(createTemplate(aServiceSpecifier).get());
+}
+
+rtl::Reference< ::chart::ChartTypeTemplate > ChartTypeManager::createTemplate(
+ const OUString& aServiceSpecifier )
+{
+ TemplateId nId = lcl_GetTemplateIdForService( aServiceSpecifier );
+
+ rtl::Reference< ::chart::ChartTypeTemplate > xTemplate;
+ switch( nId )
+ {
+ // Point (category x axis)
+ case TEMPLATE_SYMBOL:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, true, false ));
+ break;
+ case TEMPLATE_STACKEDSYMBOL:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, true, false ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDSYMBOL:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, true, false ));
+ break;
+ // Line (category x axis)
+ case TEMPLATE_LINE:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, false ));
+ break;
+ case TEMPLATE_STACKEDLINE:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, false ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDLINE:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, false ));
+ break;
+ case TEMPLATE_LINESYMBOL:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, true ));
+ break;
+ case TEMPLATE_STACKEDLINESYMBOL:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, true ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDLINESYMBOL:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, true ));
+ break;
+ case TEMPLATE_THREEDLINE:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, false, true, 3 ));
+ break;
+ case TEMPLATE_STACKEDTHREEDLINE:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, false, true, 3 ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDTHREEDLINE:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, false, true, 3 ));
+ break;
+ case TEMPLATE_THREEDLINEDEEP:
+ xTemplate.set( new LineChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::ZStacked, false, true, 3 ));
+ break;
+
+ // Bar/Column
+ case TEMPLATE_COLUMN:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, BarChartTypeTemplate::VERTICAL ));
+ break;
+ case TEMPLATE_STACKEDCOLUMN:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, BarChartTypeTemplate::VERTICAL ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDCOLUMN:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, BarChartTypeTemplate::VERTICAL ));
+ break;
+ case TEMPLATE_BAR:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, BarChartTypeTemplate::HORIZONTAL ));
+ break;
+ case TEMPLATE_STACKEDBAR:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, BarChartTypeTemplate::HORIZONTAL ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDBAR:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, BarChartTypeTemplate::HORIZONTAL ));
+ break;
+ case TEMPLATE_THREEDCOLUMNDEEP:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::ZStacked, BarChartTypeTemplate::VERTICAL, 3 ));
+ break;
+ case TEMPLATE_THREEDCOLUMNFLAT:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, BarChartTypeTemplate::VERTICAL, 3 ));
+ break;
+ case TEMPLATE_STACKEDTHREEDCOLUMNFLAT:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, BarChartTypeTemplate::VERTICAL, 3 ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDTHREEDCOLUMNFLAT:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, BarChartTypeTemplate::VERTICAL, 3 ));
+ break;
+ case TEMPLATE_THREEDBARDEEP:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::ZStacked, BarChartTypeTemplate::HORIZONTAL, 3 ));
+ break;
+ case TEMPLATE_THREEDBARFLAT:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, BarChartTypeTemplate::HORIZONTAL, 3 ));
+ break;
+ case TEMPLATE_STACKEDTHREEDBARFLAT:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, BarChartTypeTemplate::HORIZONTAL, 3 ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDTHREEDBARFLAT:
+ xTemplate.set( new BarChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, BarChartTypeTemplate::HORIZONTAL, 3 ));
+ break;
+
+ // Combi-Chart Line/Column
+ case TEMPLATE_COLUMNWITHLINE:
+ case TEMPLATE_STACKEDCOLUMNWITHLINE:
+ {
+ StackMode eMode = ( nId == TEMPLATE_COLUMNWITHLINE )
+ ? StackMode::NONE
+ : StackMode::YStacked;
+
+ xTemplate.set( new ColumnLineChartTypeTemplate( m_xContext, aServiceSpecifier, eMode, 1 ));
+ }
+ break;
+
+ // Area
+ case TEMPLATE_AREA:
+ xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::NONE ));
+ break;
+ case TEMPLATE_STACKEDAREA:
+ xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::YStacked ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDAREA:
+ xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::YStackedPercent ));
+ break;
+ case TEMPLATE_THREEDAREA:
+ xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::ZStacked, 3 ));
+ break;
+ case TEMPLATE_STACKEDTHREEDAREA:
+ xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::YStacked, 3 ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDTHREEDAREA:
+ xTemplate.set( new AreaChartTypeTemplate( m_xContext, aServiceSpecifier, StackMode::YStackedPercent, 3 ));
+ break;
+
+ case TEMPLATE_PIE:
+ xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier,
+ chart2::PieChartOffsetMode_NONE, false ));
+ break;
+ case TEMPLATE_PIEALLEXPLODED:
+ xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier,
+ chart2::PieChartOffsetMode_ALL_EXPLODED, false ));
+ break;
+ case TEMPLATE_DONUT:
+ xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier,
+ chart2::PieChartOffsetMode_NONE, true ));
+ break;
+ case TEMPLATE_DONUTALLEXPLODED:
+ xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier,
+ chart2::PieChartOffsetMode_ALL_EXPLODED, true ));
+ break;
+ case TEMPLATE_THREEDPIE:
+ xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier,
+ chart2::PieChartOffsetMode_NONE, false, 3 ));
+ break;
+ case TEMPLATE_THREEDPIEALLEXPLODED:
+ xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier,
+ chart2::PieChartOffsetMode_ALL_EXPLODED, false, 3 ));
+ break;
+ case TEMPLATE_THREEDDONUT:
+ xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier,
+ chart2::PieChartOffsetMode_NONE, true, 3 ));
+ break;
+ case TEMPLATE_THREEDDONUTALLEXPLODED:
+ xTemplate.set( new PieChartTypeTemplate( m_xContext, aServiceSpecifier,
+ chart2::PieChartOffsetMode_ALL_EXPLODED, true, 3 ));
+ break;
+
+ case TEMPLATE_SCATTERLINESYMBOL:
+ xTemplate.set( new ScatterChartTypeTemplate( m_xContext, aServiceSpecifier, /* bSymbols */ true ));
+ break;
+ case TEMPLATE_SCATTERLINE:
+ xTemplate.set( new ScatterChartTypeTemplate( m_xContext, aServiceSpecifier, /* bSymbols */ false ));
+ break;
+ case TEMPLATE_SCATTERSYMBOL:
+ xTemplate.set( new ScatterChartTypeTemplate( m_xContext, aServiceSpecifier, /* bSymbols */ true, /* bHasLines */ false ));
+ break;
+ case TEMPLATE_THREEDSCATTER:
+ xTemplate.set( new ScatterChartTypeTemplate( m_xContext, aServiceSpecifier, /* bSymbols */ false, /* bHasLines */ true, 3 ));
+ break;
+
+ // NetChart
+ case TEMPLATE_NET:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, true ));
+ break;
+ case TEMPLATE_NETSYMBOL:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, true, false ));
+ break;
+ case TEMPLATE_NETLINE:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, false ));
+ break;
+
+ case TEMPLATE_STACKEDNET:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, true ));
+ break;
+ case TEMPLATE_STACKEDNETSYMBOL:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, true, false ));
+ break;
+ case TEMPLATE_STACKEDNETLINE:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, false, true ));
+ break;
+
+ case TEMPLATE_PERCENTSTACKEDNET:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, true ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDNETSYMBOL:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, true, false ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDNETLINE:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, false, true ));
+ break;
+
+ case TEMPLATE_FILLEDNET:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::NONE, false, false, true ));
+ break;
+ case TEMPLATE_STACKEDFILLEDNET:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStacked, false, false, true ));
+ break;
+ case TEMPLATE_PERCENTSTACKEDFILLEDNET:
+ xTemplate.set( new NetChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StackMode::YStackedPercent, false, false, true ));
+ break;
+
+ case TEMPLATE_STOCKLOWHIGHCLOSE:
+ xTemplate.set( new StockChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StockChartTypeTemplate::StockVariant::NONE, false ));
+ break;
+ case TEMPLATE_STOCKOPENLOWHIGHCLOSE:
+ xTemplate.set( new StockChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StockChartTypeTemplate::StockVariant::Open, true ));
+ break;
+ case TEMPLATE_STOCKVOLUMELOWHIGHCLOSE:
+ xTemplate.set( new StockChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StockChartTypeTemplate::StockVariant::Volume, false ));
+ break;
+ case TEMPLATE_STOCKVOLUMEOPENLOWHIGHCLOSE:
+ xTemplate.set( new StockChartTypeTemplate( m_xContext, aServiceSpecifier,
+ StockChartTypeTemplate::StockVariant::VolumeOpen, true ));
+ break;
+
+ //BubbleChart
+ case TEMPLATE_BUBBLE:
+ xTemplate.set( new BubbleChartTypeTemplate( m_xContext, aServiceSpecifier ));
+ break;
+
+ case TEMPLATE_NOT_FOUND:
+ SAL_WARN("chart2", "Couldn't instantiate service: "<< aServiceSpecifier );
+ assert(false);
+ break;
+
+ default: break;
+// case TEMPLATE_SURFACE:
+// case TEMPLATE_ADDIN:
+// break;
+ }
+
+ return xTemplate;
+}
+
+uno::Reference< uno::XInterface > SAL_CALL ChartTypeManager::createInstanceWithArguments(
+ const OUString& ServiceSpecifier,
+ const uno::Sequence< uno::Any >& /* Arguments */ )
+{
+ OSL_FAIL( "createInstanceWithArguments: No arguments supported" );
+ return createInstance( ServiceSpecifier );
+}
+
+uno::Sequence< OUString > SAL_CALL ChartTypeManager::getAvailableServiceNames()
+{
+ std::vector< OUString > aServices;
+ const tTemplateMapType & rMap = lcl_DefaultChartTypeMap();
+ aServices.reserve( rMap.size());
+
+ // get own default templates
+ std::transform( rMap.begin(), rMap.end(), std::back_inserter( aServices ),
+ ::o3tl::select1st< tTemplateMapType::value_type >() );
+
+ // add components that were registered in the context's factory
+ uno::Reference< container::XContentEnumerationAccess > xEnumAcc(
+ m_xContext->getServiceManager(), uno::UNO_QUERY );
+ if( xEnumAcc.is())
+ {
+ uno::Reference< container::XEnumeration > xEnum(
+ xEnumAcc->createContentEnumeration( "com.sun.star.chart2.ChartTypeTemplate" ));
+ if( xEnum.is())
+ {
+ uno::Reference< uno::XInterface > xFactIntf;
+
+ while( xEnum->hasMoreElements())
+ {
+ if( xEnum->nextElement() >>= xFactIntf )
+ {
+ uno::Reference< lang::XServiceName > xServiceName( xFactIntf, uno::UNO_QUERY );
+ if( xServiceName.is())
+ aServices.push_back( xServiceName->getServiceName());
+ }
+ }
+ }
+ }
+
+ return comphelper::containerToSequence( aServices );
+}
+
+// ____ XServiceInfo ____
+OUString SAL_CALL ChartTypeManager::getImplementationName()
+{
+ return "com.sun.star.comp.chart.ChartTypeManager";
+}
+
+sal_Bool SAL_CALL ChartTypeManager::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ChartTypeManager::getSupportedServiceNames()
+{
+ return {
+ "com.sun.star.chart2.ChartTypeManager",
+ "com.sun.star.lang.MultiServiceFactory" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_ChartTypeManager_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::ChartTypeManager(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ChartTypeTemplate.cxx b/chart2/source/model/template/ChartTypeTemplate.cxx
new file mode 100644
index 0000000000..49c93766cd
--- /dev/null
+++ b/chart2/source/model/template/ChartTypeTemplate.cxx
@@ -0,0 +1,867 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartTypeTemplate.hxx>
+#include <DataInterpreter.hxx>
+#include <CommonConverters.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartType.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesProperties.hxx>
+#include <DataSource.hxx>
+#include <GridProperties.hxx>
+
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <AxisIndexDefines.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/XColorScheme.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/property.hxx>
+
+#include <algorithm>
+#include <cstddef>
+#include <utility>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart::DataSeriesProperties;
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+
+void lcl_applyDefaultStyle(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ sal_Int32 nIndex,
+ const rtl::Reference< ::chart::Diagram > & xDiagram )
+{
+ // @deprecated: correct default color should be found by view without
+ // setting color as hard attribute
+ if( xSeries.is() && xDiagram.is())
+ {
+ Reference< chart2::XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
+ if( xColorScheme.is() )
+ xSeries->setPropertyValue(
+ "Color",
+ uno::Any( xColorScheme->getColorByIndex( nIndex )));
+ }
+}
+
+void lcl_ensureCorrectLabelPlacement( const Reference< beans::XPropertySet >& xProp, const uno::Sequence < sal_Int32 >& rAvailablePlacements )
+{
+ sal_Int32 nLabelPlacement=0;
+ if( !(xProp.is() && (xProp->getPropertyValue( "LabelPlacement" ) >>= nLabelPlacement)) )
+ return;
+
+ bool bValid = false;
+ for( sal_Int32 i : rAvailablePlacements )
+ {
+ if( i == nLabelPlacement )
+ {
+ bValid = true;
+ break;
+ }
+ }
+ if( !bValid )
+ {
+ uno::Any aNewValue;
+ //otherwise use the first supported one
+ if( rAvailablePlacements.hasElements() )
+ aNewValue <<=rAvailablePlacements[0];
+ xProp->setPropertyValue( "LabelPlacement", aNewValue );
+ }
+}
+
+void lcl_resetLabelPlacementIfDefault( const Reference< beans::XPropertySet >& xProp, sal_Int32 nDefaultPlacement )
+{
+
+ sal_Int32 nLabelPlacement=0;
+ if( xProp.is() && (xProp->getPropertyValue( "LabelPlacement" ) >>= nLabelPlacement) )
+ {
+ if( nDefaultPlacement == nLabelPlacement )
+ xProp->setPropertyValue( "LabelPlacement", uno::Any() );
+ }
+}
+
+void lcl_ensureCorrectMissingValueTreatment( const rtl::Reference< ::chart::Diagram >& xDiagram, const rtl::Reference< ::chart::ChartType >& xChartType )
+{
+ if( xDiagram.is() )
+ {
+ uno::Sequence < sal_Int32 > aAvailableMissingValueTreatment(
+ ::chart::ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) );
+
+ if( aAvailableMissingValueTreatment.hasElements() )
+ xDiagram->setPropertyValue( "MissingValueTreatment", uno::Any( aAvailableMissingValueTreatment[0] ) );
+ else
+ xDiagram->setPropertyValue( "MissingValueTreatment", uno::Any() );
+ }
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+ChartTypeTemplate::ChartTypeTemplate(
+ Reference< uno::XComponentContext > const & xContext,
+ OUString aServiceName ) :
+ m_xContext( xContext ),
+ m_aServiceName(std::move( aServiceName ))
+{
+}
+
+ChartTypeTemplate::~ChartTypeTemplate()
+{}
+
+// ____ ChartTypeTemplate ____
+rtl::Reference< Diagram > ChartTypeTemplate::createDiagramByDataSource2(
+ const uno::Reference< data::XDataSource >& xDataSource,
+ const uno::Sequence< beans::PropertyValue >& aArguments )
+{
+ rtl::Reference< Diagram > xDia;
+
+ try
+ {
+ // create diagram
+ xDia = new Diagram(GetComponentContext());
+
+ // modify diagram
+ rtl::Reference< DataInterpreter > xInterpreter( getDataInterpreter2());
+ InterpretedData aData(
+ xInterpreter->interpretDataSource(
+ xDataSource, aArguments, {} ));
+
+ sal_Int32 nCount = 0;
+ for( auto const & i : aData.Series )
+ for( auto const & j : i )
+ lcl_applyDefaultStyle( j, nCount++, xDia );
+
+ std::vector< rtl::Reference< ChartType > > aOldChartTypesSeq;
+ FillDiagram( xDia, aData.Series, aData.Categories, aOldChartTypesSeq );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xDia;
+}
+
+sal_Bool SAL_CALL ChartTypeTemplate::supportsCategories()
+{
+ return true;
+}
+
+void ChartTypeTemplate::changeDiagram( const rtl::Reference< Diagram >& xDiagram )
+{
+ if( ! xDiagram.is())
+ return;
+
+ try
+ {
+ std::vector< std::vector< rtl::Reference< DataSeries > > > aSeriesSeq =
+ xDiagram->getDataSeriesGroups();
+ std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq ));
+ const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.size();
+
+ // chart-type specific interpretation of existing data series
+ rtl::Reference< DataInterpreter > xInterpreter( getDataInterpreter2());
+ InterpretedData aData;
+ aData.Series = aSeriesSeq;
+ aData.Categories = xDiagram->getCategories();
+
+ if( xInterpreter->isDataCompatible( aData ) )
+ {
+ aData = xInterpreter->reinterpretDataSeries( aData );
+ }
+ else
+ {
+ rtl::Reference< DataSource > xSource = DataInterpreter::mergeInterpretedData( aData );
+ // todo: get a "range-union" from the data provider by calling
+ // OUString aRange = getRangeRepresentationByData( xSource );
+ // xSource.set( getDataByRangeRepresentation( aRange, aParam ));
+ // where aParam == ??
+ Sequence< beans::PropertyValue > aParam;
+ if( aData.Categories.is())
+ {
+ aParam = { beans::PropertyValue( "HasCategories", -1, uno::Any( true ),
+ beans::PropertyState_DIRECT_VALUE ) };
+ }
+ aData = xInterpreter->interpretDataSource( xSource, aParam, aFlatSeriesSeq );
+ }
+ aSeriesSeq = aData.Series;
+
+ sal_Int32 nIndex = 0;
+ for( auto const & i : std::as_const(aSeriesSeq) )
+ for( auto const & j : i )
+ {
+ if( nIndex >= nFormerSeriesCount )
+ lcl_applyDefaultStyle( j, nIndex++, xDiagram );
+ }
+
+ // remove charttype groups from all coordinate systems
+ std::vector< rtl::Reference< ChartType > > aOldChartTypesSeq =
+ xDiagram->getChartTypes();
+
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() )
+ {
+ coords->setChartTypes( Sequence< Reference< XChartType > >() );
+ }
+
+ FillDiagram( xDiagram, aSeriesSeq, aData.Categories, aOldChartTypesSeq );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ChartTypeTemplate::changeDiagramData(
+ const rtl::Reference< Diagram >& xDiagram,
+ const Reference< chart2::data::XDataSource >& xDataSource,
+ const Sequence< beans::PropertyValue >& aArguments )
+{
+ if( ! (xDiagram.is() &&
+ xDataSource.is()) )
+ return;
+
+ try
+ {
+ // interpret new data and re-use existing series
+ std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq =
+ xDiagram->getDataSeries();
+ const sal_Int32 nFormerSeriesCount = aFlatSeriesSeq.size();
+ rtl::Reference< DataInterpreter > xInterpreter( getDataInterpreter2());
+ InterpretedData aData =
+ xInterpreter->interpretDataSource( xDataSource, aArguments, aFlatSeriesSeq );
+
+ // data series
+ sal_Int32 nIndex = 0;
+ for( std::size_t i=0; i<aData.Series.size(); ++i )
+ for( std::size_t j=0; j<aData.Series[i].size(); ++j, ++nIndex )
+ {
+ if( nIndex >= nFormerSeriesCount )
+ {
+ lcl_applyDefaultStyle( aData.Series[i][j], nIndex, xDiagram );
+ applyStyle2( aData.Series[i][j], i, j, aData.Series[i].size() );
+ }
+ }
+
+ // categories
+ xDiagram->setCategories( aData.Categories, true, supportsCategories() );
+
+ std::vector< rtl::Reference< ChartType > > aChartTypes =
+ xDiagram->getChartTypes();
+ sal_Int32 nMax = std::min( aChartTypes.size(), aData.Series.size());
+ for( sal_Int32 i=0; i<nMax; ++i )
+ {
+ aChartTypes[i]->setDataSeries( aData.Series[i] );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+bool ChartTypeTemplate::matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool /* bAdaptProperties */ )
+{
+ bool bResult = false;
+
+ if( ! xDiagram.is())
+ return bResult;
+
+ try
+ {
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq(
+ xDiagram->getBaseCoordinateSystems());
+
+ // need to have at least one coordinate system
+ bResult = !aCooSysSeq.empty();
+ if( bResult )
+ {
+ std::vector< rtl::Reference< ChartType > > aFormerlyUsedChartTypes;
+ rtl::Reference<ChartType> xOldCT = getChartTypeForNewSeries2(aFormerlyUsedChartTypes);
+ if (!xOldCT.is())
+ return false;
+
+ const OUString aChartTypeToMatch = xOldCT->getChartType();
+ const sal_Int32 nDimensionToMatch = getDimension();
+ for( std::size_t nCooSysIdx=0; bResult && (nCooSysIdx < aCooSysSeq.size()); ++nCooSysIdx )
+ {
+ // match dimension
+ bResult = bResult && (aCooSysSeq[nCooSysIdx]->getDimension() == nDimensionToMatch);
+
+ const std::vector< rtl::Reference< ChartType > > & aChartTypeSeq( aCooSysSeq[nCooSysIdx]->getChartTypes2());
+ for( std::size_t nCTIdx=0; bResult && (nCTIdx < aChartTypeSeq.size()); ++nCTIdx )
+ {
+ // match chart type
+ bResult = bResult && aChartTypeSeq[nCTIdx]->getChartType() == aChartTypeToMatch;
+ bool bFound=false;
+ bool bAmbiguous=false;
+ // match stacking mode
+ bResult = bResult &&
+ ( DiagramHelper::getStackModeFromChartType(
+ aChartTypeSeq[nCTIdx], bFound, bAmbiguous,
+ aCooSysSeq[nCooSysIdx] )
+ == getStackMode( nCTIdx ) );
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return bResult;
+}
+
+rtl::Reference< DataInterpreter > ChartTypeTemplate::getDataInterpreter2()
+{
+ if( ! m_xDataInterpreter.is())
+ m_xDataInterpreter.set( new DataInterpreter );
+
+ return m_xDataInterpreter;
+}
+
+void ChartTypeTemplate::applyStyle2(
+ const rtl::Reference< DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 /* nSeriesIndex */,
+ ::sal_Int32 /* nSeriesCount */ )
+{
+ // sset stacking mode
+ if( !xSeries.is())
+ return;
+
+ try
+ {
+ StackMode eStackMode = getStackMode( nChartTypeIndex );
+ const uno::Any aPropValue(
+ ( (eStackMode == StackMode::YStacked) ||
+ (eStackMode == StackMode::YStackedPercent) )
+ ? chart2::StackingDirection_Y_STACKING
+ : (eStackMode == StackMode::ZStacked )
+ ? chart2::StackingDirection_Z_STACKING
+ : chart2::StackingDirection_NO_STACKING );
+ xSeries->setPropertyValue( "StackingDirection", aPropValue );
+
+ //ensure valid label placement
+ {
+ uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
+ getChartTypeForIndex( nChartTypeIndex ), isSwapXAndY(), xSeries ) );
+ lcl_ensureCorrectLabelPlacement( xSeries, aAvailablePlacements );
+
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ // "AttributedDataPoints"
+ if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
+ for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
+ lcl_ensureCorrectLabelPlacement( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), aAvailablePlacements );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ChartTypeTemplate::applyStyles( const rtl::Reference< ::chart::Diagram >& xDiagram )
+{
+ // apply chart-type specific styles, like "symbols on" for example
+ std::vector< std::vector< rtl::Reference< DataSeries > > > aNewSeriesSeq(
+ xDiagram->getDataSeriesGroups());
+ for( std::size_t i=0; i<aNewSeriesSeq.size(); ++i )
+ {
+ const sal_Int32 nNumSeries = aNewSeriesSeq[i].size();
+ for( sal_Int32 j=0; j<nNumSeries; ++j )
+ applyStyle2( aNewSeriesSeq[i][j], i, j, nNumSeries );
+ }
+
+ //ensure valid empty cell handling (for first chart type...)
+ lcl_ensureCorrectMissingValueTreatment( xDiagram, getChartTypeForIndex( 0 ) );
+}
+
+void ChartTypeTemplate::resetStyles2( const rtl::Reference< ::chart::Diagram >& xDiagram )
+{
+ // reset number format if we had percent stacking on
+ bool bPercent = (getStackMode(0) == StackMode::YStackedPercent);
+ if( bPercent )
+ {
+ const std::vector< rtl::Reference< Axis > > aAxisSeq( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
+ for( rtl::Reference< Axis > const & axis : aAxisSeq )
+ {
+ if( AxisHelper::getDimensionIndexOfAxis( axis, xDiagram )== 1 )
+ {
+ // set number format to source format
+ axis->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(true));
+ axis->setPropertyValue(CHART_UNONAME_NUMFMT, uno::Any());
+ }
+ }
+ }
+
+ //reset label placement if default
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : xDiagram->getBaseCoordinateSystems() )
+ {
+ //iterate through all chart types in the current coordinate system
+ for( rtl::Reference< ChartType > const & xChartType : xCooSys->getChartTypes2() )
+ {
+ //iterate through all series in this chart type
+ for( rtl::Reference< DataSeries > const & xSeries : xChartType->getDataSeries2() )
+ {
+ uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
+ xChartType, isSwapXAndY(), xSeries ) );
+ if(!aAvailablePlacements.hasElements())
+ continue;
+
+ sal_Int32 nDefaultPlacement = aAvailablePlacements[0];
+
+ lcl_resetLabelPlacementIfDefault( xSeries, nDefaultPlacement );
+
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ // "AttributedDataPoints"
+ if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
+ for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
+ lcl_resetLabelPlacementIfDefault( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]), nDefaultPlacement );
+ }
+ }
+ }
+
+}
+
+// ____ XServiceName ____
+ OUString SAL_CALL ChartTypeTemplate::getServiceName()
+{
+ return m_aServiceName;
+}
+
+sal_Int32 ChartTypeTemplate::getDimension() const
+{
+ return 2;
+}
+
+StackMode ChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
+{
+ return StackMode::NONE;
+}
+
+bool ChartTypeTemplate::isSwapXAndY() const
+{
+ return false;
+}
+
+void ChartTypeTemplate::createCoordinateSystems(
+ const rtl::Reference< ::chart::Diagram > & xDiagram )
+{
+ if( ! xDiagram.is())
+ return;
+ std::vector< rtl::Reference< ChartType > > aFormerlyUsedChartTypes;
+ rtl::Reference< ChartType > xChartType( getChartTypeForNewSeries2(aFormerlyUsedChartTypes));
+ if( ! xChartType.is())
+ return;
+ rtl::Reference< BaseCoordinateSystem > xCooSys = xChartType->createCoordinateSystem2( getDimension());
+ if( ! xCooSys.is())
+ {
+ // chart type wants no coordinate systems
+ xDiagram->setCoordinateSystems( Sequence< Reference< XCoordinateSystem > >());
+ return;
+ }
+ // #i69680# make grid of first y-axis visible (was in the CooSys CTOR before)
+ if( xCooSys->getDimension() >= 2 )
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( 1, 0 );
+ if( xAxis.is())
+ AxisHelper::makeGridVisible( xAxis->getGridProperties2() );
+ }
+
+ std::vector< rtl::Reference< BaseCoordinateSystem > > aCoordinateSystems(
+ xDiagram->getBaseCoordinateSystems());
+
+ if( !aCoordinateSystems.empty() )
+ {
+ bool bOk = true;
+ for( std::size_t i=0; bOk && i<aCoordinateSystems.size(); ++i )
+ bOk = bOk && ( xCooSys->getCoordinateSystemType() == aCoordinateSystems[i]->getCoordinateSystemType() &&
+ (xCooSys->getDimension() == aCoordinateSystems[i]->getDimension()) );
+ // coordinate systems are ok
+ if( bOk )
+ return;
+ // there are coordinate systems but they do not fit. So overwrite them.
+ }
+
+ //copy as much info from former coordinate system as possible:
+ if( !aCoordinateSystems.empty() )
+ {
+ rtl::Reference< BaseCoordinateSystem > xOldCooSys( aCoordinateSystems[0] );
+ sal_Int32 nMaxDimensionCount = std::min( xCooSys->getDimension(), xOldCooSys->getDimension() );
+
+ for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nMaxDimensionCount; nDimensionIndex++)
+ {
+ const sal_Int32 nMaximumAxisIndex = xOldCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
+ {
+ rtl::Reference< Axis > xAxis = xOldCooSys->getAxisByDimension2( nDimensionIndex, nAxisIndex );
+ if( xAxis.is())
+ {
+ xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
+ }
+ }
+ }
+ }
+
+ // set new coordinate systems
+ aCoordinateSystems = { xCooSys };
+
+ xDiagram->setCoordinateSystems( aCoordinateSystems );
+}
+
+void ChartTypeTemplate::adaptScales(
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq,
+ const Reference< data::XLabeledDataSequence > & xCategories //@todo: in future there may be more than one sequence of categories (e.g. charttype with categories at x and y axis )
+ )
+{
+ bool bSupportsCategories( supportsCategories() );
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : aCooSysSeq )
+ {
+ try
+ {
+ // attach categories to first axis
+ sal_Int32 nDim( xCooSys->getDimension());
+ if( nDim > 0 )
+ {
+ const sal_Int32 nDimensionX = 0;
+ const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionX);
+ for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI)
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2(nDimensionX,nI);
+ if( xAxis.is())
+ {
+ ScaleData aData( xAxis->getScaleData() );
+ aData.Categories = xCategories;
+ if(bSupportsCategories)
+ {
+ rtl::Reference< ChartType > xChartType = getChartTypeForNewSeries2({});
+ if( aData.AxisType == AxisType::CATEGORY )
+ {
+ aData.ShiftedCategoryPosition = m_aServiceName.indexOf("Column") != -1 || m_aServiceName.indexOf("Bar") != -1 || m_aServiceName.endsWith("Close");
+ }
+ bool bSupportsDates = ::chart::ChartTypeHelper::isSupportingDateAxis( xChartType, nDimensionX );
+ if( aData.AxisType != AxisType::CATEGORY && ( aData.AxisType != AxisType::DATE || !bSupportsDates) )
+ {
+ aData.AxisType = AxisType::CATEGORY;
+ aData.AutoDateAxis = true;
+ AxisHelper::removeExplicitScaling( aData );
+ }
+ }
+ else
+ aData.AxisType = AxisType::REALNUMBER;
+
+ xAxis->setScaleData( aData );
+ }
+ }
+ }
+ // set percent stacking mode at second axis
+ if( nDim > 1 )
+ {
+ const sal_Int32 nMaxIndex = xCooSys->getMaximumAxisIndexByDimension(1);
+ for(sal_Int32 nI=0; nI<=nMaxIndex; ++nI)
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( 1,nI );
+ if( xAxis.is())
+ {
+ bool bPercent = (getStackMode(0) == StackMode::YStackedPercent);
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+
+ if( bPercent != (aScaleData.AxisType==AxisType::PERCENT) )
+ {
+ if( bPercent )
+ aScaleData.AxisType = AxisType::PERCENT;
+ else
+ aScaleData.AxisType = AxisType::REALNUMBER;
+ xAxis->setScaleData( aScaleData );
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+}
+
+void ChartTypeTemplate::adaptDiagram( const rtl::Reference< ::chart::Diagram > & /* xDiagram */ )
+{
+}
+
+void ChartTypeTemplate::createAxes(
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys )
+{
+ //create missing axes
+ if( rCoordSys.empty() )
+ return;
+
+ rtl::Reference< BaseCoordinateSystem > xCooSys( rCoordSys[0] );
+ if(!xCooSys.is())
+ return;
+
+ //create main axis in first coordinate system
+ sal_Int32 nDimCount = xCooSys->getDimension();
+ sal_Int32 nDim=0;
+ for( nDim=0; nDim<nDimCount; ++nDim )
+ {
+ sal_Int32 nAxisCount = getAxisCountByDimension( nDim );
+ if( nDim == 1 &&
+ nAxisCount < 2 && AxisHelper::isSecondaryYAxisNeeded( xCooSys ))
+ nAxisCount = 2;
+ for( sal_Int32 nAxisIndex = 0; nAxisIndex < nAxisCount; ++nAxisIndex )
+ {
+ Reference< XAxis > xAxis = AxisHelper::getAxis( nDim, nAxisIndex, xCooSys );
+ if( !xAxis.is())
+ {
+ // create and add axis
+ xAxis.set( AxisHelper::createAxis(
+ nDim, nAxisIndex, xCooSys, GetComponentContext() ));
+ }
+ }
+ }
+}
+
+void ChartTypeTemplate::adaptAxes(
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys )
+{
+ //adapt properties of existing axes and remove superfluous axes
+
+ if( rCoordSys.empty() )
+ return;
+
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : rCoordSys )
+ {
+ if( !xCooSys.is() )
+ continue;
+ sal_Int32 nDimCount = xCooSys->getDimension();
+ for( sal_Int32 nDim=0; nDim<nDimCount; ++nDim )
+ {
+ sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension( nDim );
+ for( sal_Int32 nAxisIndex=0; nAxisIndex<=nMaxAxisIndex; nAxisIndex++ )
+ {
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDim, nAxisIndex, xCooSys );
+ if( !xAxis.is() )
+ continue;
+
+ if( nAxisIndex == MAIN_AXIS_INDEX || nAxisIndex == SECONDARY_AXIS_INDEX )
+ {
+ // adapt scales
+ bool bPercent = (getStackMode(0) == StackMode::YStackedPercent);
+ if( bPercent && nDim == 1 )
+ {
+ // set number format to source format
+ xAxis->setPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT, uno::Any(true));
+ xAxis->setPropertyValue(CHART_UNONAME_NUMFMT, uno::Any());
+ }
+ }
+ }
+ }
+ }
+}
+
+sal_Int32 ChartTypeTemplate::getAxisCountByDimension( sal_Int32 nDimension )
+{
+ return (nDimension < getDimension()) ? 1 : 0;
+}
+
+void ChartTypeTemplate::FillDiagram(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ const std::vector< std::vector< rtl::Reference< DataSeries > > >& aSeriesSeq,
+ const uno::Reference< chart2::data::XLabeledDataSequence >& xCategories,
+ const std::vector< rtl::Reference< ChartType > >& aOldChartTypesSeq )
+{
+ adaptDiagram( xDiagram );
+
+ try
+ {
+ // create coordinate systems and scales
+ createCoordinateSystems( xDiagram );
+ std::vector< rtl::Reference< BaseCoordinateSystem > > aCoordinateSystems( xDiagram->getBaseCoordinateSystems());
+ createAxes( aCoordinateSystems );
+ adaptAxes( aCoordinateSystems );
+ adaptScales( aCoordinateSystems, xCategories );
+
+ // chart types
+ createChartTypes( aSeriesSeq, aCoordinateSystems, aOldChartTypesSeq );
+ applyStyles( xDiagram );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ChartTypeTemplate::createChartTypes(
+ const std::vector< std::vector< rtl::Reference< DataSeries > > > & aSeriesSeq,
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys,
+ const std::vector< rtl::Reference< ChartType > >& aOldChartTypesSeq )
+{
+ if( rCoordSys.empty() )
+ return;
+
+ try
+ {
+ std::size_t nCooSysIdx=0;
+ rtl::Reference< ChartType > xCT;
+ if( aSeriesSeq.empty() )
+ {
+ // we need a new chart type
+ xCT = getChartTypeForNewSeries2( aOldChartTypesSeq );
+ rCoordSys[nCooSysIdx]->setChartTypes(std::vector{ xCT });
+ }
+ else
+ {
+ for( std::size_t nSeriesIdx=0; nSeriesIdx<aSeriesSeq.size(); ++nSeriesIdx )
+ {
+ if( nSeriesIdx == nCooSysIdx )
+ {
+ // we need a new chart type
+ xCT = getChartTypeForNewSeries2( aOldChartTypesSeq );
+ std::vector< rtl::Reference< ChartType > > aCTSeq( rCoordSys[nCooSysIdx]->getChartTypes2());
+ if( !aCTSeq.empty())
+ {
+ aCTSeq[0] = xCT;
+ rCoordSys[nCooSysIdx]->setChartTypes( aCTSeq );
+ }
+ else
+ rCoordSys[nCooSysIdx]->addChartType( xCT );
+
+ xCT->setDataSeries( aSeriesSeq[nSeriesIdx] );
+ }
+ else
+ {
+ // reuse existing chart type
+ OSL_ASSERT( xCT.is());
+ std::vector< rtl::Reference< DataSeries > > aNewSeriesSeq = xCT->getDataSeries2();
+ sal_Int32 nNewStartIndex = aNewSeriesSeq.size();
+ aNewSeriesSeq.resize( nNewStartIndex + aSeriesSeq[nSeriesIdx].size() );
+ std::copy( aSeriesSeq[nSeriesIdx].begin(),
+ aSeriesSeq[nSeriesIdx].end(),
+ aNewSeriesSeq.begin() + nNewStartIndex );
+ xCT->setDataSeries( aNewSeriesSeq );
+ }
+
+ // spread the series over the available coordinate systems
+ if( rCoordSys.size() > (nCooSysIdx + 1) )
+ ++nCooSysIdx;
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem(
+ const std::vector< rtl::Reference< ChartType > > & rOldChartTypesSeq,
+ const rtl::Reference< ChartType > & xNewChartType )
+{
+ if( !xNewChartType.is() )
+ return;
+
+ OUString aNewChartType( xNewChartType->getChartType() );
+
+ Reference< beans::XPropertySet > xSource;
+ for( rtl::Reference< ChartType > const & xOldType : rOldChartTypesSeq )
+ {
+ if( xOldType.is() && xOldType->getChartType() == aNewChartType )
+ {
+ xSource = xOldType;
+ if( xSource.is() )
+ break;
+ }
+ }
+ if( xSource.is() )
+ comphelper::copyProperties( xSource, xNewChartType );
+}
+
+css::uno::Reference< css::uno::XInterface > ChartTypeTemplate::getDataInterpreter()
+{
+ return static_cast<cppu::OWeakObject*>(getDataInterpreter2().get());
+}
+css::uno::Reference< css::chart2::XDiagram > ChartTypeTemplate::createDiagramByDataSource(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments )
+{
+ return createDiagramByDataSource2(xDataSource, aArguments);
+}
+void ChartTypeTemplate::changeDiagram(
+ const css::uno::Reference< css::chart2::XDiagram >& xDiagram )
+{
+ changeDiagram(rtl::Reference<Diagram>(dynamic_cast<Diagram*>(xDiagram.get())));
+}
+void ChartTypeTemplate::changeDiagramData(
+ const css::uno::Reference< css::chart2::XDiagram >& xDiagram,
+ const css::uno::Reference< css::chart2::data::XDataSource >& xDataSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments )
+{
+ changeDiagramData(rtl::Reference<Diagram>(dynamic_cast<Diagram*>(xDiagram.get())), xDataSource, aArguments);
+}
+sal_Bool ChartTypeTemplate::matchesTemplate(
+ const css::uno::Reference<css::chart2::XDiagram >& xDiagram,
+ sal_Bool bAdaptProperties )
+{
+ return matchesTemplate2(dynamic_cast<Diagram*>(xDiagram.get()), static_cast<bool>(bAdaptProperties));
+}
+css::uno::Reference< ::css::chart2::XChartType > ChartTypeTemplate::getChartTypeForNewSeries(
+ const css::uno::Sequence< css::uno::Reference< css::chart2::XChartType > >& aFormerlyUsedChartTypes )
+{
+ std::vector< rtl::Reference< ::chart::ChartType > > aTmp;
+ aTmp.reserve(aFormerlyUsedChartTypes.getLength());
+ for (auto const & rxChartType : aFormerlyUsedChartTypes)
+ aTmp.push_back(dynamic_cast<ChartType*>(rxChartType.get()));
+ return getChartTypeForNewSeries2(aTmp);
+}
+void ChartTypeTemplate::applyStyle(
+ const css::uno::Reference< css::chart2::XDataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount )
+{
+ applyStyle2(dynamic_cast<DataSeries*>(xSeries.get()), nChartTypeIndex, nSeriesIndex, nSeriesCount);
+}
+void ChartTypeTemplate::resetStyles(
+ const css::uno::Reference< css::chart2::XDiagram >& xDiagram )
+{
+ resetStyles2(dynamic_cast<Diagram*>(xDiagram.get()));
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ColumnChartType.cxx b/chart2/source/model/template/ColumnChartType.cxx
new file mode 100644
index 0000000000..cc351e7751
--- /dev/null
+++ b/chart2/source/model/template/ColumnChartType.cxx
@@ -0,0 +1,168 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ColumnChartType.hxx"
+#include <servicenames_charttypes.hxx>
+#include <PropertyHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+enum
+{
+ PROP_BARCHARTTYPE_OVERLAP_SEQUENCE,
+ PROP_BARCHARTTYPE_GAPWIDTH_SEQUENCE
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "OverlapSequence",
+ PROP_BARCHARTTYPE_OVERLAP_SEQUENCE,
+ cppu::UnoType<Sequence< sal_Int32 >>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "GapwidthSequence",
+ PROP_BARCHARTTYPE_GAPWIDTH_SEQUENCE,
+ cppu::UnoType<Sequence< sal_Int32 >>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+::cppu::OPropertyArrayHelper & StaticColumnChartTypeInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper = []()
+ {
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+ColumnChartType::ColumnChartType()
+{}
+
+ColumnChartType::ColumnChartType( const ColumnChartType & rOther ) :
+ ChartType( rOther )
+{
+}
+
+ColumnChartType::~ColumnChartType()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL ColumnChartType::createClone()
+{
+ return uno::Reference< util::XCloneable >( new ColumnChartType( *this ));
+}
+
+rtl::Reference< ChartType > ColumnChartType::cloneChartType() const
+{
+ return new ColumnChartType( *this );
+}
+
+// ____ XChartType ____
+OUString SAL_CALL ColumnChartType::getChartType()
+{
+ return CHART2_SERVICE_NAME_CHARTTYPE_COLUMN;
+}
+
+uno::Sequence< OUString > ColumnChartType::getSupportedPropertyRoles()
+{
+ return { "FillColor", "BorderColor" };
+}
+
+// ____ OPropertySet ____
+void ColumnChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ static const ::chart::tPropertyValueMap aStaticDefaults = []()
+ {
+ ::chart::tPropertyValueMap aTmp;
+ Sequence< sal_Int32 > aSeq{ 0, 0 };
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_BARCHARTTYPE_OVERLAP_SEQUENCE, aSeq );
+ aSeq = { 100, 100 };
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_BARCHARTTYPE_GAPWIDTH_SEQUENCE, aSeq );
+ return aTmp;
+ }();
+ tPropertyValueMap::const_iterator aFound( aStaticDefaults.find( nHandle ) );
+ if( aFound == aStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL ColumnChartType::getInfoHelper()
+{
+ return StaticColumnChartTypeInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL ColumnChartType::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticColumnChartTypeInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+OUString SAL_CALL ColumnChartType::getImplementationName()
+{
+ return "com.sun.star.comp.chart.ColumnChartType";
+}
+
+sal_Bool SAL_CALL ColumnChartType::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ColumnChartType::getSupportedServiceNames()
+{
+ return {
+ CHART2_SERVICE_NAME_CHARTTYPE_COLUMN,
+ "com.sun.star.chart2.ChartType" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_ColumnChartType_get_implementation(css::uno::XComponentContext * /*context*/,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::ColumnChartType());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ColumnChartType.hxx b/chart2/source/model/template/ColumnChartType.hxx
new file mode 100644
index 0000000000..2c6b3d7623
--- /dev/null
+++ b/chart2/source/model/template/ColumnChartType.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartType.hxx>
+
+namespace chart
+{
+
+class ColumnChartType final : public ChartType
+{
+public:
+ explicit ColumnChartType();
+ virtual ~ColumnChartType() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const override;
+
+private:
+ explicit ColumnChartType( const ColumnChartType & rOther );
+
+ // ____ XChartType ____
+ virtual OUString SAL_CALL getChartType() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedPropertyRoles() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ColumnLineChartTypeTemplate.cxx b/chart2/source/model/template/ColumnLineChartTypeTemplate.cxx
new file mode 100644
index 0000000000..69769bc08f
--- /dev/null
+++ b/chart2/source/model/template/ColumnLineChartTypeTemplate.cxx
@@ -0,0 +1,355 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ColumnLineChartTypeTemplate.hxx"
+#include "ColumnChartType.hxx"
+#include "LineChartType.hxx"
+#include <CommonConverters.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <servicenames_charttypes.hxx>
+#include "ColumnLineDataInterpreter.hxx"
+#include <PropertyHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star::chart2;
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+enum
+{
+ PROP_COL_LINE_NUMBER_OF_LINES
+};
+
+::chart::tPropertyValueMap& StaticColumnLineChartTypeTemplateDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults =
+ []()
+ {
+ ::chart::tPropertyValueMap aOutMap;
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_COL_LINE_NUMBER_OF_LINES, 1 );
+ return aOutMap;
+ }();
+ return aStaticDefaults;
+}
+
+::cppu::OPropertyArrayHelper& StaticColumnLineChartTypeTemplateInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper(
+ []()
+ {
+ std::vector< css::beans::Property > aProperties {
+ { "NumberOfLines",
+ PROP_COL_LINE_NUMBER_OF_LINES,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT } };
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }());
+ return aPropHelper;
+}
+
+uno::Reference< beans::XPropertySetInfo >& StaticColumnLineChartTypeTemplateInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticColumnLineChartTypeTemplateInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+ColumnLineChartTypeTemplate::ColumnLineChartTypeTemplate(
+ Reference<
+ uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StackMode eStackMode,
+ sal_Int32 nNumberOfLines ) :
+ ChartTypeTemplate( xContext, rServiceName ),
+ m_eStackMode( eStackMode )
+{
+ setFastPropertyValue_NoBroadcast( PROP_COL_LINE_NUMBER_OF_LINES, uno::Any( nNumberOfLines ));
+}
+
+ColumnLineChartTypeTemplate::~ColumnLineChartTypeTemplate()
+{}
+
+// ____ OPropertySet ____
+void ColumnLineChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticColumnLineChartTypeTemplateDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL ColumnLineChartTypeTemplate::getInfoHelper()
+{
+ return StaticColumnLineChartTypeTemplateInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL ColumnLineChartTypeTemplate::getPropertySetInfo()
+{
+ return StaticColumnLineChartTypeTemplateInfo();
+}
+
+void ColumnLineChartTypeTemplate::createChartTypes(
+ const std::vector< std::vector< rtl::Reference< DataSeries > > > & aSeriesSeq,
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys,
+ const std::vector< rtl::Reference< ChartType > >& aOldChartTypesSeq )
+{
+ if( rCoordSys.empty() )
+ return;
+
+ try
+ {
+ const std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq( FlattenSequence( aSeriesSeq ));
+ sal_Int32 nNumberOfSeries = aFlatSeriesSeq.size();
+ sal_Int32 nNumberOfLines = 0;
+ sal_Int32 nNumberOfColumns = 0;
+
+ getFastPropertyValue( PROP_COL_LINE_NUMBER_OF_LINES ) >>= nNumberOfLines;
+ OSL_ENSURE( nNumberOfLines>=0, "number of lines should be not negative" );
+ if( nNumberOfLines < 0 )
+ nNumberOfLines = 0;
+
+ if( nNumberOfLines >= nNumberOfSeries )
+ {
+ if( nNumberOfSeries > 0 )
+ {
+ nNumberOfLines = nNumberOfSeries - 1;
+ nNumberOfColumns = 1;
+ }
+ else
+ nNumberOfLines = 0;
+ }
+ else
+ nNumberOfColumns = nNumberOfSeries - nNumberOfLines;
+
+ // Columns
+
+ rtl::Reference< ChartType > xCT = new ColumnChartType();
+
+ ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aOldChartTypesSeq, xCT );
+
+ rCoordSys[ 0 ]->setChartTypes( std::vector{xCT} );
+
+ if( nNumberOfColumns > 0 )
+ {
+ std::vector< rtl::Reference< DataSeries > > aColumnSeq( nNumberOfColumns );
+ std::copy( aFlatSeriesSeq.begin(),
+ aFlatSeriesSeq.begin() + nNumberOfColumns,
+ aColumnSeq.begin());
+ xCT->setDataSeries( aColumnSeq );
+ }
+
+ // Lines
+
+ xCT = new LineChartType();
+ rCoordSys[ 0 ]->addChartType( xCT );
+
+ if( nNumberOfLines > 0 )
+ {
+ std::vector< rtl::Reference< DataSeries > > aLineSeq( nNumberOfLines );
+ std::copy( aFlatSeriesSeq.begin() + nNumberOfColumns,
+ aFlatSeriesSeq.end(),
+ aLineSeq.begin());
+ xCT->setDataSeries( aLineSeq );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ColumnLineChartTypeTemplate::applyStyle2(
+ const rtl::Reference< DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount )
+{
+ ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount );
+
+ if( nChartTypeIndex==0 ) // columns
+ {
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) );
+ }
+ else if( nChartTypeIndex==1 ) // lines
+ {
+ DataSeriesHelper::switchLinesOnOrOff( xSeries, true );
+ DataSeriesHelper::switchSymbolsOnOrOff( xSeries, false, nSeriesIndex );
+ DataSeriesHelper::makeLinesThickOrThin( xSeries, true );
+ }
+}
+
+StackMode ColumnLineChartTypeTemplate::getStackMode( sal_Int32 nChartTypeIndex ) const
+{
+ if( nChartTypeIndex == 0 )
+ return m_eStackMode;
+ return StackMode::NONE;
+}
+
+// ____ XChartTypeTemplate ____
+bool ColumnLineChartTypeTemplate::matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties )
+{
+ bool bResult = false;
+
+ if( ! xDiagram.is())
+ return bResult;
+
+ try
+ {
+ rtl::Reference< ChartType > xColumnChartType;
+ rtl::Reference< BaseCoordinateSystem > xColumnChartCooSys;
+ rtl::Reference< ChartType > xLineChartType;
+ sal_Int32 nNumberOfChartTypes = 0;
+
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() )
+ {
+ const std::vector< rtl::Reference< ChartType > > aChartTypeSeq( coords->getChartTypes2());
+ for( rtl::Reference< ChartType > const & chartType : aChartTypeSeq )
+ {
+ ++nNumberOfChartTypes;
+ if( nNumberOfChartTypes > 2 )
+ break;
+ OUString aCTService = chartType->getChartType();
+ if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_COLUMN )
+ {
+ xColumnChartType = chartType;
+ xColumnChartCooSys = coords;
+ }
+ else if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_LINE )
+ xLineChartType = chartType;
+ }
+ if( nNumberOfChartTypes > 2 )
+ break;
+ }
+
+ if( nNumberOfChartTypes == 2 &&
+ xColumnChartType.is() &&
+ xLineChartType.is())
+ {
+ OSL_ASSERT( xColumnChartCooSys.is());
+
+ // check stackmode of bars
+ bResult = (xColumnChartCooSys->getDimension() == getDimension());
+ if( bResult )
+ {
+ bool bFound=false;
+ bool bAmbiguous=false;
+ bResult = ( DiagramHelper::getStackModeFromChartType(
+ xColumnChartType, bFound, bAmbiguous,
+ xColumnChartCooSys )
+ == getStackMode( 0 ) );
+
+ if( bResult && bAdaptProperties )
+ {
+ if( xLineChartType.is() )
+ {
+ sal_Int32 nNumberOfLines = xLineChartType->getDataSeries().getLength();
+ setFastPropertyValue_NoBroadcast( PROP_COL_LINE_NUMBER_OF_LINES, uno::Any( nNumberOfLines ));
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return bResult;
+}
+
+rtl::Reference< ChartType > ColumnLineChartTypeTemplate::getChartTypeForIndex( sal_Int32 nChartTypeIndex )
+{
+ if( nChartTypeIndex == 0 )
+ return new ColumnChartType();
+ else
+ return new LineChartType();
+}
+
+rtl::Reference< ChartType > ColumnLineChartTypeTemplate::getChartTypeForNewSeries2(
+ const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes )
+{
+ rtl::Reference< ChartType > xResult;
+
+ try
+ {
+ xResult = new LineChartType();
+ ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+rtl::Reference< DataInterpreter > ColumnLineChartTypeTemplate::getDataInterpreter2()
+{
+ if( ! m_xDataInterpreter.is())
+ {
+ sal_Int32 nNumberOfLines = 1;
+ getFastPropertyValue( PROP_COL_LINE_NUMBER_OF_LINES ) >>= nNumberOfLines;
+ m_xDataInterpreter = new ColumnLineDataInterpreter( nNumberOfLines );
+ }
+ else
+ {
+ //todo...
+ OSL_FAIL( "number of lines may not be valid anymore in the datainterpreter" );
+
+ }
+
+ return m_xDataInterpreter;
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( ColumnLineChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( ColumnLineChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ColumnLineChartTypeTemplate.hxx b/chart2/source/model/template/ColumnLineChartTypeTemplate.hxx
new file mode 100644
index 0000000000..68f144d6fe
--- /dev/null
+++ b/chart2/source/model/template/ColumnLineChartTypeTemplate.hxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartTypeTemplate.hxx>
+#include <StackMode.hxx>
+
+#include <OPropertySet.hxx>
+#include <comphelper/uno3.hxx>
+
+namespace chart
+{
+
+class ColumnLineChartTypeTemplate :
+ public ChartTypeTemplate,
+ public ::property::OPropertySet
+{
+public:
+ explicit ColumnLineChartTypeTemplate(
+ css::uno::Reference< css::uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StackMode eStackMode,
+ sal_Int32 nNumberOfLines );
+ virtual ~ColumnLineChartTypeTemplate() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+protected:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ ChartTypeTemplate ____
+ virtual bool matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties ) override;
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForNewSeries2( const std::vector<
+ rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override;
+ virtual void applyStyle2(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeGroupIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount ) override;
+ virtual rtl::Reference< ::chart::DataInterpreter > getDataInterpreter2() override;
+
+ // ____ ChartTypeTemplate ____
+ virtual void createChartTypes(
+ const std::vector<
+ std::vector<
+ rtl::Reference<
+ ::chart::DataSeries > > > & aSeriesSeq,
+ const std::vector<
+ rtl::Reference<
+ ::chart::BaseCoordinateSystem > > & rCoordSys,
+ const std::vector< rtl::Reference< ChartType > > & aOldChartTypesSeq
+ ) override;
+
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override;
+
+ virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override;
+
+private:
+ StackMode m_eStackMode;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ColumnLineDataInterpreter.cxx b/chart2/source/model/template/ColumnLineDataInterpreter.cxx
new file mode 100644
index 0000000000..5cce30cd97
--- /dev/null
+++ b/chart2/source/model/template/ColumnLineDataInterpreter.cxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ColumnLineDataInterpreter.hxx"
+#include <DataSeries.hxx>
+#include <osl/diagnose.h>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+// explicit
+ColumnLineDataInterpreter::ColumnLineDataInterpreter(
+ sal_Int32 nNumberOfLines ) :
+ m_nNumberOfLines( nNumberOfLines )
+{}
+
+ColumnLineDataInterpreter::~ColumnLineDataInterpreter()
+{}
+
+// ____ DataInterpreter ____
+InterpretedData ColumnLineDataInterpreter::interpretDataSource(
+ const Reference< data::XDataSource >& xSource,
+ const Sequence< beans::PropertyValue >& aArguments,
+ const std::vector< rtl::Reference< DataSeries > >& aSeriesToReUse )
+{
+ InterpretedData aResult( DataInterpreter::interpretDataSource( xSource, aArguments, aSeriesToReUse ));
+
+ // the base class should return one group
+ OSL_ASSERT( aResult.Series.size() == 1 );
+ if( aResult.Series.size() == 1 )
+ {
+ sal_Int32 nNumberOfSeries = aResult.Series[0].size();
+
+ // if we have more than one series put the last nNumOfLines ones into a new group
+ if( nNumberOfSeries > 1 && m_nNumberOfLines > 0 )
+ {
+ sal_Int32 nNumOfLines = std::min( m_nNumberOfLines, nNumberOfSeries - 1 );
+ aResult.Series.resize(2);
+
+ std::vector< rtl::Reference< DataSeries > > & rColumnDataSeries = aResult.Series[0];
+ std::vector< rtl::Reference< DataSeries > > & rLineDataSeries = aResult.Series[1];
+ rLineDataSeries.resize( nNumOfLines );
+ std::copy( std::cbegin(rColumnDataSeries) + nNumberOfSeries - nNumOfLines,
+ std::cbegin(rColumnDataSeries) + nNumberOfSeries,
+ rLineDataSeries.begin() );
+ rColumnDataSeries.resize( nNumberOfSeries - nNumOfLines );
+ }
+ }
+
+ return aResult;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ColumnLineDataInterpreter.hxx b/chart2/source/model/template/ColumnLineDataInterpreter.hxx
new file mode 100644
index 0000000000..c2ec758260
--- /dev/null
+++ b/chart2/source/model/template/ColumnLineDataInterpreter.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <DataInterpreter.hxx>
+
+namespace chart
+{
+class ColumnLineDataInterpreter : public DataInterpreter
+{
+public:
+ explicit ColumnLineDataInterpreter(sal_Int32 nNumberOfLines);
+ virtual ~ColumnLineDataInterpreter() override;
+
+protected:
+ // ____ DataInterpreter ____
+ virtual InterpretedData interpretDataSource(
+ const css::uno::Reference<css::chart2::data::XDataSource>& xSource,
+ const css::uno::Sequence<css::beans::PropertyValue>& aArguments,
+ const std::vector<rtl::Reference<::chart::DataSeries>>& aSeriesToReUse) override;
+
+private:
+ sal_Int32 m_nNumberOfLines;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/DataInterpreter.cxx b/chart2/source/model/template/DataInterpreter.cxx
new file mode 100644
index 0000000000..0f5cebc3bb
--- /dev/null
+++ b/chart2/source/model/template/DataInterpreter.cxx
@@ -0,0 +1,444 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DataInterpreter.hxx>
+#include <DataSeries.hxx>
+#include <DataSource.hxx>
+#include <DataSeriesHelper.hxx>
+#include <CommonConverters.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+#include <cstddef>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+#ifdef DEBUG_CHART2_TEMPLATE
+namespace
+{
+void lcl_ShowDataSource( const Reference< data::XDataSource > & xSource );
+}
+#endif
+
+namespace chart
+{
+
+DataInterpreter::DataInterpreter()
+{}
+
+DataInterpreter::~DataInterpreter()
+{}
+
+// ____ XDataInterpreter ____
+InterpretedData DataInterpreter::interpretDataSource(
+ const Reference< data::XDataSource >& xSource,
+ const Sequence< beans::PropertyValue >& aArguments,
+ const std::vector< rtl::Reference< DataSeries > >& aSeriesToReUse )
+{
+ if( ! xSource.is())
+ return InterpretedData();
+
+#ifdef DEBUG_CHART2_TEMPLATE
+ lcl_ShowDataSource( xSource );
+#endif
+
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = getDataSequences(xSource);
+
+ uno::Reference< chart2::data::XLabeledDataSequence > xCategories;
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSequencesVec;
+
+ // check if we should use categories
+
+ bool bHasCategories( HasCategories( aArguments, aData ));
+
+ // parse data
+ bool bCategoriesUsed = false;
+ for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledData : aData )
+ {
+ try
+ {
+ if( bHasCategories && ! bCategoriesUsed )
+ {
+ xCategories = labeledData;
+ if( xCategories.is())
+ SetRole( xCategories->getValues(), "categories");
+ bCategoriesUsed = true;
+ }
+ else
+ {
+ aSequencesVec.push_back( labeledData );
+ if( labeledData.is())
+ SetRole( labeledData->getValues(), "values-y");
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ // create DataSeries
+ std::size_t nSeriesIndex = 0;
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec;
+ aSeriesVec.reserve( aSequencesVec.size());
+
+ for (auto const& elem : aSequencesVec)
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewData { elem };
+ rtl::Reference< DataSeries > xSeries;
+ if( nSeriesIndex < aSeriesToReUse.size())
+ xSeries = aSeriesToReUse[nSeriesIndex];
+ else
+ xSeries = new DataSeries;
+ assert( xSeries.is() );
+ xSeries->setData( aNewData );
+
+ aSeriesVec.push_back( xSeries );
+ ++nSeriesIndex;
+ }
+
+ return { { aSeriesVec }, xCategories };
+}
+
+InterpretedData DataInterpreter::reinterpretDataSeries(
+ const InterpretedData& aInterpretedData )
+{
+ InterpretedData aResult( aInterpretedData );
+
+ sal_Int32 i=0;
+ std::vector< rtl::Reference< DataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
+ const sal_Int32 nCount = aSeries.size();
+ for( ; i<nCount; ++i )
+ {
+ try
+ {
+ std::vector< uno::Reference< data::XLabeledDataSequence > > aNewSequences;
+
+ // values-y
+ uno::Reference< data::XLabeledDataSequence > xValuesY =
+ DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-y" );
+ // re-use values-... as values-y
+ if( ! xValuesY.is())
+ {
+ xValuesY =
+ DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values", true );
+ if( xValuesY.is())
+ SetRole( xValuesY->getValues(), "values-y");
+ }
+ if( xValuesY.is())
+ {
+ aNewSequences = { xValuesY };
+ }
+
+ const std::vector< uno::Reference< data::XLabeledDataSequence > > & aSeqs = aSeries[i]->getDataSequences2();
+ if( aSeqs.size() != aNewSequences.size() )
+ {
+#ifdef DEBUG_CHART2_TEMPLATE
+ sal_Int32 j=0;
+ for( ; j<aSeqs.(); ++j )
+ {
+ assert( aSeqs[j] == xValuesY && "All sequences should be used" );
+ }
+#endif
+ aSeries[i]->setData( aNewSequences );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return aResult;
+}
+
+// criterion: all series must have exactly one data::XLabeledDataSequence
+bool DataInterpreter::isDataCompatible(
+ const InterpretedData& aInterpretedData )
+{
+ const std::vector< rtl::Reference< DataSeries > > aSeries( FlattenSequence( aInterpretedData.Series ));
+ for( rtl::Reference< DataSeries > const & i : aSeries )
+ {
+ try
+ {
+ if( i->getDataSequences2().size() != 1 )
+ return false;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return true;
+}
+
+namespace
+{
+
+struct lcl_LabeledSequenceEquals
+{
+ explicit lcl_LabeledSequenceEquals( const Reference< data::XLabeledDataSequence > & xLSeqToCmp ) :
+ m_bHasLabels ( false ),
+ m_bHasValues ( false )
+ {
+ if( !xLSeqToCmp.is())
+ return;
+
+ Reference< data::XDataSequence > xSeq( xLSeqToCmp->getValues());
+ if( xSeq.is())
+ {
+ m_bHasValues = true;
+ m_aValuesRangeRep = xSeq->getSourceRangeRepresentation();
+ }
+
+ xSeq.set( xLSeqToCmp->getLabel());
+ if( xSeq.is())
+ {
+ m_bHasLabels = true;
+ m_aLabelRangeRep = xSeq->getSourceRangeRepresentation();
+ }
+ }
+
+ bool operator() ( const Reference< data::XLabeledDataSequence > & xSeq )
+ {
+ if( ! xSeq.is())
+ return false;
+
+ Reference< data::XDataSequence > xSeqValues( xSeq->getValues() );
+ Reference< data::XDataSequence > xSeqLabels( xSeq->getLabel() );
+ bool bHasValues = xSeqValues.is();
+ bool bHasLabels = xSeqLabels.is();
+
+ return ( ( (m_bHasValues == bHasValues) &&
+ (!bHasValues || m_aValuesRangeRep == xSeqValues->getSourceRangeRepresentation()) ) &&
+ ( (m_bHasLabels == bHasLabels) &&
+ (!bHasLabels || m_aLabelRangeRep == xSeqLabels->getSourceRangeRepresentation()) )
+ );
+ }
+
+private:
+ bool m_bHasLabels;
+ bool m_bHasValues;
+ OUString m_aValuesRangeRep;
+ OUString m_aLabelRangeRep;
+};
+
+} // anonymous namespace
+
+rtl::Reference< DataSource > DataInterpreter::mergeInterpretedData(
+ const InterpretedData& aInterpretedData )
+{
+ std::vector< Reference< data::XLabeledDataSequence > > aResultVec;
+ aResultVec.reserve( aInterpretedData.Series.size() +
+ 1 // categories
+ );
+
+ if( aInterpretedData.Categories.is())
+ aResultVec.push_back( aInterpretedData.Categories );
+
+ const std::vector< rtl::Reference< DataSeries > > aSeries = FlattenSequence( aInterpretedData.Series );
+ for( rtl::Reference< DataSeries > const & dataSeries : aSeries )
+ {
+ try
+ {
+ // add all sequences of data series
+ for( uno::Reference< data::XLabeledDataSequence > const & xAdd : dataSeries->getDataSequences2() )
+ {
+ // only add if sequence is not yet in the result
+ if( none_of( aResultVec.begin(), aResultVec.end(),
+ lcl_LabeledSequenceEquals( xAdd )) )
+ {
+ aResultVec.push_back( xAdd );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return new DataSource(aResultVec);
+}
+
+uno::Any DataInterpreter::getChartTypeSpecificData(
+ const OUString & )
+{
+ return uno::Any();
+}
+
+// convenience methods
+
+OUString DataInterpreter::GetRole( const Reference< data::XDataSequence > & xSeq )
+{
+ OUString aResult;
+ if( ! xSeq.is())
+ return aResult;
+
+ try
+ {
+ Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
+ xProp->getPropertyValue( "Role") >>= aResult;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return aResult;
+}
+
+void DataInterpreter::SetRole( const Reference< data::XDataSequence > & xSeq, const OUString & rRole )
+{
+ if( ! xSeq.is())
+ return;
+ try
+ {
+ Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
+ xProp->setPropertyValue( "Role", uno::Any( rRole ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+uno::Any DataInterpreter::GetProperty(
+ const Sequence< beans::PropertyValue > & aArguments,
+ std::u16string_view rName )
+{
+ for( sal_Int32 i=aArguments.getLength(); i--; )
+ {
+ if( aArguments[i].Name == rName )
+ return aArguments[i].Value;
+ }
+ return uno::Any();
+}
+
+bool DataInterpreter::HasCategories(
+ const Sequence< beans::PropertyValue > & rArguments,
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & rData )
+{
+ bool bHasCategories = false;
+
+ if( rArguments.hasElements() )
+ GetProperty( rArguments, u"HasCategories" ) >>= bHasCategories;
+
+ for( std::size_t nLSeqIdx=0; ! bHasCategories && nLSeqIdx<rData.size(); ++nLSeqIdx )
+ bHasCategories = ( rData[nLSeqIdx].is() && GetRole( rData[nLSeqIdx]->getValues() ) == "categories");
+
+ return bHasCategories;
+}
+
+bool DataInterpreter::UseCategoriesAsX( const Sequence< beans::PropertyValue > & rArguments )
+{
+ bool bUseCategoriesAsX = true;
+ if( rArguments.hasElements() )
+ GetProperty( rArguments, u"UseCategoriesAsX" ) >>= bUseCategoriesAsX;
+ return bUseCategoriesAsX;
+}
+
+OUString SAL_CALL DataInterpreter::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.DataInterpreter";
+}
+
+sal_Bool SAL_CALL DataInterpreter::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL DataInterpreter::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.DataInterpreter" };
+}
+
+std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > DataInterpreter::getDataSequences(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xSource)
+{
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData;
+ for (const Reference< data::XLabeledDataSequence > & rLDS : xSource->getDataSequences() )
+ {
+ aData.push_back(rLDS);
+ }
+ return aData;
+}
+
+} // namespace chart
+
+#ifdef DEBUG_CHART2_TEMPLATE
+namespace
+{
+
+void lcl_ShowDataSource( const Reference< data::XDataSource > & xSource )
+{
+ if( ! xSource.is())
+ return;
+
+ SAL_INFO("chart2", "DataSource in DataInterpreter:" );
+ Sequence< Reference< data::XLabeledDataSequence > > aSequences( xSource->getDataSequences());
+ Reference< beans::XPropertySet > xProp;
+ OUString aId;
+ const sal_Int32 nMax = aSequences.getLength();
+ for( sal_Int32 k = 0; k < nMax; ++k )
+ {
+ if( aSequences[k].is())
+ {
+ OUString aSourceRepr("<none>");
+ if( aSequences[k]->getValues().is())
+ aSourceRepr = aSequences[k]->getValues()->getSourceRangeRepresentation();
+ xProp.set( aSequences[k]->getValues(), uno::UNO_QUERY );
+ if( xProp.is() &&
+ ( xProp->getPropertyValue( "Role") >>= aId ))
+ {
+ SAL_INFO("chart2", " <data sequence " << k << "> Role: " << aId << ", Source: "<< aSourceRepr);
+ }
+ else
+ {
+ SAL_INFO("chart2", " <data sequence " << k << "> unknown Role, Source: " << aSourceRepr );
+ }
+
+ aSourceRepr = "<none>";
+ if( aSequences[k]->getLabel().is())
+ aSourceRepr = aSequences[k]->getLabel()->getSourceRangeRepresentation();
+ xProp.set( aSequences[k]->getLabel(), uno::UNO_QUERY );
+ if( xProp.is() &&
+ ( xProp->getPropertyValue( "Role") >>= aId ))
+ {
+ SAL_INFO("chart2", " <data sequence label " << k << "> Role: " << aId
+ << ", Source: " << aSourceRepr );
+ }
+ else
+ {
+ SAL_INFO("chart2", " <data sequence label " << k << "> unknown Role, Source: " << aSourceRepr );
+ }
+ }
+ }
+}
+
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/FilledNetChartType.cxx b/chart2/source/model/template/FilledNetChartType.cxx
new file mode 100644
index 0000000000..6ec39d9835
--- /dev/null
+++ b/chart2/source/model/template/FilledNetChartType.cxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "FilledNetChartType.hxx"
+#include <servicenames_charttypes.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+FilledNetChartType::FilledNetChartType()
+{}
+
+FilledNetChartType::FilledNetChartType( const FilledNetChartType & rOther ) :
+ NetChartType_Base( rOther )
+{
+}
+
+FilledNetChartType::~FilledNetChartType()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL FilledNetChartType::createClone()
+{
+ return uno::Reference< util::XCloneable >( new FilledNetChartType( *this ));
+}
+
+rtl::Reference< ChartType > FilledNetChartType::cloneChartType() const
+{
+ return new FilledNetChartType( *this );
+}
+
+// ____ XChartType ____
+OUString SAL_CALL FilledNetChartType::getChartType()
+{
+ return CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET;
+}
+
+OUString SAL_CALL FilledNetChartType::getImplementationName()
+{
+ return "com.sun.star.comp.chart.FilledNetChartType";
+}
+
+sal_Bool SAL_CALL FilledNetChartType::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL FilledNetChartType::getSupportedServiceNames()
+{
+ return {
+ CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET,
+ "com.sun.star.chart2.ChartType",
+ "com.sun.star.beans.PropertySet" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_FilledNetChartType_get_implementation(css::uno::XComponentContext * /*context*/,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::FilledNetChartType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/FilledNetChartType.hxx b/chart2/source/model/template/FilledNetChartType.hxx
new file mode 100644
index 0000000000..b2d239aeca
--- /dev/null
+++ b/chart2/source/model/template/FilledNetChartType.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "NetChartType.hxx"
+
+namespace chart
+{
+class FilledNetChartType final : public NetChartType_Base
+{
+public:
+ explicit FilledNetChartType();
+ virtual ~FilledNetChartType() override;
+
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const override;
+
+private:
+ explicit FilledNetChartType(const FilledNetChartType& rOther);
+
+ // ____ XChartType ____
+ virtual OUString SAL_CALL getChartType() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone() override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/LineChartType.cxx b/chart2/source/model/template/LineChartType.cxx
new file mode 100644
index 0000000000..e9d7cf808e
--- /dev/null
+++ b/chart2/source/model/template/LineChartType.cxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "LineChartType.hxx"
+#include <PropertyHelper.hxx>
+#include <servicenames_charttypes.hxx>
+#include <unonames.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart2/CurveStyle.hpp>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+
+enum
+{
+ PROP_LINECHARTTYPE_CURVE_STYLE,
+ PROP_LINECHARTTYPE_CURVE_RESOLUTION,
+ PROP_LINECHARTTYPE_SPLINE_ORDER
+};
+
+::chart::tPropertyValueMap& StaticLineChartTypeDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults =
+ []()
+ {
+ ::chart::tPropertyValueMap aOutMap;
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_LINECHARTTYPE_CURVE_STYLE, ::chart2::CurveStyle_LINES );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_LINECHARTTYPE_CURVE_RESOLUTION, 20 );
+
+ // todo: check whether order 3 means polygons of order 3 or 2. (see
+ // http://www.people.nnov.ru/fractal/Splines/Basis.htm )
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_LINECHARTTYPE_SPLINE_ORDER, 3 );
+ return aOutMap;
+ }();
+ return aStaticDefaults;
+}
+
+::cppu::OPropertyArrayHelper& StaticLineChartTypeInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper(
+ []()
+ {
+ std::vector< css::beans::Property > aProperties {
+ { CHART_UNONAME_CURVE_STYLE,
+ PROP_LINECHARTTYPE_CURVE_STYLE,
+ cppu::UnoType<chart2::CurveStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { CHART_UNONAME_CURVE_RESOLUTION,
+ PROP_LINECHARTTYPE_CURVE_RESOLUTION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { CHART_UNONAME_SPLINE_ORDER,
+ PROP_LINECHARTTYPE_SPLINE_ORDER,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT } };
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }());
+ return aPropHelper;
+}
+
+uno::Reference< beans::XPropertySetInfo >& StaticLineChartTypeInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticLineChartTypeInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+LineChartType::LineChartType()
+{
+}
+
+LineChartType::LineChartType( const LineChartType & rOther ) :
+ ChartType( rOther )
+{
+}
+
+LineChartType::~LineChartType()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL LineChartType::createClone()
+{
+ return uno::Reference< util::XCloneable >( new LineChartType( *this ));
+}
+
+rtl::Reference< ChartType > LineChartType::cloneChartType() const
+{
+ return new LineChartType( *this );
+}
+
+// ____ XChartType ____
+OUString SAL_CALL LineChartType::getChartType()
+{
+ return CHART2_SERVICE_NAME_CHARTTYPE_LINE;
+}
+
+// ____ OPropertySet ____
+void LineChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticLineChartTypeDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL LineChartType::getInfoHelper()
+{
+ return StaticLineChartTypeInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL LineChartType::getPropertySetInfo()
+{
+ return StaticLineChartTypeInfo();
+}
+
+OUString SAL_CALL LineChartType::getImplementationName()
+{
+ return "com.sun.star.comp.chart.LineChartType";
+}
+
+sal_Bool SAL_CALL LineChartType::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL LineChartType::getSupportedServiceNames()
+{
+ return {
+ CHART2_SERVICE_NAME_CHARTTYPE_LINE,
+ "com.sun.star.chart2.ChartType",
+ "com.sun.star.beans.PropertySet" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_LineChartType_get_implementation(css::uno::XComponentContext * /*context*/,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::LineChartType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/LineChartType.hxx b/chart2/source/model/template/LineChartType.hxx
new file mode 100644
index 0000000000..4c44cca9c3
--- /dev/null
+++ b/chart2/source/model/template/LineChartType.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartType.hxx>
+
+namespace chart
+{
+
+class LineChartType final : public ChartType
+{
+public:
+ explicit LineChartType();
+ virtual ~LineChartType() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const override;
+
+private:
+ explicit LineChartType( const LineChartType & rOther );
+
+ // ____ XChartType ____
+ virtual OUString SAL_CALL getChartType() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/LineChartTypeTemplate.cxx b/chart2/source/model/template/LineChartTypeTemplate.cxx
new file mode 100644
index 0000000000..6b04b3094c
--- /dev/null
+++ b/chart2/source/model/template/LineChartTypeTemplate.cxx
@@ -0,0 +1,327 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "LineChartTypeTemplate.hxx"
+#include "LineChartType.hxx"
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <ChartType.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/chart2/CurveStyle.hpp>
+#include <com/sun/star/chart2/SymbolStyle.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+enum
+{
+ PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE,
+ PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION,
+ PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER
+
+};
+
+::chart::tPropertyValueMap& StaticLineChartTypeTemplateDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults =
+ []()
+ {
+ ::chart::tPropertyValueMap aOutMap;
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE, chart2::CurveStyle_LINES );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION, 20 );
+
+ // todo: check whether order 3 means polygons of order 3 or 2. (see
+ // http://www.people.nnov.ru/fractal/Splines/Basis.htm )
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER, 3 );
+ return aOutMap;
+ }();
+ return aStaticDefaults;
+}
+
+::cppu::OPropertyArrayHelper& StaticLineChartTypeTemplateInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper(
+ []()
+ {
+ std::vector< css::beans::Property > aProperties {
+ { CHART_UNONAME_CURVE_STYLE,
+ PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE,
+ cppu::UnoType<chart2::CurveStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { CHART_UNONAME_CURVE_RESOLUTION,
+ PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { CHART_UNONAME_SPLINE_ORDER,
+ PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT } };
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }());
+ return aPropHelper;
+}
+
+uno::Reference< beans::XPropertySetInfo >& StaticLineChartTypeTemplateInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticLineChartTypeTemplateInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+LineChartTypeTemplate::LineChartTypeTemplate(
+ uno::Reference<
+ uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StackMode eStackMode,
+ bool bSymbols,
+ bool bHasLines /* = true */,
+ sal_Int32 nDim /* = 2 */ ) :
+ ChartTypeTemplate( xContext, rServiceName ),
+ m_eStackMode( eStackMode ),
+ m_bHasSymbols( bSymbols ),
+ m_bHasLines( bHasLines ),
+ m_nDim( nDim )
+{
+ if( nDim == 3 )
+ m_bHasSymbols = false;
+}
+
+LineChartTypeTemplate::~LineChartTypeTemplate()
+{}
+
+// ____ OPropertySet ____
+void LineChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticLineChartTypeTemplateDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL LineChartTypeTemplate::getInfoHelper()
+{
+ return StaticLineChartTypeTemplateInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL LineChartTypeTemplate::getPropertySetInfo()
+{
+ return StaticLineChartTypeTemplateInfo();
+}
+
+sal_Int32 LineChartTypeTemplate::getDimension() const
+{
+ return m_nDim;
+}
+
+StackMode LineChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
+{
+ return m_eStackMode;
+}
+
+// ____ ChartTypeTemplate ____
+bool LineChartTypeTemplate::matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties )
+{
+ bool bResult = ChartTypeTemplate::matchesTemplate2( xDiagram, bAdaptProperties );
+
+ // check symbol-style and line-style
+ // for a template with symbols (or with lines) it is ok, if there is at least one series
+ // with symbols (or with lines)
+ if( bResult )
+ {
+ bool bSymbolFound = false;
+ bool bLineFound = false;
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec =
+ xDiagram->getDataSeries();
+
+ for (auto const& series : aSeriesVec)
+ {
+ try
+ {
+ chart2::Symbol aSymbProp;
+ drawing::LineStyle eLineStyle;
+
+ bool bCurrentHasSymbol = (series->getPropertyValue( "Symbol") >>= aSymbProp) &&
+ (aSymbProp.Style != chart2::SymbolStyle_NONE);
+
+ if( bCurrentHasSymbol )
+ bSymbolFound = true;
+
+ if( bCurrentHasSymbol && (!m_bHasSymbols) )
+ {
+ bResult = false;
+ break;
+ }
+
+ bool bCurrentHasLine = (series->getPropertyValue( "LineStyle") >>= eLineStyle) &&
+ ( eLineStyle != drawing::LineStyle_NONE );
+
+ if( bCurrentHasLine )
+ bLineFound = true;
+
+ if( bCurrentHasLine && (!m_bHasLines) )
+ {
+ bResult = false;
+ break;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ if(bResult)
+ {
+ if( !bLineFound && m_bHasLines && bSymbolFound )
+ bResult = false;
+ else if( !bSymbolFound && m_bHasSymbols && bLineFound )
+ bResult = false;
+ else if( !bLineFound && !bSymbolFound )
+ return m_bHasLines && m_bHasSymbols;
+ }
+ }
+
+ // adapt curve style, spline order and resolution
+ if( bResult && bAdaptProperties )
+ {
+ try
+ {
+ rtl::Reference< ChartType > xChartType = xDiagram->getChartTypeByIndex( 0 );
+ setFastPropertyValue_NoBroadcast( PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE, xChartType->getPropertyValue(CHART_UNONAME_CURVE_STYLE) );
+ setFastPropertyValue_NoBroadcast( PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION, xChartType->getPropertyValue(CHART_UNONAME_CURVE_RESOLUTION) );
+ setFastPropertyValue_NoBroadcast( PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER, xChartType->getPropertyValue(CHART_UNONAME_SPLINE_ORDER) );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return bResult;
+}
+
+rtl::Reference< ChartType > LineChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ )
+{
+ rtl::Reference< ChartType > xResult;
+
+ try
+ {
+ xResult = new LineChartType();
+
+ xResult->setPropertyValue(
+ CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE ));
+ xResult->setPropertyValue(
+ CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION ));
+ xResult->setPropertyValue(
+ CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+rtl::Reference< ChartType > LineChartTypeTemplate::getChartTypeForNewSeries2(
+ const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes )
+{
+ rtl::Reference< ChartType > xResult;
+
+ try
+ {
+ xResult = new LineChartType();
+
+ ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult );
+
+ xResult->setPropertyValue(
+ CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_STYLE ));
+ xResult->setPropertyValue(
+ CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_CURVE_RESOLUTION ));
+ xResult->setPropertyValue(
+ CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_LINECHARTTYPE_TEMPLATE_SPLINE_ORDER ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+void LineChartTypeTemplate::applyStyle2(
+ const rtl::Reference< DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount )
+{
+ ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount );
+
+ try
+ {
+ DataSeriesHelper::switchSymbolsOnOrOff( xSeries, m_bHasSymbols, nSeriesIndex );
+ DataSeriesHelper::switchLinesOnOrOff( xSeries, m_bHasLines );
+ DataSeriesHelper::makeLinesThickOrThin( xSeries, m_nDim==2 );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( LineChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( LineChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/LineChartTypeTemplate.hxx b/chart2/source/model/template/LineChartTypeTemplate.hxx
new file mode 100644
index 0000000000..a634fb390a
--- /dev/null
+++ b/chart2/source/model/template/LineChartTypeTemplate.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartTypeTemplate.hxx>
+#include <OPropertySet.hxx>
+#include <StackMode.hxx>
+#include <comphelper/uno3.hxx>
+
+namespace chart
+{
+
+class LineChartTypeTemplate :
+ public ChartTypeTemplate,
+ public ::property::OPropertySet
+{
+public:
+ explicit LineChartTypeTemplate(
+ css::uno::Reference< css::uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StackMode eStackMode,
+ bool bSymbols,
+ bool bHasLines = true,
+ sal_Int32 nDim = 2 );
+ virtual ~LineChartTypeTemplate() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+protected:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ ChartTypeTemplate ____
+ virtual bool matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties ) override;
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForNewSeries2( const std::vector<
+ rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override;
+ virtual void applyStyle2(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeGroupIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount ) override;
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override;
+ virtual sal_Int32 getDimension() const override;
+ virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override;
+
+private:
+ StackMode m_eStackMode;
+ bool m_bHasSymbols;
+ bool m_bHasLines;
+ sal_Int32 m_nDim;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/NetChartType.cxx b/chart2/source/model/template/NetChartType.cxx
new file mode 100644
index 0000000000..cb4512c748
--- /dev/null
+++ b/chart2/source/model/template/NetChartType.cxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "NetChartType.hxx"
+#include <PolarCoordinateSystem.hxx>
+#include <servicenames_charttypes.hxx>
+#include <AxisIndexDefines.hxx>
+#include <AxisHelper.hxx>
+#include <Axis.hxx>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/chart2/AxisType.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+NetChartType_Base::NetChartType_Base()
+{}
+
+NetChartType_Base::NetChartType_Base( const NetChartType_Base & rOther ) :
+ ChartType( rOther )
+{
+}
+
+NetChartType_Base::~NetChartType_Base()
+{}
+
+rtl::Reference< ::chart::BaseCoordinateSystem >
+ NetChartType_Base::createCoordinateSystem2( sal_Int32 DimensionCount )
+{
+ if( DimensionCount != 2 )
+ throw lang::IllegalArgumentException(
+ "NetChart must be two-dimensional",
+ static_cast< ::cppu::OWeakObject* >( this ), 0 );
+
+ rtl::Reference< PolarCoordinateSystem > xResult =
+ new PolarCoordinateSystem( DimensionCount );
+
+ rtl::Reference< Axis > xAxis = xResult->getAxisByDimension2( 0, MAIN_AXIS_INDEX );
+ if( xAxis.is() )
+ {
+ ScaleData aScaleData = xAxis->getScaleData();
+ aScaleData.Scaling = AxisHelper::createLinearScaling();
+ aScaleData.AxisType = AxisType::CATEGORY;
+ aScaleData.Orientation = AxisOrientation_MATHEMATICAL;
+ xAxis->setScaleData( aScaleData );
+ }
+
+ xAxis = xResult->getAxisByDimension2( 1, MAIN_AXIS_INDEX );
+ if( xAxis.is() )
+ {
+ ScaleData aScaleData = xAxis->getScaleData();
+ aScaleData.Orientation = AxisOrientation_MATHEMATICAL;
+ aScaleData.AxisType = AxisType::REALNUMBER;
+ xAxis->setScaleData( aScaleData );
+ }
+
+ return xResult;
+}
+
+// ____ OPropertySet ____
+void NetChartType_Base::GetDefaultValue( sal_Int32 /*nHandle*/, uno::Any& rAny ) const
+{
+ rAny.clear();
+}
+
+namespace
+{
+
+::cppu::OPropertyArrayHelper& StaticNetChartTypeInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper(Sequence< beans::Property >{});
+ return aPropHelper;
+}
+
+uno::Reference< beans::XPropertySetInfo >& StaticNetChartTypeInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticNetChartTypeInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+}
+
+// ____ OPropertySet ____
+::cppu::IPropertyArrayHelper & SAL_CALL NetChartType_Base::getInfoHelper()
+{
+ return StaticNetChartTypeInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL NetChartType_Base::getPropertySetInfo()
+{
+ return StaticNetChartTypeInfo();
+}
+
+NetChartType::NetChartType()
+{}
+
+NetChartType::NetChartType( const NetChartType & rOther ) :
+ NetChartType_Base( rOther )
+{
+}
+
+NetChartType::~NetChartType()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL NetChartType::createClone()
+{
+ return uno::Reference< util::XCloneable >( new NetChartType( *this ));
+}
+
+rtl::Reference< ChartType > NetChartType::cloneChartType() const
+{
+ return new NetChartType( *this );
+}
+
+// ____ XChartType ____
+OUString SAL_CALL NetChartType::getChartType()
+{
+ return CHART2_SERVICE_NAME_CHARTTYPE_NET;
+}
+
+OUString SAL_CALL NetChartType::getImplementationName()
+{
+ return "com.sun.star.comp.chart.NetChartType";
+}
+
+sal_Bool SAL_CALL NetChartType::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL NetChartType::getSupportedServiceNames()
+{
+ return {
+ CHART2_SERVICE_NAME_CHARTTYPE_NET,
+ "com.sun.star.chart2.ChartType",
+ "com.sun.star.beans.PropertySet" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_NetChartType_get_implementation(css::uno::XComponentContext * /*context*/,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::NetChartType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/NetChartType.hxx b/chart2/source/model/template/NetChartType.hxx
new file mode 100644
index 0000000000..ae414a27c4
--- /dev/null
+++ b/chart2/source/model/template/NetChartType.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartType.hxx>
+
+namespace chart
+{
+
+class NetChartType_Base : public ChartType
+{
+public:
+ explicit NetChartType_Base();
+ virtual ~NetChartType_Base() override;
+
+protected:
+ explicit NetChartType_Base( const NetChartType_Base & rOther );
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ virtual rtl::Reference< ::chart::BaseCoordinateSystem >
+ createCoordinateSystem2( sal_Int32 DimensionCount ) override;
+};
+
+class NetChartType final : public NetChartType_Base
+{
+public:
+ explicit NetChartType();
+ virtual ~NetChartType() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const override;
+
+private:
+ explicit NetChartType( const NetChartType & rOther );
+
+ // ____ XChartType ____
+ virtual OUString SAL_CALL getChartType() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/NetChartTypeTemplate.cxx b/chart2/source/model/template/NetChartTypeTemplate.cxx
new file mode 100644
index 0000000000..77908172b7
--- /dev/null
+++ b/chart2/source/model/template/NetChartTypeTemplate.cxx
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "NetChartTypeTemplate.hxx"
+#include "FilledNetChartType.hxx"
+#include "NetChartType.hxx"
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <ChartType.hxx>
+#include <com/sun/star/chart2/SymbolStyle.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+NetChartTypeTemplate::NetChartTypeTemplate(
+ Reference< uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StackMode eStackMode,
+ bool bSymbols,
+ bool bHasLines ,
+ bool bHasFilledArea ) :
+ ChartTypeTemplate( xContext, rServiceName ),
+ m_eStackMode( eStackMode ),
+ m_bHasSymbols( bSymbols ),
+ m_bHasLines( bHasLines ),
+ m_bHasFilledArea( bHasFilledArea )
+{}
+
+NetChartTypeTemplate::~NetChartTypeTemplate()
+{}
+
+StackMode NetChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
+{
+ return m_eStackMode;
+}
+
+void NetChartTypeTemplate::applyStyle2(
+ const rtl::Reference< DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount )
+{
+ ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount );
+
+ try
+ {
+ DataSeriesHelper::switchSymbolsOnOrOff( xSeries, m_bHasSymbols, nSeriesIndex );
+ DataSeriesHelper::switchLinesOnOrOff( xSeries, m_bHasLines );
+ DataSeriesHelper::makeLinesThickOrThin( xSeries, true );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// ____ ChartTypeTemplate ____
+bool NetChartTypeTemplate::matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties )
+{
+ bool bResult = ChartTypeTemplate::matchesTemplate2( xDiagram, bAdaptProperties );
+
+ if( bResult )
+ {
+ //filled net chart?:
+ if( m_bHasFilledArea )
+ return true;
+
+ // check symbol-style
+ // for a template with symbols it is ok, if there is at least one series
+ // with symbols, otherwise an unknown template is too easy to achieve
+ bool bSymbolFound = false;
+ bool bLineFound = false;
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec =
+ xDiagram->getDataSeries();
+
+ for (auto const& series : aSeriesVec)
+ {
+ try
+ {
+ chart2::Symbol aSymbProp;
+ drawing::LineStyle eLineStyle;
+
+ bool bCurrentHasSymbol = (series->getPropertyValue( "Symbol") >>= aSymbProp) &&
+ (aSymbProp.Style != chart2::SymbolStyle_NONE);
+
+ if( bCurrentHasSymbol )
+ bSymbolFound = true;
+
+ if( bCurrentHasSymbol && (!m_bHasSymbols) )
+ {
+ bResult = false;
+ break;
+ }
+
+ bool bCurrentHasLine = (series->getPropertyValue( "LineStyle") >>= eLineStyle) &&
+ ( eLineStyle != drawing::LineStyle_NONE );
+
+ if( bCurrentHasLine )
+ bLineFound = true;
+
+ if( bCurrentHasLine && (!m_bHasLines) )
+ {
+ bResult = false;
+ break;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ if(bResult)
+ {
+ if( !bLineFound && m_bHasLines && bSymbolFound )
+ bResult = false;
+ else if( !bSymbolFound && m_bHasSymbols && bLineFound )
+ bResult = false;
+ else if( !bLineFound && !bSymbolFound )
+ return m_bHasLines && m_bHasSymbols;
+ }
+ }
+
+ return bResult;
+}
+
+rtl::Reference< ChartType > NetChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ )
+{
+ if( m_bHasFilledArea )
+ return new FilledNetChartType();
+ else
+ return new NetChartType();
+}
+
+rtl::Reference< ChartType > NetChartTypeTemplate::getChartTypeForNewSeries2(
+ const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes )
+{
+ rtl::Reference< ChartType > xResult( getChartTypeForIndex( 0 ) );
+ ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult );
+ return xResult;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/NetChartTypeTemplate.hxx b/chart2/source/model/template/NetChartTypeTemplate.hxx
new file mode 100644
index 0000000000..b1f5ac9dbd
--- /dev/null
+++ b/chart2/source/model/template/NetChartTypeTemplate.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartTypeTemplate.hxx>
+#include <StackMode.hxx>
+
+namespace chart
+{
+
+class NetChartTypeTemplate : public ChartTypeTemplate
+{
+public:
+ explicit NetChartTypeTemplate(
+ css::uno::Reference< css::uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StackMode eStackMode,
+ bool bSymbols,
+ bool bHasLines = true,
+ bool bHasFilledArea = false
+ );
+ virtual ~NetChartTypeTemplate() override;
+
+protected:
+ // ____ ChartTypeTemplate ____
+ virtual bool matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties ) override;
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForNewSeries2( const std::vector<
+ rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override;
+ virtual void applyStyle2(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeGroupIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount ) override;
+
+ // ____ ChartTypeTemplate ____
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override;
+ virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override;
+
+private:
+ StackMode m_eStackMode;
+ bool m_bHasSymbols;
+ bool m_bHasLines;
+ bool m_bHasFilledArea;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/PieChartType.cxx b/chart2/source/model/template/PieChartType.cxx
new file mode 100644
index 0000000000..dc45c24b1a
--- /dev/null
+++ b/chart2/source/model/template/PieChartType.cxx
@@ -0,0 +1,208 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "PieChartType.hxx"
+#include <PropertyHelper.hxx>
+#include <PolarCoordinateSystem.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <servicenames_charttypes.hxx>
+#include <AxisIndexDefines.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+
+::chart::tPropertyValueMap& StaticPieChartTypeDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults =
+ []()
+ {
+ ::chart::tPropertyValueMap aOutMap;
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, ::chart::PROP_PIECHARTTYPE_USE_RINGS, false );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, ::chart::PROP_PIECHARTTYPE_3DRELATIVEHEIGHT, 100 );
+ return aOutMap;
+ }();
+ return aStaticDefaults;
+}
+
+::cppu::OPropertyArrayHelper& StaticPieChartTypeInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper(
+ []()
+ {
+ std::vector< css::beans::Property > aProperties {
+ { "UseRings",
+ ::chart::PROP_PIECHARTTYPE_USE_RINGS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { "3DRelativeHeight",
+ ::chart::PROP_PIECHARTTYPE_3DRELATIVEHEIGHT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::MAYBEVOID }
+ };
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }());
+ return aPropHelper;
+}
+
+uno::Reference< beans::XPropertySetInfo >& StaticPieChartTypeInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo( StaticPieChartTypeInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+PieChartType::PieChartType()
+{
+}
+
+PieChartType::PieChartType( const PieChartType & rOther ) :
+ ChartType( rOther )
+{
+}
+
+PieChartType::~PieChartType()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL PieChartType::createClone()
+{
+ return uno::Reference< util::XCloneable >( new PieChartType( *this ));
+}
+
+rtl::Reference< ChartType > PieChartType::cloneChartType() const
+{
+ return new PieChartType( *this );
+}
+
+// ____ XChartType ____
+OUString SAL_CALL PieChartType::getChartType()
+{
+ return CHART2_SERVICE_NAME_CHARTTYPE_PIE;
+}
+
+rtl::Reference< ::chart::BaseCoordinateSystem >
+ PieChartType::createCoordinateSystem2( sal_Int32 DimensionCount )
+{
+ rtl::Reference< PolarCoordinateSystem > xResult =
+ new PolarCoordinateSystem( DimensionCount );
+
+ for( sal_Int32 i=0; i<DimensionCount; ++i )
+ {
+ rtl::Reference< Axis > xAxis = xResult->getAxisByDimension2( i, MAIN_AXIS_INDEX );
+ if( !xAxis.is() )
+ {
+ OSL_FAIL("a created coordinate system should have an axis for each dimension");
+ continue;
+ }
+
+ //hhhh todo make axis invisible
+
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ aScaleData.Scaling = AxisHelper::createLinearScaling();
+ aScaleData.AxisType = chart2::AxisType::REALNUMBER;
+
+ if( i == 0 )
+ aScaleData.Orientation = chart2::AxisOrientation_REVERSE;
+ else
+ aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
+
+ //remove explicit scalings from all axes
+ AxisHelper::removeExplicitScaling( aScaleData );
+
+ xAxis->setScaleData( aScaleData );
+ }
+
+ return xResult;
+}
+
+uno::Sequence< OUString > PieChartType::getSupportedPropertyRoles()
+{
+ return { "FillColor", "BorderColor" };
+}
+
+// ____ OPropertySet ____
+void PieChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticPieChartTypeDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+// ____ OPropertySet ____
+::cppu::IPropertyArrayHelper & SAL_CALL PieChartType::getInfoHelper()
+{
+ return StaticPieChartTypeInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL PieChartType::getPropertySetInfo()
+{
+ return StaticPieChartTypeInfo();
+}
+
+OUString SAL_CALL PieChartType::getImplementationName()
+{
+ return "com.sun.star.comp.chart.PieChartType";
+}
+
+sal_Bool SAL_CALL PieChartType::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL PieChartType::getSupportedServiceNames()
+{
+ return {
+ CHART2_SERVICE_NAME_CHARTTYPE_PIE,
+ "com.sun.star.chart2.ChartType",
+ "com.sun.star.beans.PropertySet" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_PieChartType_get_implementation(css::uno::XComponentContext * /*context*/,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::PieChartType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/PieChartType.hxx b/chart2/source/model/template/PieChartType.hxx
new file mode 100644
index 0000000000..5a1e46f43d
--- /dev/null
+++ b/chart2/source/model/template/PieChartType.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartType.hxx>
+
+namespace chart
+{
+
+class PieChartType final: public ChartType
+{
+public:
+ explicit PieChartType();
+ virtual ~PieChartType() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const override;
+
+private:
+ explicit PieChartType( const PieChartType & rOther );
+
+ // ____ XChartType ____
+ virtual OUString SAL_CALL getChartType() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedPropertyRoles() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ virtual rtl::Reference< ::chart::BaseCoordinateSystem >
+ createCoordinateSystem2( sal_Int32 DimensionCount ) override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/PieChartTypeTemplate.cxx b/chart2/source/model/template/PieChartTypeTemplate.cxx
new file mode 100644
index 0000000000..e4300dd01f
--- /dev/null
+++ b/chart2/source/model/template/PieChartTypeTemplate.cxx
@@ -0,0 +1,568 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "PieChartTypeTemplate.hxx"
+#include "PieChartType.hxx"
+#include <BaseCoordinateSystem.hxx>
+#include <CommonConverters.hxx>
+#include <ChartType.hxx>
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DataSeriesProperties.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <ThreeDHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <officecfg/Office/Compatibility.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <rtl/math.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::chart::DataSeriesProperties;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+
+enum
+{
+ PROP_PIE_TEMPLATE_DEFAULT_OFFSET,
+ PROP_PIE_TEMPLATE_OFFSET_MODE,
+ PROP_PIE_TEMPLATE_DIMENSION,
+ PROP_PIE_TEMPLATE_USE_RINGS
+};
+
+::chart::tPropertyValueMap& StaticPieChartTypeTemplateDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults =
+ []{
+ ::chart::tPropertyValueMap aOutMap;
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_PIE_TEMPLATE_OFFSET_MODE, chart2::PieChartOffsetMode_NONE );
+ ::chart::PropertyHelper::setPropertyValueDefault< double >( aOutMap, PROP_PIE_TEMPLATE_DEFAULT_OFFSET, 0.5 );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_PIE_TEMPLATE_DIMENSION, 2 );
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_PIE_TEMPLATE_USE_RINGS, false );
+ return aOutMap;
+ }();
+ return aStaticDefaults;
+}
+
+::cppu::OPropertyArrayHelper& StaticPieChartTypeTemplateInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper(
+ []()
+ {
+ std::vector< css::beans::Property > aProperties {
+ { "OffsetMode",
+ PROP_PIE_TEMPLATE_OFFSET_MODE,
+ cppu::UnoType<chart2::PieChartOffsetMode>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { "DefaultOffset",
+ PROP_PIE_TEMPLATE_DEFAULT_OFFSET,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { "Dimension",
+ PROP_PIE_TEMPLATE_DIMENSION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { "UseRings",
+ PROP_PIE_TEMPLATE_USE_RINGS,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT } };
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }() );
+ return aPropHelper;
+}
+
+uno::Reference< beans::XPropertySetInfo >& StaticPieChartTypeTemplateInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticPieChartTypeTemplateInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+PieChartTypeTemplate::PieChartTypeTemplate(
+ uno::Reference<
+ uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ chart2::PieChartOffsetMode eMode,
+ bool bRings /* = false */,
+ sal_Int32 nDim /* = 2 */ ) :
+ ChartTypeTemplate( xContext, rServiceName )
+{
+ setFastPropertyValue_NoBroadcast( PROP_PIE_TEMPLATE_OFFSET_MODE, uno::Any( eMode ));
+ setFastPropertyValue_NoBroadcast( PROP_PIE_TEMPLATE_DIMENSION, uno::Any( nDim ));
+ setFastPropertyValue_NoBroadcast( PROP_PIE_TEMPLATE_USE_RINGS, uno::Any( bRings ));
+}
+
+PieChartTypeTemplate::~PieChartTypeTemplate()
+{}
+
+// ____ OPropertySet ____
+void PieChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticPieChartTypeTemplateDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL PieChartTypeTemplate::getInfoHelper()
+{
+ return StaticPieChartTypeTemplateInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL PieChartTypeTemplate::getPropertySetInfo()
+{
+ return StaticPieChartTypeTemplateInfo();
+}
+
+// ____ ChartTypeTemplate ____
+sal_Int32 PieChartTypeTemplate::getDimension() const
+{
+ sal_Int32 nDim = 2;
+ try
+ {
+ // note: UNO-methods are never const
+ const_cast< PieChartTypeTemplate * >( this )->
+ getFastPropertyValue( PROP_PIE_TEMPLATE_DIMENSION ) >>= nDim;
+ }
+ catch( const beans::UnknownPropertyException & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return nDim;
+}
+
+sal_Int32 PieChartTypeTemplate::getAxisCountByDimension( sal_Int32 /*nDimension*/ )
+{
+ return 0;
+}
+
+void PieChartTypeTemplate::adaptAxes(
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & /*rCoordSys*/ )
+{
+ // hide existing axes
+ //hhhh todo
+}
+
+void PieChartTypeTemplate::adaptScales(
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysSeq,
+ const Reference< chart2::data::XLabeledDataSequence > & xCategories //@todo: in future there may be more than one sequence of categories (e.g. charttype with categories at x and y axis )
+ )
+{
+ ChartTypeTemplate::adaptScales( aCooSysSeq, xCategories );
+
+ //remove explicit scalings from radius axis
+ //and ensure correct orientation of scales for donuts
+
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : aCooSysSeq )
+ {
+ try
+ {
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( 1 /*nDimensionIndex*/,0 /*nAxisIndex*/
+ , coords );
+ if( xAxis.is() )
+ {
+ chart2::ScaleData aScaleData( xAxis->getScaleData() );
+ AxisHelper::removeExplicitScaling( aScaleData );
+ // tdf#108059 Create new pie/donut charts with clockwise orientation
+ if (!officecfg::Office::Compatibility::View::ClockwisePieChartDirection::get())
+ {
+ aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
+ }
+ else
+ {
+ aScaleData.Orientation = chart2::AxisOrientation_REVERSE;
+ }
+ xAxis->setScaleData( aScaleData );
+ }
+
+ xAxis = AxisHelper::getAxis( 0 /*nDimensionIndex*/,0 /*nAxisIndex*/
+ , coords );
+ if( xAxis.is() )
+ {
+ chart2::ScaleData aScaleData( xAxis->getScaleData() );
+
+ //tdf#123218 Don't reverse the orientation in OOXML-heavy environments
+ if( officecfg::Office::Compatibility::View::ReverseXAxisOrientationDoughnutChart::get() )
+ aScaleData.Orientation = chart2::AxisOrientation_REVERSE;
+ else
+ aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
+ xAxis->setScaleData( aScaleData );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+}
+
+void PieChartTypeTemplate::createChartTypes(
+ const std::vector< std::vector< rtl::Reference< DataSeries > > > & aSeriesSeq,
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys,
+ const std::vector< rtl::Reference< ChartType > >& /* aOldChartTypesSeq */ )
+{
+ if( rCoordSys.empty() )
+ return;
+
+ try
+ {
+ rtl::Reference< ChartType > xCT = new PieChartType();
+ xCT->setFastPropertyValue(
+ PROP_PIECHARTTYPE_USE_RINGS, getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS )); // "UseRings"
+ rCoordSys[0]->setChartTypes( std::vector{xCT} );
+
+ if( !aSeriesSeq.empty() )
+ {
+ std::vector< rtl::Reference< DataSeries > > aFlatSeriesSeq = FlattenSequence( aSeriesSeq );
+ xCT->setDataSeries( aFlatSeriesSeq );
+
+ DataSeriesHelper::setStackModeAtSeries(
+ aFlatSeriesSeq, rCoordSys[0], getStackMode( 0 ));
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// ____ XChartTypeTemplate ____
+bool PieChartTypeTemplate::matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties )
+{
+ bool bResult = ChartTypeTemplate::matchesTemplate2( xDiagram, bAdaptProperties );
+
+ bool bTemplateUsesRings = false;
+ getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS ) >>= bTemplateUsesRings;
+ chart2::PieChartOffsetMode ePieOffsetMode;
+ getFastPropertyValue( PROP_PIE_TEMPLATE_OFFSET_MODE ) >>= ePieOffsetMode;
+
+ //check offset-mode
+ if( bResult )
+ {
+ try
+ {
+ double fOffset=0.0;
+ bool bAllOffsetsEqual = true;
+ sal_Int32 nOuterSeriesIndex = 0;
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec =
+ xDiagram->getDataSeries();
+
+ //tdf#108067 The outer series is the last series in OOXML-heavy environments
+ if( !officecfg::Office::Compatibility::View::ReverseXAxisOrientationDoughnutChart::get() )
+ nOuterSeriesIndex = aSeriesVec.size() - 1;
+
+ //check offset of outer series
+ if( !aSeriesVec.empty() )
+ {
+ //@todo in future this will depend on Orientation of the radius axis scale
+ rtl::Reference< DataSeries > xSeries( aSeriesVec[nOuterSeriesIndex] );
+ xSeries->getPropertyValue( "Offset") >>= fOffset;
+
+ // "AttributedDataPoints"
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
+ {
+ for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
+ {
+ uno::Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
+ if(xPointProp.is())
+ {
+ double fPointOffset=0.0;
+ if( xSeries->getPropertyValue( "Offset") >>= fPointOffset )
+ {
+ if( ! ::rtl::math::approxEqual( fPointOffset, fOffset ) )
+ {
+ bAllOffsetsEqual = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ chart2::PieChartOffsetMode eOffsetMode = chart2::PieChartOffsetMode_NONE;
+ if( bAllOffsetsEqual && fOffset > 0.0 )
+ {
+ eOffsetMode = chart2::PieChartOffsetMode_ALL_EXPLODED;
+ if( bAdaptProperties )
+ setFastPropertyValue_NoBroadcast( PROP_PIE_TEMPLATE_DEFAULT_OFFSET, uno::Any( fOffset ));
+ }
+
+ bResult = ( eOffsetMode == ePieOffsetMode );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ bResult = false;
+ }
+ }
+
+ //check UseRings
+ if( bResult )
+ {
+ rtl::Reference< ChartType > xCTProp = xDiagram->getChartTypeByIndex( 0 );
+ bool bUseRings = false;
+ if( xCTProp->getFastPropertyValue( PROP_PIECHARTTYPE_USE_RINGS ) >>= bUseRings ) // "UseRings"
+ {
+ bResult = ( bTemplateUsesRings == bUseRings );
+ }
+ }
+
+ return bResult;
+}
+
+rtl::Reference< ChartType > PieChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ )
+{
+ rtl::Reference< ChartType > xResult;
+
+ try
+ {
+ xResult = new PieChartType();
+ xResult->setFastPropertyValue(
+ PROP_PIECHARTTYPE_USE_RINGS, getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS )); // "UseRings"
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+rtl::Reference< ChartType > PieChartTypeTemplate::getChartTypeForNewSeries2(
+ const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes )
+{
+ rtl::Reference< ChartType > xResult;
+
+ try
+ {
+ xResult = new PieChartType();
+ ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult );
+ xResult->setFastPropertyValue(
+ PROP_PIECHARTTYPE_USE_RINGS, getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS )); // "UseRings"
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+void PieChartTypeTemplate::applyStyle2(
+ const rtl::Reference< DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount )
+{
+ ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount );
+
+ try
+ {
+ bool bTemplateUsesRings = false;
+ sal_Int32 nOuterSeriesIndex = 0;
+ getFastPropertyValue( PROP_PIE_TEMPLATE_USE_RINGS ) >>= bTemplateUsesRings;
+
+ //tdf#108067 The outer series is the last series in OOXML-heavy environments
+ if( !officecfg::Office::Compatibility::View::ReverseXAxisOrientationDoughnutChart::get() )
+ nOuterSeriesIndex = nSeriesCount - 1;
+
+ if( nSeriesIndex == nOuterSeriesIndex ) //@todo in future this will depend on Orientation of the radius axis scale
+ {
+ static constexpr OUString aOffsetPropName( u"Offset"_ustr );
+ // get offset mode
+ chart2::PieChartOffsetMode ePieOffsetMode;
+ getFastPropertyValue( PROP_PIE_TEMPLATE_OFFSET_MODE ) >>= ePieOffsetMode;
+
+ // get default offset
+ double fDefaultOffset = 0.5;
+ getFastPropertyValue( PROP_PIE_TEMPLATE_DEFAULT_OFFSET ) >>= fDefaultOffset;
+ double fOffsetToSet = fDefaultOffset;
+
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ // "AttributedDataPoints"
+ xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList;
+
+ // determine whether to set the new offset
+ bool bSetOffset = ( ePieOffsetMode == chart2::PieChartOffsetMode_ALL_EXPLODED );
+ if( !bSetOffset &&
+ (ePieOffsetMode == chart2::PieChartOffsetMode_NONE) )
+ {
+ // set offset to 0 if the offset was exactly "all exploded"
+ // before (individual offsets are kept)
+ double fOffset = 0.0;
+ if( (xSeries->getPropertyValue( aOffsetPropName ) >>= fOffset) &&
+ ::rtl::math::approxEqual( fOffset, fDefaultOffset ))
+ {
+ fOffsetToSet = 0.0;
+ bSetOffset = true;
+ for( auto const & pointIndex : std::as_const(aAttributedDataPointIndexList) )
+ {
+ uno::Reference< beans::XPropertySet > xPointProp(
+ xSeries->getDataPointByIndex( pointIndex ));
+ uno::Reference< beans::XPropertyState > xPointState( xPointProp, uno::UNO_QUERY );
+ double fPointOffset = 0.0;
+ if( xPointState.is() &&
+ (xPointState->getPropertyState( aOffsetPropName ) == beans::PropertyState_DIRECT_VALUE) &&
+ xPointProp.is() &&
+ (xPointProp->getPropertyValue( aOffsetPropName ) >>= fPointOffset ) &&
+ ! ::rtl::math::approxEqual( fPointOffset, fDefaultOffset ) )
+ {
+ bSetOffset = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if( bSetOffset )
+ {
+ // set the offset to the series and to the attributed data points
+ xSeries->setPropertyValue( aOffsetPropName, uno::Any( fOffsetToSet ));
+
+ // remove hard attributes from data points
+ for( auto const & pointIndex : std::as_const(aAttributedDataPointIndexList) )
+ {
+ uno::Reference< beans::XPropertyState > xPointState(
+ xSeries->getDataPointByIndex( pointIndex ), uno::UNO_QUERY );
+ if( xPointState.is())
+ xPointState->setPropertyToDefault( aOffsetPropName );
+ }
+ }
+ }
+
+ // line style
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) );
+
+ // vary colors by point
+ xSeries->setFastPropertyValue( PROP_DATASERIES_VARY_COLORS_BY_POINT, uno::Any( true )); // "VaryColorsByPoint"
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void PieChartTypeTemplate::resetStyles2( const rtl::Reference< ::chart::Diagram >& xDiagram )
+{
+ // reset axes and grids
+ if( xDiagram.is())
+ {
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > aCooSysSeq( xDiagram->getBaseCoordinateSystems());
+ ChartTypeTemplate::createAxes( aCooSysSeq );
+
+ //reset scale orientation
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : aCooSysSeq )
+ {
+ try
+ {
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( 0 /*nDimensionIndex*/,0 /*nAxisIndex*/
+ , coords );
+ if( xAxis.is() )
+ {
+ chart2::ScaleData aScaleData( xAxis->getScaleData() );
+ aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
+ xAxis->setScaleData( aScaleData );
+ }
+
+ xAxis = AxisHelper::getAxis( 1, 0, coords );
+ if( xAxis.is() )
+ {
+ chart2::ScaleData aScaleData( xAxis->getScaleData() );
+ aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
+ xAxis->setScaleData( aScaleData );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+
+ ChartTypeTemplate::resetStyles2( xDiagram );
+
+ // vary colors by point,
+ // line style
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec =
+ xDiagram->getDataSeries();
+ uno::Any aLineStyleAny( drawing::LineStyle_NONE );
+ for (auto const& series : aSeriesVec)
+ {
+ series->setPropertyToDefault( "VaryColorsByPoint");
+ if( series->getPropertyValue( "BorderStyle") == aLineStyleAny )
+ {
+ series->setPropertyToDefault( "BorderStyle");
+ }
+ }
+
+ //reset scene properties
+ xDiagram->setDefaultRotation( false );
+}
+
+// ____ XChartTypeTemplate ____
+void PieChartTypeTemplate::adaptDiagram( const rtl::Reference< ::chart::Diagram >& xDiagram )
+{
+ if( !xDiagram.is() )
+ return;
+
+ //different default for scene geometry:
+ xDiagram->setDefaultRotation( true );
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( PieChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( PieChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/PieChartTypeTemplate.hxx b/chart2/source/model/template/PieChartTypeTemplate.hxx
new file mode 100644
index 0000000000..a92cfbfd0f
--- /dev/null
+++ b/chart2/source/model/template/PieChartTypeTemplate.hxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <OPropertySet.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <ChartTypeTemplate.hxx>
+#include <com/sun/star/chart2/PieChartOffsetMode.hpp>
+
+namespace chart
+{
+
+class PieChartTypeTemplate :
+ public ChartTypeTemplate,
+ public ::property::OPropertySet
+{
+public:
+ PieChartTypeTemplate(
+ css::uno::Reference< css::uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ css::chart2::PieChartOffsetMode eMode,
+ bool bRings,
+ sal_Int32 nDim = 2 );
+ virtual ~PieChartTypeTemplate() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+protected:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ ChartTypeTemplate ____
+ virtual bool matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties ) override;
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForNewSeries2( const std::vector<
+ rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override;
+ virtual void applyStyle2(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeGroupIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount ) override;
+ virtual void resetStyles2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram ) override;
+
+ // ____ ChartTypeTemplate ____
+ virtual sal_Int32 getDimension() const override;
+
+ virtual void adaptDiagram(
+ const rtl::Reference< ::chart::Diagram > & xDiagram ) override;
+
+ virtual sal_Int32 getAxisCountByDimension( sal_Int32 nDimension ) override;
+
+ virtual void adaptAxes(
+ const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > & rCoordSys ) override;
+
+ virtual void adaptScales(
+ const std::vector< rtl::Reference< ::chart::BaseCoordinateSystem > > & aCooSysSeq,
+ const css::uno::Reference< css::chart2::data::XLabeledDataSequence > & xCategories ) override;
+
+ virtual void createChartTypes(
+ const std::vector<
+ std::vector<
+ rtl::Reference<
+ ::chart::DataSeries > > >& aSeriesSeq,
+ const std::vector<
+ rtl::Reference<
+ ::chart::BaseCoordinateSystem > > & rCoordSys,
+ const std::vector< rtl::Reference< ChartType > > & aOldChartTypesSeq
+ ) override;
+
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ScatterChartType.cxx b/chart2/source/model/template/ScatterChartType.cxx
new file mode 100644
index 0000000000..cee026913b
--- /dev/null
+++ b/chart2/source/model/template/ScatterChartType.cxx
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ScatterChartType.hxx"
+#include <PropertyHelper.hxx>
+#include <servicenames_charttypes.hxx>
+#include <CartesianCoordinateSystem.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <AxisIndexDefines.hxx>
+#include <unonames.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/CurveStyle.hpp>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+
+enum
+{
+ PROP_SCATTERCHARTTYPE_CURVE_STYLE,
+ PROP_SCATTERCHARTTYPE_CURVE_RESOLUTION,
+ PROP_SCATTERCHARTTYPE_SPLINE_ORDER
+};
+
+::chart::tPropertyValueMap& StaticScatterChartTypeDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults =
+ []()
+ {
+ ::chart::tPropertyValueMap aOutMap;
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_SCATTERCHARTTYPE_CURVE_STYLE, chart2::CurveStyle_LINES );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_SCATTERCHARTTYPE_CURVE_RESOLUTION, 20 );
+
+ // todo: check whether order 3 means polygons of order 3 or 2. (see
+ // http://www.people.nnov.ru/fractal/Splines/Basis.htm )
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_SCATTERCHARTTYPE_SPLINE_ORDER, 3 );
+ return aOutMap;
+ }();
+ return aStaticDefaults;
+}
+
+::cppu::OPropertyArrayHelper& StaticScatterChartTypeInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper(
+ []()
+ {
+ std::vector< css::beans::Property > aProperties {
+ { CHART_UNONAME_CURVE_STYLE,
+ PROP_SCATTERCHARTTYPE_CURVE_STYLE,
+ cppu::UnoType<chart2::CurveStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { CHART_UNONAME_CURVE_RESOLUTION,
+ PROP_SCATTERCHARTTYPE_CURVE_RESOLUTION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { CHART_UNONAME_SPLINE_ORDER,
+ PROP_SCATTERCHARTTYPE_SPLINE_ORDER,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT } };
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+ return comphelper::containerToSequence( aProperties );
+ }() );
+ return aPropHelper;
+}
+
+const uno::Reference< beans::XPropertySetInfo >& StaticScatterChartTypeInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticScatterChartTypeInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+ScatterChartType::ScatterChartType()
+{
+}
+
+ScatterChartType::ScatterChartType( const ScatterChartType & rOther ) :
+ ChartType( rOther )
+{
+}
+
+ScatterChartType::~ScatterChartType()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL ScatterChartType::createClone()
+{
+ return uno::Reference< util::XCloneable >( new ScatterChartType( *this ));
+}
+
+rtl::Reference< ChartType > ScatterChartType::cloneChartType() const
+{
+ return new ScatterChartType( *this );
+}
+
+// ____ XChartType ____
+rtl::Reference< ::chart::BaseCoordinateSystem >
+ ScatterChartType::createCoordinateSystem2( sal_Int32 DimensionCount )
+{
+ rtl::Reference< CartesianCoordinateSystem > xResult =
+ new CartesianCoordinateSystem( DimensionCount );
+
+ for( sal_Int32 i=0; i<DimensionCount; ++i )
+ {
+ rtl::Reference< Axis > xAxis = xResult->getAxisByDimension2( i, MAIN_AXIS_INDEX );
+ if( !xAxis.is() )
+ {
+ OSL_FAIL("a created coordinate system should have an axis for each dimension");
+ continue;
+ }
+
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL;
+ aScaleData.Scaling = AxisHelper::createLinearScaling();
+
+ if( i == 2 )
+ aScaleData.AxisType = chart2::AxisType::SERIES;
+ else
+ aScaleData.AxisType = chart2::AxisType::REALNUMBER;
+
+ xAxis->setScaleData( aScaleData );
+ }
+
+ return xResult;
+}
+
+OUString SAL_CALL ScatterChartType::getChartType()
+{
+ return CHART2_SERVICE_NAME_CHARTTYPE_SCATTER;
+}
+
+uno::Sequence< OUString > SAL_CALL ScatterChartType::getSupportedMandatoryRoles()
+{
+ return { "label", "values-x", "values-y" };
+}
+
+// ____ OPropertySet ____
+void ScatterChartType::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticScatterChartTypeDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+// ____ OPropertySet ____
+::cppu::IPropertyArrayHelper & SAL_CALL ScatterChartType::getInfoHelper()
+{
+ return StaticScatterChartTypeInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL ScatterChartType::getPropertySetInfo()
+{
+ return StaticScatterChartTypeInfo();
+}
+
+OUString SAL_CALL ScatterChartType::getImplementationName()
+{
+ return "com.sun.star.comp.chart.ScatterChartType";
+}
+
+sal_Bool SAL_CALL ScatterChartType::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ScatterChartType::getSupportedServiceNames()
+{
+ return {
+ CHART2_SERVICE_NAME_CHARTTYPE_SCATTER,
+ "com.sun.star.chart2.ChartType",
+ "com.sun.star.beans.PropertySet" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_ScatterChartType_get_implementation(css::uno::XComponentContext * /*context*/,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::ScatterChartType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ScatterChartType.hxx b/chart2/source/model/template/ScatterChartType.hxx
new file mode 100644
index 0000000000..f490c108ca
--- /dev/null
+++ b/chart2/source/model/template/ScatterChartType.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartType.hxx>
+
+namespace chart
+{
+
+class ScatterChartType final : public ChartType
+{
+public:
+ ScatterChartType();
+ virtual ~ScatterChartType() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName() override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual rtl::Reference<ChartType> cloneChartType() const override;
+
+private:
+ explicit ScatterChartType( const ScatterChartType & rOther );
+
+ // ____ XChartType ____
+ virtual OUString SAL_CALL getChartType() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedMandatoryRoles() override;
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ // ____ OPropertySet ____
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ virtual rtl::Reference< ::chart::BaseCoordinateSystem >
+ createCoordinateSystem2( sal_Int32 DimensionCount ) override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ScatterChartTypeTemplate.cxx b/chart2/source/model/template/ScatterChartTypeTemplate.cxx
new file mode 100644
index 0000000000..e54d202bb1
--- /dev/null
+++ b/chart2/source/model/template/ScatterChartTypeTemplate.cxx
@@ -0,0 +1,344 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ScatterChartTypeTemplate.hxx"
+#include "ScatterChartType.hxx"
+#include "XYDataInterpreter.hxx"
+#include <ChartType.hxx>
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/chart2/CurveStyle.hpp>
+#include <com/sun/star/chart2/SymbolStyle.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+enum
+{
+ PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE,
+ PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION,
+ PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER
+
+};
+
+const ::chart::tPropertyValueMap& StaticScatterChartTypeTemplateDefaults()
+{
+ static const ::chart::tPropertyValueMap aStaticDefaults =
+ []()
+ {
+ ::chart::tPropertyValueMap aOutMap;
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE, chart2::CurveStyle_LINES );
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION, 20 );
+
+ // todo: check whether order 3 means polygons of order 3 or 2. (see
+ // http://www.people.nnov.ru/fractal/Splines/Basis.htm )
+ ::chart::PropertyHelper::setPropertyValueDefault< sal_Int32 >( aOutMap, PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER, 3 );
+ return aOutMap;
+ }();
+ return aStaticDefaults;
+}
+
+
+::cppu::OPropertyArrayHelper& StaticScatterChartTypeTemplateInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper(
+ []()
+ {
+ std::vector< css::beans::Property > aProperties {
+ { CHART_UNONAME_CURVE_STYLE,
+ PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE,
+ cppu::UnoType<chart2::CurveStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { CHART_UNONAME_CURVE_RESOLUTION,
+ PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT },
+ { CHART_UNONAME_SPLINE_ORDER,
+ PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT } };
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+ return comphelper::containerToSequence( aProperties );
+ }() );
+ return aPropHelper;
+}
+
+const uno::Reference< beans::XPropertySetInfo >& StaticScatterChartTypeTemplateInfo()
+{
+ static const uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(StaticScatterChartTypeTemplateInfoHelper() ) );
+ return xPropertySetInfo;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+ScatterChartTypeTemplate::ScatterChartTypeTemplate(
+ Reference<
+ uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ bool bSymbols,
+ bool bHasLines /* = true */,
+ sal_Int32 nDim /* = 2 */ ) :
+ ChartTypeTemplate( xContext, rServiceName ),
+ m_bHasSymbols( bSymbols ),
+ m_bHasLines( bHasLines ),
+ m_nDim( nDim )
+{
+ if( nDim == 3 )
+ m_bHasSymbols = false;
+}
+
+ScatterChartTypeTemplate::~ScatterChartTypeTemplate()
+{}
+
+// ____ OPropertySet ____
+void ScatterChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = StaticScatterChartTypeTemplateDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL ScatterChartTypeTemplate::getInfoHelper()
+{
+ return StaticScatterChartTypeTemplateInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL ScatterChartTypeTemplate::getPropertySetInfo()
+{
+ return StaticScatterChartTypeTemplateInfo();
+}
+
+sal_Int32 ScatterChartTypeTemplate::getDimension() const
+{
+ return m_nDim;
+}
+
+StackMode ScatterChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const
+{
+ if( m_nDim == 3 )
+ return StackMode::ZStacked;
+ return StackMode::NONE;
+}
+
+void ScatterChartTypeTemplate::applyStyle2(
+ const rtl::Reference< DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount )
+{
+ ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount );
+
+ try
+ {
+ DataSeriesHelper::switchSymbolsOnOrOff( xSeries, m_bHasSymbols, nSeriesIndex );
+ DataSeriesHelper::switchLinesOnOrOff( xSeries, m_bHasLines );
+ DataSeriesHelper::makeLinesThickOrThin( xSeries, m_nDim==2 );
+ if( m_nDim==3 )
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// ____ XChartTypeTemplate ____
+sal_Bool SAL_CALL ScatterChartTypeTemplate::supportsCategories()
+{
+ return false;
+}
+
+bool ScatterChartTypeTemplate::matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties )
+{
+ bool bResult = ChartTypeTemplate::matchesTemplate2( xDiagram, bAdaptProperties );
+
+ // check symbol-style and line-style
+ // for a template with symbols (or with lines) it is ok, if there is at least one series
+ // with symbols (or with lines)
+ if( bResult )
+ {
+ bool bSymbolFound = false;
+ bool bLineFound = false;
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec =
+ xDiagram->getDataSeries();
+
+ for (auto const& series : aSeriesVec)
+ {
+ try
+ {
+ chart2::Symbol aSymbProp;
+ drawing::LineStyle eLineStyle;
+
+ bool bCurrentHasSymbol = (series->getPropertyValue( "Symbol") >>= aSymbProp) &&
+ (aSymbProp.Style != chart2::SymbolStyle_NONE);
+
+ if( bCurrentHasSymbol )
+ bSymbolFound = true;
+
+ if( bCurrentHasSymbol && (!m_bHasSymbols) )
+ {
+ bResult = false;
+ break;
+ }
+
+ bool bCurrentHasLine = (series->getPropertyValue( "LineStyle") >>= eLineStyle) &&
+ ( eLineStyle != drawing::LineStyle_NONE );
+
+ if( bCurrentHasLine )
+ bLineFound = true;
+
+ if( bCurrentHasLine && (!m_bHasLines) )
+ {
+ bResult = false;
+ break;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ if(bResult)
+ {
+ if( !bLineFound && m_bHasLines && bSymbolFound )
+ bResult = false;
+ else if( !bSymbolFound && m_bHasSymbols && bLineFound )
+ bResult = false;
+ else if( !bLineFound && !bSymbolFound )
+ return m_bHasLines && m_bHasSymbols;
+ }
+ }
+
+ // adapt curve style, spline order and resolution
+ if( bResult && bAdaptProperties )
+ {
+ try
+ {
+ rtl::Reference< ChartType > xChartTypeProp =
+ xDiagram->getChartTypeByIndex(0);
+ setFastPropertyValue_NoBroadcast( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE, xChartTypeProp->getPropertyValue(CHART_UNONAME_CURVE_STYLE) );
+ setFastPropertyValue_NoBroadcast( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION, xChartTypeProp->getPropertyValue(CHART_UNONAME_CURVE_RESOLUTION) );
+ setFastPropertyValue_NoBroadcast( PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER, xChartTypeProp->getPropertyValue(CHART_UNONAME_SPLINE_ORDER) );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return bResult;
+}
+
+rtl::Reference< ChartType > ScatterChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ )
+{
+ rtl::Reference< ChartType > xResult;
+
+ try
+ {
+ xResult = new ScatterChartType();
+
+ xResult->setPropertyValue(
+ CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE ));
+ xResult->setPropertyValue(
+ CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION ));
+ xResult->setPropertyValue(
+ CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+rtl::Reference< ChartType > ScatterChartTypeTemplate::getChartTypeForNewSeries2(
+ const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes )
+{
+ rtl::Reference< ChartType > xResult;
+
+ try
+ {
+ xResult = new ScatterChartType();
+
+ ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult );
+
+ xResult->setPropertyValue(
+ CHART_UNONAME_CURVE_STYLE, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_STYLE ));
+ xResult->setPropertyValue(
+ CHART_UNONAME_CURVE_RESOLUTION, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_CURVE_RESOLUTION ));
+ xResult->setPropertyValue(
+ CHART_UNONAME_SPLINE_ORDER, getFastPropertyValue( PROP_SCATTERCHARTTYPE_TEMPLATE_SPLINE_ORDER ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+rtl::Reference< DataInterpreter > ScatterChartTypeTemplate::getDataInterpreter2()
+{
+ if( ! m_xDataInterpreter.is())
+ m_xDataInterpreter.set( new XYDataInterpreter );
+
+ return m_xDataInterpreter;
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( ScatterChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( ScatterChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/ScatterChartTypeTemplate.hxx b/chart2/source/model/template/ScatterChartTypeTemplate.hxx
new file mode 100644
index 0000000000..0d7aec7ad1
--- /dev/null
+++ b/chart2/source/model/template/ScatterChartTypeTemplate.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartTypeTemplate.hxx>
+#include <OPropertySet.hxx>
+#include <comphelper/uno3.hxx>
+
+namespace chart
+{
+
+class ScatterChartTypeTemplate :
+ public ChartTypeTemplate,
+ public ::property::OPropertySet
+{
+public:
+ explicit ScatterChartTypeTemplate(
+ css::uno::Reference< css::uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ bool bSymbols,
+ bool bHasLines = true,
+ sal_Int32 nDim = 2 );
+ virtual ~ScatterChartTypeTemplate() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+protected:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ ChartTypeTemplate ____
+ virtual sal_Bool SAL_CALL supportsCategories() override;
+ virtual bool matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties ) override;
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForNewSeries2( const std::vector<
+ rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override;
+ virtual rtl::Reference< ::chart::DataInterpreter > getDataInterpreter2() override;
+ virtual void applyStyle2(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeGroupIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount ) override;
+
+ // ____ ChartTypeTemplate ____
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override;
+ virtual sal_Int32 getDimension() const override;
+ virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const override;
+
+private:
+ bool m_bHasSymbols;
+ bool m_bHasLines;
+ sal_Int32 m_nDim;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/StockChartTypeTemplate.cxx b/chart2/source/model/template/StockChartTypeTemplate.cxx
new file mode 100644
index 0000000000..e05981bebb
--- /dev/null
+++ b/chart2/source/model/template/StockChartTypeTemplate.cxx
@@ -0,0 +1,434 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "StockChartTypeTemplate.hxx"
+#include "ColumnChartType.hxx"
+#include "CandleStickChartType.hxx"
+#include "LineChartType.hxx"
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include "StockDataInterpreter.hxx"
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <servicenames_charttypes.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <PropertyHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+#include <cstddef>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+
+enum
+{
+ PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME,
+ PROP_STOCKCHARTTYPE_TEMPLATE_OPEN,
+ PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH,
+ PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "Volume",
+ PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "Open",
+ PROP_STOCKCHARTTYPE_TEMPLATE_OPEN,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "LowHigh",
+ PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "Japanese",
+ PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+::chart::tPropertyValueMap& GetStaticStockChartTypeTemplateDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults =
+ [](){
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_STOCKCHARTTYPE_TEMPLATE_OPEN, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( aTmp, PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE, false );
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& GetStaticStockChartTypeTemplateInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper =
+ [](){
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+
+uno::Reference< beans::XPropertySetInfo >& GetStaticStockChartTypeTemplateInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(GetStaticStockChartTypeTemplateInfoHelper() ) );
+ return xPropertySetInfo;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+StockChartTypeTemplate::StockChartTypeTemplate(
+ uno::Reference<
+ uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StockVariant eVariant,
+ bool bJapaneseStyle ) :
+ ChartTypeTemplate( xContext, rServiceName ),
+ m_eStockVariant( eVariant )
+{
+ setFastPropertyValue_NoBroadcast(
+ PROP_STOCKCHARTTYPE_TEMPLATE_OPEN,
+ uno::Any( ( eVariant == StockVariant::Open ||
+ eVariant == StockVariant::VolumeOpen )));
+ setFastPropertyValue_NoBroadcast(
+ PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME,
+ uno::Any( ( eVariant == StockVariant::Volume ||
+ eVariant == StockVariant::VolumeOpen )));
+ setFastPropertyValue_NoBroadcast(
+ PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE,
+ uno::Any( bJapaneseStyle ));
+}
+
+StockChartTypeTemplate::~StockChartTypeTemplate()
+{}
+
+// ____ OPropertySet ____
+void StockChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = GetStaticStockChartTypeTemplateDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL StockChartTypeTemplate::getInfoHelper()
+{
+ return GetStaticStockChartTypeTemplateInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL StockChartTypeTemplate::getPropertySetInfo()
+{
+ return GetStaticStockChartTypeTemplateInfo();
+}
+
+sal_Int32 StockChartTypeTemplate::getAxisCountByDimension( sal_Int32 nDimension )
+{
+ // one x-axis
+ if( nDimension <= 0 )
+ return 1;
+ // no further axes
+ if( nDimension >= 2 )
+ return 0;
+
+ // one or two y-axes depending on volume
+ OSL_ASSERT( nDimension == 1 );
+ bool bHasVolume = false;
+ getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume;
+ return bHasVolume ? 2 : 1;
+}
+
+void StockChartTypeTemplate::applyStyle2(
+ const rtl::Reference< DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount )
+{
+ ChartTypeTemplate::applyStyle2( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount );
+ try
+ {
+ sal_Int32 nNewAxisIndex = 0;
+
+ bool bHasVolume = false;
+ getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume;
+ if( bHasVolume && nChartTypeIndex != 0 )
+ nNewAxisIndex = 1;
+
+ xSeries->setPropertyValue( "AttachedAxisIndex", uno::Any( nNewAxisIndex ) );
+
+ if( bHasVolume && nChartTypeIndex==0 )
+ {
+ //switch lines off for volume bars
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", uno::Any( drawing::LineStyle_NONE ) );
+ }
+ else
+ {
+ //ensure that lines are on
+ drawing::LineStyle eStyle = drawing::LineStyle_NONE;
+ xSeries->getPropertyValue( "LineStyle" ) >>= eStyle;
+ if( eStyle == drawing::LineStyle_NONE )
+ xSeries->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_SOLID ));
+ }
+
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void StockChartTypeTemplate::resetStyles2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram )
+{
+ ChartTypeTemplate::resetStyles2( xDiagram );
+ if( getDimension() == 3 )
+ {
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec =
+ xDiagram->getDataSeries();
+ for (auto const& series : aSeriesVec)
+ {
+ series->setPropertyValue( "AttachedAxisIndex", uno::Any( sal_Int32(0) ) );
+ }
+ }
+
+ xDiagram->setVertical( false );
+}
+
+rtl::Reference< ChartType > StockChartTypeTemplate::getChartTypeForIndex( sal_Int32 nChartTypeIndex )
+{
+ rtl::Reference< ChartType > xCT;
+ bool bHasVolume = false;
+ getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume;
+ if( bHasVolume )
+ {
+ if( nChartTypeIndex == 0 )
+ xCT = new ColumnChartType();
+ else if( nChartTypeIndex == 1 )
+ xCT = new CandleStickChartType();
+ else
+ xCT = new LineChartType();
+ }
+ else
+ {
+ if( nChartTypeIndex == 0 )
+ xCT = new CandleStickChartType();
+ else
+ xCT = new LineChartType();
+ }
+ return xCT;
+}
+
+void StockChartTypeTemplate::createChartTypes(
+ const std::vector< std::vector< rtl::Reference< DataSeries > > > & aSeriesSeq,
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & rCoordSys,
+ const std::vector< rtl::Reference< ChartType > >& /* aOldChartTypesSeq */ )
+{
+ if( rCoordSys.empty() )
+ return;
+
+ try
+ {
+ bool bHasVolume = false;
+ bool bShowFirst = false;
+ bool bJapaneseStyle = false;
+ bool bShowHighLow = true;
+
+ getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume;
+ getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_OPEN ) >>= bShowFirst;
+ getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE ) >>= bJapaneseStyle;
+ getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_LOW_HIGH ) >>= bShowHighLow;
+
+ std::size_t nSeriesIndex = 0;
+
+ std::vector< rtl::Reference< ChartType > > aChartTypeVec;
+ // Bars (Volume)
+ if( bHasVolume )
+ {
+ // chart type
+ rtl::Reference< ChartType > xCT = new ColumnChartType();
+ aChartTypeVec.push_back( xCT );
+
+ if( aSeriesSeq.size() > nSeriesIndex &&
+ !aSeriesSeq[nSeriesIndex].empty() )
+ {
+ xCT->setDataSeries( aSeriesSeq[ nSeriesIndex ] );
+ }
+ ++nSeriesIndex;
+ }
+
+ rtl::Reference< ChartType > xCT = new CandleStickChartType();
+ aChartTypeVec.push_back( xCT );
+
+ xCT->setPropertyValue( "Japanese", uno::Any( bJapaneseStyle ));
+ xCT->setPropertyValue( "ShowFirst", uno::Any( bShowFirst ));
+ xCT->setPropertyValue( "ShowHighLow", uno::Any( bShowHighLow ));
+
+ if( aSeriesSeq.size() > nSeriesIndex &&
+ !aSeriesSeq[ nSeriesIndex ].empty() )
+ {
+ xCT->setDataSeries( aSeriesSeq[ nSeriesIndex ] );
+ }
+ ++nSeriesIndex;
+
+ // Lines (remaining series)
+ if( aSeriesSeq.size() > nSeriesIndex &&
+ !aSeriesSeq[ nSeriesIndex ].empty() )
+ {
+ xCT = new LineChartType();
+ aChartTypeVec.push_back( xCT );
+
+ xCT->setDataSeries( aSeriesSeq[ nSeriesIndex ] );
+ }
+
+ rCoordSys[ 0 ]->setChartTypes( aChartTypeVec );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// ____ ChartTypeTemplate ____
+bool StockChartTypeTemplate::matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool /* bAdaptProperties */ )
+{
+ bool bResult = false;
+
+ if( ! xDiagram.is())
+ return bResult;
+
+ try
+ {
+ bool bHasVolume = false, bHasOpenValue = false, bHasJapaneseStyle = false;
+
+ getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_VOLUME ) >>= bHasVolume;
+ getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_OPEN ) >>= bHasOpenValue;
+ getFastPropertyValue( PROP_STOCKCHARTTYPE_TEMPLATE_JAPANESE ) >>= bHasJapaneseStyle;
+
+ rtl::Reference< ChartType > xVolumeChartType;
+ rtl::Reference< ChartType > xCandleStickChartType;
+ rtl::Reference< ChartType > xLineChartType;
+ sal_Int32 nNumberOfChartTypes = 0;
+
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() )
+ {
+ for( rtl::Reference< ChartType > const & chartType : coords->getChartTypes2() )
+ {
+ ++nNumberOfChartTypes;
+ if( nNumberOfChartTypes > 3 )
+ break;
+ OUString aCTService = chartType->getChartType();
+ if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_COLUMN )
+ xVolumeChartType = chartType;
+ else if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK )
+ xCandleStickChartType = chartType;
+ else if( aCTService == CHART2_SERVICE_NAME_CHARTTYPE_LINE )
+ xLineChartType = chartType;
+ }
+ if( nNumberOfChartTypes > 3 )
+ break;
+ }
+
+ if (xCandleStickChartType.is() && bHasVolume == xVolumeChartType.is())
+ {
+ bResult = true;
+
+ // check for japanese style
+ bool bJapaneseProp = false;
+ xCandleStickChartType->getPropertyValue( "Japanese") >>= bJapaneseProp;
+ bResult = bResult && ( bHasJapaneseStyle == bJapaneseProp );
+
+ // in old chart japanese == showFirst
+ bool bShowFirstProp = false;
+ xCandleStickChartType->getPropertyValue( "ShowFirst") >>= bShowFirstProp;
+ bResult = bResult && ( bHasOpenValue == bShowFirstProp );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return bResult;
+}
+
+rtl::Reference< ChartType > StockChartTypeTemplate::getChartTypeForNewSeries2(
+ const std::vector< rtl::Reference< ChartType > >& aFormerlyUsedChartTypes )
+{
+ rtl::Reference< ChartType > xResult;
+
+ try
+ {
+ xResult = new LineChartType();
+ ChartTypeTemplate::copyPropertiesFromOldToNewCoordinateSystem( aFormerlyUsedChartTypes, xResult );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+rtl::Reference< DataInterpreter > StockChartTypeTemplate::getDataInterpreter2()
+{
+ if( ! m_xDataInterpreter.is())
+ m_xDataInterpreter.set( new StockDataInterpreter( m_eStockVariant ) );
+
+ return m_xDataInterpreter;
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( StockChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( StockChartTypeTemplate, ChartTypeTemplate, OPropertySet )
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/StockChartTypeTemplate.hxx b/chart2/source/model/template/StockChartTypeTemplate.hxx
new file mode 100644
index 0000000000..aed35a0009
--- /dev/null
+++ b/chart2/source/model/template/StockChartTypeTemplate.hxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <ChartTypeTemplate.hxx>
+#include <OPropertySet.hxx>
+#include <comphelper/uno3.hxx>
+
+namespace chart
+{
+
+class StockChartTypeTemplate :
+ public ChartTypeTemplate,
+ public ::property::OPropertySet
+{
+public:
+ enum class StockVariant
+ {
+ NONE,
+ Open,
+ Volume,
+ VolumeOpen
+ };
+
+ /** CTOR
+
+ @param bJapaneseStyle
+ If true, the candlesticks are drawn as solid white or black boxes
+ depending on rising or falling stock-values. Otherwise the
+ open-value will be drawn as a small line at the left side of a
+ straight vertical line, and the close-value on the right hand side.
+ */
+ explicit StockChartTypeTemplate(
+ css::uno::Reference< css::uno::XComponentContext > const & xContext,
+ const OUString & rServiceName,
+ StockVariant eVariant,
+ bool bJapaneseStyle );
+ virtual ~StockChartTypeTemplate() override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+ /// merge XTypeProvider implementations
+ DECLARE_XTYPEPROVIDER()
+
+protected:
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XChartTypeTemplate ____
+ virtual bool matchesTemplate2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram,
+ bool bAdaptProperties ) override;
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForNewSeries2( const std::vector<
+ rtl::Reference< ::chart::ChartType > >& aFormerlyUsedChartTypes ) override;
+ virtual rtl::Reference< ::chart::DataInterpreter > getDataInterpreter2() override;
+ virtual void applyStyle2(
+ const rtl::Reference< ::chart::DataSeries >& xSeries,
+ ::sal_Int32 nChartTypeIndex,
+ ::sal_Int32 nSeriesIndex,
+ ::sal_Int32 nSeriesCount ) override;
+ virtual void resetStyles2(
+ const rtl::Reference< ::chart::Diagram >& xDiagram ) override;
+
+ // ChartTypeTemplate
+ virtual sal_Int32 getAxisCountByDimension( sal_Int32 nDimension ) override;
+
+ // ____ ChartTypeTemplate ____
+ virtual void createChartTypes(
+ const std::vector<
+ std::vector<
+ rtl::Reference<
+ ::chart::DataSeries > > >& aSeriesSeq,
+ const std::vector<
+ rtl::Reference<
+ ::chart::BaseCoordinateSystem > > & rCoordSys,
+ const std::vector< rtl::Reference< ChartType > > & aOldChartTypesSeq
+ ) override;
+
+ virtual rtl::Reference< ::chart::ChartType >
+ getChartTypeForIndex( sal_Int32 nChartTypeIndex ) override;
+
+private:
+ // todo: deprecate this variable
+ StockVariant m_eStockVariant;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/StockDataInterpreter.cxx b/chart2/source/model/template/StockDataInterpreter.cxx
new file mode 100644
index 0000000000..1575bba1b2
--- /dev/null
+++ b/chart2/source/model/template/StockDataInterpreter.cxx
@@ -0,0 +1,341 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cstddef>
+
+#include "StockDataInterpreter.hxx"
+#include "StockChartTypeTemplate.hxx"
+#include <DataSeries.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+// explicit
+StockDataInterpreter::StockDataInterpreter(
+ StockChartTypeTemplate::StockVariant eVariant ) :
+ m_eStockVariant( eVariant )
+{}
+
+StockDataInterpreter::~StockDataInterpreter()
+{}
+
+// ____ XDataInterpreter ____
+InterpretedData StockDataInterpreter::interpretDataSource(
+ const Reference< data::XDataSource >& xSource,
+ const Sequence< beans::PropertyValue >& rArguments,
+ const std::vector< rtl::Reference< ::chart::DataSeries > >& rSeriesToReUse )
+{
+ if( ! xSource.is())
+ return InterpretedData();
+
+ uno::Reference< chart2::data::XLabeledDataSequence > xCategories;
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = DataInterpreter::getDataSequences(xSource);
+ const sal_Int32 nDataCount( aData.size());
+
+ // sub-type properties
+ const StockChartTypeTemplate::StockVariant eVar( GetStockVariant());
+ const bool bHasOpenValues (( eVar == StockChartTypeTemplate::StockVariant::Open ) ||
+ ( eVar == StockChartTypeTemplate::StockVariant::VolumeOpen ));
+ const bool bHasVolume (( eVar == StockChartTypeTemplate::StockVariant::Volume ) ||
+ ( eVar == StockChartTypeTemplate::StockVariant::VolumeOpen ));
+ const bool bHasCategories( HasCategories( rArguments, aData ));
+
+ // necessary roles for "full series"
+ // low/high/close
+ sal_Int32 nNumberOfNecessarySequences( 3 );
+ if( bHasOpenValues )
+ ++nNumberOfNecessarySequences;
+ if( bHasVolume )
+ ++nNumberOfNecessarySequences;
+
+ // calculate number of full series (nNumOfFullSeries) and the number of remaining
+ // sequences used for additional "incomplete series" (nRemaining)
+ sal_Int32 nNumOfFullSeries( 0 );
+ sal_Int32 nRemaining( 0 );
+ {
+ sal_Int32 nAvailableSequences( nDataCount );
+ if( bHasCategories )
+ --nAvailableSequences;
+ nNumOfFullSeries = nAvailableSequences / nNumberOfNecessarySequences;
+ nRemaining = nAvailableSequences % nNumberOfNecessarySequences;
+ }
+ sal_Int32 nCandleStickSeries = nNumOfFullSeries;
+ sal_Int32 nVolumeSeries = nNumOfFullSeries;
+
+ sal_Int32 nNumberOfGroups( bHasVolume ? 2 : 1 );
+ // sequences of data::XLabeledDataSequence per series per group
+ std::vector< std::vector< std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > > > aSequences( nNumberOfGroups );
+ const sal_Int32 nBarGroupIndex( 0 );
+ const sal_Int32 nCandleStickGroupIndex( nNumberOfGroups - 1 );
+
+ // allocate space for labeled sequences
+ if( nRemaining > 0 )
+ ++nCandleStickSeries;
+ aSequences[nCandleStickGroupIndex].resize( nCandleStickSeries );
+ auto & pCandleStickGroup = aSequences[nCandleStickGroupIndex];
+ if( bHasVolume )
+ {
+ // if there are remaining sequences, the first one is taken for
+ // additional close values, the second one is taken as volume, if volume
+ // is used
+ if( nRemaining > 1 )
+ ++nVolumeSeries;
+ aSequences[nBarGroupIndex].resize( nVolumeSeries );
+ }
+ auto & pBarGroup = aSequences[nBarGroupIndex];
+
+ // create data
+ sal_Int32 nSourceIndex = 0; // index into aData sequence
+
+ // 1. categories
+ if( bHasCategories )
+ {
+ xCategories = aData[nSourceIndex];
+ ++nSourceIndex;
+ }
+
+ // 2. create "full" series
+ for( sal_Int32 nLabeledSeqIdx=0; nLabeledSeqIdx<nNumOfFullSeries; ++nLabeledSeqIdx )
+ {
+ // bar
+ if( bHasVolume )
+ {
+ pBarGroup[nLabeledSeqIdx].resize( 1 );
+ pBarGroup[nLabeledSeqIdx][0] = aData[nSourceIndex];
+ if( aData[nSourceIndex].is())
+ SetRole( aData[nSourceIndex]->getValues(), "values-y");
+ ++nSourceIndex;
+ }
+
+ sal_Int32 nSeqIdx = 0;
+ if( bHasOpenValues )
+ {
+ pCandleStickGroup[nLabeledSeqIdx].resize( 4 );
+ pCandleStickGroup[nLabeledSeqIdx][nSeqIdx] = aData[nSourceIndex];
+ if( aData[nSourceIndex].is())
+ SetRole( aData[nSourceIndex]->getValues(), "values-first");
+ ++nSourceIndex;
+ ++nSeqIdx;
+ }
+ else
+ pCandleStickGroup[nLabeledSeqIdx].resize( 3 );
+ auto & pLabeledSeq = pCandleStickGroup[nLabeledSeqIdx];
+
+ pLabeledSeq[nSeqIdx] = aData[nSourceIndex];
+ if( aData[nSourceIndex].is())
+ SetRole( aData[nSourceIndex]->getValues(), "values-min");
+ ++nSourceIndex;
+ ++nSeqIdx;
+
+ pLabeledSeq[nSeqIdx] = aData[nSourceIndex];
+ if( aData[nSourceIndex].is())
+ SetRole( aData[nSourceIndex]->getValues(), "values-max");
+ ++nSourceIndex;
+ ++nSeqIdx;
+
+ pLabeledSeq[nSeqIdx] = aData[nSourceIndex];
+ if( aData[nSourceIndex].is())
+ SetRole( aData[nSourceIndex]->getValues(), "values-last");
+ ++nSourceIndex;
+ ++nSeqIdx;
+ }
+
+ // 3. create series with remaining sequences
+ if( bHasVolume && nRemaining > 1 )
+ {
+ OSL_ASSERT( nVolumeSeries > nNumOfFullSeries );
+ pBarGroup[nVolumeSeries - 1].resize( 1 );
+ OSL_ASSERT( nDataCount > nSourceIndex );
+ if( aData[nSourceIndex].is())
+ SetRole( aData[nSourceIndex]->getValues(), "values-y");
+ pBarGroup[nVolumeSeries - 1][0] = aData[nSourceIndex];
+ ++nSourceIndex;
+ --nRemaining;
+ OSL_ENSURE( nRemaining, "additional bar should only be used if there is at least one more sequence for a candle stick" );
+ }
+
+ // candle-stick
+ if( nRemaining > 0 )
+ {
+ OSL_ASSERT( nCandleStickSeries > nNumOfFullSeries );
+ const sal_Int32 nSeriesIndex = nCandleStickSeries - 1;
+ pCandleStickGroup[nSeriesIndex].resize( nRemaining );
+ auto & pLabeledSeq = pCandleStickGroup[nSeriesIndex];
+ OSL_ASSERT( nDataCount > nSourceIndex );
+
+ // 1. low
+ sal_Int32 nSeqIdx( 0 );
+ pLabeledSeq[nSeqIdx] = aData[nSourceIndex];
+ if( aData[nSourceIndex].is())
+ SetRole( aData[nSourceIndex]->getValues(), "values-min");
+ ++nSourceIndex;
+ ++nSeqIdx;
+
+ // 2. high
+ if( nSeqIdx < nRemaining )
+ {
+ pLabeledSeq[nSeqIdx] = aData[nSourceIndex];
+ if( aData[nSourceIndex].is())
+ SetRole( aData[nSourceIndex]->getValues(), "values-max");
+ ++nSourceIndex;
+ ++nSeqIdx;
+ }
+
+ // 3. close
+ OSL_ENSURE( bHasOpenValues || nSeqIdx >= nRemaining, "could have created full series" );
+ if( nSeqIdx < nRemaining )
+ {
+ pLabeledSeq[nSeqIdx] = aData[nSourceIndex];
+ if( aData[nSourceIndex].is())
+ SetRole( aData[nSourceIndex]->getValues(), "values-last");
+ ++nSourceIndex;
+ ++nSeqIdx;
+ }
+
+ // 4. open
+ OSL_ENSURE( nSeqIdx >= nRemaining, "could have created full series" );
+ }
+
+ // create DataSeries
+ std::vector< std::vector< rtl::Reference< DataSeries > > > aResultSeries( nNumberOfGroups );
+ sal_Int32 nGroupIndex;
+ std::size_t nReUsedSeriesIdx = 0;
+ for( nGroupIndex=0; nGroupIndex<nNumberOfGroups; ++nGroupIndex )
+ {
+ const sal_Int32 nNumSeriesData = aSequences[nGroupIndex].size();
+ aResultSeries[nGroupIndex].resize( nNumSeriesData );
+ auto & pResultSerie = aResultSeries[nGroupIndex];
+ for( sal_Int32 nSeriesIdx = 0; nSeriesIdx < nNumSeriesData; ++nSeriesIdx, ++nReUsedSeriesIdx )
+ {
+ try
+ {
+ rtl::Reference< DataSeries > xSeries;
+ if( nReUsedSeriesIdx < rSeriesToReUse.size())
+ xSeries = rSeriesToReUse[nReUsedSeriesIdx];
+ else
+ xSeries = new DataSeries;
+ assert( xSeries.is() );
+ xSeries->setData( aSequences[nGroupIndex][nSeriesIdx] );
+ pResultSerie[nSeriesIdx] = xSeries;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+
+ return { aResultSeries, xCategories };
+}
+
+// criterion: there must be two groups for stock-charts with volume and all
+// series must have the correct number of data::XLabeledDataSequences
+
+// todo: skip first criterion? (to allow easy switch from stock-chart without
+// volume to one with volume)
+bool StockDataInterpreter::isDataCompatible(
+ const InterpretedData& aInterpretedData )
+{
+ // high/low/close
+ std::size_t nNumberOfNecessarySequences = 3;
+ // open
+ StockChartTypeTemplate::StockVariant eVar( GetStockVariant());
+ if( ( eVar == StockChartTypeTemplate::StockVariant::Open ) ||
+ ( eVar == StockChartTypeTemplate::StockVariant::VolumeOpen ))
+ ++nNumberOfNecessarySequences;
+ // volume
+ bool bHasVolume = (( eVar == StockChartTypeTemplate::StockVariant::Volume ) ||
+ ( eVar == StockChartTypeTemplate::StockVariant::VolumeOpen ));
+
+ // 1. correct number of sub-types
+ if( aInterpretedData.Series.size() < (bHasVolume ? 2U : 1U ))
+ return false;
+
+ // 2. a. volume -- use default check
+ if( bHasVolume )
+ {
+ if( ! DataInterpreter::isDataCompatible(
+ { std::vector< std::vector< rtl::Reference< DataSeries > > >{
+ aInterpretedData.Series[0] },
+ aInterpretedData.Categories }))
+ return false;
+ }
+
+ // 2. b. candlestick
+ {
+ OSL_ASSERT( aInterpretedData.Series.size() > (bHasVolume ? 1U : 0U));
+ const std::vector< rtl::Reference< DataSeries > > & aSeries = aInterpretedData.Series[(bHasVolume ? 1 : 0)];
+ if(aSeries.empty())
+ return false;
+ for( rtl::Reference< DataSeries > const & dataSeries : aSeries )
+ {
+ try
+ {
+ if( dataSeries->getDataSequences2().size() != nNumberOfNecessarySequences )
+ return false;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+
+ // 2. c. additional series
+ // ignore
+
+ return true;
+}
+
+InterpretedData StockDataInterpreter::reinterpretDataSeries(
+ const InterpretedData& aInterpretedData )
+{
+ // prerequisite: StockDataInterpreter::isDataCompatible() returned true
+ return aInterpretedData;
+}
+
+uno::Any StockDataInterpreter::getChartTypeSpecificData(
+ const OUString& sKey )
+{
+ if( sKey == "stock variant" )
+ {
+ StockChartTypeTemplate::StockVariant eStockVariant( GetStockVariant());
+ std::map< StockChartTypeTemplate::StockVariant, sal_Int32 > aTranslation {
+ { StockChartTypeTemplate::StockVariant::NONE, 0 },
+ { StockChartTypeTemplate::StockVariant::Open, 1 },
+ { StockChartTypeTemplate::StockVariant::Volume, 2 },
+ { StockChartTypeTemplate::StockVariant::VolumeOpen, 3 }
+ };
+ return uno::Any( aTranslation[eStockVariant] );
+ }
+ return uno::Any();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/StockDataInterpreter.hxx b/chart2/source/model/template/StockDataInterpreter.hxx
new file mode 100644
index 0000000000..4617da5974
--- /dev/null
+++ b/chart2/source/model/template/StockDataInterpreter.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <DataInterpreter.hxx>
+
+#include "StockChartTypeTemplate.hxx"
+
+namespace chart
+{
+
+class StockDataInterpreter : public DataInterpreter
+{
+public:
+ explicit StockDataInterpreter(
+ StockChartTypeTemplate::StockVariant eVariant );
+ virtual ~StockDataInterpreter() override;
+
+protected:
+ // ____ XDataInterpreter ____
+ virtual InterpretedData interpretDataSource(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments,
+ const std::vector< rtl::Reference< ::chart::DataSeries > >& aSeriesToReUse ) override;
+ virtual bool isDataCompatible(
+ const InterpretedData& aInterpretedData ) override;
+ virtual InterpretedData reinterpretDataSeries(
+ const InterpretedData& aInterpretedData ) override;
+ virtual css::uno::Any getChartTypeSpecificData(
+ const OUString& sKey ) override;
+
+private:
+ StockChartTypeTemplate::StockVariant m_eStockVariant;
+
+ StockChartTypeTemplate::StockVariant GetStockVariant() const { return m_eStockVariant;}
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/XYDataInterpreter.cxx b/chart2/source/model/template/XYDataInterpreter.cxx
new file mode 100644
index 0000000000..1fc053f14c
--- /dev/null
+++ b/chart2/source/model/template/XYDataInterpreter.cxx
@@ -0,0 +1,242 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cstddef>
+
+#include "XYDataInterpreter.hxx"
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <CommonConverters.hxx>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+XYDataInterpreter::XYDataInterpreter()
+{
+}
+
+XYDataInterpreter::~XYDataInterpreter()
+{
+}
+
+// ____ XDataInterpreter ____
+InterpretedData XYDataInterpreter::interpretDataSource(
+ const Reference< chart2::data::XDataSource >& xSource,
+ const Sequence< beans::PropertyValue >& aArguments,
+ const std::vector< rtl::Reference< DataSeries > >& aSeriesToReUse )
+{
+ if( ! xSource.is())
+ return InterpretedData();
+
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = DataInterpreter::getDataSequences(xSource);
+
+ uno::Reference< chart2::data::XLabeledDataSequence > xValuesX;
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSequencesVec;
+
+ uno::Reference< chart2::data::XLabeledDataSequence > xCategories;
+ bool bHasCategories = HasCategories( aArguments, aData );
+ bool bUseCategoriesAsX = UseCategoriesAsX( aArguments );
+
+ // parse data
+ bool bCategoriesUsed = false;
+ bool bSetXValues = aData.size()>1;
+ for( uno::Reference< chart2::data::XLabeledDataSequence > const & labelData : aData )
+ {
+ try
+ {
+ if( bHasCategories && ! bCategoriesUsed )
+ {
+ xCategories = labelData;
+ if( xCategories.is())
+ {
+ SetRole( xCategories->getValues(), "categories");
+ if( bUseCategoriesAsX )
+ bSetXValues = false;
+ }
+ bCategoriesUsed = true;
+ }
+ else if( !xValuesX.is() && bSetXValues )
+ {
+ xValuesX = labelData;
+ if( xValuesX.is())
+ SetRole( xValuesX->getValues(), "values-x");
+ }
+ else
+ {
+ aSequencesVec.push_back( labelData );
+ if( labelData.is())
+ SetRole( labelData->getValues(), "values-y");
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ // create DataSeries
+ std::vector< rtl::Reference< DataSeries > > aSeriesVec;
+ aSeriesVec.reserve( aSequencesVec.size());
+
+ Reference< data::XLabeledDataSequence > xClonedXValues = xValuesX;
+ Reference< util::XCloneable > xCloneable( xValuesX, uno::UNO_QUERY );
+
+ std::size_t nSeriesIndex = 0;
+ for (auto const& elem : aSequencesVec)
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewData;
+
+ if( nSeriesIndex && xCloneable.is() )
+ xClonedXValues.set( xCloneable->createClone(), uno::UNO_QUERY );
+ if( xValuesX.is() )
+ aNewData.push_back( xClonedXValues );
+
+ aNewData.push_back(elem);
+
+ rtl::Reference< DataSeries > xSeries;
+ if( nSeriesIndex < aSeriesToReUse.size())
+ xSeries = aSeriesToReUse[nSeriesIndex];
+ else
+ xSeries = new DataSeries;
+ assert( xSeries.is() );
+ xSeries->setData( aNewData );
+
+ aSeriesVec.push_back( xSeries );
+ ++nSeriesIndex;
+ }
+
+ return { { aSeriesVec }, xCategories };
+}
+
+InterpretedData XYDataInterpreter::reinterpretDataSeries(
+ const InterpretedData& aInterpretedData )
+{
+ InterpretedData aResult( aInterpretedData );
+
+ sal_Int32 i=0;
+ std::vector< rtl::Reference< DataSeries > > aSeries = FlattenSequence( aInterpretedData.Series );
+ const sal_Int32 nCount = aSeries.size();
+ for( ; i<nCount; ++i )
+ {
+ try
+ {
+ std::vector< uno::Reference< data::XLabeledDataSequence > > aNewSequences;
+
+ // values-y
+ uno::Reference< chart2::data::XLabeledDataSequence > xValuesY(
+ DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-y" ));
+ uno::Reference< chart2::data::XLabeledDataSequence > xValuesX(
+ DataSeriesHelper::getDataSequenceByRole( aSeries[i], "values-x" ));
+ // re-use values-... as values-x/values-y
+ if( ! xValuesX.is() ||
+ ! xValuesY.is())
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aValueSeqVec(
+ DataSeriesHelper::getAllDataSequencesByRole(
+ aSeries[i]->getDataSequences2(), "values" ));
+ if( xValuesX.is())
+ aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesX ));
+ if( xValuesY.is())
+ aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesY ));
+
+ size_t nIndex = 0;
+ if( ! xValuesY.is() &&
+ aValueSeqVec.size() > nIndex )
+ {
+ xValuesY = aValueSeqVec[nIndex++];
+ if( xValuesY.is())
+ SetRole( xValuesY->getValues(), "values-y");
+ }
+
+ if( ! xValuesX.is() &&
+ aValueSeqVec.size() > nIndex )
+ {
+ xValuesX = aValueSeqVec[nIndex++];
+ if( xValuesX.is())
+ SetRole( xValuesY->getValues(), "values-x");
+ }
+ }
+ if( xValuesY.is())
+ {
+ if( xValuesX.is())
+ {
+ aNewSequences = { xValuesX, xValuesY };
+ }
+ else
+ {
+ aNewSequences = { xValuesY };
+ }
+ }
+
+ const std::vector< uno::Reference< data::XLabeledDataSequence > > & aSeqs = aSeries[i]->getDataSequences2();
+ if( aSeqs.size() != aNewSequences.size() )
+ {
+#ifdef DBG_UTIL
+ for( auto const & j : aSeqs )
+ {
+ SAL_WARN_IF((j == xValuesY || j == xValuesX), "chart2.template", "All sequences should be used" );
+ }
+#endif
+ aSeries[i]->setData( aNewSequences );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return aResult;
+}
+
+// criterion: all series must have exactly two data::XLabeledDataSequences
+bool XYDataInterpreter::isDataCompatible(
+ const InterpretedData& aInterpretedData )
+{
+ const std::vector< rtl::Reference< DataSeries > > aSeries = FlattenSequence( aInterpretedData.Series );
+ for( rtl::Reference< DataSeries > const & dataSeries : aSeries )
+ {
+ try
+ {
+ if( dataSeries->getDataSequences2().size() != 2 )
+ return false;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return true;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/model/template/XYDataInterpreter.hxx b/chart2/source/model/template/XYDataInterpreter.hxx
new file mode 100644
index 0000000000..56343013da
--- /dev/null
+++ b/chart2/source/model/template/XYDataInterpreter.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <DataInterpreter.hxx>
+
+namespace chart
+{
+
+class XYDataInterpreter : public DataInterpreter
+{
+public:
+ explicit XYDataInterpreter();
+ virtual ~XYDataInterpreter() override;
+
+protected:
+ // ____ DataInterpreter ____
+ virtual InterpretedData interpretDataSource(
+ const css::uno::Reference< css::chart2::data::XDataSource >& xSource,
+ const css::uno::Sequence< css::beans::PropertyValue >& aArguments,
+ const std::vector< rtl::Reference< ::chart::DataSeries > >& aSeriesToReUse ) override;
+ virtual InterpretedData reinterpretDataSeries(
+ const InterpretedData& aInterpretedData ) override;
+ virtual bool isDataCompatible(
+ const InterpretedData& aInterpretedData ) override;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/AxisHelper.cxx b/chart2/source/tools/AxisHelper.cxx
new file mode 100644
index 0000000000..e8e90c5e42
--- /dev/null
+++ b/chart2/source/tools/AxisHelper.cxx
@@ -0,0 +1,1109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <AxisHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartType.hxx>
+#include <Axis.hxx>
+#include <AxisIndexDefines.hxx>
+#include <DataSource.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <servicenames_coosystems.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <Scaling.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <DataSourceHelper.hxx>
+#include <ReferenceSizeProvider.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <unonames.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <GridProperties.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <unotools/saveopt.hxx>
+
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+
+#include <sal/log.hxx>
+
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/sequence.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <cstddef>
+#include <map>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+Reference< chart2::XScaling > AxisHelper::createLinearScaling()
+{
+ return new LinearScaling( 1.0, 0.0 );
+}
+
+Reference< chart2::XScaling > AxisHelper::createLogarithmicScaling( double fBase )
+{
+ return new LogarithmicScaling( fBase );
+}
+
+ScaleData AxisHelper::createDefaultScale()
+{
+ ScaleData aScaleData;
+ aScaleData.AxisType = chart2::AxisType::REALNUMBER;
+ aScaleData.AutoDateAxis = true;
+ aScaleData.ShiftedCategoryPosition = false;
+ Sequence< SubIncrement > aSubIncrements{ SubIncrement() };
+ aScaleData.IncrementData.SubIncrements = aSubIncrements;
+ return aScaleData;
+}
+
+void AxisHelper::removeExplicitScaling( ScaleData& rScaleData )
+{
+ uno::Any aEmpty;
+ rScaleData.Minimum = rScaleData.Maximum = rScaleData.Origin = aEmpty;
+ rScaleData.Scaling = nullptr;
+ ScaleData aDefaultScale( createDefaultScale() );
+ rScaleData.IncrementData = aDefaultScale.IncrementData;
+ rScaleData.TimeIncrement = aDefaultScale.TimeIncrement;
+}
+
+bool AxisHelper::isLogarithmic( const Reference< XScaling >& xScaling )
+{
+ Reference< lang::XServiceName > xServiceName( xScaling, uno::UNO_QUERY );
+ return xServiceName.is()
+ && xServiceName->getServiceName() == "com.sun.star.chart2.LogarithmicScaling";
+}
+
+chart2::ScaleData AxisHelper::getDateCheckedScale( const rtl::Reference< Axis >& xAxis, ChartModel& rModel )
+{
+ ScaleData aScale = xAxis->getScaleData();
+ rtl::Reference< BaseCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( &rModel ) );
+ if( aScale.AutoDateAxis && aScale.AxisType == AxisType::CATEGORY )
+ {
+ sal_Int32 nDimensionIndex=0; sal_Int32 nAxisIndex=0;
+ AxisHelper::getIndicesForAxis(xAxis, xCooSys, nDimensionIndex, nAxisIndex );
+ bool bChartTypeAllowsDateAxis = ChartTypeHelper::isSupportingDateAxis( AxisHelper::getChartTypeByIndex( xCooSys, 0 ), nDimensionIndex );
+ if( bChartTypeAllowsDateAxis )
+ aScale.AxisType = AxisType::DATE;
+ }
+ if( aScale.AxisType == AxisType::DATE )
+ {
+ ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, rModel );
+ if( !aExplicitCategoriesProvider.isDateAxis() )
+ aScale.AxisType = AxisType::CATEGORY;
+ }
+ return aScale;
+}
+
+void AxisHelper::checkDateAxis( chart2::ScaleData& rScale, ExplicitCategoriesProvider* pExplicitCategoriesProvider, bool bChartTypeAllowsDateAxis )
+{
+ if( rScale.AutoDateAxis && rScale.AxisType == AxisType::CATEGORY && bChartTypeAllowsDateAxis )
+ {
+ rScale.AxisType = AxisType::DATE;
+ removeExplicitScaling( rScale );
+ }
+ if( rScale.AxisType == AxisType::DATE && (!pExplicitCategoriesProvider || !pExplicitCategoriesProvider->isDateAxis()) )
+ {
+ rScale.AxisType = AxisType::CATEGORY;
+ removeExplicitScaling( rScale );
+ }
+}
+
+sal_Int32 AxisHelper::getExplicitNumberFormatKeyForAxis(
+ const rtl::Reference< Axis >& xAxis
+ , const rtl::Reference< BaseCoordinateSystem > & xCorrespondingCoordinateSystem
+ , const rtl::Reference<ChartModel>& xChartDoc
+ , bool bSearchForParallelAxisIfNothingIsFound )
+{
+ sal_Int32 nNumberFormatKey(0);
+ sal_Int32 nAxisIndex = 0;
+ sal_Int32 nDimensionIndex = 1;
+ AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex );
+
+ if (!xAxis.is())
+ return 0;
+
+ bool bLinkToSource = true;
+ xAxis->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource;
+ xAxis->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormatKey;
+
+ if (bLinkToSource)
+ {
+ bool bFormatSet = false;
+ //check whether we have a percent scale -> use percent format
+ if (xChartDoc)
+ {
+ ScaleData aData = AxisHelper::getDateCheckedScale( xAxis, *xChartDoc );
+ if( aData.AxisType==AxisType::PERCENT )
+ {
+ sal_Int32 nPercentFormat = DiagramHelper::getPercentNumberFormat( xChartDoc );
+ if( nPercentFormat != -1 )
+ {
+ nNumberFormatKey = nPercentFormat;
+ bFormatSet = true;
+ }
+ }
+ else if( aData.AxisType==AxisType::DATE )
+ {
+ if( aData.Categories.is() )
+ {
+ Reference< data::XDataSequence > xSeq( aData.Categories->getValues());
+ if( xSeq.is() && !( xChartDoc.is() && xChartDoc->hasInternalDataProvider()) )
+ nNumberFormatKey = xSeq->getNumberFormatKeyByIndex( -1 );
+ else
+ nNumberFormatKey = DiagramHelper::getDateNumberFormat( xChartDoc );
+ bFormatSet = true;
+ }
+ }
+ else if( xChartDoc.is() && xChartDoc->hasInternalDataProvider() && nDimensionIndex == 0 ) //maybe date axis
+ {
+ rtl::Reference< Diagram > xDiagram( xChartDoc->getFirstChartDiagram() );
+ if( xDiagram->isSupportingDateAxis() )
+ {
+ nNumberFormatKey = DiagramHelper::getDateNumberFormat( xChartDoc );
+ }
+ else
+ {
+ rtl::Reference< DataSource > xSource = DataSourceHelper::getUsedData( *xChartDoc );
+ if( xSource.is() )
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aXValues(
+ DataSeriesHelper::getAllDataSequencesByRole( xSource->getDataSequences(), "values-x" ) );
+ if( aXValues.empty() )
+ {
+ uno::Reference< chart2::data::XLabeledDataSequence > xCategories( xDiagram->getCategories() );
+ if( xCategories.is() )
+ {
+ Reference< data::XDataSequence > xSeq( xCategories->getValues());
+ if( xSeq.is() )
+ {
+ bool bHasValidDoubles = false;
+ double fTest=0.0;
+ Sequence< uno::Any > aCats( xSeq->getData() );
+ sal_Int32 nCount = aCats.getLength();
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ if( (aCats[i]>>=fTest) && !std::isnan(fTest) )
+ {
+ bHasValidDoubles=true;
+ break;
+ }
+ }
+ if( bHasValidDoubles )
+ nNumberFormatKey = DiagramHelper::getDateNumberFormat( xChartDoc );
+ }
+ }
+ }
+ }
+ }
+ bFormatSet = true;
+ }
+ }
+
+ if( !bFormatSet )
+ {
+ std::map< sal_Int32, sal_Int32 > aKeyMap;
+ bool bNumberFormatKeyFoundViaAttachedData = false;
+
+ try
+ {
+ OUString aRoleToMatch;
+ if( nDimensionIndex == 0 )
+ aRoleToMatch = "values-x";
+ const std::vector< rtl::Reference< ChartType > > & aChartTypes( xCorrespondingCoordinateSystem->getChartTypes2());
+ for( rtl::Reference< ChartType > const & chartType : aChartTypes )
+ {
+ if( nDimensionIndex != 0 )
+ aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( chartType );
+ for( rtl::Reference< DataSeries > const & xDataSeries : chartType->getDataSeries2() )
+ {
+ if( nDimensionIndex == 1 )
+ {
+ //only take those series into account that are attached to this axis
+ sal_Int32 nAttachedAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
+ if( nAttachedAxisIndex != nAxisIndex )
+ continue;
+ }
+
+ Reference< data::XLabeledDataSequence > xLabeledSeq(
+ DataSeriesHelper::getDataSequenceByRole( xDataSeries, aRoleToMatch ) );
+
+ if( !xLabeledSeq.is() && nDimensionIndex==0 )
+ {
+ ScaleData aData = xAxis->getScaleData();
+ xLabeledSeq = aData.Categories;
+ }
+
+ if( xLabeledSeq.is() )
+ {
+ Reference< data::XDataSequence > xSeq( xLabeledSeq->getValues());
+ if( xSeq.is() )
+ {
+ sal_Int32 nKey = xSeq->getNumberFormatKeyByIndex( -1 );
+ // increase frequency
+ aKeyMap[ nKey ] ++;
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ if( ! aKeyMap.empty())
+ {
+ sal_Int32 nMaxFreq = 0;
+ // find most frequent key
+ for (auto const& elem : aKeyMap)
+ {
+ SAL_INFO(
+ "chart2.tools",
+ "NumberFormatKey " << elem.first << " appears "
+ << elem.second << " times");
+ // all values must at least be 1
+ if( elem.second > nMaxFreq )
+ {
+ nNumberFormatKey = elem.first;
+ bNumberFormatKeyFoundViaAttachedData = true;
+ nMaxFreq = elem.second;
+ }
+ }
+ }
+
+ if( bSearchForParallelAxisIfNothingIsFound )
+ {
+ //no format is set to this axis and no data is set to this axis
+ //--> try to obtain the format from the parallel y-axis
+ if( !bNumberFormatKeyFoundViaAttachedData && nDimensionIndex == 1 )
+ {
+ sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
+ rtl::Reference< Axis > xParallelAxis = AxisHelper::getAxis( 1, nParallelAxisIndex, xCorrespondingCoordinateSystem );
+ nNumberFormatKey = AxisHelper::getExplicitNumberFormatKeyForAxis(xParallelAxis, xCorrespondingCoordinateSystem, xChartDoc, false);
+ }
+ }
+ }
+ }
+
+ return nNumberFormatKey;
+}
+
+rtl::Reference< Axis > AxisHelper::createAxis(
+ sal_Int32 nDimensionIndex
+ , sal_Int32 nAxisIndex // 0==main or 1==secondary axis
+ , const rtl::Reference< BaseCoordinateSystem >& xCooSys
+ , const Reference< uno::XComponentContext > & xContext
+ , ReferenceSizeProvider * pRefSizeProvider )
+{
+ if( !xContext.is() || !xCooSys.is() )
+ return nullptr;
+ if( nDimensionIndex >= xCooSys->getDimension() )
+ return nullptr;
+
+ rtl::Reference< Axis > xAxis = new Axis();
+
+ xCooSys->setAxisByDimension( nDimensionIndex, xAxis, nAxisIndex );
+
+ if( nAxisIndex>0 )//when inserting secondary axes copy some things from the main axis
+ {
+ css::chart::ChartAxisPosition eNewAxisPos( css::chart::ChartAxisPosition_END );
+
+ rtl::Reference< Axis > xMainAxis = xCooSys->getAxisByDimension2( nDimensionIndex, 0 );
+ if( xMainAxis.is() )
+ {
+ ScaleData aScale = xAxis->getScaleData();
+ ScaleData aMainScale = xMainAxis->getScaleData();
+
+ aScale.AxisType = aMainScale.AxisType;
+ aScale.AutoDateAxis = aMainScale.AutoDateAxis;
+ aScale.Categories = aMainScale.Categories;
+ aScale.Orientation = aMainScale.Orientation;
+ aScale.ShiftedCategoryPosition = aMainScale.ShiftedCategoryPosition;
+
+ xAxis->setScaleData( aScale );
+
+ //ensure that the second axis is not placed on the main axis
+ css::chart::ChartAxisPosition eMainAxisPos( css::chart::ChartAxisPosition_ZERO );
+ xMainAxis->getPropertyValue("CrossoverPosition") >>= eMainAxisPos;
+ if( eMainAxisPos == css::chart::ChartAxisPosition_END )
+ eNewAxisPos = css::chart::ChartAxisPosition_START;
+ }
+
+ xAxis->setPropertyValue("CrossoverPosition", uno::Any(eNewAxisPos) );
+ }
+
+ try
+ {
+ // set correct initial AutoScale
+ if( pRefSizeProvider )
+ pRefSizeProvider->setValuesAtPropertySet( xAxis );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xAxis;
+}
+
+rtl::Reference< Axis > AxisHelper::createAxis( sal_Int32 nDimensionIndex, bool bMainAxis
+ , const rtl::Reference< Diagram >& xDiagram
+ , const Reference< uno::XComponentContext >& xContext
+ , ReferenceSizeProvider * pRefSizeProvider )
+{
+ OSL_ENSURE( xContext.is(), "need a context to create an axis" );
+ if( !xContext.is() )
+ return nullptr;
+
+ sal_Int32 nAxisIndex = bMainAxis ? MAIN_AXIS_INDEX : SECONDARY_AXIS_INDEX;
+ rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 );
+
+ // create axis
+ return AxisHelper::createAxis(
+ nDimensionIndex, nAxisIndex, xCooSys, xContext, pRefSizeProvider );
+}
+
+void AxisHelper::showAxis( sal_Int32 nDimensionIndex, bool bMainAxis
+ , const rtl::Reference< Diagram >& xDiagram
+ , const Reference< uno::XComponentContext >& xContext
+ , ReferenceSizeProvider * pRefSizeProvider )
+{
+ if( !xDiagram.is() )
+ return;
+
+ bool bNewAxisCreated = false;
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram );
+ if( !xAxis.is() && xContext.is() )
+ {
+ // create axis
+ bNewAxisCreated = true;
+ xAxis = AxisHelper::createAxis( nDimensionIndex, bMainAxis, xDiagram, xContext, pRefSizeProvider );
+ }
+
+ OSL_ASSERT( xAxis.is());
+ if( !bNewAxisCreated ) //default is true already if created
+ AxisHelper::makeAxisVisible( xAxis );
+}
+
+void AxisHelper::showGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ if( !xDiagram.is() )
+ return;
+
+ rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
+ if(!xCooSys.is())
+ return;
+
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys );
+ if(!xAxis.is())
+ {
+ //hhhh todo create axis without axis visibility
+ }
+ if(!xAxis.is())
+ return;
+
+ if( bMainGrid )
+ AxisHelper::makeGridVisible( xAxis->getGridProperties2() );
+ else
+ {
+ std::vector< rtl::Reference< GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
+ for( auto const & i : aSubGrids )
+ AxisHelper::makeGridVisible( i );
+ }
+}
+
+void AxisHelper::makeAxisVisible( const rtl::Reference< Axis >& xAxis )
+{
+ if( xAxis.is() )
+ {
+ xAxis->setPropertyValue( "Show", uno::Any( true ) );
+ LinePropertiesHelper::SetLineVisible( xAxis );
+ xAxis->setPropertyValue( "DisplayLabels", uno::Any( true ) );
+ }
+}
+
+void AxisHelper::makeGridVisible( const rtl::Reference< GridProperties >& xGridProperties )
+{
+ if( xGridProperties.is() )
+ {
+ xGridProperties->setPropertyValue( "Show", uno::Any( true ) );
+ LinePropertiesHelper::SetLineVisible( xGridProperties );
+ }
+}
+
+void AxisHelper::hideAxis( sal_Int32 nDimensionIndex, bool bMainAxis
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ AxisHelper::makeAxisInvisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
+}
+
+void AxisHelper::makeAxisInvisible( const rtl::Reference< Axis >& xAxis )
+{
+ if( xAxis.is() )
+ {
+ xAxis->setPropertyValue( "Show", uno::Any( false ) );
+ }
+}
+
+void AxisHelper::hideAxisIfNoDataIsAttached( const rtl::Reference< Axis >& xAxis, const rtl::Reference< Diagram >& xDiagram )
+{
+ //axis is hidden if no data is attached anymore but data is available
+ bool bOtherSeriesAttachedToThisAxis = false;
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector = xDiagram->getDataSeries();
+ for (auto const& series : aSeriesVector)
+ {
+ rtl::Reference< Axis > xCurrentAxis = xDiagram->getAttachedAxis(series);
+ if( xCurrentAxis==xAxis )
+ {
+ bOtherSeriesAttachedToThisAxis = true;
+ break;
+ }
+ }
+ if(!bOtherSeriesAttachedToThisAxis && !aSeriesVector.empty() )
+ AxisHelper::makeAxisInvisible( xAxis );
+}
+
+void AxisHelper::hideGrid( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ if( !xDiagram.is() )
+ return;
+
+ rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
+ if(!xCooSys.is())
+ return;
+
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys );
+ if(!xAxis.is())
+ return;
+
+ if( bMainGrid )
+ AxisHelper::makeGridInvisible( xAxis->getGridProperties2() );
+ else
+ {
+ std::vector< rtl::Reference< ::chart::GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
+ for( auto const & i : aSubGrids)
+ AxisHelper::makeGridInvisible( i );
+ }
+}
+
+void AxisHelper::makeGridInvisible( const rtl::Reference< ::chart::GridProperties >& xGridProperties )
+{
+ if( xGridProperties.is() )
+ {
+ xGridProperties->setPropertyValue( "Show", uno::Any( false ) );
+ }
+}
+
+bool AxisHelper::isGridShown( sal_Int32 nDimensionIndex, sal_Int32 nCooSysIndex, bool bMainGrid
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ bool bRet = false;
+
+ rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, nCooSysIndex );
+ if(!xCooSys.is())
+ return bRet;
+
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, MAIN_AXIS_INDEX, xCooSys );
+ if(!xAxis.is())
+ return bRet;
+
+ if( bMainGrid )
+ bRet = AxisHelper::isGridVisible( xAxis->getGridProperties2() );
+ else
+ {
+ std::vector< rtl::Reference< ::chart::GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
+ if( !aSubGrids.empty() )
+ bRet = AxisHelper::isGridVisible( aSubGrids[0] );
+ }
+
+ return bRet;
+}
+
+rtl::Reference< ::chart::BaseCoordinateSystem > AxisHelper::getCoordinateSystemByIndex(
+ const rtl::Reference< Diagram >& xDiagram, sal_Int32 nIndex )
+{
+ if(!xDiagram.is())
+ return nullptr;
+ auto aCooSysList = xDiagram->getBaseCoordinateSystems();
+ if(0<=nIndex && o3tl::make_unsigned(nIndex) < aCooSysList.size())
+ return aCooSysList[nIndex];
+ return nullptr;
+}
+
+rtl::Reference< Axis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, bool bMainAxis
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ rtl::Reference< Axis > xRet;
+ try
+ {
+ rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 );
+ xRet = AxisHelper::getAxis( nDimensionIndex, bMainAxis ? 0 : 1, xCooSys );
+ }
+ catch( const uno::Exception & )
+ {
+ }
+ return xRet;
+}
+
+rtl::Reference< Axis > AxisHelper::getAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex
+ , const rtl::Reference< BaseCoordinateSystem >& xCooSys )
+{
+ rtl::Reference< Axis > xRet;
+ if(!xCooSys.is())
+ return xRet;
+
+ if(nDimensionIndex >= xCooSys->getDimension())
+ return xRet;
+
+ if(nAxisIndex > xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex))
+ return xRet;
+
+ assert(nAxisIndex >= 0);
+ assert(nDimensionIndex >= 0);
+ xRet = xCooSys->getAxisByDimension2( nDimensionIndex, nAxisIndex );
+ return xRet;
+}
+
+rtl::Reference< Axis > AxisHelper::getCrossingMainAxis( const rtl::Reference< Axis >& xAxis
+ , const rtl::Reference< BaseCoordinateSystem >& xCooSys )
+{
+ sal_Int32 nDimensionIndex = 0;
+ sal_Int32 nAxisIndex = 0;
+ AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex );
+ if( nDimensionIndex==2 )
+ {
+ nDimensionIndex=1;
+ bool bSwapXY = false;
+ if( (xCooSys->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXY) && bSwapXY )
+ nDimensionIndex=0;
+ }
+ else if( nDimensionIndex==1 )
+ nDimensionIndex=0;
+ else
+ nDimensionIndex=1;
+ return AxisHelper::getAxis( nDimensionIndex, 0, xCooSys );
+}
+
+rtl::Reference< Axis > AxisHelper::getParallelAxis( const rtl::Reference< Axis >& xAxis
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ try
+ {
+ sal_Int32 nCooSysIndex=-1;
+ sal_Int32 nDimensionIndex=-1;
+ sal_Int32 nAxisIndex=-1;
+ if( getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex ) )
+ {
+ sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
+ return getAxis( nDimensionIndex, nParallelAxisIndex, getCoordinateSystemByIndex( xDiagram, nCooSysIndex ) );
+ }
+ }
+ catch( const uno::RuntimeException& )
+ {
+ }
+ return nullptr;
+}
+
+bool AxisHelper::isAxisShown( sal_Int32 nDimensionIndex, bool bMainAxis
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ return AxisHelper::isAxisVisible( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) );
+}
+
+bool AxisHelper::isAxisVisible( const rtl::Reference< Axis >& xAxis )
+{
+ bool bRet = false;
+
+ if( xAxis.is() )
+ {
+ xAxis->getPropertyValue( "Show" ) >>= bRet;
+ bRet = bRet && ( LinePropertiesHelper::IsLineVisible( xAxis )
+ || areAxisLabelsVisible( xAxis ) );
+ }
+
+ return bRet;
+}
+
+bool AxisHelper::areAxisLabelsVisible( const rtl::Reference< Axis >& xAxis )
+{
+ bool bRet = false;
+ if( xAxis.is() )
+ {
+ xAxis->getPropertyValue( "DisplayLabels" ) >>= bRet;
+ }
+ return bRet;
+}
+
+bool AxisHelper::isGridVisible( const rtl::Reference< ::chart::GridProperties >& xGridproperties )
+{
+ bool bRet = false;
+
+ if( xGridproperties.is() )
+ {
+ xGridproperties->getPropertyValue( "Show" ) >>= bRet;
+ bRet = bRet && LinePropertiesHelper::IsLineVisible( xGridproperties );
+ }
+
+ return bRet;
+}
+
+rtl::Reference< GridProperties > AxisHelper::getGridProperties(
+ const rtl::Reference< BaseCoordinateSystem >& xCooSys
+ , sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex, sal_Int32 nSubGridIndex )
+{
+ rtl::Reference< GridProperties > xRet;
+
+ rtl::Reference< Axis > xAxis( AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ) );
+ if( xAxis.is() )
+ {
+ if( nSubGridIndex<0 )
+ xRet = xAxis->getGridProperties2();
+ else
+ {
+ std::vector< rtl::Reference< GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
+ if (nSubGridIndex < static_cast<sal_Int32>(aSubGrids.size()))
+ xRet = aSubGrids[nSubGridIndex];
+ }
+ }
+
+ return xRet;
+}
+
+sal_Int32 AxisHelper::getDimensionIndexOfAxis(
+ const rtl::Reference< Axis >& xAxis
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ sal_Int32 nDimensionIndex = -1;
+ sal_Int32 nCooSysIndex = -1;
+ sal_Int32 nAxisIndex = -1;
+ AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex , nDimensionIndex, nAxisIndex );
+ return nDimensionIndex;
+}
+
+bool AxisHelper::getIndicesForAxis(
+ const rtl::Reference< Axis >& xAxis
+ , const rtl::Reference< BaseCoordinateSystem >& xCooSys
+ , sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
+{
+ //returns true if indices are found
+
+ rOutDimensionIndex = -1;
+ rOutAxisIndex = -1;
+
+ if( !xCooSys || !xAxis )
+ return false;
+
+ rtl::Reference< Axis > xCurrentAxis;
+ sal_Int32 nDimensionCount( xCooSys->getDimension() );
+ for( sal_Int32 nDimensionIndex = 0; nDimensionIndex < nDimensionCount; nDimensionIndex++ )
+ {
+ sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ )
+ {
+ xCurrentAxis = xCooSys->getAxisByDimension2(nDimensionIndex,nAxisIndex);
+ if( xCurrentAxis == xAxis )
+ {
+ rOutDimensionIndex = nDimensionIndex;
+ rOutAxisIndex = nAxisIndex;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool AxisHelper::getIndicesForAxis( const rtl::Reference< Axis >& xAxis, const rtl::Reference< Diagram >& xDiagram
+ , sal_Int32& rOutCooSysIndex, sal_Int32& rOutDimensionIndex, sal_Int32& rOutAxisIndex )
+{
+ //returns true if indices are found
+
+ rOutCooSysIndex = -1;
+ rOutDimensionIndex = -1;
+ rOutAxisIndex = -1;
+
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysList = xDiagram->getBaseCoordinateSystems();
+ for( std::size_t nC=0; nC < aCooSysList.size(); ++nC )
+ {
+ if( AxisHelper::getIndicesForAxis( xAxis, aCooSysList[nC], rOutDimensionIndex, rOutAxisIndex ) )
+ {
+ rOutCooSysIndex = nC;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+std::vector< rtl::Reference< Axis > > AxisHelper::getAllAxesOfCoordinateSystem(
+ const rtl::Reference< BaseCoordinateSystem >& xCooSys
+ , bool bOnlyVisible /* = false */ )
+{
+ std::vector< rtl::Reference< Axis > > aAxisVector;
+
+ if(xCooSys.is())
+ {
+ sal_Int32 nMaxDimensionIndex = xCooSys->getDimension() -1;
+ if( nMaxDimensionIndex>=0 )
+ {
+ sal_Int32 nDimensionIndex = 0;
+ for(; nDimensionIndex<=nMaxDimensionIndex; ++nDimensionIndex)
+ {
+ const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
+ {
+ try
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2( nDimensionIndex, nAxisIndex );
+ if( xAxis.is() )
+ {
+ bool bAddAxis = true;
+ if( bOnlyVisible )
+ {
+ if( !(xAxis->getPropertyValue( "Show") >>= bAddAxis) )
+ bAddAxis = false;
+ }
+ if( bAddAxis )
+ aAxisVector.push_back( xAxis );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ }
+ }
+
+ return aAxisVector;
+}
+
+std::vector< rtl::Reference< Axis > > AxisHelper::getAllAxesOfDiagram(
+ const rtl::Reference< Diagram >& xDiagram
+ , bool bOnlyVisible )
+{
+ std::vector< rtl::Reference< Axis > > aAxisVector;
+
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : xDiagram->getBaseCoordinateSystems() )
+ {
+ std::vector< rtl::Reference< Axis > > aAxesPerCooSys = AxisHelper::getAllAxesOfCoordinateSystem( coords, bOnlyVisible );
+ aAxisVector.insert( aAxisVector.end(), aAxesPerCooSys.begin(), aAxesPerCooSys.end() );
+ }
+
+ return aAxisVector;
+}
+
+std::vector< rtl::Reference< GridProperties > > AxisHelper::getAllGrids( const rtl::Reference< Diagram >& xDiagram )
+{
+ const std::vector< rtl::Reference< Axis > > aAllAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
+ std::vector< rtl::Reference< GridProperties > > aGridVector;
+
+ for( rtl::Reference< Axis > const & xAxis : aAllAxes )
+ {
+ rtl::Reference< GridProperties > xGridProperties( xAxis->getGridProperties2() );
+ if( xGridProperties.is() )
+ aGridVector.push_back( xGridProperties );
+
+ std::vector< rtl::Reference< GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
+ for( rtl::Reference< GridProperties > const & xSubGrid : aSubGrids )
+ {
+ if( xSubGrid.is() )
+ aGridVector.push_back( xSubGrid );
+ }
+ }
+
+ return aGridVector;
+}
+
+void AxisHelper::getAxisOrGridPossibilities( Sequence< sal_Bool >& rPossibilityList
+ , const rtl::Reference< Diagram>& xDiagram, bool bAxis )
+{
+ rPossibilityList.realloc(6);
+ sal_Bool* pPossibilityList = rPossibilityList.getArray();
+
+ sal_Int32 nDimensionCount = -1;
+ if (xDiagram)
+ nDimensionCount = xDiagram->getDimension();
+
+ //set possibilities:
+ sal_Int32 nIndex=0;
+ rtl::Reference< ChartType > xChartType;
+ if (xDiagram)
+ xChartType = xDiagram->getChartTypeByIndex( 0 );
+ for(nIndex=0;nIndex<3;nIndex++)
+ pPossibilityList[nIndex]=ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nIndex);
+ for(nIndex=3;nIndex<6;nIndex++)
+ if( bAxis )
+ pPossibilityList[nIndex]=ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount);
+ else
+ pPossibilityList[nIndex] = rPossibilityList[nIndex-3];
+}
+
+bool AxisHelper::isSecondaryYAxisNeeded( const rtl::Reference< BaseCoordinateSystem >& xCooSys )
+{
+ if( !xCooSys.is() )
+ return false;
+
+ const std::vector< rtl::Reference< ChartType > > & aChartTypes( xCooSys->getChartTypes2() );
+ for( rtl::Reference< ChartType > const & chartType : aChartTypes )
+ {
+ const std::vector< rtl::Reference< DataSeries > > & aSeriesList = chartType->getDataSeries2();
+ for( sal_Int32 nS = aSeriesList.size(); nS-- ; )
+ {
+ sal_Int32 nAttachedAxisIndex = 0;
+ if( ( aSeriesList[nS]->getPropertyValue( "AttachedAxisIndex" ) >>= nAttachedAxisIndex ) &&
+ nAttachedAxisIndex>0 )
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AxisHelper::shouldAxisBeDisplayed( const rtl::Reference< Axis >& xAxis
+ , const rtl::Reference< BaseCoordinateSystem >& xCooSys )
+{
+ bool bRet = false;
+
+ if( xAxis.is() && xCooSys.is() )
+ {
+ sal_Int32 nDimensionIndex=-1;
+ sal_Int32 nAxisIndex=-1;
+ if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
+ {
+ sal_Int32 nDimensionCount = xCooSys->getDimension();
+ rtl::Reference< ChartType > xChartType( AxisHelper::getChartTypeByIndex( xCooSys, 0 ) );
+
+ bool bMainAxis = (nAxisIndex==MAIN_AXIS_INDEX);
+ if( bMainAxis )
+ bRet = ChartTypeHelper::isSupportingMainAxis(xChartType,nDimensionCount,nDimensionIndex);
+ else
+ bRet = ChartTypeHelper::isSupportingSecondaryAxis(xChartType,nDimensionCount);
+ }
+ }
+
+ return bRet;
+}
+
+void AxisHelper::getAxisOrGridExistence( Sequence< sal_Bool >& rExistenceList
+ , const rtl::Reference< Diagram>& xDiagram, bool bAxis )
+{
+ rExistenceList.realloc(6);
+ sal_Bool* pExistenceList = rExistenceList.getArray();
+
+ if(bAxis)
+ {
+ sal_Int32 nN;
+ for(nN=0;nN<3;nN++)
+ pExistenceList[nN] = AxisHelper::isAxisShown( nN, true, xDiagram );
+ for(nN=3;nN<6;nN++)
+ pExistenceList[nN] = AxisHelper::isAxisShown( nN%3, false, xDiagram );
+ }
+ else
+ {
+ sal_Int32 nN;
+
+ for(nN=0;nN<3;nN++)
+ pExistenceList[nN] = AxisHelper::isGridShown( nN, 0, true, xDiagram );
+ for(nN=3;nN<6;nN++)
+ pExistenceList[nN] = AxisHelper::isGridShown( nN%3, 0, false, xDiagram );
+ }
+}
+
+bool AxisHelper::changeVisibilityOfAxes( const rtl::Reference< Diagram >& xDiagram
+ , const Sequence< sal_Bool >& rOldExistenceList
+ , const Sequence< sal_Bool >& rNewExistenceList
+ , const Reference< uno::XComponentContext >& xContext
+ , ReferenceSizeProvider * pRefSizeProvider )
+{
+ bool bChanged = false;
+ for(sal_Int32 nN=0;nN<6;nN++)
+ {
+ if(rOldExistenceList[nN]!=rNewExistenceList[nN])
+ {
+ bChanged = true;
+ if(rNewExistenceList[nN])
+ {
+ AxisHelper::showAxis( nN%3, nN<3, xDiagram, xContext, pRefSizeProvider );
+ }
+ else
+ AxisHelper::hideAxis( nN%3, nN<3, xDiagram );
+ }
+ }
+ return bChanged;
+}
+
+bool AxisHelper::changeVisibilityOfGrids( const rtl::Reference< Diagram >& xDiagram
+ , const Sequence< sal_Bool >& rOldExistenceList
+ , const Sequence< sal_Bool >& rNewExistenceList )
+{
+ bool bChanged = false;
+ for(sal_Int32 nN=0;nN<6;nN++)
+ {
+ if(rOldExistenceList[nN]!=rNewExistenceList[nN])
+ {
+ bChanged = true;
+ if(rNewExistenceList[nN])
+ AxisHelper::showGrid( nN%3, 0, nN<3, xDiagram );
+ else
+ AxisHelper::hideGrid( nN%3, 0, nN<3, xDiagram );
+ }
+ }
+ return bChanged;
+}
+
+rtl::Reference< BaseCoordinateSystem > AxisHelper::getCoordinateSystemOfAxis(
+ const rtl::Reference< Axis >& xAxis
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ if (!xDiagram)
+ return nullptr;
+
+ rtl::Reference< BaseCoordinateSystem > xRet;
+ for( rtl::Reference< BaseCoordinateSystem > const & xCooSys : xDiagram->getBaseCoordinateSystems() )
+ {
+ std::vector< rtl::Reference< Axis > > aAllAxis = AxisHelper::getAllAxesOfCoordinateSystem( xCooSys );
+
+ auto aFound = std::find( aAllAxis.begin(), aAllAxis.end(), xAxis );
+ if( aFound != aAllAxis.end())
+ {
+ xRet = xCooSys;
+ break;
+ }
+ }
+ return xRet;
+}
+
+rtl::Reference< ChartType > AxisHelper::getChartTypeByIndex( const rtl::Reference< BaseCoordinateSystem >& xCooSys, sal_Int32 nIndex )
+{
+ rtl::Reference< ChartType > xChartType;
+
+ if( xCooSys.is() )
+ {
+ const std::vector< rtl::Reference< ChartType > > aChartTypeList( xCooSys->getChartTypes2() );
+ if( nIndex >= 0 && o3tl::make_unsigned(nIndex) < aChartTypeList.size() )
+ xChartType = aChartTypeList[nIndex];
+ }
+
+ return xChartType;
+}
+
+void AxisHelper::setRTLAxisLayout( const rtl::Reference< BaseCoordinateSystem >& xCooSys )
+{
+ if( !xCooSys.is() )
+ return;
+
+ bool bCartesian = xCooSys->getViewServiceName() == CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME;
+ if( !bCartesian )
+ return;
+
+ bool bVertical = false;
+ xCooSys->getPropertyValue( "SwapXAndYAxis" ) >>= bVertical;
+
+ sal_Int32 nHorizontalAxisDimension = bVertical ? 1 : 0;
+ sal_Int32 nVerticalAxisDimension = bVertical ? 0 : 1;
+
+ try
+ {
+ //reverse direction for horizontal main axis
+ rtl::Reference< Axis > xHorizontalMainAxis = AxisHelper::getAxis( nHorizontalAxisDimension, MAIN_AXIS_INDEX, xCooSys );
+ if( xHorizontalMainAxis.is() )
+ {
+ chart2::ScaleData aScale = xHorizontalMainAxis->getScaleData();
+ aScale.Orientation = chart2::AxisOrientation_REVERSE;
+ xHorizontalMainAxis->setScaleData(aScale);
+ }
+
+ //mathematical direction for vertical main axis
+ rtl::Reference< Axis > xVerticalMainAxis = AxisHelper::getAxis( nVerticalAxisDimension, MAIN_AXIS_INDEX, xCooSys );
+ if( xVerticalMainAxis.is() )
+ {
+ chart2::ScaleData aScale = xVerticalMainAxis->getScaleData();
+ aScale.Orientation = chart2::AxisOrientation_MATHEMATICAL;
+ xVerticalMainAxis->setScaleData(aScale);
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+
+ try
+ {
+ //reverse direction for horizontal secondary axis
+ rtl::Reference< Axis > xHorizontalSecondaryAxis = AxisHelper::getAxis( nHorizontalAxisDimension, SECONDARY_AXIS_INDEX, xCooSys );
+ if( xHorizontalSecondaryAxis.is() )
+ {
+ chart2::ScaleData aScale = xHorizontalSecondaryAxis->getScaleData();
+ aScale.Orientation = chart2::AxisOrientation_REVERSE;
+ xHorizontalSecondaryAxis->setScaleData(aScale);
+ }
+
+ //mathematical direction for vertical secondary axis
+ rtl::Reference< Axis > xVerticalSecondaryAxis = AxisHelper::getAxis( nVerticalAxisDimension, SECONDARY_AXIS_INDEX, xCooSys );
+ if( xVerticalSecondaryAxis.is() )
+ {
+ chart2::ScaleData aScale = xVerticalSecondaryAxis->getScaleData();
+ aScale.Orientation = chart2::AxisOrientation_MATHEMATICAL;
+ xVerticalSecondaryAxis->setScaleData(aScale);
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+rtl::Reference< ChartType > AxisHelper::getFirstChartTypeWithSeriesAttachedToAxisIndex( const rtl::Reference< Diagram >& xDiagram, const sal_Int32 nAttachedAxisIndex )
+{
+ rtl::Reference< ChartType > xChartType;
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector = xDiagram->getDataSeries();
+ for (auto const& series : aSeriesVector)
+ {
+ sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex(series);
+ if( nAttachedAxisIndex == nCurrentIndex )
+ {
+ xChartType = xDiagram->getChartTypeOfSeries(series);
+ if(xChartType.is())
+ break;
+ }
+ }
+ return xChartType;
+}
+
+bool AxisHelper::isAxisPositioningEnabled()
+{
+ const SvtSaveOptions::ODFSaneDefaultVersion nCurrentVersion(GetODFSaneDefaultVersion());
+ return nCurrentVersion >= SvtSaveOptions::ODFSVER_012;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/BaseGFXHelper.cxx b/chart2/source/tools/BaseGFXHelper.cxx
new file mode 100644
index 0000000000..17bd4f5e18
--- /dev/null
+++ b/chart2/source/tools/BaseGFXHelper.cxx
@@ -0,0 +1,236 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <BaseGFXHelper.hxx>
+#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::drawing;
+using namespace ::basegfx;
+
+namespace chart::BaseGFXHelper
+{
+
+::basegfx::B3DRange getBoundVolume( const drawing::PolyPolygonShape3D& rPolyPoly )
+{
+ ::basegfx::B3DRange aRet;
+
+ bool bInited = false;
+ sal_Int32 nPolyCount = rPolyPoly.SequenceX.getLength();
+ for(sal_Int32 nPoly = 0; nPoly < nPolyCount; nPoly++)
+ {
+ sal_Int32 nPointCount = rPolyPoly.SequenceX[nPoly].getLength();
+ for( sal_Int32 nPoint = 0; nPoint < nPointCount; nPoint++)
+ {
+ if(!bInited)
+ {
+ aRet = ::basegfx::B3DRange(::basegfx::B3DTuple(
+ rPolyPoly.SequenceX[nPoly][nPoint]
+ , rPolyPoly.SequenceY[nPoly][nPoint]
+ , rPolyPoly.SequenceZ[nPoly][nPoint]));
+ bInited = true;
+ }
+ else
+ {
+ aRet.expand( ::basegfx::B3DTuple(
+ rPolyPoly.SequenceX[nPoly][nPoint]
+ , rPolyPoly.SequenceY[nPoly][nPoint]
+ , rPolyPoly.SequenceZ[nPoly][nPoint]));
+ }
+ }
+ }
+
+ return aRet;
+}
+
+::basegfx::B3DRange getBoundVolume( const std::vector<std::vector<css::drawing::Position3D>>& rPolyPoly )
+{
+ ::basegfx::B3DRange aRet;
+
+ bool bInited = false;
+ sal_Int32 nPolyCount = rPolyPoly.size();
+ for(sal_Int32 nPoly = 0; nPoly < nPolyCount; nPoly++)
+ {
+ sal_Int32 nPointCount = rPolyPoly[nPoly].size();
+ for( sal_Int32 nPoint = 0; nPoint < nPointCount; nPoint++)
+ {
+ if(!bInited)
+ {
+ aRet = ::basegfx::B3DRange(::basegfx::B3DTuple(
+ rPolyPoly[nPoly][nPoint].PositionX
+ , rPolyPoly[nPoly][nPoint].PositionY
+ , rPolyPoly[nPoly][nPoint].PositionZ));
+ bInited = true;
+ }
+ else
+ {
+ aRet.expand( ::basegfx::B3DTuple(
+ rPolyPoly[nPoly][nPoint].PositionX
+ , rPolyPoly[nPoly][nPoint].PositionY
+ , rPolyPoly[nPoly][nPoint].PositionZ));
+ }
+ }
+ }
+
+ return aRet;
+}
+
+B2IRectangle makeRectangle( const awt::Point& rPos, const awt::Size& rSize )
+{
+ return B2IRectangle(rPos.X,rPos.Y,rPos.X+rSize.Width,rPos.Y+rSize.Height);
+}
+
+B2IRectangle makeRectangle( const awt::Rectangle& rRect )
+{
+ return B2IRectangle(rRect.X, rRect.Y, rRect.X+rRect.Width, rRect.Y+rRect.Height);
+}
+
+awt::Point B2IRectangleToAWTPoint( const ::basegfx::B2IRectangle& rB2IRectangle )
+{
+ return awt::Point( rB2IRectangle.getMinX(), rB2IRectangle.getMinY() );
+}
+
+awt::Size B2IRectangleToAWTSize( const ::basegfx::B2IRectangle& rB2IRectangle )
+{
+ return awt::Size( static_cast< sal_Int32 >( rB2IRectangle.getWidth()),
+ static_cast< sal_Int32 >( rB2IRectangle.getHeight()));
+}
+
+awt::Rectangle toAwtRectangle(const basegfx::B2IRectangle& rRectangle)
+{
+ return awt::Rectangle(rRectangle.getMinX(), rRectangle.getMinY(),
+ rRectangle.getWidth(), rRectangle.getHeight());
+}
+
+B3DVector Direction3DToB3DVector( const Direction3D& rDirection )
+{
+ return B3DVector(
+ rDirection.DirectionX
+ , rDirection.DirectionY
+ , rDirection.DirectionZ
+ );
+}
+
+Direction3D B3DVectorToDirection3D( const B3DVector& rB3DVector )
+{
+ return Direction3D(
+ rB3DVector.getX()
+ , rB3DVector.getY()
+ , rB3DVector.getZ()
+ );
+}
+
+B3DVector Position3DToB3DVector( const Position3D& rPosition )
+{
+ return B3DVector(
+ rPosition.PositionX
+ , rPosition.PositionY
+ , rPosition.PositionZ
+ );
+}
+
+Position3D B3DVectorToPosition3D( const B3DVector& rB3DVector )
+{
+ return Position3D(
+ rB3DVector.getX()
+ , rB3DVector.getY()
+ , rB3DVector.getZ()
+ );
+}
+
+B3DHomMatrix HomogenMatrixToB3DHomMatrix( const HomogenMatrix & rHomogenMatrix )
+{
+ B3DHomMatrix aResult;
+
+ aResult.set( 0, 0, rHomogenMatrix.Line1.Column1 );
+ aResult.set( 0, 1, rHomogenMatrix.Line1.Column2 );
+ aResult.set( 0, 2, rHomogenMatrix.Line1.Column3 );
+ aResult.set( 0, 3, rHomogenMatrix.Line1.Column4 );
+
+ aResult.set( 1, 0, rHomogenMatrix.Line2.Column1 );
+ aResult.set( 1, 1, rHomogenMatrix.Line2.Column2 );
+ aResult.set( 1, 2, rHomogenMatrix.Line2.Column3 );
+ aResult.set( 1, 3, rHomogenMatrix.Line2.Column4 );
+
+ aResult.set( 2, 0, rHomogenMatrix.Line3.Column1 );
+ aResult.set( 2, 1, rHomogenMatrix.Line3.Column2 );
+ aResult.set( 2, 2, rHomogenMatrix.Line3.Column3 );
+ aResult.set( 2, 3, rHomogenMatrix.Line3.Column4 );
+
+ aResult.set( 3, 0, rHomogenMatrix.Line4.Column1 );
+ aResult.set( 3, 1, rHomogenMatrix.Line4.Column2 );
+ aResult.set( 3, 2, rHomogenMatrix.Line4.Column3 );
+ aResult.set( 3, 3, rHomogenMatrix.Line4.Column4 );
+
+ return aResult;
+}
+
+HomogenMatrix B3DHomMatrixToHomogenMatrix( const B3DHomMatrix & rB3DMatrix )
+{
+ HomogenMatrix aResult;
+
+ aResult.Line1.Column1 = rB3DMatrix.get( 0, 0 );
+ aResult.Line1.Column2 = rB3DMatrix.get( 0, 1 );
+ aResult.Line1.Column3 = rB3DMatrix.get( 0, 2 );
+ aResult.Line1.Column4 = rB3DMatrix.get( 0, 3 );
+
+ aResult.Line2.Column1 = rB3DMatrix.get( 1, 0 );
+ aResult.Line2.Column2 = rB3DMatrix.get( 1, 1 );
+ aResult.Line2.Column3 = rB3DMatrix.get( 1, 2 );
+ aResult.Line2.Column4 = rB3DMatrix.get( 1, 3 );
+
+ aResult.Line3.Column1 = rB3DMatrix.get( 2, 0 );
+ aResult.Line3.Column2 = rB3DMatrix.get( 2, 1 );
+ aResult.Line3.Column3 = rB3DMatrix.get( 2, 2 );
+ aResult.Line3.Column4 = rB3DMatrix.get( 2, 3 );
+
+ aResult.Line4.Column1 = rB3DMatrix.get( 3, 0 );
+ aResult.Line4.Column2 = rB3DMatrix.get( 3, 1 );
+ aResult.Line4.Column3 = rB3DMatrix.get( 3, 2 );
+ aResult.Line4.Column4 = rB3DMatrix.get( 3, 3 );
+
+ return aResult;
+}
+
+B3DTuple GetRotationFromMatrix( const B3DHomMatrix & rB3DMatrix )
+{
+ B3DTuple aScale, aTranslation, aRotation, aShearing;
+ rB3DMatrix.decompose( aScale, aTranslation, aRotation, aShearing );
+ return aRotation;
+}
+
+B3DTuple GetScaleFromMatrix( const B3DHomMatrix & rB3DMatrix )
+{
+ B3DTuple aScale, aTranslation, aRotation, aShearing;
+ rB3DMatrix.decompose( aScale, aTranslation, aRotation, aShearing );
+ return aScale;
+}
+
+void ReduceToRotationMatrix( ::basegfx::B3DHomMatrix & rB3DMatrix )
+{
+ B3DTuple aR( GetRotationFromMatrix( rB3DMatrix ) );
+ ::basegfx::B3DHomMatrix aRotationMatrix;
+ aRotationMatrix.rotate(aR.getX(),aR.getY(),aR.getZ());
+ rB3DMatrix = aRotationMatrix;
+}
+
+} // namespace chart::BaseGFXHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/CachedDataSequence.cxx b/chart2/source/tools/CachedDataSequence.cxx
new file mode 100644
index 0000000000..23f5add5f8
--- /dev/null
+++ b/chart2/source/tools/CachedDataSequence.cxx
@@ -0,0 +1,350 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <CachedDataSequence.hxx>
+#include <CommonFunctors.hxx>
+#include <ModifyListenerHelper.hxx>
+
+#include <comphelper/sequenceashashmap.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::osl::MutexGuard;
+
+// necessary for MS compiler
+using ::comphelper::OPropertyContainer;
+using ::chart::impl::CachedDataSequence_Base;
+
+namespace
+{
+constexpr OUString lcl_aServiceName = u"com.sun.star.comp.chart.CachedDataSequence"_ustr;
+
+enum
+{
+// PROP_SOURCE_IDENTIFIER,
+ PROP_NUMBERFORMAT_KEY,
+ PROP_PROPOSED_ROLE
+};
+} // anonymous namespace
+
+namespace chart
+{
+
+CachedDataSequence::CachedDataSequence()
+ : OPropertyContainer( GetBroadcastHelper()),
+ CachedDataSequence_Base( GetMutex()),
+ m_eCurrentDataType( NUMERICAL ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ registerProperties();
+}
+CachedDataSequence::CachedDataSequence( const Reference< uno::XComponentContext > & /*xContext*/ )
+ : OPropertyContainer( GetBroadcastHelper()),
+ CachedDataSequence_Base( GetMutex()),
+ m_eCurrentDataType( MIXED ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ registerProperties();
+}
+
+CachedDataSequence::CachedDataSequence( const OUString & rSingleText )
+ : OPropertyContainer( GetBroadcastHelper()),
+ CachedDataSequence_Base( GetMutex()),
+ m_eCurrentDataType( TEXTUAL ),
+ m_aTextualSequence({rSingleText}),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ registerProperties();
+}
+
+CachedDataSequence::CachedDataSequence( const CachedDataSequence & rSource )
+ : OPropertyContainer( GetBroadcastHelper()),
+ CachedDataSequence_Base( GetMutex()),
+ m_nNumberFormatKey( rSource.m_nNumberFormatKey ),
+ m_sRole( rSource.m_sRole ),
+ m_eCurrentDataType( rSource.m_eCurrentDataType ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ switch( m_eCurrentDataType )
+ {
+ case TEXTUAL:
+ m_aTextualSequence = rSource.m_aTextualSequence;
+ break;
+ case NUMERICAL:
+ m_aNumericalSequence = rSource.m_aNumericalSequence;
+ break;
+ case MIXED:
+ m_aMixedSequence = rSource.m_aMixedSequence;
+ break;
+ }
+
+ registerProperties();
+}
+
+CachedDataSequence::~CachedDataSequence()
+{}
+
+void CachedDataSequence::registerProperties()
+{
+ registerProperty( "NumberFormatKey",
+ PROP_NUMBERFORMAT_KEY,
+ 0, // PropertyAttributes
+ & m_nNumberFormatKey,
+ cppu::UnoType<decltype(m_nNumberFormatKey)>::get() );
+
+ registerProperty( "Role",
+ PROP_PROPOSED_ROLE,
+ 0, // PropertyAttributes
+ & m_sRole,
+ cppu::UnoType<decltype(m_sRole)>::get() );
+}
+
+Sequence< double > CachedDataSequence::Impl_getNumericalData() const
+{
+ if( m_eCurrentDataType == NUMERICAL )
+ return m_aNumericalSequence;
+
+ sal_Int32 nSize = ( m_eCurrentDataType == TEXTUAL )
+ ? m_aTextualSequence.getLength()
+ : m_aMixedSequence.getLength();
+
+ Sequence< double > aResult( nSize );
+ double * pResultArray = aResult.getArray();
+
+ if( m_eCurrentDataType == TEXTUAL )
+ {
+ const OUString * pTextArray = m_aTextualSequence.getConstArray();
+ std::transform( pTextArray, pTextArray + nSize,
+ pResultArray,
+ CommonFunctors::OUStringToDouble() );
+ }
+ else
+ {
+ OSL_ASSERT( m_eCurrentDataType == MIXED );
+ const Any * pMixedArray = m_aMixedSequence.getConstArray();
+ std::transform( pMixedArray, pMixedArray + nSize,
+ pResultArray,
+ CommonFunctors::AnyToDouble() );
+ }
+ return aResult;
+}
+
+Sequence< OUString > CachedDataSequence::Impl_getTextualData() const
+{
+ if( m_eCurrentDataType == TEXTUAL )
+ return m_aTextualSequence;
+
+ sal_Int32 nSize = ( m_eCurrentDataType == NUMERICAL )
+ ? m_aNumericalSequence.getLength()
+ : m_aMixedSequence.getLength();
+
+ Sequence< OUString > aResult( nSize );
+ OUString * pResultArray = aResult.getArray();
+
+ if( m_eCurrentDataType == NUMERICAL )
+ {
+ const double * pTextArray = m_aNumericalSequence.getConstArray();
+ std::transform( pTextArray, pTextArray + nSize,
+ pResultArray,
+ CommonFunctors::DoubleToOUString() );
+ }
+ else
+ {
+ OSL_ASSERT( m_eCurrentDataType == MIXED );
+ const Any * pMixedArray = m_aMixedSequence.getConstArray();
+ std::transform( pMixedArray, pMixedArray + nSize,
+ pResultArray,
+ CommonFunctors::AnyToString() );
+ }
+
+ return aResult;
+}
+
+Sequence< Any > CachedDataSequence::Impl_getMixedData() const
+{
+ if( m_eCurrentDataType == MIXED )
+ return m_aMixedSequence;
+
+ sal_Int32 nSize = ( m_eCurrentDataType == NUMERICAL )
+ ? m_aNumericalSequence.getLength()
+ : m_aTextualSequence.getLength();
+
+ Sequence< Any > aResult( nSize );
+ Any * pResultArray = aResult.getArray();
+
+ if( m_eCurrentDataType == NUMERICAL )
+ {
+ const double * pTextArray = m_aNumericalSequence.getConstArray();
+ std::transform( pTextArray, pTextArray + nSize,
+ pResultArray,
+ CommonFunctors::makeAny< double >() );
+ }
+ else
+ {
+ OSL_ASSERT( m_eCurrentDataType == TEXTUAL );
+ const OUString * pMixedArray = m_aTextualSequence.getConstArray();
+ std::transform( pMixedArray, pMixedArray + nSize,
+ pResultArray,
+ CommonFunctors::makeAny< OUString >() );
+ }
+
+ return aResult;
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( CachedDataSequence, CachedDataSequence_Base, OPropertyContainer )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( CachedDataSequence, CachedDataSequence_Base, OPropertyContainer )
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL CachedDataSequence::getPropertySetInfo()
+{
+ return createPropertySetInfo( getInfoHelper() );
+}
+
+// ____ ::comphelper::OPropertySetHelper ____
+::cppu::IPropertyArrayHelper& CachedDataSequence::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+// ____ ::comphelper::OPropertyArrayHelper ____
+::cppu::IPropertyArrayHelper* CachedDataSequence::createArrayHelper() const
+{
+ Sequence< beans::Property > aProps;
+ // describes all properties which have been registered in the ctor
+ describeProperties( aProps );
+
+ return new ::cppu::OPropertyArrayHelper( aProps );
+}
+
+OUString SAL_CALL CachedDataSequence::getImplementationName()
+{
+ return lcl_aServiceName;
+}
+
+sal_Bool SAL_CALL CachedDataSequence::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL CachedDataSequence::getSupportedServiceNames()
+{
+ return {
+ lcl_aServiceName,
+ "com.sun.star.chart2.data.DataSequence",
+ "com.sun.star.chart2.data.NumericalDataSequence",
+ "com.sun.star.chart2.data.TextualDataSequence"
+ };
+}
+
+// ________ XNumericalDataSequence ________
+Sequence< double > SAL_CALL CachedDataSequence::getNumericalData()
+{
+ MutexGuard aGuard( GetMutex() );
+
+ if( m_eCurrentDataType == NUMERICAL )
+ return m_aNumericalSequence;
+ else
+ return Impl_getNumericalData();
+}
+
+// ________ XTextualDataSequence ________
+Sequence< OUString > SAL_CALL CachedDataSequence::getTextualData()
+{
+ MutexGuard aGuard( GetMutex() );
+
+ if( m_eCurrentDataType == TEXTUAL )
+ return m_aTextualSequence;
+ else
+ return Impl_getTextualData();
+}
+
+// ________ XDataSequence ________
+Sequence< Any > SAL_CALL CachedDataSequence::getData()
+{
+ MutexGuard aGuard( GetMutex() );
+ return Impl_getMixedData();
+}
+
+OUString SAL_CALL CachedDataSequence::getSourceRangeRepresentation()
+{
+ return m_sRole;
+}
+
+Sequence< OUString > SAL_CALL CachedDataSequence::generateLabel( chart2::data::LabelOrigin /*eLabelOrigin*/ )
+{
+ // return empty label, as we have no range representations to determine something useful
+ return Sequence< OUString >();
+}
+
+::sal_Int32 SAL_CALL CachedDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ )
+{
+ return 0;
+}
+
+Reference< util::XCloneable > SAL_CALL CachedDataSequence::createClone()
+{
+ return new CachedDataSequence( *this );
+}
+
+void SAL_CALL CachedDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL CachedDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// lang::XInitialization:
+void SAL_CALL CachedDataSequence::initialize(const uno::Sequence< uno::Any > & _aArguments)
+{
+ ::comphelper::SequenceAsHashMap aMap(_aArguments);
+ m_aNumericalSequence = aMap.getUnpackedValueOrDefault( "DataSequence" ,m_aNumericalSequence);
+ if ( m_aNumericalSequence.hasElements() )
+ m_eCurrentDataType = NUMERICAL;
+ else
+ {
+ m_aTextualSequence = aMap.getUnpackedValueOrDefault( "DataSequence" ,m_aTextualSequence);
+ if ( m_aTextualSequence.hasElements() )
+ m_eCurrentDataType = TEXTUAL;
+ else
+ {
+ m_aMixedSequence = aMap.getUnpackedValueOrDefault( "DataSequence" ,m_aMixedSequence);
+ if ( m_aMixedSequence.hasElements() )
+ m_eCurrentDataType = MIXED;
+ }
+ }
+}
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_CachedDataSequence_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::CachedDataSequence(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/CharacterProperties.cxx b/chart2/source/tools/CharacterProperties.cxx
new file mode 100644
index 0000000000..7669d3245a
--- /dev/null
+++ b/chart2/source/tools/CharacterProperties.cxx
@@ -0,0 +1,460 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <CharacterProperties.hxx>
+
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/text/FontRelief.hpp>
+#include <com/sun/star/text/FontEmphasis.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <osl/diagnose.h>
+#include <unotools/lingucfg.hxx>
+#include <i18nlangtag/mslangid.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <tools/color.hxx>
+#include <vcl/outdev.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+
+namespace chart
+{
+
+void CharacterProperties::AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ // CharacterProperties
+ rOutProperties.emplace_back( "CharFontName",
+ PROP_CHAR_FONT_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "CharFontStyleName",
+ PROP_CHAR_FONT_STYLE_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+ // CharFontFamily (see awt.FontFamily)
+ rOutProperties.emplace_back( "CharFontFamily",
+ PROP_CHAR_FONT_FAMILY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharFontCharSet (see awt.CharSet)
+ rOutProperties.emplace_back( "CharFontCharSet",
+ PROP_CHAR_FONT_CHAR_SET,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharFontPitch (see awt.FontPitch)
+ rOutProperties.emplace_back( "CharFontPitch",
+ PROP_CHAR_FONT_PITCH,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharColor
+ rOutProperties.emplace_back( "CharColor",
+ PROP_CHAR_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharEscapement
+ rOutProperties.emplace_back( "CharEscapement",
+ PROP_CHAR_ESCAPEMENT,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ // CharHeight
+ rOutProperties.emplace_back( "CharHeight",
+ PROP_CHAR_CHAR_HEIGHT,
+ cppu::UnoType<float>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharUnderline (see awt.FontUnderline)
+ rOutProperties.emplace_back( "CharUnderline",
+ PROP_CHAR_UNDERLINE,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharUnderlineColor
+ rOutProperties.emplace_back( "CharUnderlineColor",
+ PROP_CHAR_UNDERLINE_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+ // CharUnderlineHasColor
+ rOutProperties.emplace_back( "CharUnderlineHasColor",
+ PROP_CHAR_UNDERLINE_HAS_COLOR,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharOverline (see awt.FontUnderline)
+ rOutProperties.emplace_back( "CharOverline",
+ PROP_CHAR_OVERLINE,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharOverlineColor
+ rOutProperties.emplace_back( "CharOverlineColor",
+ PROP_CHAR_OVERLINE_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+ // CharOverlineHasColor
+ rOutProperties.emplace_back( "CharOverlineHasColor",
+ PROP_CHAR_OVERLINE_HAS_COLOR,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharWeight (see awt.FontWeight)
+ rOutProperties.emplace_back( "CharWeight",
+ PROP_CHAR_WEIGHT,
+ cppu::UnoType<float>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharPosture
+ rOutProperties.emplace_back( "CharPosture",
+ PROP_CHAR_POSTURE,
+ cppu::UnoType<awt::FontSlant>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "CharAutoKerning",
+ PROP_CHAR_AUTO_KERNING,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "CharKerning",
+ PROP_CHAR_KERNING,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+ // CharEscapementHeight
+ rOutProperties.emplace_back( "CharEscapementHeight",
+ PROP_CHAR_ESCAPEMENT_HEIGHT,
+ cppu::UnoType<sal_Int8>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ // CharStrikeout (see awt.FontStrikeout)
+ rOutProperties.emplace_back( "CharStrikeout",
+ PROP_CHAR_STRIKE_OUT,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharWordMode
+ rOutProperties.emplace_back( "CharWordMode",
+ PROP_CHAR_WORD_MODE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharLocale
+ rOutProperties.emplace_back( "CharLocale",
+ PROP_CHAR_LOCALE,
+ cppu::UnoType<lang::Locale>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharShadowed
+ rOutProperties.emplace_back( "CharShadowed",
+ PROP_CHAR_SHADOWED,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharContoured
+ rOutProperties.emplace_back( "CharContoured",
+ PROP_CHAR_CONTOURED,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharRelief (see text.FontRelief)
+ rOutProperties.emplace_back( "CharRelief",
+ PROP_CHAR_RELIEF,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // CharEmphasize (see text.FontEmphasis)
+ rOutProperties.emplace_back( "CharEmphasis",
+ PROP_CHAR_EMPHASIS,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharacterPropertiesAsian
+
+ // CharFontNameAsian
+ rOutProperties.emplace_back( "CharFontNameAsian",
+ PROP_CHAR_ASIAN_FONT_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharFontStyleNameAsian
+ rOutProperties.emplace_back( "CharFontStyleNameAsian",
+ PROP_CHAR_ASIAN_FONT_STYLE_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+ // CharFontFamilyAsian (see awt.FontFamily)
+ rOutProperties.emplace_back( "CharFontFamilyAsian",
+ PROP_CHAR_ASIAN_FONT_FAMILY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharFontCharSetAsian (see awt.CharSet)
+ rOutProperties.emplace_back( "CharFontCharSetAsian",
+ PROP_CHAR_ASIAN_CHAR_SET,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharFontPitchAsian (see awt.FontPitch)
+ rOutProperties.emplace_back( "CharFontPitchAsian",
+ PROP_CHAR_ASIAN_FONT_PITCH,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharHeightAsian
+ rOutProperties.emplace_back( "CharHeightAsian",
+ PROP_CHAR_ASIAN_CHAR_HEIGHT,
+ cppu::UnoType<float>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharWeightAsian
+ rOutProperties.emplace_back( "CharWeightAsian",
+ PROP_CHAR_ASIAN_WEIGHT,
+ cppu::UnoType<float>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharPostureAsian
+ rOutProperties.emplace_back( "CharPostureAsian",
+ PROP_CHAR_ASIAN_POSTURE,
+ cppu::UnoType<awt::FontSlant>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharLocaleAsian
+ rOutProperties.emplace_back( "CharLocaleAsian",
+ PROP_CHAR_ASIAN_LOCALE,
+ cppu::UnoType<lang::Locale>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // CharacterPropertiesComplex
+
+ // CharFontNameComplex
+ rOutProperties.emplace_back( "CharFontNameComplex",
+ PROP_CHAR_COMPLEX_FONT_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharFontStyleNameComplex
+ rOutProperties.emplace_back( "CharFontStyleNameComplex",
+ PROP_CHAR_COMPLEX_FONT_STYLE_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+ // CharFontFamilyComplex (see awt.FontFamily)
+ rOutProperties.emplace_back( "CharFontFamilyComplex",
+ PROP_CHAR_COMPLEX_FONT_FAMILY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharFontCharSetComplex (see awt.CharSet)
+ rOutProperties.emplace_back( "CharFontCharSetComplex",
+ PROP_CHAR_COMPLEX_CHAR_SET,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharFontPitchComplex (see awt.FontPitch)
+ rOutProperties.emplace_back( "CharFontPitchComplex",
+ PROP_CHAR_COMPLEX_FONT_PITCH,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharHeightComplex
+ rOutProperties.emplace_back( "CharHeightComplex",
+ PROP_CHAR_COMPLEX_CHAR_HEIGHT,
+ cppu::UnoType<float>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharWeightComplex
+ rOutProperties.emplace_back( "CharWeightComplex",
+ PROP_CHAR_COMPLEX_WEIGHT,
+ cppu::UnoType<float>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharPostureComplex
+ rOutProperties.emplace_back( "CharPostureComplex",
+ PROP_CHAR_COMPLEX_POSTURE,
+ cppu::UnoType<awt::FontSlant>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // CharLocaleComplex
+ rOutProperties.emplace_back( "CharLocaleComplex",
+ PROP_CHAR_COMPLEX_LOCALE,
+ cppu::UnoType<lang::Locale>::get(),
+ //#i111967# no PropertyChangeEvent is fired on change so far
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // Writing Mode left to right vs right to left
+ rOutProperties.emplace_back( "WritingMode",
+ PROP_WRITING_MODE,
+ cppu::UnoType<sal_Int16>::get(), /*css::text::WritingMode2*/
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ParaIsCharacterDistance",
+ PROP_PARA_IS_CHARACTER_DISTANCE,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+void CharacterProperties::AddDefaultsToMap(
+ ::chart::tPropertyValueMap & rOutMap )
+{
+ const float fDefaultFontHeight = 13.0;
+
+ SvtLinguConfig aLinguConfig;
+ lang::Locale aDefaultLocale;
+ aLinguConfig.GetProperty(u"DefaultLocale") >>= aDefaultLocale;
+ lang::Locale aDefaultLocale_CJK;
+ aLinguConfig.GetProperty(u"DefaultLocale_CJK") >>= aDefaultLocale_CJK;
+ lang::Locale aDefaultLocale_CTL;
+ aLinguConfig.GetProperty(u"DefaultLocale_CTL") >>= aDefaultLocale_CTL;
+
+ using namespace ::com::sun::star::i18n::ScriptType;
+ LanguageType nLang;
+ nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aDefaultLocale, false), LATIN);
+ vcl::Font aFont = OutputDevice::GetDefaultFont( DefaultFontType::LATIN_SPREADSHEET, nLang, GetDefaultFontFlags::OnlyOne );
+ nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aDefaultLocale_CJK, false), ASIAN);
+ vcl::Font aFontCJK = OutputDevice::GetDefaultFont( DefaultFontType::CJK_SPREADSHEET, nLang, GetDefaultFontFlags::OnlyOne );
+ nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aDefaultLocale_CTL, false), COMPLEX);
+ vcl::Font aFontCTL = OutputDevice::GetDefaultFont( DefaultFontType::CTL_SPREADSHEET, nLang, GetDefaultFontFlags::OnlyOne );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FONT_NAME, aFont.GetFamilyName() );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FONT_STYLE_NAME, aFont.GetStyleName() );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FONT_FAMILY, sal_Int16(aFont.GetFamilyType()) );//awt::FontFamily::SWISS
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FONT_CHAR_SET, sal_Int16(aFont.GetCharSet()) );//use awt::CharSet::DONTKNOW instead of SYSTEM to avoid assertion issue 50249
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_FONT_PITCH, sal_Int16(aFont.GetPitch()) );//awt::FontPitch::VARIABLE
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COLOR, COL_AUTO ); //automatic color
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_CHAR_HEIGHT, fDefaultFontHeight );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_UNDERLINE, awt::FontUnderline::NONE );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_UNDERLINE_COLOR, COL_AUTO ); //automatic color
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_UNDERLINE_HAS_COLOR, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_OVERLINE, awt::FontUnderline::NONE );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_OVERLINE_COLOR, COL_AUTO ); //automatic color
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_OVERLINE_HAS_COLOR, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_WEIGHT, awt::FontWeight::NORMAL );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_POSTURE, awt::FontSlant_NONE );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_AUTO_KERNING, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_KERNING, sal_Int16(0) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_STRIKE_OUT, awt::FontStrikeout::NONE );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_WORD_MODE, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_LOCALE, aDefaultLocale );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_SHADOWED, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_CONTOURED, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_RELIEF, text::FontRelief::NONE );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_EMPHASIS, text::FontEmphasis::NONE );
+
+ // Asian (com.sun.star.style.CharacterPropertiesAsian)
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultFontHeight );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_WEIGHT, awt::FontWeight::NORMAL );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_POSTURE, awt::FontSlant_NONE );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_LOCALE, aDefaultLocale_CJK );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_FONT_NAME, aFontCJK.GetFamilyName() );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_FONT_STYLE_NAME, aFontCJK.GetStyleName() );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_FONT_FAMILY, sal_Int16(aFontCJK.GetFamilyType()) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_CHAR_SET, sal_Int16(aFontCJK.GetCharSet()) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_ASIAN_FONT_PITCH, sal_Int16(aFontCJK.GetPitch()) );
+
+ // Complex Text Layout (com.sun.star.style.CharacterPropertiesComplex)
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultFontHeight );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_WEIGHT, awt::FontWeight::NORMAL );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_POSTURE, awt::FontSlant_NONE );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_LOCALE, aDefaultLocale_CTL );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_FONT_NAME, aFontCTL.GetFamilyName() );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_FONT_STYLE_NAME, aFontCTL.GetStyleName() );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_FONT_FAMILY, sal_Int16(aFontCTL.GetFamilyType()) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_CHAR_SET, sal_Int16(aFontCTL.GetCharSet()) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_CHAR_COMPLEX_FONT_PITCH, sal_Int16(aFontCTL.GetPitch()) );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_WRITING_MODE, sal_Int16( css::text::WritingMode2::PAGE ) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_PARA_IS_CHARACTER_DISTANCE, true );
+}
+
+bool CharacterProperties::IsCharacterPropertyHandle( sal_Int32 nHandle )
+{
+ return ( FAST_PROPERTY_ID_START_CHAR_PROP <= nHandle &&
+ nHandle < CharacterProperties::FAST_PROPERTY_ID_END_CHAR_PROP );
+}
+
+awt::FontDescriptor CharacterProperties::createFontDescriptorFromPropertySet(
+ const uno::Reference< beans::XMultiPropertySet > & xMultiPropSet )
+{
+ awt::FontDescriptor aResult;
+ // Note: keep this sorted!
+ uno::Sequence< OUString > aPropNameSeq{
+ "CharFontCharSet", // CharSet
+ "CharFontFamily", // Family
+ "CharFontName", // Name
+ "CharFontPitch", // Pitch
+ "CharFontStyleName", // StyleName
+ "CharHeight", // Height
+ "CharPosture", // Slant
+ "CharStrikeout", // Strikeout
+ "CharUnderline", // Underline
+ "CharWeight", // Weight
+ "CharWordMode"}; // WordLineMode
+ uno::Sequence< uno::Any > aValues( xMultiPropSet->getPropertyValues( aPropNameSeq ));
+
+ sal_Int32 i=0;
+ // Note keep this sorted according to the list above (comments are the fieldnames)
+ aValues[ i++ ] >>= aResult.CharSet;
+ aValues[ i++ ] >>= aResult.Family;
+ aValues[ i++ ] >>= aResult.Name;
+ aValues[ i++ ] >>= aResult.Pitch;
+ aValues[ i++ ] >>= aResult.StyleName;
+ float fCharHeight = 0;
+ aValues[ i++ ] >>= fCharHeight;
+ aResult.Height = static_cast< sal_Int16 >( fCharHeight );
+ aValues[ i++ ] >>= aResult.Slant;
+ aValues[ i++ ] >>= aResult.Strikeout;
+ aValues[ i++ ] >>= aResult.Underline;
+ aValues[ i++ ] >>= aResult.Weight;
+ aValues[ i++ ] >>= aResult.WordLineMode;
+ OSL_ASSERT( i == aValues.getLength());
+
+ return aResult;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ChartModelHelper.cxx b/chart2/source/tools/ChartModelHelper.cxx
new file mode 100644
index 0000000000..0aa2288ff8
--- /dev/null
+++ b/chart2/source/tools/ChartModelHelper.cxx
@@ -0,0 +1,223 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartModelHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <DataSource.hxx>
+#include <DataSourceHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <RangeHighlighter.hxx>
+#include <InternalDataProvider.hxx>
+#include <ChartModel.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <ChartType.hxx>
+#include <DataSeries.hxx>
+
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+rtl::Reference< InternalDataProvider > ChartModelHelper::createInternalDataProvider(
+ const rtl::Reference<::chart::ChartModel>& xChartDoc, bool bConnectToModel )
+{
+ bool bDefaultDataInColumns(true);
+
+ // #i120559# Try to access the current state of "DataRowSource" for the
+ // chart data and use it as default for creating a new InternalDataProvider
+ if(xChartDoc.is())
+ {
+ // old XChartDocument interface
+ css::uno::Reference< css::chart::XChartDocument > xDoc(static_cast<cppu::OWeakObject*>(xChartDoc.get()), uno::UNO_QUERY);
+
+ if(xDoc.is())
+ {
+ css::uno::Reference< css::chart::XDiagram > aDiagram = xDoc->getDiagram();
+
+ if(aDiagram.is())
+ {
+ css::uno::Reference< css::beans::XPropertySet > xProp(aDiagram, uno::UNO_QUERY);
+
+ if(xProp.is())
+ {
+ css::chart::ChartDataRowSource aDataRowSource(css::chart::ChartDataRowSource_COLUMNS);
+
+ xProp->getPropertyValue( "DataRowSource" ) >>= aDataRowSource;
+
+ bDefaultDataInColumns = (aDataRowSource == css::chart::ChartDataRowSource_COLUMNS);
+ }
+ }
+ }
+ }
+
+ return new InternalDataProvider( xChartDoc, bConnectToModel, bDefaultDataInColumns );
+}
+
+rtl::Reference< BaseCoordinateSystem > ChartModelHelper::getFirstCoordinateSystem( const rtl::Reference<::chart::ChartModel>& xModel )
+{
+ rtl::Reference< Diagram > xDiagram = xModel->getFirstChartDiagram();
+ if( xDiagram.is() )
+ {
+ auto aCooSysSeq( xDiagram->getBaseCoordinateSystems() );
+ if( !aCooSysSeq.empty() )
+ return aCooSysSeq[0];
+ }
+ return nullptr;
+}
+
+std::vector< rtl::Reference< DataSeries > > ChartModelHelper::getDataSeries(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc )
+{
+ std::vector< rtl::Reference< DataSeries > > aResult;
+
+ rtl::Reference< Diagram > xDiagram = xChartDoc->getFirstChartDiagram();
+ if( xDiagram.is())
+ aResult = xDiagram->getDataSeries();
+
+ return aResult;
+}
+
+rtl::Reference< ChartType > ChartModelHelper::getChartTypeOfSeries(
+ const rtl::Reference<::chart::ChartModel>& xModel
+ , const rtl::Reference< DataSeries >& xGivenDataSeries )
+{
+ rtl::Reference<Diagram> xDiagram = xModel->getFirstChartDiagram();
+ return xDiagram ? xDiagram->getChartTypeOfSeries( xGivenDataSeries ) : nullptr;
+}
+
+awt::Size ChartModelHelper::getDefaultPageSize()
+{
+ return awt::Size( 16000, 9000 );
+}
+
+awt::Size ChartModelHelper::getPageSize( const rtl::Reference<::chart::ChartModel>& xModel )
+{
+ awt::Size aPageSize( ChartModelHelper::getDefaultPageSize() );
+ OSL_ENSURE(xModel.is(),"need xVisualObject for page size");
+ if( xModel.is() )
+ aPageSize = xModel->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
+ return aPageSize;
+}
+
+void ChartModelHelper::triggerRangeHighlighting( const rtl::Reference<::chart::ChartModel>& xModel )
+{
+ if( xModel.is() )
+ {
+ uno::Reference< view::XSelectionChangeListener > xSelectionChangeListener( xModel->getRangeHighlighter(), uno::UNO_QUERY );
+ //trigger selection of cell range
+ if( xSelectionChangeListener.is() )
+ {
+ lang::EventObject aEvent( xSelectionChangeListener );
+ xSelectionChangeListener->selectionChanged( aEvent );
+ }
+ }
+}
+
+bool ChartModelHelper::isIncludeHiddenCells( const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ bool bIncluded = true; // hidden cells are included by default.
+
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ if (!xDiagram.is())
+ return bIncluded;
+
+ try
+ {
+ xDiagram->getPropertyValue("IncludeHiddenCells") >>= bIncluded;
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ }
+
+ return bIncluded;
+}
+
+bool ChartModelHelper::setIncludeHiddenCells( bool bIncludeHiddenCells, ChartModel& rModel )
+{
+ bool bChanged = false;
+ try
+ {
+ ControllerLockGuard aLockedControllers( rModel );
+
+ uno::Reference< beans::XPropertySet > xDiagramProperties( rModel.getFirstDiagram(), uno::UNO_QUERY );
+ if (xDiagramProperties.is())
+ {
+ bool bOldValue = bIncludeHiddenCells;
+ xDiagramProperties->getPropertyValue( "IncludeHiddenCells" ) >>= bOldValue;
+ if( bOldValue == bIncludeHiddenCells )
+ bChanged = true;
+
+ //set the property on all instances in all cases to get the different objects in sync!
+
+ uno::Any aNewValue(bIncludeHiddenCells);
+
+ try
+ {
+ uno::Reference< beans::XPropertySet > xDataProviderProperties( rModel.getDataProvider(), uno::UNO_QUERY );
+ if( xDataProviderProperties.is() )
+ xDataProviderProperties->setPropertyValue("IncludeHiddenCells", aNewValue );
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ //the property is optional!
+ }
+
+ try
+ {
+ rtl::Reference< DataSource > xUsedData = DataSourceHelper::getUsedData( rModel );
+ if( xUsedData.is() )
+ {
+ uno::Reference< beans::XPropertySet > xProp;
+ const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aData( xUsedData->getDataSequences());
+ for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledData : aData )
+ {
+ xProp.set( uno::Reference< beans::XPropertySet >( labeledData->getValues(), uno::UNO_QUERY ) );
+ if(xProp.is())
+ xProp->setPropertyValue("IncludeHiddenCells", aNewValue );
+ xProp.set( uno::Reference< beans::XPropertySet >( labeledData->getLabel(), uno::UNO_QUERY ) );
+ if(xProp.is())
+ xProp->setPropertyValue("IncludeHiddenCells", aNewValue );
+ }
+ }
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ //the property is optional!
+ }
+
+ xDiagramProperties->setPropertyValue( "IncludeHiddenCells", aNewValue);
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return bChanged;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ChartTypeHelper.cxx b/chart2/source/tools/ChartTypeHelper.cxx
new file mode 100644
index 0000000000..15f00eac6f
--- /dev/null
+++ b/chart2/source/tools/ChartTypeHelper.cxx
@@ -0,0 +1,724 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartTypeHelper.hxx>
+#include <ChartType.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <DataSeriesProperties.hxx>
+#include <DiagramHelper.hxx>
+#include <servicenames_charttypes.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart::DataSeriesProperties;
+
+namespace chart
+{
+
+bool ChartTypeHelper::isSupportingAxisSideBySide(
+ const rtl::Reference< ::chart::ChartType >& xChartType, sal_Int32 nDimensionCount )
+{
+ bool bResult = false;
+
+ if( xChartType.is() &&
+ nDimensionCount < 3 )
+ {
+ bool bFound=false;
+ bool bAmbiguous=false;
+ StackMode eStackMode = DiagramHelper::getStackModeFromChartType( xChartType, bFound, bAmbiguous, nullptr );
+ if( eStackMode == StackMode::NONE && !bAmbiguous )
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ bResult = ( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) ||
+ aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) );
+ }
+ }
+
+ return bResult;
+}
+
+bool ChartTypeHelper::isSupportingGeometryProperties( const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount )
+{
+ //form tab only for 3D-bar and 3D-column charts.
+
+ //@todo ask charttype itself --> need model change first
+ if(xChartType.is())
+ {
+ if(nDimensionCount==3)
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_BAR )
+ return true;
+ if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_COLUMN )
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ChartTypeHelper::isSupportingStatisticProperties( const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount )
+{
+ //3D charts, pie, net and stock do not support statistic properties
+
+ //@todo ask charttype itself (and series? --> stock chart?) --> need model change first
+ if(xChartType.is())
+ {
+ if(nDimensionCount==3)
+ return false;
+
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) //todo: BubbleChart support error bars and trend lines
+ return false;
+ }
+ return true;
+}
+
+bool ChartTypeHelper::isSupportingRegressionProperties( const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount )
+{
+ // note: old chart: only scatter chart
+ return isSupportingStatisticProperties( xChartType, nDimensionCount );
+}
+
+bool ChartTypeHelper::isSupportingAreaProperties( const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount )
+{
+ //2D line charts, net and stock do not support area properties
+
+ //@todo ask charttype itself --> need model change first
+ if(xChartType.is())
+ {
+ if(nDimensionCount==2)
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ChartTypeHelper::isSupportingSymbolProperties( const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount )
+{
+ //2D line charts, 2D scatter charts and 2D net charts do support symbols
+
+ //@todo ask charttype itself --> need model change first
+ if(xChartType.is())
+ {
+ if(nDimensionCount==3)
+ return false;
+
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) )
+ return true;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) )
+ return true;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ return true;
+ }
+ return false;
+}
+
+bool ChartTypeHelper::isSupportingMainAxis( const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount, sal_Int32 nDimensionIndex )
+{
+ //pie charts do not support axis at all
+ //no 3rd axis for 2D charts
+
+ //@todo ask charttype itself --> need model change first
+ if(xChartType.is())
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ return false;
+
+ if( nDimensionIndex == 2 )
+ return nDimensionCount == 3;
+ }
+ return true;
+}
+
+bool ChartTypeHelper::isSupportingSecondaryAxis( const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount )
+{
+ //3D, pie and net charts do not support a secondary axis at all
+
+ //@todo ask charttype itself --> need model change first
+ if(xChartType.is())
+ {
+ if(nDimensionCount==3)
+ return false;
+
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
+ return false;
+ }
+ return true;
+}
+
+bool ChartTypeHelper::isSupportingOverlapAndGapWidthProperties(
+ const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount )
+{
+ //2D bar charts do support a this special properties
+
+ //@todo ask charttype itself --> need model change first
+ if(xChartType.is())
+ {
+ if(nDimensionCount==3)
+ return false;
+
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) )
+ return true;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) )
+ return true;
+ }
+ return false;
+}
+
+bool ChartTypeHelper::isSupportingBarConnectors(
+ const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount )
+{
+ //2D bar charts with stacked series support this
+
+ //@todo ask charttype itself --> need model change first
+ if(xChartType.is())
+ {
+ if(nDimensionCount==3)
+ return false;
+
+ bool bFound=false;
+ bool bAmbiguous=false;
+ StackMode eStackMode = DiagramHelper::getStackModeFromChartType( xChartType, bFound, bAmbiguous, nullptr );
+ if( eStackMode != StackMode::YStacked || bAmbiguous )
+ return false;
+
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) )
+ return true;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) )
+ return true; // note: old chart was false here
+ }
+ return false;
+}
+
+uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedLabelPlacements( const rtl::Reference< ChartType >& xChartType
+ , bool bSwapXAndY
+ , const rtl::Reference< DataSeries >& xSeries )
+{
+ uno::Sequence < sal_Int32 > aRet;
+ if( !xChartType.is() )
+ return aRet;
+
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ {
+ bool bDonut = false;
+ xChartType->getFastPropertyValue( PROP_PIECHARTTYPE_USE_RINGS ) >>= bDonut; // "UseRings"
+
+ if(!bDonut)
+ {
+ aRet.realloc(5);
+ sal_Int32* pSeq = aRet.getArray();
+ *pSeq++ = css::chart::DataLabelPlacement::AVOID_OVERLAP;
+ *pSeq++ = css::chart::DataLabelPlacement::OUTSIDE;
+ *pSeq++ = css::chart::DataLabelPlacement::INSIDE;
+ *pSeq++ = css::chart::DataLabelPlacement::CENTER;
+ *pSeq++ = css::chart::DataLabelPlacement::CUSTOM;
+ }
+ else
+ {
+ aRet.realloc(1);
+ sal_Int32* pSeq = aRet.getArray();
+ *pSeq++ = css::chart::DataLabelPlacement::CENTER;
+ }
+ }
+ else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER)
+ || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE)
+ || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE)
+ )
+ {
+ aRet.realloc(5);
+ sal_Int32* pSeq = aRet.getArray();
+ *pSeq++ = css::chart::DataLabelPlacement::TOP;
+ *pSeq++ = css::chart::DataLabelPlacement::BOTTOM;
+ *pSeq++ = css::chart::DataLabelPlacement::LEFT;
+ *pSeq++ = css::chart::DataLabelPlacement::RIGHT;
+ *pSeq++ = css::chart::DataLabelPlacement::CENTER;
+ }
+ else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN)
+ || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) )
+ {
+
+ bool bStacked = false;
+ {
+ chart2::StackingDirection eStacking = chart2::StackingDirection_NO_STACKING;
+ xSeries->getFastPropertyValue( PROP_DATASERIES_STACKING_DIRECTION ) >>= eStacking; // "StackingDirection"
+ bStacked = (eStacking == chart2::StackingDirection_Y_STACKING);
+ }
+
+ aRet.realloc( bStacked ? 3 : 6 );
+ sal_Int32* pSeq = aRet.getArray();
+ if(!bStacked)
+ {
+ if(bSwapXAndY)
+ {
+ *pSeq++ = css::chart::DataLabelPlacement::RIGHT;
+ *pSeq++ = css::chart::DataLabelPlacement::LEFT;
+ }
+ else
+ {
+ *pSeq++ = css::chart::DataLabelPlacement::TOP;
+ *pSeq++ = css::chart::DataLabelPlacement::BOTTOM;
+ }
+ }
+ *pSeq++ = css::chart::DataLabelPlacement::CENTER;
+ if(!bStacked)
+ *pSeq++ = css::chart::DataLabelPlacement::OUTSIDE;
+ *pSeq++ = css::chart::DataLabelPlacement::INSIDE;
+ *pSeq++ = css::chart::DataLabelPlacement::NEAR_ORIGIN;
+ }
+ else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) )
+ {
+ bool bStacked = false;
+ {
+ chart2::StackingDirection eStacking = chart2::StackingDirection_NO_STACKING;
+ xSeries->getFastPropertyValue(PROP_DATASERIES_STACKING_DIRECTION) >>= eStacking; // "StackingDirection"
+ bStacked = (eStacking == chart2::StackingDirection_Y_STACKING);
+ }
+
+ aRet.realloc(2);
+ sal_Int32* pSeq = aRet.getArray();
+ if (bStacked)
+ {
+ *pSeq++ = css::chart::DataLabelPlacement::CENTER;
+ *pSeq++ = css::chart::DataLabelPlacement::TOP;
+ }
+ else
+ {
+ *pSeq++ = css::chart::DataLabelPlacement::TOP;
+ *pSeq++ = css::chart::DataLabelPlacement::CENTER;
+ }
+ }
+ else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ {
+ aRet.realloc(6);
+ sal_Int32* pSeq = aRet.getArray();
+ *pSeq++ = css::chart::DataLabelPlacement::OUTSIDE;
+ *pSeq++ = css::chart::DataLabelPlacement::TOP;
+ *pSeq++ = css::chart::DataLabelPlacement::BOTTOM;
+ *pSeq++ = css::chart::DataLabelPlacement::LEFT;
+ *pSeq++ = css::chart::DataLabelPlacement::RIGHT;
+ *pSeq++ = css::chart::DataLabelPlacement::CENTER;
+ }
+ else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
+ {
+ aRet.realloc(1);
+ sal_Int32* pSeq = aRet.getArray();
+ *pSeq++ = css::chart::DataLabelPlacement::OUTSIDE;
+ }
+ else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
+ {
+ aRet.realloc( 1 );
+ sal_Int32* pSeq = aRet.getArray();
+ *pSeq++ = css::chart::DataLabelPlacement::OUTSIDE;
+ }
+ else
+ {
+ OSL_FAIL( "unknown charttype" );
+ }
+
+ return aRet;
+}
+
+bool ChartTypeHelper::isSupportingRightAngledAxes( const rtl::Reference< ChartType >& xChartType )
+{
+ if(xChartType.is())
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ return false;
+ }
+ return true;
+}
+
+bool ChartTypeHelper::isSupportingStartingAngle( const rtl::Reference< ChartType >& xChartType )
+{
+ if(xChartType.is())
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ return true;
+ }
+ return false;
+}
+bool ChartTypeHelper::isSupportingBaseValue( const rtl::Reference< ChartType >& xChartType )
+{
+ if(xChartType.is())
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN)
+ || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR)
+ || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA)
+ )
+ return true;
+ }
+ return false;
+}
+
+bool ChartTypeHelper::isSupportingAxisPositioning( const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount, sal_Int32 nDimensionIndex )
+{
+ if(xChartType.is())
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
+ return false;
+ }
+ if( nDimensionCount==3 )
+ return nDimensionIndex<2;
+ return true;
+}
+
+bool ChartTypeHelper::isSupportingDateAxis( const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionIndex )
+{
+ if( nDimensionIndex!=0 )
+ return false;
+ if( xChartType.is() )
+ {
+ sal_Int32 nType = ChartTypeHelper::getAxisType( xChartType, nDimensionIndex );
+ if( nType != AxisType::CATEGORY )
+ return false;
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ return false;
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
+ return false;
+ }
+ return true;
+}
+
+bool ChartTypeHelper::isSupportingComplexCategory( const rtl::Reference< ChartType >& xChartType )
+{
+ if( xChartType.is() )
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ return false;
+ }
+ return true;
+}
+
+bool ChartTypeHelper::isSupportingCategoryPositioning( const rtl::Reference< ChartType >& xChartType, sal_Int32 nDimensionCount )
+{
+ if( xChartType.is() )
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) ||
+ aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) ||
+ aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK))
+ return true;
+ else if (nDimensionCount == 2 &&
+ (aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR)))
+ return true;
+ }
+ return false;
+}
+
+bool ChartTypeHelper::shiftCategoryPosAtXAxisPerDefault( const rtl::Reference< ChartType >& xChartType )
+{
+ if(xChartType.is())
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN)
+ || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR)
+ || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
+ return true;
+ }
+ return false;
+}
+
+bool ChartTypeHelper::noBordersForSimpleScheme( const rtl::Reference< ChartType >& xChartType )
+{
+ if(xChartType.is())
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ return true;
+ }
+ return false;
+}
+
+sal_Int32 ChartTypeHelper::getDefaultDirectLightColor( bool bSimple, const rtl::Reference< ChartType >& xChartType )
+{
+ sal_Int32 nRet = static_cast< sal_Int32 >( 0x808080 ); // grey
+ if( xChartType .is() )
+ {
+ OUString aChartType = xChartType->getChartType();
+ if( aChartType == CHART2_SERVICE_NAME_CHARTTYPE_PIE )
+ {
+ if( bSimple )
+ nRet = static_cast< sal_Int32 >( 0x333333 ); // grey80
+ else
+ nRet = static_cast< sal_Int32 >( 0xb3b3b3 ); // grey30
+ }
+ else if( aChartType == CHART2_SERVICE_NAME_CHARTTYPE_LINE
+ || aChartType == CHART2_SERVICE_NAME_CHARTTYPE_SCATTER )
+ nRet = static_cast< sal_Int32 >( 0x666666 ); // grey60
+ }
+ return nRet;
+}
+
+sal_Int32 ChartTypeHelper::getDefaultAmbientLightColor( bool bSimple, const rtl::Reference< ChartType >& xChartType )
+{
+ sal_Int32 nRet = static_cast< sal_Int32 >( 0x999999 ); // grey40
+ if( xChartType .is() )
+ {
+ OUString aChartType = xChartType->getChartType();
+ if( aChartType == CHART2_SERVICE_NAME_CHARTTYPE_PIE )
+ {
+ if( bSimple )
+ nRet = static_cast< sal_Int32 >( 0xcccccc ); // grey20
+ else
+ nRet = static_cast< sal_Int32 >( 0x666666 ); // grey60
+ }
+ }
+ return nRet;
+}
+
+drawing::Direction3D ChartTypeHelper::getDefaultSimpleLightDirection( const rtl::Reference< ChartType >& xChartType )
+{
+ drawing::Direction3D aRet(0.0, 0.0, 1.0);
+ if( xChartType .is() )
+ {
+ OUString aChartType = xChartType->getChartType();
+ if( aChartType == CHART2_SERVICE_NAME_CHARTTYPE_PIE )
+ aRet = drawing::Direction3D(0.0, 0.8, 0.5);
+ else if( aChartType == CHART2_SERVICE_NAME_CHARTTYPE_LINE
+ || aChartType == CHART2_SERVICE_NAME_CHARTTYPE_SCATTER )
+ aRet = drawing::Direction3D(0.9, 0.5, 0.05);
+ }
+ return aRet;
+}
+
+drawing::Direction3D ChartTypeHelper::getDefaultRealisticLightDirection( const rtl::Reference< ChartType >& xChartType )
+{
+ drawing::Direction3D aRet(0.0, 0.0, 1.0);
+ if( xChartType .is() )
+ {
+ OUString aChartType = xChartType->getChartType();
+ if( aChartType == CHART2_SERVICE_NAME_CHARTTYPE_PIE )
+ aRet = drawing::Direction3D(0.6, 0.6, 0.6);
+ else if( aChartType == CHART2_SERVICE_NAME_CHARTTYPE_LINE
+ || aChartType == CHART2_SERVICE_NAME_CHARTTYPE_SCATTER )
+ aRet = drawing::Direction3D(0.9, 0.5, 0.05);
+ }
+ return aRet;
+}
+
+sal_Int32 ChartTypeHelper::getAxisType( const rtl::Reference<
+ ChartType >& xChartType, sal_Int32 nDimensionIndex )
+{
+ //returned is a constant from constant group css::chart2::AxisType
+
+ //@todo ask charttype itself --> need model change first
+ if(!xChartType.is())
+ return AxisType::CATEGORY;
+
+ OUString aChartTypeName = xChartType->getChartType();
+ if(nDimensionIndex==2)//z-axis
+ return AxisType::SERIES;
+ if(nDimensionIndex==1)//y-axis
+ return AxisType::REALNUMBER;
+ if(nDimensionIndex==0)//x-axis
+ {
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER)
+ || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) )
+ return AxisType::REALNUMBER;
+ return AxisType::CATEGORY;
+ }
+ return AxisType::CATEGORY;
+}
+
+sal_Int32 ChartTypeHelper::getNumberOfDisplayedSeries(
+ const rtl::Reference< ChartType >& xChartType,
+ sal_Int32 nNumberOfSeries )
+{
+ if( xChartType.is() )
+ {
+ try
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_PIE )
+ {
+ bool bDonut = false;
+ if( (xChartType->getFastPropertyValue( PROP_PIECHARTTYPE_USE_RINGS ) >>= bDonut) // "UseRings"
+ && !bDonut )
+ {
+ return nNumberOfSeries>0 ? 1 : 0;
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ return nNumberOfSeries;
+}
+
+uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedMissingValueTreatments( const rtl::Reference< ChartType >& xChartType )
+{
+ uno::Sequence < sal_Int32 > aRet;
+ if( !xChartType.is() )
+ return aRet;
+
+ bool bFound=false;
+ bool bAmbiguous=false;
+ StackMode eStackMode = DiagramHelper::getStackModeFromChartType( xChartType, bFound, bAmbiguous, nullptr );
+ bool bStacked = bFound && (eStackMode == StackMode::YStacked);
+
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) ||
+ aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ||
+ aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) )
+ {
+ aRet.realloc( 2 );
+ sal_Int32* pSeq = aRet.getArray();
+ *pSeq++ = css::chart::MissingValueTreatment::LEAVE_GAP;
+ *pSeq++ = css::chart::MissingValueTreatment::USE_ZERO;
+ }
+ else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) )
+ {
+ aRet.realloc( bStacked ? 1 : 2 );
+ sal_Int32* pSeq = aRet.getArray();
+ *pSeq++ = css::chart::MissingValueTreatment::USE_ZERO;
+ if( !bStacked )
+ *pSeq++ = css::chart::MissingValueTreatment::CONTINUE;
+ }
+ else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) ||
+ aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_NET) ||
+ aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
+ {
+ aRet.realloc( bStacked ? 2 : 3 );
+ sal_Int32* pSeq = aRet.getArray();
+ *pSeq++ = css::chart::MissingValueTreatment::LEAVE_GAP;
+ *pSeq++ = css::chart::MissingValueTreatment::USE_ZERO;
+ if( !bStacked )
+ *pSeq++ = css::chart::MissingValueTreatment::CONTINUE;
+ }
+ else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) )
+ {
+ aRet.realloc( 3 );
+ sal_Int32* pSeq = aRet.getArray();
+ *pSeq++ = css::chart::MissingValueTreatment::CONTINUE;
+ *pSeq++ = css::chart::MissingValueTreatment::LEAVE_GAP;
+ *pSeq++ = css::chart::MissingValueTreatment::USE_ZERO;
+ }
+ else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ||
+ aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
+ {
+ aRet.realloc( 0 );
+ }
+ else
+ {
+ OSL_FAIL( "unknown charttype" );
+ }
+
+ return aRet;
+}
+
+bool ChartTypeHelper::isSeriesInFrontOfAxisLine( const rtl::Reference< ChartType >& xChartType )
+{
+ if( xChartType.is() )
+ {
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match( CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET ) )
+ return false;
+ }
+ return true;
+}
+
+OUString ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( const rtl::Reference< ChartType >& xChartType )
+{
+ OUString aRet( "values-y" );
+ if( !xChartType.is() )
+ return aRet;
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
+ aRet = xChartType->getRoleOfSequenceForSeriesLabel();
+ return aRet;
+}
+
+OUString ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( const rtl::Reference< ChartType >& xChartType )
+{
+ OUString aRet( "values-y" );
+ if( !xChartType.is() )
+ return aRet;
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK)
+ || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) )
+ aRet = xChartType->getRoleOfSequenceForSeriesLabel();
+ return aRet;
+}
+
+bool ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( const rtl::Reference< ChartType >& xChartType )
+{
+ bool bRet = false;
+ if( !xChartType.is() )
+ return bRet;
+
+ OUString aChartTypeName = xChartType->getChartType();
+ if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) ||
+ aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) ||
+ aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) )
+ {
+ bRet = true;
+ }
+ return bRet;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ChartViewHelper.cxx b/chart2/source/tools/ChartViewHelper.cxx
new file mode 100644
index 0000000000..8011da3c17
--- /dev/null
+++ b/chart2/source/tools/ChartViewHelper.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ChartViewHelper.hxx>
+#include <ChartModel.hxx>
+#include <servicenames.hxx>
+
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+
+void ChartViewHelper::setViewToDirtyState(const rtl::Reference<::chart::ChartModel>& xChartModel)
+{
+ try
+ {
+ if (xChartModel.is())
+ {
+ Reference<util::XModifyListener> xModifyListener(
+ xChartModel->createInstance(CHART_VIEW_SERVICE_NAME), uno::UNO_QUERY);
+ if (xModifyListener.is())
+ {
+ lang::EventObject aEvent(static_cast<cppu::OWeakObject*>(xChartModel.get()));
+ xModifyListener->modified(aEvent);
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ChartViewHelper::setViewToDirtyState_UNO(
+ const css::uno::Reference<css::chart2::XChartDocument>& xChartModel)
+{
+ if (auto pChartModel = dynamic_cast<ChartModel*>(xChartModel.get()))
+ setViewToDirtyState(rtl::Reference(pChartModel));
+}
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ColorPerPointHelper.cxx b/chart2/source/tools/ColorPerPointHelper.cxx
new file mode 100644
index 0000000000..04cc09cb44
--- /dev/null
+++ b/chart2/source/tools/ColorPerPointHelper.cxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ColorPerPointHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesProperties.hxx>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart::DataSeriesProperties;
+
+namespace chart
+{
+
+bool ColorPerPointHelper::hasPointOwnColor(
+ const rtl::Reference< DataSeries >& xDataSeries
+ , sal_Int32 nPointIndex
+ , const css::uno::Reference< css::beans::XPropertySet >& xDataPointProperties //may be NULL this is just for performance
+ )
+{
+ if( !xDataSeries.is() )
+ return false;
+
+ if( hasPointOwnProperties( xDataSeries, nPointIndex ))
+ {
+ uno::Reference< beans::XPropertyState > xPointState( xDataPointProperties, uno::UNO_QUERY );
+ if( !xPointState.is() )
+ {
+ xPointState.set( xDataSeries->getDataPointByIndex( nPointIndex ), uno::UNO_QUERY );
+ }
+ if( !xPointState.is() )
+ return false;
+
+ return (xPointState->getPropertyState( "Color") != beans::PropertyState_DEFAULT_VALUE );
+ }
+
+ return false;
+}
+
+bool ColorPerPointHelper::hasPointOwnProperties(
+ const rtl::Reference< ::chart::DataSeries >& xDataSeries
+ , sal_Int32 nPointIndex )
+{
+ if( xDataSeries.is() )
+ {
+ uno::Sequence< sal_Int32 > aIndexList;
+ if( xDataSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aIndexList ) // "AttributedDataPoints"
+ {
+ const sal_Int32 * pBegIt = aIndexList.getConstArray();
+ const sal_Int32 * pEndIt = pBegIt + aIndexList.getLength();
+ return ( std::find( pBegIt, pEndIt, nPointIndex ) != pEndIt );
+ }
+ }
+
+ return false;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/CommonConverters.cxx b/chart2/source/tools/CommonConverters.cxx
new file mode 100644
index 0000000000..293fa7b11d
--- /dev/null
+++ b/chart2/source/tools/CommonConverters.cxx
@@ -0,0 +1,601 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <CommonConverters.hxx>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
+#include <com/sun/star/chart2/data/XDataSequence.hpp>
+#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+
+#include <cstddef>
+#include <limits>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+
+// diverse methods for class conversions; e.g. ::basegfx::B3DHomMatrix to HomogenMatrix
+
+drawing::HomogenMatrix B3DHomMatrixToHomogenMatrix( const ::basegfx::B3DHomMatrix& rM )
+{
+ drawing::HomogenMatrix aHM;
+ aHM.Line1.Column1 = rM.get(0, 0);
+ aHM.Line1.Column2 = rM.get(0, 1);
+ aHM.Line1.Column3 = rM.get(0, 2);
+ aHM.Line1.Column4 = rM.get(0, 3);
+ aHM.Line2.Column1 = rM.get(1, 0);
+ aHM.Line2.Column2 = rM.get(1, 1);
+ aHM.Line2.Column3 = rM.get(1, 2);
+ aHM.Line2.Column4 = rM.get(1, 3);
+ aHM.Line3.Column1 = rM.get(2, 0);
+ aHM.Line3.Column2 = rM.get(2, 1);
+ aHM.Line3.Column3 = rM.get(2, 2);
+ aHM.Line3.Column4 = rM.get(2, 3);
+ aHM.Line4.Column1 = rM.get(3, 0);
+ aHM.Line4.Column2 = rM.get(3, 1);
+ aHM.Line4.Column3 = rM.get(3, 2);
+ aHM.Line4.Column4 = rM.get(3, 3);
+ return aHM;
+}
+
+::basegfx::B3DHomMatrix HomogenMatrixToB3DHomMatrix( const drawing::HomogenMatrix& rHM )
+{
+ ::basegfx::B3DHomMatrix aM;
+ aM.set(0, 0, rHM.Line1.Column1);
+ aM.set(0, 1, rHM.Line1.Column2);
+ aM.set(0, 2, rHM.Line1.Column3);
+ aM.set(0, 3, rHM.Line1.Column4);
+ aM.set(1, 0, rHM.Line2.Column1);
+ aM.set(1, 1, rHM.Line2.Column2);
+ aM.set(1, 2, rHM.Line2.Column3);
+ aM.set(1, 3, rHM.Line2.Column4);
+ aM.set(2, 0, rHM.Line3.Column1);
+ aM.set(2, 1, rHM.Line3.Column2);
+ aM.set(2, 2, rHM.Line3.Column3);
+ aM.set(2, 3, rHM.Line3.Column4);
+ aM.set(3, 0, rHM.Line4.Column1);
+ aM.set(3, 1, rHM.Line4.Column2);
+ aM.set(3, 2, rHM.Line4.Column3);
+ aM.set(3, 3, rHM.Line4.Column4);
+ return aM;
+}
+
+::basegfx::B2DHomMatrix IgnoreZ( const ::basegfx::B3DHomMatrix& rM )
+{
+ ::basegfx::B2DHomMatrix aM;
+ aM.set(0, 0, rM.get(0, 0));
+ aM.set(0, 1, rM.get(0, 1));
+ aM.set(0, 2, rM.get(0, 3));
+ aM.set(1, 0, rM.get(1, 0));
+ aM.set(1, 1, rM.get(1, 1));
+ aM.set(1, 2, rM.get(1, 3));
+ // For this to be a valid 2D transform matrix, the last row must be [0,0,1]
+ assert( rM.get(3, 0) == 0 );
+ assert( rM.get(3, 1) == 0 );
+ assert( rM.get(3, 3) == 1 );
+ return aM;
+}
+
+drawing::HomogenMatrix3 B2DHomMatrixToHomogenMatrix3( const ::basegfx::B2DHomMatrix& rM )
+{
+ drawing::HomogenMatrix3 aHM;
+ aHM.Line1.Column1 = rM.get(0, 0);
+ aHM.Line1.Column2 = rM.get(0, 1);
+ aHM.Line1.Column3 = rM.get(0, 2);
+ aHM.Line2.Column1 = rM.get(1, 0);
+ aHM.Line2.Column2 = rM.get(1, 1);
+ aHM.Line2.Column3 = rM.get(1, 2);
+ aHM.Line3.Column1 = 0;
+ aHM.Line3.Column2 = 0;
+ aHM.Line3.Column3 = 1;
+ return aHM;
+}
+
+::basegfx::B3DPoint Position3DToB3DPoint( const drawing::Position3D& rPosition )
+{
+ return ::basegfx::B3DPoint(
+ rPosition.PositionX ,
+ rPosition.PositionY ,
+ rPosition.PositionZ );
+}
+
+drawing::Direction3D B3DVectorToDirection3D( const ::basegfx::B3DVector& rVector)
+{
+ return drawing::Direction3D(
+ rVector.getX()
+ , rVector.getY()
+ , rVector.getZ()
+ );
+}
+
+drawing::Position3D B3DPointToPosition3D( const ::basegfx::B3DPoint& rPoint)
+{
+ return drawing::Position3D(
+ rPoint.getX()
+ , rPoint.getY()
+ , rPoint.getZ()
+ );
+}
+
+::basegfx::B3DVector Direction3DToB3DVector( const drawing::Direction3D& rDirection)
+{
+ return ::basegfx::B3DVector(
+ rDirection.DirectionX
+ , rDirection.DirectionY
+ , rDirection.DirectionZ
+ );
+}
+
+void AddPointToPoly( drawing::PolyPolygonShape3D& rPoly, const drawing::Position3D& rPos, sal_Int32 nPolygonIndex )
+{
+ if(nPolygonIndex<0)
+ {
+ OSL_FAIL( "The polygon index needs to be > 0");
+ nPolygonIndex=0;
+ }
+
+ //make sure that we have enough polygons
+ if(nPolygonIndex >= rPoly.SequenceX.getLength() )
+ {
+ rPoly.SequenceX.realloc(nPolygonIndex+1);
+ rPoly.SequenceY.realloc(nPolygonIndex+1);
+ rPoly.SequenceZ.realloc(nPolygonIndex+1);
+ }
+
+ drawing::DoubleSequence* pOuterSequenceX = &rPoly.SequenceX.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceY = &rPoly.SequenceY.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceZ = &rPoly.SequenceZ.getArray()[nPolygonIndex];
+
+ sal_Int32 nOldPointCount = pOuterSequenceX->getLength();
+
+ pOuterSequenceX->realloc(nOldPointCount+1);
+ pOuterSequenceY->realloc(nOldPointCount+1);
+ pOuterSequenceZ->realloc(nOldPointCount+1);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ pInnerSequenceX[nOldPointCount] = rPos.PositionX;
+ pInnerSequenceY[nOldPointCount] = rPos.PositionY;
+ pInnerSequenceZ[nOldPointCount] = rPos.PositionZ;
+}
+
+void AddPointToPoly( std::vector<std::vector<css::drawing::Position3D>>& rPoly, const drawing::Position3D& rPos, sal_Int32 nPolygonIndex )
+{
+ if(nPolygonIndex<0)
+ {
+ OSL_FAIL( "The polygon index needs to be > 0");
+ nPolygonIndex=0;
+ }
+
+ //make sure that we have enough polygons
+ if(o3tl::make_unsigned(nPolygonIndex) >= rPoly.size() )
+ {
+ rPoly.resize(nPolygonIndex+1);
+ }
+
+ std::vector<css::drawing::Position3D>* pOuterSequence = &rPoly[nPolygonIndex];
+ pOuterSequence->push_back(rPos);
+}
+
+drawing::Position3D getPointFromPoly( const drawing::PolyPolygonShape3D& rPolygon, sal_Int32 nPointIndex, sal_Int32 nPolyIndex )
+{
+ drawing::Position3D aRet(0.0,0.0,0.0);
+
+ if( nPolyIndex>=0 && nPolyIndex<rPolygon.SequenceX.getLength())
+ {
+ if(nPointIndex<rPolygon.SequenceX[nPolyIndex].getLength())
+ {
+ aRet.PositionX = rPolygon.SequenceX[nPolyIndex][nPointIndex];
+ aRet.PositionY = rPolygon.SequenceY[nPolyIndex][nPointIndex];
+ aRet.PositionZ = rPolygon.SequenceZ[nPolyIndex][nPointIndex];
+ }
+ else
+ {
+ OSL_FAIL("polygon was accessed with a wrong index");
+ }
+ }
+ else
+ {
+ OSL_FAIL("polygon was accessed with a wrong index");
+ }
+ return aRet;
+}
+
+drawing::Position3D getPointFromPoly( const std::vector<std::vector<css::drawing::Position3D>>& rPolygon, sal_Int32 nPointIndex, sal_Int32 nPolyIndex )
+{
+ drawing::Position3D aRet(0.0,0.0,0.0);
+
+ if( nPolyIndex>=0 && o3tl::make_unsigned(nPolyIndex)<rPolygon.size())
+ {
+ if(nPointIndex<static_cast<sal_Int32>(rPolygon[nPolyIndex].size()))
+ {
+ aRet = rPolygon[nPolyIndex][nPointIndex];
+ }
+ else
+ {
+ OSL_FAIL("polygon was accessed with a wrong index");
+ }
+ }
+ else
+ {
+ OSL_FAIL("polygon was accessed with a wrong index");
+ }
+ return aRet;
+}
+
+void addPolygon( std::vector<std::vector<css::drawing::Position3D>>& rRet, const std::vector<std::vector<css::drawing::Position3D>>& rAdd )
+{
+ sal_Int32 nAddOuterCount = rAdd.size();
+ sal_Int32 nOuterCount = rRet.size() + nAddOuterCount;
+ rRet.resize( nOuterCount );
+ auto pSequence = rRet.data();
+
+ sal_Int32 nIndex = 0;
+ sal_Int32 nOuter = nOuterCount - nAddOuterCount;
+ for( ; nOuter < nOuterCount; nOuter++ )
+ {
+ if( nIndex >= nAddOuterCount )
+ break;
+
+ pSequence[nOuter] = rAdd[nIndex];
+
+ nIndex++;
+ }
+}
+
+void appendPoly( std::vector<std::vector<css::drawing::Position3D>>& rRet, const std::vector<std::vector<css::drawing::Position3D>>& rAdd )
+{
+ std::size_t nOuterCount = std::max( rRet.size(), rAdd.size() );
+ rRet.resize(nOuterCount);
+ auto pSequence = rRet.data();
+
+ for( std::size_t nOuter=0;nOuter<nOuterCount;nOuter++ )
+ {
+ sal_Int32 nOldPointCount = rRet[nOuter].size();
+ sal_Int32 nAddPointCount = 0;
+ if(nOuter<rAdd.size())
+ nAddPointCount = rAdd[nOuter].size();
+ if(!nAddPointCount)
+ continue;
+
+ sal_Int32 nNewPointCount = nOldPointCount + nAddPointCount;
+
+ pSequence[nOuter].resize(nNewPointCount);
+ auto pSequence_nOuter = pSequence[nOuter].data();
+
+ sal_Int32 nPointTarget=nOldPointCount;
+ sal_Int32 nPointSource=nAddPointCount;
+ for( ; nPointSource-- ; nPointTarget++ )
+ {
+ pSequence_nOuter[nPointTarget] = rAdd[nOuter][nPointSource];
+ }
+ }
+}
+
+drawing::PolyPolygonShape3D BezierToPoly(
+ const drawing::PolyPolygonBezierCoords& rBezier )
+{
+ const drawing::PointSequenceSequence& rPointSequence = rBezier.Coordinates;
+
+ drawing::PolyPolygonShape3D aRet;
+ aRet.SequenceX.realloc( rPointSequence.getLength() );
+ auto pSequenceX = aRet.SequenceX.getArray();
+ aRet.SequenceY.realloc( rPointSequence.getLength() );
+ auto pSequenceY = aRet.SequenceY.getArray();
+ aRet.SequenceZ.realloc( rPointSequence.getLength() );
+ auto pSequenceZ = aRet.SequenceZ.getArray();
+
+ sal_Int32 nRealOuter = 0;
+ for(sal_Int32 nN = 0; nN < rPointSequence.getLength(); nN++)
+ {
+ sal_Int32 nInnerLength = rPointSequence[nN].getLength();
+ pSequenceX[nRealOuter].realloc( nInnerLength );
+ auto pSequenceX_nRealOuter = pSequenceX[nRealOuter].getArray();
+ pSequenceY[nRealOuter].realloc( nInnerLength );
+ auto pSequenceY_nRealOuter = pSequenceY[nRealOuter].getArray();
+ pSequenceZ[nRealOuter].realloc( nInnerLength );
+ auto pSequenceZ_nRealOuter = pSequenceZ[nRealOuter].getArray();
+
+ bool bHasOuterFlags = nN < rBezier.Flags.getLength();
+
+ sal_Int32 nRealInner = 0;
+ for( sal_Int32 nM = 0; nM < nInnerLength; nM++)
+ {
+ bool bHasInnerFlags = bHasOuterFlags && (nM < rBezier.Flags[nN].getLength());
+
+ if( !bHasInnerFlags || (rBezier.Flags[nN][nM] == drawing::PolygonFlags_NORMAL) )
+ {
+ pSequenceX_nRealOuter[nRealInner] = rPointSequence[nN][nM].X;
+ pSequenceY_nRealOuter[nRealInner] = rPointSequence[nN][nM].Y;
+ pSequenceZ_nRealOuter[nRealInner] = 0.0;
+ nRealInner++;
+ }
+ }
+
+ pSequenceX[nRealOuter].realloc( nRealInner );
+ pSequenceY[nRealOuter].realloc( nRealInner );
+ pSequenceZ[nRealOuter].realloc( nRealInner );
+
+ if( nRealInner>0 )
+ nRealOuter++;
+ }
+
+ aRet.SequenceX.realloc( nRealOuter );
+ aRet.SequenceY.realloc( nRealOuter );
+ aRet.SequenceZ.realloc( nRealOuter );
+
+ return aRet;
+}
+
+drawing::PointSequenceSequence PolyToPointSequence(
+ const drawing::PolyPolygonShape3D& rPolyPolygon )
+{
+ drawing::PointSequenceSequence aRet;
+ aRet.realloc( rPolyPolygon.SequenceX.getLength() );
+ auto pRet = aRet.getArray();
+
+ for(sal_Int32 nN = 0; nN < rPolyPolygon.SequenceX.getLength(); nN++)
+ {
+ sal_Int32 nInnerLength = rPolyPolygon.SequenceX[nN].getLength();
+ pRet[nN].realloc( nInnerLength );
+ auto pRet_nN = pRet[nN].getArray();
+ for( sal_Int32 nM = 0; nM < nInnerLength; nM++)
+ {
+ pRet_nN[nM].X = static_cast<sal_Int32>(rPolyPolygon.SequenceX[nN][nM]);
+ pRet_nN[nM].Y = static_cast<sal_Int32>(rPolyPolygon.SequenceY[nN][nM]);
+ }
+ }
+ return aRet;
+}
+
+drawing::PointSequenceSequence PolyToPointSequence(
+ const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon )
+{
+ drawing::PointSequenceSequence aRet;
+ aRet.realloc( rPolyPolygon.size() );
+ auto pRet = aRet.getArray();
+
+ for(std::size_t nN = 0; nN < rPolyPolygon.size(); nN++)
+ {
+ sal_Int32 nInnerLength = rPolyPolygon[nN].size();
+ pRet[nN].realloc( nInnerLength );
+ auto pRet_nN = pRet[nN].getArray();
+ for( sal_Int32 nM = 0; nM < nInnerLength; nM++)
+ {
+ pRet_nN[nM].X = static_cast<sal_Int32>(rPolyPolygon[nN][nM].PositionX);
+ pRet_nN[nM].Y = static_cast<sal_Int32>(rPolyPolygon[nN][nM].PositionY);
+ }
+ }
+ return aRet;
+}
+
+basegfx::B2DPolyPolygon PolyToB2DPolyPolygon(
+ const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon )
+{
+ basegfx::B2DPolyPolygon aRetval;
+
+ for(auto const & nN: rPolyPolygon)
+ {
+ basegfx::B2DPolygon aNewPolygon;
+ sal_Int32 nInnerLength = nN.size();
+ if(nInnerLength)
+ {
+ aNewPolygon.reserve(nInnerLength);
+ for( sal_Int32 nM = 0; nM < nInnerLength; nM++)
+ {
+ auto X = static_cast<sal_Int32>(nN[nM].PositionX);
+ auto Y = static_cast<sal_Int32>(nN[nM].PositionY);
+ aNewPolygon.append(basegfx::B2DPoint(X, Y));
+ }
+ // check for closed state flag
+ basegfx::utils::checkClosed(aNewPolygon);
+ }
+ aRetval.append(std::move(aNewPolygon));
+ }
+
+ return aRetval;
+}
+
+void appendPointSequence( drawing::PointSequenceSequence& rTarget
+ , const drawing::PointSequenceSequence& rAdd )
+{
+ sal_Int32 nAddCount = rAdd.getLength();
+ if(!nAddCount)
+ return;
+ sal_Int32 nOldCount = rTarget.getLength();
+
+ rTarget.realloc(nOldCount+nAddCount);
+ auto pTarget = rTarget.getArray();
+ for(sal_Int32 nS=0; nS<nAddCount; nS++ )
+ pTarget[nOldCount+nS]=rAdd[nS];
+}
+
+drawing::Position3D operator+( const drawing::Position3D& rPos
+ , const drawing::Direction3D& rDirection)
+{
+ return drawing::Position3D(
+ rPos.PositionX + rDirection.DirectionX
+ , rPos.PositionY + rDirection.DirectionY
+ , rPos.PositionZ + rDirection.DirectionZ
+ );
+}
+
+drawing::Direction3D operator-( const drawing::Position3D& rPos1
+ , const drawing::Position3D& rPos2)
+{
+ return drawing::Direction3D(
+ rPos1.PositionX - rPos2.PositionX
+ , rPos1.PositionY - rPos2.PositionY
+ , rPos1.PositionZ - rPos2.PositionZ
+ );
+}
+
+awt::Point Position3DToAWTPoint( const drawing::Position3D& rPos )
+{
+ awt::Point aRet;
+ aRet.X = static_cast<sal_Int32>(rPos.PositionX);
+ aRet.Y = static_cast<sal_Int32>(rPos.PositionY);
+ return aRet;
+}
+
+awt::Point ToPoint( const awt::Rectangle& rRectangle )
+{
+ return awt::Point( rRectangle.X, rRectangle.Y );
+}
+
+awt::Size ToSize( const awt::Rectangle& rRectangle )
+{
+ return awt::Size( rRectangle.Width, rRectangle.Height );
+}
+
+awt::Size Direction3DToAWTSize( const drawing::Direction3D& rDirection )
+{
+ awt::Size aRet;
+ aRet.Width = static_cast<sal_Int32>(rDirection.DirectionX);
+ aRet.Height = static_cast<sal_Int32>(rDirection.DirectionY);
+ return aRet;
+}
+
+drawing::Position3D SequenceToPosition3D( const uno::Sequence< double >& rSeq )
+{
+ OSL_ENSURE(rSeq.getLength()==3,"The sequence needs to have length 3 for conversion into vector");
+
+ drawing::Position3D aRet;
+ aRet.PositionX = rSeq.getLength()>0?rSeq[0]:0.0;
+ aRet.PositionY = rSeq.getLength()>1?rSeq[1]:0.0;
+ aRet.PositionZ = rSeq.getLength()>2?rSeq[2]:0.0;
+ return aRet;
+}
+
+using namespace ::com::sun::star::chart2;
+
+uno::Sequence< double > DataSequenceToDoubleSequence(
+ const uno::Reference< data::XDataSequence >& xDataSequence )
+{
+ uno::Sequence< double > aResult;
+ OSL_ASSERT( xDataSequence.is());
+ if(!xDataSequence.is())
+ return aResult;
+
+ uno::Reference< data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
+ if( xNumericalDataSequence.is() )
+ {
+ aResult = xNumericalDataSequence->getNumericalData();
+ }
+ else
+ {
+ uno::Sequence< uno::Any > aValues = xDataSequence->getData();
+ aResult.realloc(aValues.getLength());
+ auto pResult = aResult.getArray();
+ for(sal_Int32 nN=aValues.getLength();nN--;)
+ {
+ if( !(aValues[nN] >>= pResult[nN]) )
+ pResult[nN] = std::numeric_limits<double>::quiet_NaN();
+ }
+ }
+
+ return aResult;
+}
+
+uno::Sequence< OUString > DataSequenceToStringSequence(
+ const uno::Reference< data::XDataSequence >& xDataSequence )
+{
+ uno::Sequence< OUString > aResult;
+ if(!xDataSequence.is())
+ return aResult;
+
+ uno::Reference< data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
+ if( xTextualDataSequence.is() )
+ {
+ aResult = xTextualDataSequence->getTextualData();
+ }
+ else
+ {
+ uno::Sequence< uno::Any > aValues = xDataSequence->getData();
+ aResult.realloc(aValues.getLength());
+ auto pResult = aResult.getArray();
+
+ for(sal_Int32 nN=aValues.getLength();nN--;)
+ aValues[nN] >>= pResult[nN];
+ }
+
+ return aResult;
+}
+
+bool hasDoubleValue( const uno::Any& rAny )
+{
+ bool bRet = false;
+ double fValue = 0.0;
+ if( rAny >>= fValue )
+ bRet = true;
+ return bRet;
+}
+
+bool hasLongOrShortValue( const uno::Any& rAny )
+{
+ bool bRet = false;
+ sal_Int32 n32 = 0;
+ if( rAny >>= n32 )
+ bRet = true;
+ else
+ {
+ sal_Int16 n16 = 0;
+ if( rAny >>= n16 )
+ bRet = true;
+ }
+ return bRet;
+}
+sal_Int16 getShortForLongAlso( const uno::Any& rAny )
+{
+ sal_Int16 nRet = 0;
+
+ if( !(rAny >>= nRet) )
+ {
+ sal_Int32 n32 = 0;
+ if( rAny >>= n32 )
+ nRet = static_cast<sal_Int16>(n32);
+ }
+ return nRet;
+}
+
+bool replaceParamterInString( OUString & rInOutResourceString,
+ std::u16string_view rParamToReplace,
+ std::u16string_view rReplaceWith )
+{
+ sal_Int32 nPos = rInOutResourceString.indexOf( rParamToReplace );
+ if( nPos == -1 )
+ return false;
+
+ rInOutResourceString = rInOutResourceString.replaceAt( nPos
+ , rParamToReplace.size(), rReplaceWith );
+ return true;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ConfigColorScheme.cxx b/chart2/source/tools/ConfigColorScheme.cxx
new file mode 100644
index 0000000000..24ee5facb6
--- /dev/null
+++ b/chart2/source/tools/ConfigColorScheme.cxx
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ConfigColorScheme.hxx>
+
+#include <unotools/configitem.hxx>
+#include <sal/macros.h>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <set>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+
+constexpr OUString aSeriesPropName = u"Series"_ustr;
+
+} // anonymous namespace
+
+namespace chart
+{
+
+uno::Reference< chart2::XColorScheme > createConfigColorScheme( const uno::Reference< uno::XComponentContext > & xContext )
+{
+ return new ConfigColorScheme( xContext );
+}
+
+namespace impl
+{
+class ChartConfigItem : public ::utl::ConfigItem
+{
+public:
+ explicit ChartConfigItem( ConfigColorScheme & rListener );
+
+ uno::Any getProperty( const OUString & aPropertyName );
+
+protected:
+ // ____ ::utl::ConfigItem ____
+ virtual void ImplCommit() override;
+ virtual void Notify( const Sequence< OUString > & aPropertyNames ) override;
+
+private:
+ ConfigColorScheme & m_rListener;
+};
+
+ChartConfigItem::ChartConfigItem( ConfigColorScheme & rListener ) :
+ ::utl::ConfigItem( "Office.Chart/DefaultColor" ),
+ m_rListener( rListener )
+{
+ EnableNotification( { aSeriesPropName } );
+}
+
+void ChartConfigItem::Notify( const Sequence< OUString > & aPropertyNames )
+{
+ for( OUString const & s : aPropertyNames )
+ {
+ if( s == aSeriesPropName )
+ m_rListener.notify();
+ }
+}
+
+void ChartConfigItem::ImplCommit()
+{}
+
+uno::Any ChartConfigItem::getProperty( const OUString & aPropertyName )
+{
+ Sequence< uno::Any > aValues(
+ GetProperties( Sequence< OUString >( &aPropertyName, 1 )));
+ if( ! aValues.hasElements())
+ return uno::Any();
+ return aValues[0];
+}
+
+} // namespace impl
+
+// explicit
+ConfigColorScheme::ConfigColorScheme(
+ const Reference< uno::XComponentContext > & xContext ) :
+ m_xContext( xContext ),
+ m_nNumberOfColors( 0 ),
+ m_bNeedsUpdate( true )
+{
+}
+
+ConfigColorScheme::~ConfigColorScheme()
+{}
+
+void ConfigColorScheme::retrieveConfigColors()
+{
+ if( ! m_xContext.is())
+ return;
+
+ // create config item if necessary
+ if (!m_apChartConfigItem)
+ {
+ m_apChartConfigItem.reset(
+ new impl::ChartConfigItem( *this ));
+ }
+ assert(m_apChartConfigItem && "this can only be set at this point");
+
+ // retrieve colors
+ uno::Any aValue(
+ m_apChartConfigItem->getProperty( aSeriesPropName ));
+ if( aValue >>= m_aColorSequence )
+ m_nNumberOfColors = m_aColorSequence.getLength();
+ m_bNeedsUpdate = false;
+}
+
+// ____ XColorScheme ____
+::sal_Int32 SAL_CALL ConfigColorScheme::getColorByIndex( ::sal_Int32 nIndex )
+{
+ if( m_bNeedsUpdate )
+ retrieveConfigColors();
+
+ if( m_nNumberOfColors > 0 )
+ return static_cast< sal_Int32 >( m_aColorSequence[ nIndex % m_nNumberOfColors ] );
+
+ // fall-back: hard-coded standard colors
+ static const sal_Int32 nDefaultColors[] = {
+ 0x9999ff, 0x993366, 0xffffcc,
+ 0xccffff, 0x660066, 0xff8080,
+ 0x0066cc, 0xccccff, 0x000080,
+ 0xff00ff, 0x00ffff, 0xffff00
+ };
+
+ static const sal_Int32 nMaxDefaultColors = std::size( nDefaultColors );
+ return nDefaultColors[ nIndex % nMaxDefaultColors ];
+}
+
+void ConfigColorScheme::notify()
+{
+ m_bNeedsUpdate = true;
+}
+
+OUString SAL_CALL ConfigColorScheme::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.ConfigDefaultColorScheme" ;
+}
+
+sal_Bool SAL_CALL ConfigColorScheme::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ConfigColorScheme::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.ColorScheme" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_ConfigDefaultColorScheme_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::ConfigColorScheme(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ControllerLockGuard.cxx b/chart2/source/tools/ControllerLockGuard.cxx
new file mode 100644
index 0000000000..6bfe8e4a95
--- /dev/null
+++ b/chart2/source/tools/ControllerLockGuard.cxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ControllerLockGuard.hxx>
+#include <ChartModel.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+ControllerLockGuardUNO::ControllerLockGuardUNO( rtl::Reference<::chart::ChartModel> xModel ) :
+ mxModel(std::move( xModel ))
+{
+ mxModel->lockControllers();
+}
+
+ControllerLockGuardUNO::~ControllerLockGuardUNO()
+{
+ mxModel->unlockControllers();
+}
+
+ControllerLockGuard::ControllerLockGuard( ChartModel& rModel ) :
+ mrModel( rModel )
+{
+ mrModel.lockControllers();
+}
+
+ControllerLockGuard::~ControllerLockGuard()
+{
+ mrModel.unlockControllers();
+}
+
+ControllerLockHelper::ControllerLockHelper( rtl::Reference<::chart::ChartModel> xModel ) :
+ m_xModel(std::move( xModel ))
+{}
+
+ControllerLockHelper::~ControllerLockHelper()
+{}
+
+void ControllerLockHelper::lockControllers()
+{
+ if( m_xModel.is())
+ m_xModel->lockControllers();
+}
+
+void ControllerLockHelper::unlockControllers()
+{
+ if( m_xModel.is())
+ m_xModel->unlockControllers();
+}
+
+ControllerLockHelperGuard::ControllerLockHelperGuard( ControllerLockHelper & rHelper ) :
+ m_rHelper( rHelper )
+{
+ m_rHelper.lockControllers();
+}
+
+ControllerLockHelperGuard::~ControllerLockHelperGuard()
+{
+ m_rHelper.unlockControllers();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/DataSeriesHelper.cxx b/chart2/source/tools/DataSeriesHelper.cxx
new file mode 100644
index 0000000000..de88c37ecc
--- /dev/null
+++ b/chart2/source/tools/DataSeriesHelper.cxx
@@ -0,0 +1,680 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DataSeriesHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesProperties.hxx>
+#include <DataSource.hxx>
+#include <ChartType.hxx>
+#include <unonames.hxx>
+#include <Diagram.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <Axis.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/data/LabelOrigin.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/SymbolStyle.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart2/XDiagram.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+
+#include <comphelper/sequence.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+#include <iterator>
+#include <utility>
+#include <vector>
+#include <set>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart::DataSeriesProperties;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+
+class lcl_MatchesRole
+{
+public:
+ explicit lcl_MatchesRole( OUString aRole, bool bMatchPrefix ) :
+ m_aRole(std::move( aRole )),
+ m_bMatchPrefix( bMatchPrefix )
+ {}
+
+ bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
+ {
+ if(!xSeq.is())
+ return false;
+ Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
+ OUString aRole;
+
+ if( m_bMatchPrefix )
+ return ( xProp.is() &&
+ (xProp->getPropertyValue( "Role" ) >>= aRole ) &&
+ aRole.match( m_aRole ));
+
+ return ( xProp.is() &&
+ (xProp->getPropertyValue( "Role" ) >>= aRole ) &&
+ m_aRole == aRole );
+ }
+
+private:
+ OUString m_aRole;
+ bool m_bMatchPrefix;
+};
+
+void lcl_getCooSysAndChartTypeOfSeries(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ const Reference< chart2::XDiagram > & xDiagram,
+ rtl::Reference< ::chart::BaseCoordinateSystem > & xOutCooSys,
+ rtl::Reference< ::chart::ChartType > & xOutChartType )
+{
+ if( !xDiagram.is())
+ return;
+ ::chart::Diagram* pDiagram = dynamic_cast<::chart::Diagram*>(xDiagram.get());
+
+ for( rtl::Reference< ::chart::BaseCoordinateSystem > const & coords : pDiagram->getBaseCoordinateSystems() )
+ {
+ for( rtl::Reference< ::chart::ChartType > const & chartType : coords->getChartTypes2() )
+ {
+ for( rtl::Reference< ::chart::DataSeries > const & dataSeries : chartType->getDataSeries2() )
+ {
+ if( dataSeries == xSeries )
+ {
+ xOutCooSys = coords;
+ xOutChartType = chartType;
+ }
+ }
+ }
+ }
+}
+
+void lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( const rtl::Reference< ::chart::DataSeries >& xSeries, bool bInsert )
+{
+ try
+ {
+ if( xSeries.is() )
+ {
+ DataPointLabel aLabelAtSeries;
+ xSeries->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabelAtSeries;
+ aLabelAtSeries.ShowNumber = bInsert;
+ if( !bInsert )
+ {
+ aLabelAtSeries.ShowNumberInPercent = false;
+ aLabelAtSeries.ShowCategoryName = false;
+ }
+ xSeries->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabelAtSeries));
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ // "AttributedDataPoints"
+ if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
+ {
+ for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
+ {
+ Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
+ if( xPointProp.is() )
+ {
+ DataPointLabel aLabel;
+ xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel;
+ aLabel.ShowNumber = bInsert;
+ if( !bInsert )
+ {
+ aLabel.ShowNumberInPercent = false;
+ aLabel.ShowCategoryName = false;
+ aLabel.ShowCustomLabel = false;
+ aLabel.ShowSeriesName = false;
+ }
+ xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabel));
+ xPointProp->setPropertyValue(CHART_UNONAME_CUSTOM_LABEL_FIELDS, uno::Any());
+ }
+ }
+ }
+ }
+ }
+ catch(const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+} // anonymous namespace
+
+namespace chart::DataSeriesHelper
+{
+
+OUString getRole( const uno::Reference< chart2::data::XLabeledDataSequence >& xLabeledDataSequence )
+{
+ OUString aRet;
+ if( xLabeledDataSequence.is() )
+ {
+ Reference< beans::XPropertySet > xProp( xLabeledDataSequence->getValues(), uno::UNO_QUERY );
+ if( xProp.is() )
+ xProp->getPropertyValue( "Role" ) >>= aRet;
+ }
+ return aRet;
+}
+
+uno::Reference< chart2::data::XLabeledDataSequence >
+ getDataSequenceByRole(
+ const Reference< chart2::data::XDataSource > & xSource,
+ const OUString& aRole,
+ bool bMatchPrefix /* = false */ )
+{
+ uno::Reference< chart2::data::XLabeledDataSequence > aNoResult;
+ if( ! xSource.is())
+ return aNoResult;
+ const Sequence< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences());
+ try
+ {
+ for (auto const & i : aLabeledSeq)
+ {
+ if (lcl_MatchesRole(aRole, bMatchPrefix)(i))
+ return i;
+ }
+ }
+ catch (const lang::DisposedException&)
+ {
+ TOOLS_WARN_EXCEPTION( "chart2", "unexpected exception caught" );
+ }
+
+ return aNoResult;
+}
+
+std::vector< uno::Reference< chart2::data::XLabeledDataSequence > >
+ getAllDataSequencesByRole( const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aDataSequences,
+ const OUString& aRole )
+{
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aResultVec;
+ for (const auto & i : aDataSequences)
+ {
+ if (lcl_MatchesRole(aRole, /*bMatchPrefix*/true)(i))
+ aResultVec.push_back(i);
+ }
+ return aResultVec;
+}
+
+std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence > >
+ getAllDataSequencesByRole( const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aDataSequences,
+ const OUString& aRole )
+{
+ std::vector< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > aResultVec;
+ std::copy_if( aDataSequences.begin(), aDataSequences.end(),
+ std::back_inserter( aResultVec ),
+ lcl_MatchesRole(aRole, /*bMatchPrefix*/true) );
+ return aResultVec;
+}
+
+std::vector<uno::Reference<chart2::data::XLabeledDataSequence> >
+getAllDataSequences( const std::vector<rtl::Reference<DataSeries> >& aSeries )
+{
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aSeqVec;
+
+ for( rtl::Reference<DataSeries> const & dataSeries : aSeries )
+ {
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aSeq( dataSeries->getDataSequences2());
+ aSeqVec.insert( aSeqVec.end(), aSeq.begin(), aSeq.end() );
+ }
+
+ return aSeqVec;
+}
+
+rtl::Reference< DataSource >
+ getDataSource( const std::vector< rtl::Reference< DataSeries > > & aSeries )
+{
+ return new DataSource(getAllDataSequences(aSeries));
+}
+
+void setStackModeAtSeries(
+ const std::vector< rtl::Reference< DataSeries > > & aSeries,
+ const rtl::Reference< BaseCoordinateSystem > & xCorrespondingCoordinateSystem,
+ StackMode eStackMode )
+{
+ const uno::Any aPropValue(
+ ( (eStackMode == StackMode::YStacked) ||
+ (eStackMode == StackMode::YStackedPercent) )
+ ? chart2::StackingDirection_Y_STACKING
+ : (eStackMode == StackMode::ZStacked )
+ ? chart2::StackingDirection_Z_STACKING
+ : chart2::StackingDirection_NO_STACKING );
+
+ std::set< sal_Int32 > aAxisIndexSet;
+ for( rtl::Reference< DataSeries > const & dataSeries : aSeries )
+ {
+ try
+ {
+ if( dataSeries.is() )
+ {
+ dataSeries->setPropertyValue( "StackingDirection", aPropValue );
+
+ sal_Int32 nAxisIndex = 0;
+ dataSeries->getPropertyValue( "AttachedAxisIndex" ) >>= nAxisIndex;
+ aAxisIndexSet.insert(nAxisIndex);
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ if( !(xCorrespondingCoordinateSystem.is() &&
+ 1 < xCorrespondingCoordinateSystem->getDimension()) )
+ return;
+
+ if( aAxisIndexSet.empty() )
+ {
+ aAxisIndexSet.insert(0);
+ }
+
+ for (auto const& axisIndex : aAxisIndexSet)
+ {
+ rtl::Reference< Axis > xAxis =
+ xCorrespondingCoordinateSystem->getAxisByDimension2(1, axisIndex);
+ if( xAxis.is())
+ {
+ bool bPercent = (eStackMode == StackMode::YStackedPercent);
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+
+ if( bPercent != (aScaleData.AxisType==chart2::AxisType::PERCENT) )
+ {
+ if( bPercent )
+ aScaleData.AxisType = chart2::AxisType::PERCENT;
+ else
+ aScaleData.AxisType = chart2::AxisType::REALNUMBER;
+ xAxis->setScaleData( aScaleData );
+ }
+ }
+ }
+}
+
+sal_Int32 getAttachedAxisIndex( const rtl::Reference< DataSeries > & xSeries )
+{
+ sal_Int32 nRet = 0;
+ try
+ {
+ if( xSeries.is() )
+ {
+ xSeries->getPropertyValue( "AttachedAxisIndex" ) >>= nRet;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return nRet;
+}
+
+sal_Int32 getNumberFormatKeyFromAxis(
+ const rtl::Reference< DataSeries > & xSeries,
+ const rtl::Reference< BaseCoordinateSystem > & xCorrespondingCoordinateSystem,
+ sal_Int32 nDimensionIndex,
+ sal_Int32 nAxisIndex /* = -1 */ )
+{
+ sal_Int32 nResult = 0;
+ if( nAxisIndex == -1 )
+ nAxisIndex = getAttachedAxisIndex( xSeries );
+ try
+ {
+ rtl::Reference< Axis > xAxisProp =
+ xCorrespondingCoordinateSystem->getAxisByDimension2( nDimensionIndex, nAxisIndex );
+ if( xAxisProp.is())
+ xAxisProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nResult;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return nResult;
+}
+
+rtl::Reference< ::chart::BaseCoordinateSystem > getCoordinateSystemOfSeries(
+ const rtl::Reference< DataSeries > & xSeries,
+ const rtl::Reference< Diagram > & xDiagram )
+{
+ rtl::Reference< ::chart::BaseCoordinateSystem > xResult;
+ rtl::Reference< ::chart::ChartType > xDummy;
+ lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xResult, xDummy );
+
+ return xResult;
+}
+
+rtl::Reference< ::chart::ChartType > getChartTypeOfSeries(
+ const rtl::Reference< DataSeries > & xSeries,
+ const rtl::Reference< Diagram > & xDiagram )
+{
+ rtl::Reference< ::chart::ChartType > xResult;
+ rtl::Reference< ::chart::BaseCoordinateSystem > xDummy;
+ lcl_getCooSysAndChartTypeOfSeries( xSeries, xDiagram, xDummy, xResult );
+
+ return xResult;
+}
+
+void deleteSeries(
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ const rtl::Reference< ::chart::ChartType > & xChartType )
+{
+ try
+ {
+ std::vector< rtl::Reference< DataSeries > > aSeries = xChartType->getDataSeries2();
+ auto aIt = std::find( aSeries.begin(), aSeries.end(), xSeries );
+ if( aIt != aSeries.end())
+ {
+ aSeries.erase( aIt );
+ xChartType->setDataSeries( aSeries );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void switchSymbolsOnOrOff( const rtl::Reference< DataSeries > & xSeries,
+ bool bSymbolsOn, sal_Int32 nSeriesIndex )
+{
+ if( !xSeries )
+ return;
+
+ chart2::Symbol aSymbProp;
+ if( xSeries->getPropertyValue( "Symbol") >>= aSymbProp )
+ {
+ if( !bSymbolsOn )
+ aSymbProp.Style = chart2::SymbolStyle_NONE;
+ else if( aSymbProp.Style == chart2::SymbolStyle_NONE )
+ {
+ aSymbProp.Style = chart2::SymbolStyle_STANDARD;
+ aSymbProp.StandardSymbol = nSeriesIndex;
+ }
+ xSeries->setPropertyValue( "Symbol", uno::Any( aSymbProp ));
+ }
+ //todo: check attributed data points
+}
+
+void switchLinesOnOrOff( const rtl::Reference< DataSeries > & xSeries, bool bLinesOn )
+{
+ if( !xSeries )
+ return;
+
+ if( bLinesOn )
+ {
+ // keep line-styles that are not NONE
+ drawing::LineStyle eLineStyle;
+ if( (xSeries->getPropertyValue( "LineStyle") >>= eLineStyle ) &&
+ eLineStyle == drawing::LineStyle_NONE )
+ {
+ xSeries->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_SOLID ) );
+ }
+ }
+ else
+ xSeries->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE ) );
+}
+
+void makeLinesThickOrThin( const rtl::Reference< ::chart::DataSeries > & xSeries, bool bThick )
+{
+ if( !xSeries )
+ return;
+
+ sal_Int32 nNewValue = bThick ? 80 : 0;
+ sal_Int32 nOldValue = 0;
+ if( (xSeries->getPropertyValue( "LineWidth") >>= nOldValue ) &&
+ nOldValue != nNewValue )
+ {
+ if( !(bThick && nOldValue>0))
+ xSeries->setPropertyValue( "LineWidth", uno::Any( nNewValue ) );
+ }
+}
+
+void setPropertyAlsoToAllAttributedDataPoints( const rtl::Reference< ::chart::DataSeries >& xSeries,
+ const OUString& rPropertyName, const uno::Any& rPropertyValue )
+{
+ if( !xSeries.is() )
+ return;
+
+ xSeries->setPropertyValue( rPropertyName, rPropertyValue );
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ // "AttributedDataPoints"
+ if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
+ {
+ for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
+ {
+ Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
+ if(!xPointProp.is())
+ continue;
+ xPointProp->setPropertyValue( rPropertyName, rPropertyValue );
+ if( rPropertyName == "LabelPlacement" )
+ xPointProp->setPropertyValue("CustomLabelPosition", uno::Any());
+ }
+ }
+}
+
+bool hasAttributedDataPointDifferentValue( const rtl::Reference< DataSeries >& xSeries,
+ const OUString& rPropertyName, const uno::Any& rPropertyValue )
+{
+ if( !xSeries.is() )
+ return false;
+
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ // "AttributedDataPoints"
+ if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
+ {
+ for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
+ {
+ Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
+ if(!xPointProp.is())
+ continue;
+ uno::Any aPointValue( xPointProp->getPropertyValue( rPropertyName ) );
+ if( rPropertyValue != aPointValue )
+ return true;
+ }
+ }
+ return false;
+}
+
+namespace
+{
+
+}
+
+sal_Int32 translateIndexFromHiddenToFullSequence( sal_Int32 nIndex, const Reference< chart2::data::XDataSequence >& xDataSequence, bool bTranslate )
+{
+ if( !bTranslate )
+ return nIndex;
+
+ try
+ {
+ uno::Reference<beans::XPropertySet> xProp( xDataSequence, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ Sequence<sal_Int32> aHiddenIndicesSeq;
+ xProp->getPropertyValue( "HiddenValues" ) >>= aHiddenIndicesSeq;
+ if( aHiddenIndicesSeq.hasElements() )
+ {
+ auto aHiddenIndices( comphelper::sequenceToContainer<std::vector< sal_Int32 >>( aHiddenIndicesSeq ) );
+ std::sort( aHiddenIndices.begin(), aHiddenIndices.end() );
+
+ sal_Int32 nHiddenCount = static_cast<sal_Int32>(aHiddenIndices.size());
+ for( sal_Int32 nN = 0; nN < nHiddenCount; ++nN)
+ {
+ if( aHiddenIndices[nN] <= nIndex )
+ nIndex += 1;
+ else
+ break;
+ }
+ }
+ }
+ }
+ catch (const beans::UnknownPropertyException&)
+ {
+ }
+ return nIndex;
+}
+
+bool hasDataLabelsAtSeries( const rtl::Reference< DataSeries >& xSeries )
+{
+ bool bRet = false;
+ try
+ {
+ if( xSeries.is() )
+ {
+ DataPointLabel aLabel;
+ if( xSeries->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel )
+ bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent || aLabel.ShowCategoryName
+ || aLabel.ShowSeriesName;
+ }
+ }
+ catch(const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return bRet;
+}
+
+bool hasDataLabelsAtPoints( const rtl::Reference< DataSeries >& xSeries )
+{
+ bool bRet = false;
+ try
+ {
+ if( xSeries.is() )
+ {
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ // "AttributedDataPoints"
+ if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
+ {
+ for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
+ {
+ Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex(aAttributedDataPointIndexList[nN]) );
+ if( xPointProp.is() )
+ {
+ DataPointLabel aLabel;
+ if( xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel )
+ bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent
+ || aLabel.ShowCategoryName || aLabel.ShowCustomLabel
+ || aLabel.ShowSeriesName;
+ if( bRet )
+ break;
+ }
+ }
+ }
+ }
+ }
+ catch(const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return bRet;
+}
+
+bool hasDataLabelAtPoint( const rtl::Reference< DataSeries >& xSeries, sal_Int32 nPointIndex )
+{
+ bool bRet = false;
+ try
+ {
+ Reference< beans::XPropertySet > xProp;
+ if( xSeries.is() )
+ {
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ // "AttributedDataPoints"
+ if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
+ {
+ auto aIt = std::find( std::as_const(aAttributedDataPointIndexList).begin(), std::as_const(aAttributedDataPointIndexList).end(), nPointIndex );
+ if( aIt != std::as_const(aAttributedDataPointIndexList).end())
+ xProp = xSeries->getDataPointByIndex(nPointIndex);
+ else
+ xProp = xSeries;
+ }
+ if( xProp.is() )
+ {
+ DataPointLabel aLabel;
+ if( xProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel )
+ bRet = aLabel.ShowNumber || aLabel.ShowNumberInPercent
+ || aLabel.ShowCategoryName || aLabel.ShowCustomLabel
+ || aLabel.ShowSeriesName;
+ }
+ }
+ }
+ catch(const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return bRet;
+}
+
+void insertDataLabelsToSeriesAndAllPoints( const rtl::Reference< DataSeries >& xSeries )
+{
+ lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, true /*bInsert*/ );
+}
+
+void deleteDataLabelsFromSeriesAndAllPoints( const rtl::Reference< DataSeries >& xSeries )
+{
+ lcl_insertOrDeleteDataLabelsToSeriesAndAllPoints( xSeries, false /*bInsert*/ );
+}
+
+void insertDataLabelToPoint( const Reference< beans::XPropertySet >& xPointProp )
+{
+ try
+ {
+ if( xPointProp.is() )
+ {
+ DataPointLabel aLabel;
+ xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel;
+ aLabel.ShowNumber = true;
+ xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabel));
+ }
+ }
+ catch(const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void deleteDataLabelsFromPoint( const Reference< beans::XPropertySet >& xPointProp )
+{
+ try
+ {
+ if( xPointProp.is() )
+ {
+ DataPointLabel aLabel;
+ xPointProp->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel;
+ aLabel.ShowNumber = false;
+ aLabel.ShowNumberInPercent = false;
+ aLabel.ShowCategoryName = false;
+ aLabel.ShowCustomLabel = false;
+ aLabel.ShowSeriesName = false;
+ xPointProp->setPropertyValue(CHART_UNONAME_LABEL, uno::Any(aLabel));
+ xPointProp->setPropertyValue(CHART_UNONAME_CUSTOM_LABEL_FIELDS, uno::Any());
+ }
+ }
+ catch(const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/DataSource.cxx b/chart2/source/tools/DataSource.cxx
new file mode 100644
index 0000000000..c74687c148
--- /dev/null
+++ b/chart2/source/tools/DataSource.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DataSource.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/sequence.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+
+using namespace ::com::sun::star;
+
+
+namespace chart
+{
+
+DataSource::DataSource()
+{}
+
+DataSource::DataSource(
+ const Sequence< Reference< chart2::data::XLabeledDataSequence > > & rSequences ) :
+ m_aDataSeq( rSequences )
+{}
+
+DataSource::DataSource(
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & rSequences )
+{
+ m_aDataSeq = comphelper::containerToSequence< Reference< chart2::data::XLabeledDataSequence > >(rSequences);
+}
+
+DataSource::~DataSource()
+{}
+
+// ____ XDataSource ____
+Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL DataSource::getDataSequences()
+{
+ return m_aDataSeq;
+}
+
+// ____ XDataSink ____
+void SAL_CALL DataSource::setData( const Sequence< Reference< chart2::data::XLabeledDataSequence > >& aData )
+{
+ m_aDataSeq = aData;
+}
+
+OUString SAL_CALL DataSource::getImplementationName()
+{
+ return "com.sun.star.comp.chart.DataSource";
+}
+
+sal_Bool SAL_CALL DataSource::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL DataSource::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.data.DataSource" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_DataSource_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::DataSource);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/DataSourceHelper.cxx b/chart2/source/tools/DataSourceHelper.cxx
new file mode 100644
index 0000000000..4f42e6e640
--- /dev/null
+++ b/chart2/source/tools/DataSourceHelper.cxx
@@ -0,0 +1,477 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DataSourceHelper.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartTypeManager.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DataSource.hxx>
+#include <ControllerLockGuard.hxx>
+#include <CachedDataSequence.hxx>
+#include <LabeledDataSequence.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
+
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+void lcl_addRanges( std::vector< OUString > & rOutResult,
+ const uno::Reference< data::XLabeledDataSequence > & xLabeledSeq )
+{
+ if( ! xLabeledSeq.is())
+ return;
+ uno::Reference< data::XDataSequence > xSeq( xLabeledSeq->getLabel());
+ if( xSeq.is())
+ rOutResult.push_back( xSeq->getSourceRangeRepresentation());
+ xSeq.set( xLabeledSeq->getValues());
+ if( xSeq.is())
+ rOutResult.push_back( xSeq->getSourceRangeRepresentation());
+}
+
+void lcl_addDataSourceRanges(
+ std::vector< OUString > & rOutResult,
+ const uno::Reference< data::XDataSource > & xDataSource )
+{
+ if( xDataSource.is() )
+ {
+ const auto aDataSequences(xDataSource->getDataSequences());
+ for (const auto& rDataSequence : aDataSequences)
+ lcl_addRanges(rOutResult, rDataSequence);
+ }
+}
+
+void lcl_addErrorBarRanges(
+ std::vector< OUString > & rOutResult,
+ const rtl::Reference< DataSeries > & xDataSeries )
+{
+ if( !xDataSeries.is())
+ return;
+
+ try
+ {
+ uno::Reference< beans::XPropertySet > xErrorBarProp;
+ if( ( xDataSeries->getPropertyValue( CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarProp ) &&
+ xErrorBarProp.is())
+ {
+ sal_Int32 eStyle = css::chart::ErrorBarStyle::NONE;
+ if( ( xErrorBarProp->getPropertyValue( "ErrorBarStyle") >>= eStyle ) &&
+ eStyle == css::chart::ErrorBarStyle::FROM_DATA )
+ {
+ uno::Reference< data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
+ if( xErrorBarDataSource.is() )
+ lcl_addDataSourceRanges( rOutResult, xErrorBarDataSource );
+ }
+ }
+
+ if( ( xDataSeries->getPropertyValue(CHART_UNONAME_ERRORBAR_X) >>= xErrorBarProp ) && xErrorBarProp.is())
+ {
+ sal_Int32 eStyle = css::chart::ErrorBarStyle::NONE;
+ if( ( xErrorBarProp->getPropertyValue("ErrorBarStyle") >>= eStyle ) &&
+ eStyle == css::chart::ErrorBarStyle::FROM_DATA )
+ {
+ uno::Reference< data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
+ if( xErrorBarDataSource.is() )
+ lcl_addDataSourceRanges( rOutResult, xErrorBarDataSource );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+} // anonymous namespace
+
+Reference< chart2::data::XDataSequence > DataSourceHelper::createCachedDataSequence()
+{
+ return new ::chart::CachedDataSequence();
+}
+
+Reference< chart2::data::XDataSequence > DataSourceHelper::createCachedDataSequence( const OUString& rSingleText )
+{
+ return new ::chart::CachedDataSequence( rSingleText );
+}
+
+rtl::Reference< LabeledDataSequence > DataSourceHelper::createLabeledDataSequence(
+ const Reference< chart2::data::XDataSequence >& xValues ,
+ const Reference< chart2::data::XDataSequence >& xLabels )
+{
+ return new ::chart::LabeledDataSequence( xValues, xLabels );
+}
+
+rtl::Reference< LabeledDataSequence > DataSourceHelper::createLabeledDataSequence(
+ const Reference< chart2::data::XDataSequence >& xValues )
+{
+ return new ::chart::LabeledDataSequence( xValues );
+}
+
+rtl::Reference< LabeledDataSequence > DataSourceHelper::createLabeledDataSequence()
+{
+ return new ::chart::LabeledDataSequence;
+}
+
+uno::Sequence< beans::PropertyValue > DataSourceHelper::createArguments(
+ bool bUseColumns, bool bFirstCellAsLabel, bool bHasCategories )
+{
+ css::chart::ChartDataRowSource eRowSource = css::chart::ChartDataRowSource_ROWS;
+ if( bUseColumns )
+ eRowSource = css::chart::ChartDataRowSource_COLUMNS;
+
+ return
+ {
+ { "DataRowSource", -1, uno::Any( eRowSource), beans::PropertyState_DIRECT_VALUE },
+ { "FirstCellAsLabel", -1, uno::Any( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE },
+ { "HasCategories", -1, uno::Any( bHasCategories ), beans::PropertyState_DIRECT_VALUE }
+ };
+}
+
+uno::Sequence< beans::PropertyValue > DataSourceHelper::createArguments(
+ const OUString & rRangeRepresentation,
+ const uno::Sequence< sal_Int32 >& rSequenceMapping,
+ bool bUseColumns, bool bFirstCellAsLabel, bool bHasCategories )
+{
+ uno::Sequence< beans::PropertyValue > aArguments( createArguments( bUseColumns, bFirstCellAsLabel, bHasCategories ));
+ aArguments.realloc( aArguments.getLength() + 1 );
+ aArguments.getArray()[aArguments.getLength() - 1] =
+ beans::PropertyValue( "CellRangeRepresentation"
+ , -1, uno::Any( rRangeRepresentation )
+ , beans::PropertyState_DIRECT_VALUE );
+ if( rSequenceMapping.hasElements() )
+ {
+ aArguments.realloc( aArguments.getLength() + 1 );
+ aArguments.getArray()[aArguments.getLength() - 1] =
+ beans::PropertyValue( "SequenceMapping"
+ , -1, uno::Any( rSequenceMapping )
+ , beans::PropertyState_DIRECT_VALUE );
+ }
+ return aArguments;
+}
+
+void DataSourceHelper::readArguments( const uno::Sequence< beans::PropertyValue >& rArguments
+ , OUString & rRangeRepresentation, uno::Sequence< sal_Int32 >& rSequenceMapping
+ , bool& bUseColumns, bool& bFirstCellAsLabel, bool& bHasCategories )
+{
+ for(const beans::PropertyValue& rProperty : rArguments)
+ {
+ if ( rProperty.Name == "DataRowSource" )
+ {
+ css::chart::ChartDataRowSource eRowSource;
+ if( rProperty.Value >>= eRowSource )
+ bUseColumns = (eRowSource==css::chart::ChartDataRowSource_COLUMNS);
+ }
+ else if ( rProperty.Name == "FirstCellAsLabel" )
+ {
+ rProperty.Value >>= bFirstCellAsLabel;
+ }
+ else if ( rProperty.Name == "HasCategories" )
+ {
+ rProperty.Value >>= bHasCategories;
+ }
+ else if ( rProperty.Name == "CellRangeRepresentation" )
+ {
+ rProperty.Value >>= rRangeRepresentation;
+ }
+ else if ( rProperty.Name == "SequenceMapping" )
+ {
+ rProperty.Value >>= rSequenceMapping;
+ }
+ }
+}
+
+rtl::Reference< DataSource > DataSourceHelper::pressUsedDataIntoRectangularFormat(
+ const rtl::Reference< ChartModel >& xChartDoc )
+{
+ std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultVector;
+
+ //categories are always the first sequence
+ rtl::Reference< Diagram > xDiagram( xChartDoc->getFirstChartDiagram());
+
+ Reference< chart2::data::XLabeledDataSequence > xCategories;
+ if (xDiagram)
+ xCategories = xDiagram->getCategories();
+ if( xCategories.is() )
+ aResultVector.push_back( xCategories );
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector;
+ if (xDiagram)
+ aSeriesVector = xDiagram->getDataSeries();
+ uno::Reference< chart2::data::XDataSource > xSeriesSource =
+ DataSeriesHelper::getDataSource( aSeriesVector );
+ const Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xSeriesSource->getDataSequences() );
+
+ //the first x-values is always the next sequence //todo ... other x-values get lost for old format
+ Reference< chart2::data::XLabeledDataSequence > xXValues(
+ DataSeriesHelper::getDataSequenceByRole( xSeriesSource, "values-x" ) );
+ if( xXValues.is() )
+ aResultVector.push_back( xXValues );
+
+ //add all other sequences now without x-values
+ for( Reference< chart2::data::XLabeledDataSequence > const & labeledData : aDataSequences )
+ {
+ OUString aRole = DataSeriesHelper::getRole(labeledData);
+ if( aRole != "values-x" )
+ aResultVector.push_back( labeledData );
+ }
+
+ return new DataSource( aResultVector );
+}
+
+uno::Sequence< OUString > DataSourceHelper::getUsedDataRanges(
+ const rtl::Reference< Diagram > & xDiagram )
+{
+ std::vector< OUString > aResult;
+
+ if( xDiagram.is())
+ {
+ uno::Reference< data::XLabeledDataSequence > xCategories( xDiagram->getCategories() );
+ if( xCategories.is() )
+ lcl_addRanges( aResult, xCategories );
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector( xDiagram->getDataSeries() );
+ for (auto const& series : aSeriesVector)
+ {
+ lcl_addDataSourceRanges( aResult, series );
+ lcl_addErrorBarRanges( aResult, series );
+ }
+ }
+
+ return comphelper::containerToSequence( aResult );
+}
+
+uno::Sequence< OUString > DataSourceHelper::getUsedDataRanges( const rtl::Reference<::chart::ChartModel> & xChartModel )
+{
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ return getUsedDataRanges( xDiagram );
+}
+
+rtl::Reference< DataSource > DataSourceHelper::getUsedData(
+ ChartModel& rModel )
+{
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aResult;
+
+ rtl::Reference< Diagram > xDiagram = rModel.getFirstChartDiagram();
+ uno::Reference< chart2::data::XLabeledDataSequence > xCategories( xDiagram->getCategories() );
+ if( xCategories.is() )
+ aResult.push_back( xCategories );
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector = ChartModelHelper::getDataSeries( &rModel );
+ for (auto const& series : aSeriesVector)
+ {
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aDataSequences( series->getDataSequences2() );
+ aResult.insert( aResult.end(), aDataSequences.begin(), aDataSequences.end() );
+ }
+
+ return new DataSource( aResult );
+}
+
+bool DataSourceHelper::detectRangeSegmentation(
+ const rtl::Reference<::chart::ChartModel>& xChartModel
+ , OUString& rOutRangeString
+ , css::uno::Sequence< sal_Int32 >& rSequenceMapping
+ , bool& rOutUseColumns
+ , bool& rOutFirstCellAsLabel
+ , bool& rOutHasCategories )
+{
+ bool bSomethingDetected = false;
+
+ if( !xChartModel.is() )
+ return bSomethingDetected;
+ uno::Reference< data::XDataProvider > xDataProvider( xChartModel->getDataProvider() );
+ if( !xDataProvider.is() )
+ return bSomethingDetected;
+
+ try
+ {
+ DataSourceHelper::readArguments(
+ xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartModel ) ),
+ rOutRangeString, rSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories );
+ bSomethingDetected = !rOutRangeString.isEmpty();
+
+ rtl::Reference<Diagram> xDiagram = xChartModel->getFirstChartDiagram();
+ uno::Reference< chart2::data::XLabeledDataSequence > xCategories;
+ if (xDiagram)
+ xCategories = xDiagram->getCategories();
+ rOutHasCategories = xCategories.is();
+ }
+ catch( uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return bSomethingDetected;
+}
+
+bool DataSourceHelper::allArgumentsForRectRangeDetected(
+ const rtl::Reference<::chart::ChartModel>& xChartDocument )
+{
+ bool bHasDataRowSource = false;
+ bool bHasFirstCellAsLabel = false;
+ bool bHasCellRangeRepresentation = false;
+
+ uno::Reference< data::XDataProvider > xDataProvider( xChartDocument->getDataProvider() );
+ if( !xDataProvider.is() )
+ return false;
+
+ try
+ {
+ const uno::Sequence< beans::PropertyValue > aArguments(
+ xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartDocument )));
+ for(const beans::PropertyValue& rProperty : aArguments)
+ {
+ if ( rProperty.Name == "DataRowSource" )
+ {
+ bHasDataRowSource =
+ (rProperty.Value.hasValue() && rProperty.Value.isExtractableTo(
+ cppu::UnoType<css::chart::ChartDataRowSource>::get()));
+ }
+ else if ( rProperty.Name == "FirstCellAsLabel" )
+ {
+ bHasFirstCellAsLabel =
+ (rProperty.Value.hasValue() && rProperty.Value.isExtractableTo(cppu::UnoType<bool>::get()));
+ }
+ else if ( rProperty.Name == "CellRangeRepresentation" )
+ {
+ OUString aRange;
+ bHasCellRangeRepresentation =
+ (rProperty.Value.hasValue() && (rProperty.Value >>= aRange) && !aRange.isEmpty());
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return (bHasCellRangeRepresentation && bHasDataRowSource && bHasFirstCellAsLabel);
+}
+
+void DataSourceHelper::setRangeSegmentation(
+ const rtl::Reference<::chart::ChartModel>& xChartModel
+ , const css::uno::Sequence< sal_Int32 >& rSequenceMapping
+ , bool bUseColumns , bool bFirstCellAsLabel, bool bUseCategories )
+{
+ uno::Reference< data::XDataProvider > xDataProvider( xChartModel->getDataProvider() );
+ if( !xDataProvider.is() )
+ return;
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ if( !xDiagram.is() )
+ return;
+ rtl::Reference< ::chart::ChartTypeManager > xChartTypeManager = xChartModel->getTypeManager();
+ if( !xChartTypeManager.is() )
+ return;
+
+ OUString aRangeString;
+ bool bDummy;
+ uno::Sequence< sal_Int32 > aDummy;
+ readArguments( xDataProvider->detectArguments( pressUsedDataIntoRectangularFormat( xChartModel )),
+ aRangeString, aDummy, bDummy, bDummy, bDummy );
+
+ uno::Sequence< beans::PropertyValue > aArguments(
+ createArguments( aRangeString, rSequenceMapping, bUseColumns, bFirstCellAsLabel, bUseCategories ) );
+
+ uno::Reference< chart2::data::XDataSource > xDataSource( xDataProvider->createDataSource(
+ aArguments ) );
+ if( !xDataSource.is() )
+ return;
+
+ ControllerLockGuardUNO aCtrlLockGuard( xChartModel );
+ xDiagram->setDiagramData( xDataSource, aArguments );
+}
+
+Sequence< OUString > DataSourceHelper::getRangesFromLabeledDataSequence(
+ const Reference< data::XLabeledDataSequence > & xLSeq )
+{
+ Sequence< OUString > aResult;
+ if( xLSeq.is())
+ {
+ Reference< data::XDataSequence > xLabel( xLSeq->getLabel());
+ Reference< data::XDataSequence > xValues( xLSeq->getValues());
+
+ if( xLabel.is())
+ {
+ if( xValues.is())
+ {
+ aResult = { xLabel->getSourceRangeRepresentation(),
+ xValues->getSourceRangeRepresentation() };
+ }
+ else
+ {
+ aResult = { xLabel->getSourceRangeRepresentation() };
+ }
+ }
+ else if( xValues.is())
+ {
+ aResult = { xValues->getSourceRangeRepresentation() };
+ }
+ }
+ return aResult;
+}
+
+OUString DataSourceHelper::getRangeFromValues(
+ const Reference< data::XLabeledDataSequence > & xLSeq )
+{
+ OUString aResult;
+ if( xLSeq.is() )
+ {
+ Reference< data::XDataSequence > xValues( xLSeq->getValues() );
+ if( xValues.is() )
+ aResult = xValues->getSourceRangeRepresentation();
+ }
+ return aResult;
+}
+
+Sequence< OUString > DataSourceHelper::getRangesFromDataSource( const Reference< data::XDataSource > & xSource )
+{
+ std::vector< OUString > aResult;
+ if( xSource.is())
+ {
+ const Sequence< Reference< data::XLabeledDataSequence > > aLSeqSeq( xSource->getDataSequences());
+ for( Reference< data::XLabeledDataSequence > const & labeledData : aLSeqSeq )
+ {
+ Reference< data::XDataSequence > xLabel( labeledData->getLabel());
+ Reference< data::XDataSequence > xValues( labeledData->getValues());
+
+ if( xLabel.is())
+ aResult.push_back( xLabel->getSourceRangeRepresentation());
+ if( xValues.is())
+ aResult.push_back( xValues->getSourceRangeRepresentation());
+ }
+ }
+ return comphelper::containerToSequence( aResult );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/DiagramHelper.cxx b/chart2/source/tools/DiagramHelper.cxx
new file mode 100644
index 0000000000..79a99688fd
--- /dev/null
+++ b/chart2/source/tools/DiagramHelper.cxx
@@ -0,0 +1,552 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartTypeManager.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <servicenames_charttypes.hxx>
+#include <RelativePositionHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <unonames.hxx>
+#include <BaseCoordinateSystem.hxx>
+
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/chart/XDiagramPositioning.hpp>
+#include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+
+#include <o3tl/safeint.hxx>
+#include <unotools/saveopt.hxx>
+#include <rtl/math.hxx>
+#include <svl/numformat.hxx>
+#include <svl/zforlist.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+
+#include <cstddef>
+#include <limits>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::chart2::XAnyDescriptionAccess;
+
+namespace chart
+{
+
+StackMode DiagramHelper::getStackModeFromChartType(
+ const rtl::Reference< ChartType > & xChartType,
+ bool& rbFound, bool& rbAmbiguous,
+ const rtl::Reference< BaseCoordinateSystem > & xCorrespondingCoordinateSystem )
+{
+ StackMode eStackMode = StackMode::NONE;
+ rbFound = false;
+ rbAmbiguous = false;
+
+ try
+ {
+ const std::vector< rtl::Reference< DataSeries > > & aSeries = xChartType->getDataSeries2();
+
+ chart2::StackingDirection eCommonDirection = chart2::StackingDirection_NO_STACKING;
+ bool bDirectionInitialized = false;
+
+ // first series is irrelevant for stacking, start with second, unless
+ // there is only one series
+ const sal_Int32 nSeriesCount = aSeries.size();
+ sal_Int32 i = (nSeriesCount == 1) ? 0: 1;
+ for( ; i<nSeriesCount; ++i )
+ {
+ rbFound = true;
+ chart2::StackingDirection eCurrentDirection = eCommonDirection;
+ // property is not MAYBEVOID
+ bool bSuccess = ( aSeries[i]->getPropertyValue( "StackingDirection" ) >>= eCurrentDirection );
+ OSL_ASSERT( bSuccess );
+ if( ! bDirectionInitialized )
+ {
+ eCommonDirection = eCurrentDirection;
+ bDirectionInitialized = true;
+ }
+ else
+ {
+ if( eCommonDirection != eCurrentDirection )
+ {
+ rbAmbiguous = true;
+ break;
+ }
+ }
+ }
+
+ if( rbFound )
+ {
+ if( eCommonDirection == chart2::StackingDirection_Z_STACKING )
+ eStackMode = StackMode::ZStacked;
+ else if( eCommonDirection == chart2::StackingDirection_Y_STACKING )
+ {
+ eStackMode = StackMode::YStacked;
+
+ // percent stacking
+ if( xCorrespondingCoordinateSystem.is() )
+ {
+ if( 1 < xCorrespondingCoordinateSystem->getDimension() )
+ {
+ sal_Int32 nAxisIndex = 0;
+ if( nSeriesCount )
+ nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(aSeries[0]);
+
+ rtl::Reference< Axis > xAxis =
+ xCorrespondingCoordinateSystem->getAxisByDimension2( 1,nAxisIndex );
+ if( xAxis.is())
+ {
+ chart2::ScaleData aScaleData = xAxis->getScaleData();
+ if( aScaleData.AxisType==chart2::AxisType::PERCENT )
+ eStackMode = StackMode::YStackedPercent;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return eStackMode;
+}
+
+bool DiagramHelper::isSeriesAttachedToMainAxis(
+ const rtl::Reference< ::chart::DataSeries >& xDataSeries )
+{
+ sal_Int32 nAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
+ return (nAxisIndex==0);
+}
+
+static void lcl_generateAutomaticCategoriesFromChartType(
+ Sequence< OUString >& rRet,
+ const rtl::Reference< ChartType >& xChartType )
+{
+ if(!xChartType.is())
+ return;
+ OUString aMainSeq( xChartType->getRoleOfSequenceForSeriesLabel() );
+
+ const std::vector< rtl::Reference< DataSeries > > & aSeriesSeq = xChartType->getDataSeries2();
+ for( rtl::Reference< DataSeries > const & dataSeries : aSeriesSeq )
+ {
+ uno::Reference< data::XLabeledDataSequence > xLabeledSeq =
+ ::chart::DataSeriesHelper::getDataSequenceByRole( dataSeries, aMainSeq );
+ if( !xLabeledSeq.is() )
+ continue;
+ Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues() );
+ if( !xValueSeq.is() )
+ continue;
+ rRet = xValueSeq->generateLabel( chart2::data::LabelOrigin_LONG_SIDE );
+ if( rRet.hasElements() )
+ return;
+ }
+}
+
+Sequence< OUString > DiagramHelper::generateAutomaticCategoriesFromCooSys( const rtl::Reference< BaseCoordinateSystem > & xCooSys )
+{
+ Sequence< OUString > aRet;
+
+ if( xCooSys.is() )
+ {
+ const std::vector< rtl::Reference< ChartType > > & aChartTypes( xCooSys->getChartTypes2() );
+ for( rtl::Reference< ChartType > const & chartType : aChartTypes )
+ {
+ lcl_generateAutomaticCategoriesFromChartType( aRet, chartType );
+ if( aRet.hasElements() )
+ return aRet;
+ }
+ }
+ return aRet;
+}
+
+Sequence< OUString > DiagramHelper::getExplicitSimpleCategories(
+ ChartModel& rModel )
+{
+ rtl::Reference< BaseCoordinateSystem > xCooSys( ChartModelHelper::getFirstCoordinateSystem( &rModel ) );
+ ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, rModel );
+ return aExplicitCategoriesProvider.getSimpleCategories();
+}
+
+namespace
+{
+void lcl_switchToDateCategories( const rtl::Reference< ChartModel >& xChartDoc, const Reference< XAxis >& xAxis )
+{
+ if( !xAxis.is() )
+ return;
+ if( !xChartDoc.is() )
+ return;
+
+ ScaleData aScale( xAxis->getScaleData() );
+ if( xChartDoc->hasInternalDataProvider() )
+ {
+ //remove all content the is not of type double and remove multiple level
+ Reference< XAnyDescriptionAccess > xDataAccess( xChartDoc->getDataProvider(), uno::UNO_QUERY );
+ if( xDataAccess.is() )
+ {
+ Sequence< Sequence< Any > > aAnyCategories( xDataAccess->getAnyRowDescriptions() );
+ auto aAnyCategoriesRange = asNonConstRange(aAnyCategories);
+ double fTest = 0.0;
+ sal_Int32 nN = aAnyCategories.getLength();
+ for( ; nN--; )
+ {
+ Sequence< Any >& rCat = aAnyCategoriesRange[nN];
+ if( rCat.getLength() > 1 )
+ rCat.realloc(1);
+ if( rCat.getLength() == 1 )
+ {
+ Any& rAny = rCat.getArray()[0];
+ if( !(rAny>>=fTest) )
+ {
+ rAny <<= std::numeric_limits<double>::quiet_NaN();
+ }
+ }
+ }
+ xDataAccess->setAnyRowDescriptions( aAnyCategories );
+ }
+ //check the numberformat at the axis
+ Reference< beans::XPropertySet > xAxisProps( xAxis, uno::UNO_QUERY );
+ if( xAxisProps.is() )
+ {
+ sal_Int32 nNumberFormat = -1;
+ xAxisProps->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormat;
+
+ Reference< util::XNumberFormats > xNumberFormats( xChartDoc->getNumberFormats() );
+ if( xNumberFormats.is() )
+ {
+ Reference< beans::XPropertySet > xKeyProps;
+ try
+ {
+ xKeyProps = xNumberFormats->getByKey( nNumberFormat );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ sal_Int32 nType = util::NumberFormat::UNDEFINED;
+ if( xKeyProps.is() )
+ xKeyProps->getPropertyValue( "Type" ) >>= nType;
+ if( !( nType & util::NumberFormat::DATE ) )
+ {
+ //set a date format to the axis
+ const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
+ Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::DATE, rLocaleDataWrapper.getLanguageTag().getLocale(), true/*bCreate*/ );
+ if( aKeySeq.hasElements() )
+ {
+ xAxisProps->setPropertyValue(CHART_UNONAME_NUMFMT, uno::Any(aKeySeq[0]));
+ }
+ }
+ }
+ }
+ }
+ if( aScale.AxisType != chart2::AxisType::DATE )
+ AxisHelper::removeExplicitScaling( aScale );
+ aScale.AxisType = chart2::AxisType::DATE;
+ xAxis->setScaleData( aScale );
+}
+
+void lcl_switchToTextCategories( const rtl::Reference< ChartModel >& xChartDoc, const Reference< XAxis >& xAxis )
+{
+ if( !xAxis.is() )
+ return;
+ if( !xChartDoc.is() )
+ return;
+ ScaleData aScale( xAxis->getScaleData() );
+ if( aScale.AxisType != chart2::AxisType::CATEGORY )
+ AxisHelper::removeExplicitScaling( aScale );
+ //todo migrate dates to text?
+ aScale.AxisType = chart2::AxisType::CATEGORY;
+ aScale.AutoDateAxis = false;
+ xAxis->setScaleData( aScale );
+}
+
+}
+
+void DiagramHelper::switchToDateCategories( const rtl::Reference<::chart::ChartModel>& xChartDoc )
+{
+ if(xChartDoc.is())
+ {
+ ControllerLockGuardUNO aCtrlLockGuard( xChartDoc );
+
+ rtl::Reference< BaseCoordinateSystem > xCooSys = ChartModelHelper::getFirstCoordinateSystem( xChartDoc );
+ if( xCooSys.is() )
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2(0,0);
+ lcl_switchToDateCategories( xChartDoc, xAxis );
+ }
+ }
+}
+
+void DiagramHelper::switchToTextCategories( const rtl::Reference<::chart::ChartModel>& xChartDoc )
+{
+ if(xChartDoc.is())
+ {
+ ControllerLockGuardUNO aCtrlLockGuard( xChartDoc );
+
+ rtl::Reference< BaseCoordinateSystem > xCooSys = ChartModelHelper::getFirstCoordinateSystem( xChartDoc );
+ if( xCooSys.is() )
+ {
+ rtl::Reference< Axis > xAxis = xCooSys->getAxisByDimension2(0,0);
+ lcl_switchToTextCategories( xChartDoc, xAxis );
+ }
+ }
+}
+
+bool DiagramHelper::isDateNumberFormat( sal_Int32 nNumberFormat, const Reference< util::XNumberFormats >& xNumberFormats )
+{
+ bool bIsDate = false;
+ if( !xNumberFormats.is() )
+ return bIsDate;
+
+ Reference< beans::XPropertySet > xKeyProps = xNumberFormats->getByKey( nNumberFormat );
+ if( xKeyProps.is() )
+ {
+ sal_Int32 nType = util::NumberFormat::UNDEFINED;
+ xKeyProps->getPropertyValue( "Type" ) >>= nType;
+ bIsDate = nType & util::NumberFormat::DATE;
+ }
+ return bIsDate;
+}
+
+sal_Int32 DiagramHelper::getDateNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+{
+ sal_Int32 nRet=-1;
+
+ //try to get a date format with full year display
+ const LanguageTag& rLanguageTag = Application::GetSettings().GetLanguageTag();
+ NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
+ SvNumberFormatter* pNumFormatter = aNumberFormatterWrapper.getSvNumberFormatter();
+ if( pNumFormatter )
+ {
+ nRet = pNumFormatter->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, rLanguageTag.getLanguageType() );
+ }
+ else
+ {
+ Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
+ if( xNumberFormats.is() )
+ {
+ Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::DATE,
+ rLanguageTag.getLocale(), true/*bCreate */);
+ if( aKeySeq.hasElements() )
+ {
+ nRet = aKeySeq[0];
+ }
+ }
+ }
+ return nRet;
+}
+
+sal_Int32 DiagramHelper::getDateTimeInputNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier, double fNumber )
+{
+ sal_Int32 nRet = 0;
+
+ // Get the most detailed date/time format according to fNumber.
+ NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
+ SvNumberFormatter* pNumFormatter = aNumberFormatterWrapper.getSvNumberFormatter();
+ if (!pNumFormatter)
+ SAL_WARN("chart2", "DiagramHelper::getDateTimeInputNumberFormat - no SvNumberFormatter");
+ else
+ {
+ SvNumFormatType nType;
+ // Obtain best matching date, time or datetime format.
+ nRet = pNumFormatter->GuessDateTimeFormat( nType, fNumber, LANGUAGE_SYSTEM);
+ // Obtain the corresponding edit format.
+ nRet = pNumFormatter->GetEditFormat( fNumber, nRet, nType, nullptr);
+ }
+ return nRet;
+}
+
+sal_Int32 DiagramHelper::getPercentNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+{
+ sal_Int32 nRet=-1;
+ const LanguageTag& rLanguageTag = Application::GetSettings().GetLanguageTag();
+ NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
+ SvNumberFormatter* pNumFormatter = aNumberFormatterWrapper.getSvNumberFormatter();
+ if( pNumFormatter )
+ {
+ nRet = pNumFormatter->GetFormatIndex( NF_PERCENT_INT, rLanguageTag.getLanguageType() );
+ }
+ else
+ {
+ Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
+ if( xNumberFormats.is() )
+ {
+ Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::PERCENT,
+ rLanguageTag.getLocale(), true/*bCreate*/ );
+ if( aKeySeq.hasElements() )
+ {
+ // This *assumes* the sequence is sorted as in
+ // NfIndexTableOffset and the first format is the integer 0%
+ // format by chance... which usually is the case, but... anyway,
+ // we usually also have a number formatter so don't reach here.
+ nRet = aKeySeq[0];
+ }
+ }
+ }
+ return nRet;
+}
+
+bool DiagramHelper::areChartTypesCompatible( const rtl::Reference< ChartType >& xFirstType,
+ const rtl::Reference< ChartType >& xSecondType )
+{
+ if( !xFirstType.is() || !xSecondType.is() )
+ return false;
+
+ auto aFirstRoles( comphelper::sequenceToContainer<std::vector< OUString >>( xFirstType->getSupportedMandatoryRoles() ) );
+ auto aSecondRoles( comphelper::sequenceToContainer<std::vector< OUString >>( xSecondType->getSupportedMandatoryRoles() ) );
+ std::sort( aFirstRoles.begin(), aFirstRoles.end() );
+ std::sort( aSecondRoles.begin(), aSecondRoles.end() );
+ return ( aFirstRoles == aSecondRoles );
+}
+
+static void lcl_ensureRange0to1( double& rValue )
+{
+ if(rValue<0.0)
+ rValue=0.0;
+ if(rValue>1.0)
+ rValue=1.0;
+}
+
+bool DiagramHelper::setDiagramPositioning( const rtl::Reference<::chart::ChartModel>& xChartModel,
+ const awt::Rectangle& rPosRect /*100th mm*/ )
+{
+ ControllerLockGuardUNO aCtrlLockGuard( xChartModel );
+
+ bool bChanged = false;
+ awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) );
+ rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
+ if( !xDiagram.is() )
+ return bChanged;
+
+ RelativePosition aOldPos;
+ RelativeSize aOldSize;
+ xDiagram->getPropertyValue("RelativePosition" ) >>= aOldPos;
+ xDiagram->getPropertyValue("RelativeSize" ) >>= aOldSize;
+
+ RelativePosition aNewPos;
+ aNewPos.Anchor = drawing::Alignment_TOP_LEFT;
+ aNewPos.Primary = double(rPosRect.X)/double(aPageSize.Width);
+ aNewPos.Secondary = double(rPosRect.Y)/double(aPageSize.Height);
+
+ chart2::RelativeSize aNewSize;
+ aNewSize.Primary = double(rPosRect.Width)/double(aPageSize.Width);
+ aNewSize.Secondary = double(rPosRect.Height)/double(aPageSize.Height);
+
+ lcl_ensureRange0to1( aNewPos.Primary );
+ lcl_ensureRange0to1( aNewPos.Secondary );
+ lcl_ensureRange0to1( aNewSize.Primary );
+ lcl_ensureRange0to1( aNewSize.Secondary );
+ if( (aNewPos.Primary + aNewSize.Primary) > 1.0 )
+ aNewPos.Primary = 1.0 - aNewSize.Primary;
+ if( (aNewPos.Secondary + aNewSize.Secondary) > 1.0 )
+ aNewPos.Secondary = 1.0 - aNewSize.Secondary;
+
+ xDiagram->setPropertyValue( "RelativePosition", uno::Any(aNewPos) );
+ xDiagram->setPropertyValue( "RelativeSize", uno::Any(aNewSize) );
+
+ bChanged = (aOldPos.Anchor!=aNewPos.Anchor) ||
+ (aOldPos.Primary!=aNewPos.Primary) ||
+ (aOldPos.Secondary!=aNewPos.Secondary) ||
+ (aOldSize.Primary!=aNewSize.Primary) ||
+ (aOldSize.Secondary!=aNewSize.Secondary);
+ return bChanged;
+}
+
+awt::Rectangle DiagramHelper::getDiagramRectangleFromModel( const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ awt::Rectangle aRet(-1,-1,-1,-1);
+
+ rtl::Reference< Diagram > xDiagram = xChartModel->getFirstChartDiagram();
+ if( !xDiagram.is() )
+ return aRet;
+
+ awt::Size aPageSize( ChartModelHelper::getPageSize(xChartModel) );
+
+ RelativePosition aRelPos;
+ RelativeSize aRelSize;
+ xDiagram->getPropertyValue("RelativePosition" ) >>= aRelPos;
+ xDiagram->getPropertyValue("RelativeSize" ) >>= aRelSize;
+
+ awt::Size aAbsSize(
+ static_cast< sal_Int32 >( aRelSize.Primary * aPageSize.Width ),
+ static_cast< sal_Int32 >( aRelSize.Secondary * aPageSize.Height ));
+
+ awt::Point aAbsPos(
+ static_cast< sal_Int32 >( aRelPos.Primary * aPageSize.Width ),
+ static_cast< sal_Int32 >( aRelPos.Secondary * aPageSize.Height ));
+
+ awt::Point aAbsPosLeftTop = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( aAbsPos, aAbsSize, aRelPos.Anchor );
+
+ aRet = awt::Rectangle(aAbsPosLeftTop.X, aAbsPosLeftTop.Y, aAbsSize.Width, aAbsSize.Height );
+
+ return aRet;
+}
+
+bool DiagramHelper::switchDiagramPositioningToExcludingPositioning(
+ ChartModel& rModel, bool bResetModifiedState, bool bConvertAlsoFromAutoPositioning )
+{
+ //return true if something was changed
+ const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(GetODFSaneDefaultVersion());
+ if (SvtSaveOptions::ODFSVER_012 < nCurrentODFVersion)
+ {
+ uno::Reference< css::chart::XDiagramPositioning > xDiagramPositioning( rModel.getFirstDiagram(), uno::UNO_QUERY );
+ if( xDiagramPositioning.is() && ( bConvertAlsoFromAutoPositioning || !xDiagramPositioning->isAutomaticDiagramPositioning() )
+ && !xDiagramPositioning->isExcludingDiagramPositioning() )
+ {
+ ControllerLockGuard aCtrlLockGuard( rModel );
+ bool bModelWasModified = rModel.isModified();
+ xDiagramPositioning->setDiagramPositionExcludingAxes( xDiagramPositioning->calculateDiagramPositionExcludingAxes() );
+ if(bResetModifiedState && !bModelWasModified )
+ rModel.setModified(false);
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ErrorBar.cxx b/chart2/source/tools/ErrorBar.cxx
new file mode 100644
index 0000000000..3d049a4452
--- /dev/null
+++ b/chart2/source/tools/ErrorBar.cxx
@@ -0,0 +1,469 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ErrorBar.hxx>
+#include <EventListenerHelper.hxx>
+#include <CloneHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <svl/itemprop.hxx>
+#include <vcl/svapp.hxx>
+
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/util/Color.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+
+constexpr OUString lcl_aServiceName = u"com.sun.star.comp.chart2.ErrorBar"_ustr;
+
+bool lcl_isInternalData( const uno::Reference< chart2::data::XLabeledDataSequence > & xLSeq )
+{
+ uno::Reference< lang::XServiceInfo > xServiceInfo( xLSeq, uno::UNO_QUERY );
+ return ( xServiceInfo.is() && xServiceInfo->getImplementationName() == "com.sun.star.comp.chart2.LabeledDataSequence" );
+}
+
+const SfxItemPropertySet* GetErrorBarPropertySet()
+{
+ static const SfxItemPropertyMapEntry aErrorBarPropertyMap_Impl[] =
+ {
+ {u"ShowPositiveError"_ustr,0,cppu::UnoType<bool>::get(), 0, 0},
+ {u"ShowNegativeError"_ustr,1,cppu::UnoType<bool>::get(), 0, 0},
+ {u"PositiveError"_ustr,2,cppu::UnoType<double>::get(),0,0},
+ {u"NegativeError"_ustr,3,cppu::UnoType<double>::get(), 0, 0},
+ {u"PercentageError"_ustr,4,cppu::UnoType<double>::get(), 0, 0},
+ {u"ErrorBarStyle"_ustr,5,cppu::UnoType<sal_Int32>::get(),0,0},
+ {u"ErrorBarRangePositive"_ustr,6,cppu::UnoType<OUString>::get(),0,0}, // read-only for export
+ {u"ErrorBarRangeNegative"_ustr,7,cppu::UnoType<OUString>::get(),0,0}, // read-only for export
+ {u"Weight"_ustr,8,cppu::UnoType<double>::get(),0,0},
+ {u"LineStyle"_ustr,9,cppu::UnoType<css::drawing::LineStyle>::get(),0,0},
+ {u"LineDash"_ustr,10,cppu::UnoType<drawing::LineDash>::get(),0,0},
+ {u"LineWidth"_ustr,11,cppu::UnoType<sal_Int32>::get(),0,0},
+ {u"LineColor"_ustr,12,cppu::UnoType<css::util::Color>::get(),0,0},
+ {u"LineTransparence"_ustr,13,cppu::UnoType<sal_Int16>::get(),0,0},
+ {u"LineJoint"_ustr,14,cppu::UnoType<css::drawing::LineJoint>::get(),0,0},
+ };
+ static SfxItemPropertySet aPropSet( aErrorBarPropertyMap_Impl );
+ return &aPropSet;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+ErrorBar::ErrorBar() :
+ mnLineWidth(0),
+ meLineStyle(drawing::LineStyle_SOLID),
+ maLineColor(0),
+ mnLineTransparence(0),
+ meLineJoint(drawing::LineJoint_ROUND),
+ mbShowPositiveError(true),
+ mbShowNegativeError(true),
+ mfPositiveError(0),
+ mfNegativeError(0),
+ mfWeight(1),
+ meStyle(css::chart::ErrorBarStyle::NONE),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+ErrorBar::ErrorBar( const ErrorBar & rOther ) :
+ impl::ErrorBar_Base(rOther),
+ maDashName(rOther.maDashName),
+ maLineDash(rOther.maLineDash),
+ mnLineWidth(rOther.mnLineWidth),
+ meLineStyle(rOther.meLineStyle),
+ maLineColor(rOther.maLineColor),
+ mnLineTransparence(rOther.mnLineTransparence),
+ meLineJoint(rOther.meLineJoint),
+ mbShowPositiveError(rOther.mbShowPositiveError),
+ mbShowNegativeError(rOther.mbShowNegativeError),
+ mfPositiveError(rOther.mfPositiveError),
+ mfNegativeError(rOther.mfNegativeError),
+ mfWeight(rOther.mfWeight),
+ meStyle(rOther.meStyle),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ if( ! rOther.m_aDataSequences.empty())
+ {
+ if( lcl_isInternalData( rOther.m_aDataSequences.front()))
+ CloneHelper::CloneRefVector< css::chart2::data::XLabeledDataSequence >(
+ rOther.m_aDataSequences, m_aDataSequences );
+ else
+ m_aDataSequences = rOther.m_aDataSequences;
+ ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder );
+ }
+}
+
+ErrorBar::~ErrorBar()
+{}
+
+uno::Reference< util::XCloneable > SAL_CALL ErrorBar::createClone()
+{
+ return uno::Reference< util::XCloneable >( new ErrorBar( *this ));
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL ErrorBar::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > aRef (
+ new SfxItemPropertySetInfo( GetErrorBarPropertySet()->getPropertyMap() ) );
+ return aRef;
+}
+
+void ErrorBar::setPropertyValue( const OUString& rPropName, const uno::Any& rAny )
+{
+ SolarMutexGuard aGuard;
+
+ if(rPropName == "ErrorBarStyle")
+ rAny >>= meStyle;
+ else if(rPropName == "PositiveError")
+ rAny >>= mfPositiveError;
+ else if(rPropName == "PercentageError")
+ {
+ rAny >>= mfPositiveError;
+ rAny >>= mfNegativeError;
+ }
+ else if(rPropName == "Weight")
+ {
+ rAny >>= mfWeight;
+ }
+ else if(rPropName == "NegativeError")
+ rAny >>= mfNegativeError;
+ else if(rPropName == "ShowPositiveError")
+ rAny >>= mbShowPositiveError;
+ else if(rPropName == "ShowNegativeError")
+ rAny >>= mbShowNegativeError;
+ else if(rPropName == "ErrorBarRangePositive" || rPropName == "ErrorBarRangeNegative")
+ throw beans::UnknownPropertyException("read-only property", static_cast< uno::XWeak*>(this));
+ else if(rPropName == "LineDashName")
+ rAny >>= maDashName;
+ else if(rPropName == "LineDash")
+ rAny >>= maLineDash;
+ else if(rPropName == "LineWidth")
+ rAny >>= mnLineWidth;
+ else if(rPropName == "LineStyle")
+ rAny >>= meLineStyle;
+ else if(rPropName == "LineColor")
+ rAny >>= maLineColor;
+ else if(rPropName == "LineTransparence")
+ rAny >>= mnLineTransparence;
+ else if(rPropName == "LineJoint")
+ rAny >>= meLineJoint;
+
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+namespace {
+
+OUString getSourceRangeStrFromLabeledSequences( const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > >& aSequences, bool bPositive )
+{
+ OUString aDirection;
+ if(bPositive)
+ aDirection = "positive";
+ else
+ aDirection = "negative";
+
+ for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledData : aSequences )
+ {
+ try
+ {
+ if( labeledData.is())
+ {
+ uno::Reference< chart2::data::XDataSequence > xSequence( labeledData->getValues());
+ uno::Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
+ OUString aRole;
+ if( ( xSeqProp->getPropertyValue( "Role" ) >>= aRole ) &&
+ aRole.match( "error-bars" ) && aRole.indexOf(aDirection) >= 0 )
+ {
+ return xSequence->getSourceRangeRepresentation();
+ }
+ }
+ }
+ catch (uno::Exception const &)
+ {
+ // we can't be sure that this is 100% safe and we don't want to kill the export
+ // we should at least check why the exception is thrown
+ TOOLS_WARN_EXCEPTION("chart2", "unexpected exception");
+ }
+ catch (...)
+ {
+ // we can't be sure that this is 100% safe and we don't want to kill the export
+ // we should at least check why the exception is thrown
+ SAL_WARN("chart2", "unexpected exception! ");
+ }
+ }
+
+ return OUString();
+}
+
+}
+
+uno::Any ErrorBar::getPropertyValue(const OUString& rPropName)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Any aRet;
+ if(rPropName == "ErrorBarStyle")
+ aRet <<= meStyle;
+ else if(rPropName == "PositiveError")
+ aRet <<= mfPositiveError;
+ else if(rPropName == "NegativeError")
+ aRet <<= mfNegativeError;
+ else if(rPropName == "PercentageError")
+ aRet <<= mfPositiveError;
+ else if(rPropName == "ShowPositiveError")
+ aRet <<= mbShowPositiveError;
+ else if(rPropName == "ShowNegativeError")
+ aRet <<= mbShowNegativeError;
+ else if(rPropName == "Weight")
+ aRet <<= mfWeight;
+ else if(rPropName == "ErrorBarRangePositive")
+ {
+ OUString aRange;
+ if(meStyle == css::chart::ErrorBarStyle::FROM_DATA)
+ {
+ uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences =
+ getDataSequences();
+
+ aRange = getSourceRangeStrFromLabeledSequences( aSequences, true );
+ }
+
+ aRet <<= aRange;
+ }
+ else if(rPropName == "ErrorBarRangeNegative")
+ {
+ OUString aRange;
+ if(meStyle == css::chart::ErrorBarStyle::FROM_DATA)
+ {
+ uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences =
+ getDataSequences();
+
+ aRange = getSourceRangeStrFromLabeledSequences( aSequences, false );
+ }
+
+ aRet <<= aRange;
+ }
+ else if(rPropName == "LineDashName")
+ aRet <<= maDashName;
+ else if(rPropName == "LineDash")
+ aRet <<= maLineDash;
+ else if(rPropName == "LineWidth")
+ aRet <<= mnLineWidth;
+ else if(rPropName == "LineStyle")
+ aRet <<= meLineStyle;
+ else if(rPropName == "LineColor")
+ aRet <<= maLineColor;
+ else if(rPropName == "LineTransparence")
+ aRet <<= mnLineTransparence;
+ else if(rPropName == "LineJoint")
+ aRet <<= meLineJoint;
+
+ SAL_WARN_IF(!aRet.hasValue(), "chart2", "asked for property value: " << rPropName);
+ return aRet;
+}
+
+beans::PropertyState ErrorBar::getPropertyState( const OUString& rPropName )
+{
+ if(rPropName == "ErrorBarStyle")
+ {
+ if(meStyle == css::chart::ErrorBarStyle::NONE)
+ return beans::PropertyState_DEFAULT_VALUE;
+ return beans::PropertyState_DIRECT_VALUE;
+ }
+ else if(rPropName == "PositiveError")
+ {
+ if(mbShowPositiveError)
+ {
+ switch(meStyle)
+ {
+ case css::chart::ErrorBarStyle::ABSOLUTE:
+ case css::chart::ErrorBarStyle::ERROR_MARGIN:
+ return beans::PropertyState_DIRECT_VALUE;
+ default:
+ break;
+ }
+ }
+ return beans::PropertyState_DEFAULT_VALUE;
+ }
+ else if(rPropName == "NegativeError")
+ {
+ if(mbShowNegativeError)
+ {
+ switch(meStyle)
+ {
+ case css::chart::ErrorBarStyle::ABSOLUTE:
+ case css::chart::ErrorBarStyle::ERROR_MARGIN:
+ return beans::PropertyState_DIRECT_VALUE;
+ default:
+ break;
+ }
+ }
+ return beans::PropertyState_DEFAULT_VALUE;
+ }
+ else if(rPropName == "PercentageError")
+ {
+ if(meStyle != css::chart::ErrorBarStyle::RELATIVE)
+ return beans::PropertyState_DEFAULT_VALUE;
+ return beans::PropertyState_DIRECT_VALUE;
+ }
+ else if(rPropName == "ShowPositiveError")
+ {
+ // this value should be never default
+ return beans::PropertyState_DIRECT_VALUE;
+ }
+ else if(rPropName == "ShowNegativeError")
+ {
+ // this value should be never default
+ return beans::PropertyState_DIRECT_VALUE;
+ }
+ else if(rPropName == "ErrorBarRangePositive")
+ {
+ if(meStyle == css::chart::ErrorBarStyle::FROM_DATA && mbShowPositiveError)
+ return beans::PropertyState_DIRECT_VALUE;
+ return beans::PropertyState_DEFAULT_VALUE;
+ }
+ else if(rPropName == "ErrorBarRangeNegative")
+ {
+ if(meStyle == css::chart::ErrorBarStyle::FROM_DATA && mbShowNegativeError)
+ return beans::PropertyState_DIRECT_VALUE;
+ return beans::PropertyState_DEFAULT_VALUE;
+ }
+ else
+ return beans::PropertyState_DIRECT_VALUE;
+}
+
+uno::Sequence< beans::PropertyState > ErrorBar::getPropertyStates( const uno::Sequence< OUString >& rPropNames )
+{
+ uno::Sequence< beans::PropertyState > aRet( rPropNames.getLength() );
+ auto aRetRange = asNonConstRange(aRet);
+ for(sal_Int32 i = 0; i < rPropNames.getLength(); ++i)
+ {
+ aRetRange[i] = getPropertyState(rPropNames[i]);
+ }
+ return aRet;
+}
+
+void ErrorBar::setPropertyToDefault( const OUString& )
+{
+ //keep them unimplemented for now
+}
+
+uno::Any ErrorBar::getPropertyDefault( const OUString& )
+{
+ //keep them unimplemented for now
+ return uno::Any();
+}
+
+void ErrorBar::addPropertyChangeListener( const OUString&, const css::uno::Reference< css::beans::XPropertyChangeListener >& )
+{
+}
+
+void ErrorBar::removePropertyChangeListener( const OUString&, const css::uno::Reference< css::beans::XPropertyChangeListener >& )
+{
+}
+
+void ErrorBar::addVetoableChangeListener( const OUString&, const css::uno::Reference< css::beans::XVetoableChangeListener >& )
+{
+}
+
+void ErrorBar::removeVetoableChangeListener( const OUString&, const css::uno::Reference< css::beans::XVetoableChangeListener >& )
+{
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL ErrorBar::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL ErrorBar::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL ErrorBar::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL ErrorBar::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ XDataSink ____
+void SAL_CALL ErrorBar::setData( const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > >& aData )
+{
+ ModifyListenerHelper::removeListenerFromAllElements( m_aDataSequences, m_xModifyEventForwarder );
+ EventListenerHelper::removeListenerFromAllElements( m_aDataSequences, this );
+ m_aDataSequences = comphelper::sequenceToContainer<tDataSequenceContainer>( aData );
+ EventListenerHelper::addListenerToAllElements( m_aDataSequences, this );
+ ModifyListenerHelper::addListenerToAllElements( m_aDataSequences, m_xModifyEventForwarder );
+}
+
+// ____ XDataSource ____
+uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > SAL_CALL ErrorBar::getDataSequences()
+{
+ return comphelper::containerToSequence( m_aDataSequences );
+}
+
+OUString SAL_CALL ErrorBar::getImplementationName()
+{
+ return lcl_aServiceName;
+}
+
+sal_Bool SAL_CALL ErrorBar::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ErrorBar::getSupportedServiceNames()
+{
+ return {
+ lcl_aServiceName,
+ "com.sun.star.chart2.ErrorBar"
+ };
+}
+
+// needed by MSC compiler
+using impl::ErrorBar_Base;
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_ErrorBar_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::ErrorBar);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ExplicitCategoriesProvider.cxx b/chart2/source/tools/ExplicitCategoriesProvider.cxx
new file mode 100644
index 0000000000..59189aa193
--- /dev/null
+++ b/chart2/source/tools/ExplicitCategoriesProvider.cxx
@@ -0,0 +1,564 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ExplicitCategoriesProvider.hxx>
+#include <DiagramHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <DataSourceHelper.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <unonames.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <DataSeries.hxx>
+
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <o3tl/safeint.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <limits>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using std::vector;
+
+ExplicitCategoriesProvider::ExplicitCategoriesProvider( const rtl::Reference< BaseCoordinateSystem >& xCooSysModel
+ , ChartModel& rModel )
+ : m_bDirty(true)
+ , m_xCooSysModel( xCooSysModel.get() )
+ , mrModel(rModel)
+ , m_bIsExplicitCategoriesInited(false)
+ , m_bIsDateAxis(false)
+ , m_bIsAutoDate(false)
+{
+ try
+ {
+ if( xCooSysModel.is() )
+ {
+ // TODO: handle different category names on the primary and secondary category axis.
+ rtl::Reference< Axis > xAxis = xCooSysModel->getAxisByDimension2(0,0);
+ if( xAxis.is() )
+ {
+ ScaleData aScale( xAxis->getScaleData() );
+ m_xOriginalCategories = aScale.Categories;
+ m_bIsAutoDate = (aScale.AutoDateAxis && aScale.AxisType==chart2::AxisType::CATEGORY);
+ m_bIsDateAxis = (aScale.AxisType == chart2::AxisType::DATE || m_bIsAutoDate);
+ }
+ }
+
+ if( m_xOriginalCategories.is() )
+ {
+ uno::Reference< data::XDataProvider > xDataProvider( mrModel.getDataProvider() );
+
+ OUString aCategoriesRange( DataSourceHelper::getRangeFromValues( m_xOriginalCategories ) );
+ if( xDataProvider.is() && !aCategoriesRange.isEmpty() )
+ {
+ const bool bFirstCellAsLabel = false;
+ const bool bHasCategories = false;
+ const uno::Sequence< sal_Int32 > aSequenceMapping;
+
+ uno::Reference< data::XDataSource > xColumnCategoriesSource( xDataProvider->createDataSource(
+ DataSourceHelper::createArguments( aCategoriesRange, aSequenceMapping, true /*bUseColumns*/
+ , bFirstCellAsLabel, bHasCategories ) ) );
+
+ uno::Reference< data::XDataSource > xRowCategoriesSource( xDataProvider->createDataSource(
+ DataSourceHelper::createArguments( aCategoriesRange, aSequenceMapping, false /*bUseColumns*/
+ , bFirstCellAsLabel, bHasCategories ) ) );
+
+ if( xColumnCategoriesSource.is() && xRowCategoriesSource.is() )
+ {
+ Sequence< Reference< data::XLabeledDataSequence> > aColumns = xColumnCategoriesSource->getDataSequences();
+ Sequence< Reference< data::XLabeledDataSequence> > aRows = xRowCategoriesSource->getDataSequences();
+
+ sal_Int32 nColumnCount = aColumns.getLength();
+ sal_Int32 nRowCount = aRows.getLength();
+ if( nColumnCount>1 && nRowCount>1 )
+ {
+ //we have complex categories
+ //->split them in the direction of the first series
+ //detect whether the first series is a row or a column
+ bool bSeriesUsesColumns = true;
+ std::vector< rtl::Reference< DataSeries > > aSeries = ChartModelHelper::getDataSeries( &mrModel );
+ if( !aSeries.empty() )
+ {
+ rtl::Reference< DataSeries > xSeriesSource = aSeries.front();
+ OUString aStringDummy;
+ bool bDummy;
+ uno::Sequence< sal_Int32 > aSeqDummy;
+ DataSourceHelper::readArguments( xDataProvider->detectArguments( xSeriesSource),
+ aStringDummy, aSeqDummy, bSeriesUsesColumns, bDummy, bDummy );
+ }
+ if( bSeriesUsesColumns )
+ m_aSplitCategoriesList = comphelper::sequenceToContainer<std::vector<Reference<data::XLabeledDataSequence>>>(aColumns);
+ else
+ m_aSplitCategoriesList = comphelper::sequenceToContainer<std::vector<Reference<data::XLabeledDataSequence>>>(aRows);
+ }
+ }
+ }
+ if( m_aSplitCategoriesList.empty() )
+ {
+ m_aSplitCategoriesList = { m_xOriginalCategories };
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+ExplicitCategoriesProvider::~ExplicitCategoriesProvider()
+{
+}
+
+Reference< chart2::data::XDataSequence > ExplicitCategoriesProvider::getOriginalCategories()
+{
+ if( m_xOriginalCategories.is() )
+ return m_xOriginalCategories->getValues();
+ return nullptr;
+}
+
+bool ExplicitCategoriesProvider::hasComplexCategories() const
+{
+ return m_aSplitCategoriesList.size() > 1;
+}
+
+sal_Int32 ExplicitCategoriesProvider::getCategoryLevelCount() const
+{
+ sal_Int32 nCount = m_aSplitCategoriesList.size();
+ if(!nCount)
+ nCount = 1;
+ return nCount;
+}
+
+static std::vector<sal_Int32> lcl_getLimitingBorders( const std::vector< ComplexCategory >& rComplexCategories )
+{
+ std::vector<sal_Int32> aLimitingBorders;
+ sal_Int32 nBorderIndex = 0; /*border below the index*/
+ for (auto const& complexCategory : rComplexCategories)
+ {
+ nBorderIndex += complexCategory.Count;
+ aLimitingBorders.push_back(nBorderIndex);
+ }
+ return aLimitingBorders;
+}
+
+void ExplicitCategoriesProvider::convertCategoryAnysToText( uno::Sequence< OUString >& rOutTexts, const uno::Sequence< uno::Any >& rInAnys, ChartModel& rModel )
+{
+ sal_Int32 nCount = rInAnys.getLength();
+ if(!nCount)
+ return;
+ rOutTexts.realloc(nCount);
+ auto pOutTexts = rOutTexts.getArray();
+
+ sal_Int32 nAxisNumberFormat = 0;
+ rtl::Reference< BaseCoordinateSystem > xCooSysModel( ChartModelHelper::getFirstCoordinateSystem( &rModel ) );
+ if( xCooSysModel.is() )
+ {
+ rtl::Reference< Axis > xAxis = xCooSysModel->getAxisByDimension2(0,0);
+ nAxisNumberFormat = AxisHelper::getExplicitNumberFormatKeyForAxis(
+ xAxis, xCooSysModel, &rModel, false );
+ }
+
+ Color nLabelColor;
+ bool bColorChanged = false;
+
+ NumberFormatterWrapper aNumberFormatterWrapper( rModel.getNumberFormatsSupplier() );
+
+ for(sal_Int32 nN=0;nN<nCount;nN++)
+ {
+ OUString aText;
+ uno::Any aAny = rInAnys[nN];
+ if( aAny.hasValue() )
+ {
+ double fDouble = 0;
+ if( aAny>>=fDouble )
+ {
+ if( !std::isnan(fDouble) )
+ aText = aNumberFormatterWrapper.getFormattedString(
+ nAxisNumberFormat, fDouble, nLabelColor, bColorChanged );
+ }
+ else
+ {
+ aAny>>=aText;
+ }
+ }
+ pOutTexts[nN] = aText;
+ }
+}
+
+SplitCategoriesProvider::~SplitCategoriesProvider()
+{
+}
+
+namespace {
+
+class SplitCategoriesProvider_ForLabeledDataSequences : public SplitCategoriesProvider
+{
+public:
+
+ explicit SplitCategoriesProvider_ForLabeledDataSequences(
+ const std::vector< Reference< data::XLabeledDataSequence> >& rSplitCategoriesList
+ , ChartModel& rModel )
+ : m_rSplitCategoriesList( rSplitCategoriesList )
+ , mrModel( rModel )
+ {}
+
+ virtual sal_Int32 getLevelCount() const override;
+ virtual uno::Sequence< OUString > getStringsForLevel( sal_Int32 nIndex ) const override;
+
+private:
+ const std::vector< Reference< data::XLabeledDataSequence> >& m_rSplitCategoriesList;
+
+ ChartModel& mrModel;
+};
+
+}
+
+sal_Int32 SplitCategoriesProvider_ForLabeledDataSequences::getLevelCount() const
+{
+ return m_rSplitCategoriesList.size();
+}
+uno::Sequence< OUString > SplitCategoriesProvider_ForLabeledDataSequences::getStringsForLevel( sal_Int32 nLevel ) const
+{
+ uno::Sequence< OUString > aRet;
+ Reference< data::XLabeledDataSequence > xLabeledDataSequence( m_rSplitCategoriesList[nLevel] );
+ if( xLabeledDataSequence.is() )
+ {
+ uno::Reference< data::XDataSequence > xDataSequence( xLabeledDataSequence->getValues() );
+ if( xDataSequence.is() )
+ ExplicitCategoriesProvider::convertCategoryAnysToText( aRet, xDataSequence->getData(), mrModel );
+ }
+ return aRet;
+}
+
+static std::vector< ComplexCategory > lcl_DataSequenceToComplexCategoryVector(
+ const uno::Sequence< OUString >& rStrings
+ , const std::vector<sal_Int32>& rLimitingBorders, bool bCreateSingleCategories )
+{
+ std::vector< ComplexCategory > aResult;
+
+ sal_Int32 nMaxCount = rStrings.getLength();
+ OUString aPrevious;
+ sal_Int32 nCurrentCount=0;
+ for( sal_Int32 nN=0; nN<nMaxCount; nN++ )
+ {
+ const OUString& aCurrent = rStrings[nN];
+ if( bCreateSingleCategories || std::find( rLimitingBorders.begin(), rLimitingBorders.end(), nN ) != rLimitingBorders.end() )
+ {
+ aResult.emplace_back(aPrevious,nCurrentCount );
+ nCurrentCount=1;
+ aPrevious = aCurrent;
+ }
+ else
+ {
+ // Empty value is interpreted as a continuation of the previous
+ // category. Note that having the same value as the previous one
+ // does not equate to a continuation of the category.
+
+ if (aCurrent.isEmpty())
+ ++nCurrentCount;
+ else
+ {
+ aResult.emplace_back(aPrevious,nCurrentCount );
+ nCurrentCount=1;
+ aPrevious = aCurrent;
+ }
+ }
+ }
+ if( nCurrentCount )
+ aResult.emplace_back(aPrevious,nCurrentCount );
+
+ return aResult;
+}
+
+static sal_Int32 lcl_getCategoryCount( std::vector< ComplexCategory >& rComplexCategories )
+{
+ sal_Int32 nCount = 0;
+ for (auto const& complexCategory : rComplexCategories)
+ nCount+=complexCategory.Count;
+ return nCount;
+}
+
+static Sequence< OUString > lcl_getExplicitSimpleCategories(
+ const SplitCategoriesProvider& rSplitCategoriesProvider,
+ std::vector< std::vector< ComplexCategory > >& rComplexCats )
+{
+ Sequence< OUString > aRet;
+
+ rComplexCats.clear();
+ sal_Int32 nLCount = rSplitCategoriesProvider.getLevelCount();
+ for( sal_Int32 nL = 0; nL < nLCount; nL++ )
+ {
+ std::vector<sal_Int32> aLimitingBorders;
+ if(nL>0)
+ aLimitingBorders = lcl_getLimitingBorders( rComplexCats.back() );
+ rComplexCats.push_back( lcl_DataSequenceToComplexCategoryVector(
+ rSplitCategoriesProvider.getStringsForLevel(nL), aLimitingBorders, nL==(nLCount-1) ) );
+ }
+
+ //ensure that the category count is the same on each level
+ sal_Int32 nMaxCategoryCount = 0;
+ {
+ for (auto & complexCat : rComplexCats)
+ {
+ sal_Int32 nCurrentCount = lcl_getCategoryCount(complexCat);
+ nMaxCategoryCount = std::max( nCurrentCount, nMaxCategoryCount );
+ }
+ for (auto & complexCat : rComplexCats)
+ {
+ if ( !complexCat.empty() )
+ {
+ sal_Int32 nCurrentCount = lcl_getCategoryCount(complexCat);
+ if( nCurrentCount< nMaxCategoryCount )
+ {
+ ComplexCategory& rComplexCategory = complexCat.back();
+ rComplexCategory.Count += (nMaxCategoryCount-nCurrentCount);
+ }
+ }
+ }
+ }
+
+ //create a list with an element for every index
+ std::vector< std::vector< ComplexCategory > > aComplexCatsPerIndex;
+ for (auto const& complexCat : rComplexCats)
+ {
+ std::vector< ComplexCategory > aSingleLevel;
+ for (auto const& elem : complexCat)
+ {
+ sal_Int32 nCount = elem.Count;
+ while( nCount-- )
+ aSingleLevel.push_back(elem);
+ }
+ aComplexCatsPerIndex.push_back( aSingleLevel );
+ }
+
+ if(nMaxCategoryCount)
+ {
+ aRet.realloc(nMaxCategoryCount);
+ auto pRet = aRet.getArray();
+ for(sal_Int32 nN=0; nN<nMaxCategoryCount; nN++)
+ {
+ OUStringBuffer aText;
+ for (auto const& complexCatPerIndex : aComplexCatsPerIndex)
+ {
+ if ( o3tl::make_unsigned(nN) < complexCatPerIndex.size() )
+ {
+ OUString aAddText = complexCatPerIndex[nN].Text;
+ if( !aAddText.isEmpty() )
+ {
+ if(!aText.isEmpty())
+ aText.append(" ");
+ aText.append(aAddText);
+ }
+ }
+ }
+ pRet[nN]=aText.makeStringAndClear();
+ }
+ }
+ return aRet;
+}
+
+Sequence< OUString > ExplicitCategoriesProvider::getExplicitSimpleCategories(
+ const SplitCategoriesProvider& rSplitCategoriesProvider )
+{
+ vector< vector< ComplexCategory > > aComplexCats;
+ return lcl_getExplicitSimpleCategories( rSplitCategoriesProvider, aComplexCats );
+}
+
+static bool lcl_fillDateCategories( const uno::Reference< data::XDataSequence >& xDataSequence, std::vector< double >& rDateCategories, bool bIsAutoDate, ChartModel& rModel )
+{
+ bool bOnlyDatesFound = true;
+ bool bAnyDataFound = false;
+
+ if( xDataSequence.is() )
+ {
+ uno::Sequence< uno::Any > aValues = xDataSequence->getData();
+ sal_Int32 nCount = aValues.getLength();
+ rDateCategories.reserve(nCount);
+ Reference< util::XNumberFormats > xNumberFormats( rModel.getNumberFormats() );
+
+ bool bOwnData = false;
+ bool bOwnDataAnddAxisHasAnyFormat = false;
+ bool bOwnDataAnddAxisHasDateFormat = false;
+ rtl::Reference< BaseCoordinateSystem > xCooSysModel( ChartModelHelper::getFirstCoordinateSystem( &rModel ) );
+ if( xCooSysModel.is() )
+ {
+ if( rModel.hasInternalDataProvider() )
+ {
+ bOwnData = true;
+ rtl::Reference< Axis > xAxisProps = xCooSysModel->getAxisByDimension2(0,0);
+ sal_Int32 nAxisNumberFormat = 0;
+ if (xAxisProps.is() && (xAxisProps->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nAxisNumberFormat))
+ {
+ bOwnDataAnddAxisHasAnyFormat = true;
+ bOwnDataAnddAxisHasDateFormat = DiagramHelper::isDateNumberFormat( nAxisNumberFormat, xNumberFormats );
+ }
+ }
+ }
+
+ for(sal_Int32 nN=0;nN<nCount;nN++)
+ {
+ bool bIsDate = false;
+ if( bIsAutoDate )
+ {
+ if( bOwnData )
+ bIsDate = !bOwnDataAnddAxisHasAnyFormat || bOwnDataAnddAxisHasDateFormat;
+ else
+ bIsDate = DiagramHelper::isDateNumberFormat( xDataSequence->getNumberFormatKeyByIndex( nN ), xNumberFormats );
+ }
+ else
+ bIsDate = true;
+
+ bool bContainsEmptyString = false;
+ uno::Any aAny = aValues[nN];
+ if( aAny.hasValue() )
+ {
+ OUString aTest;
+ double fTest = 0;
+ bool bContainsNan = false;
+ if( (aAny>>=aTest) && aTest.isEmpty() ) //empty String
+ bContainsEmptyString = true;
+ else if( (aAny>>=fTest) && std::isnan(fTest) )
+ bContainsNan = true;
+
+ if( !bContainsEmptyString && !bContainsNan )
+ bAnyDataFound = true;
+ }
+ double aDate( 1.0 );
+ if( bIsDate && (aAny >>= aDate) )
+ rDateCategories.push_back( aDate );
+ else
+ {
+ if( aAny.hasValue() && !bContainsEmptyString )//empty string does not count as non date value!
+ bOnlyDatesFound=false;
+ rDateCategories.push_back( std::numeric_limits<double>::quiet_NaN() );
+ }
+ }
+ std::sort( rDateCategories.begin(), rDateCategories.end() );
+ }
+
+ return bAnyDataFound && bOnlyDatesFound;
+}
+
+void ExplicitCategoriesProvider::init()
+{
+ if( !m_bDirty )
+ return;
+
+ m_aComplexCats.clear();//not one per index
+ m_aDateCategories.clear();
+
+ if( m_xOriginalCategories.is() )
+ {
+ if( !hasComplexCategories() )
+ {
+ if(m_bIsDateAxis)
+ {
+ if( ChartTypeHelper::isSupportingDateAxis( AxisHelper::getChartTypeByIndex( m_xCooSysModel.get(), 0 ), 0 ) )
+ m_bIsDateAxis = lcl_fillDateCategories( m_xOriginalCategories->getValues(), m_aDateCategories, m_bIsAutoDate, mrModel );
+ else
+ m_bIsDateAxis = false;
+ }
+ }
+ else
+ {
+ m_bIsDateAxis = false;
+ }
+ }
+ else
+ m_bIsDateAxis=false;
+ m_bDirty = false;
+}
+
+Sequence< OUString > const & ExplicitCategoriesProvider::getSimpleCategories()
+{
+ if( !m_bIsExplicitCategoriesInited )
+ {
+ init();
+ m_aExplicitCategories.realloc(0);
+ if( m_xOriginalCategories.is() )
+ {
+ if( !hasComplexCategories() )
+ {
+ uno::Reference< data::XDataSequence > xDataSequence( m_xOriginalCategories->getValues() );
+ if( xDataSequence.is() )
+ ExplicitCategoriesProvider::convertCategoryAnysToText( m_aExplicitCategories, xDataSequence->getData(), mrModel );
+ }
+ else
+ {
+ m_aExplicitCategories = lcl_getExplicitSimpleCategories(
+ SplitCategoriesProvider_ForLabeledDataSequences( m_aSplitCategoriesList, mrModel ), m_aComplexCats );
+ }
+ }
+ if(!m_aExplicitCategories.hasElements())
+ m_aExplicitCategories = DiagramHelper::generateAutomaticCategoriesFromCooSys( m_xCooSysModel.get() );
+ m_bIsExplicitCategoriesInited = true;
+ }
+ return m_aExplicitCategories;
+}
+
+const std::vector<ComplexCategory>* ExplicitCategoriesProvider::getCategoriesByLevel( sal_Int32 nLevel )
+{
+ init();
+ sal_Int32 nMaxIndex = m_aComplexCats.size()-1;
+ if (nLevel >= 0 && nLevel <= nMaxIndex)
+ return &m_aComplexCats[nMaxIndex-nLevel];
+ return nullptr;
+}
+
+OUString ExplicitCategoriesProvider::getCategoryByIndex(
+ const rtl::Reference< BaseCoordinateSystem >& xCooSysModel
+ , ChartModel& rModel
+ , sal_Int32 nIndex )
+{
+ if( xCooSysModel.is())
+ {
+ ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSysModel, rModel );
+ Sequence< OUString > aCategories( aExplicitCategoriesProvider.getSimpleCategories());
+ if( nIndex < aCategories.getLength())
+ return aCategories[ nIndex ];
+ }
+ return OUString();
+}
+
+bool ExplicitCategoriesProvider::isDateAxis()
+{
+ init();
+ return m_bIsDateAxis;
+}
+
+const std::vector< double >& ExplicitCategoriesProvider::getDateCategories()
+{
+ init();
+ return m_aDateCategories;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx b/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx
new file mode 100644
index 0000000000..9c41822d36
--- /dev/null
+++ b/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <limits>
+#include <string_view>
+
+#include <ExponentialRegressionCurveCalculator.hxx>
+#include <RegressionCalculationHelper.hxx>
+#include <SpecialCharacters.hxx>
+
+#include <rtl/math.hxx>
+#include <rtl/ustrbuf.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+ExponentialRegressionCurveCalculator::ExponentialRegressionCurveCalculator()
+ : m_fLogSlope(std::numeric_limits<double>::quiet_NaN())
+ , m_fLogIntercept(std::numeric_limits<double>::quiet_NaN())
+ , m_fSign(1.0)
+{
+}
+
+ExponentialRegressionCurveCalculator::~ExponentialRegressionCurveCalculator()
+{}
+
+// ____ XRegressionCurveCalculator ____
+void SAL_CALL ExponentialRegressionCurveCalculator::recalculateRegression(
+ const uno::Sequence< double >& aXValues,
+ const uno::Sequence< double >& aYValues )
+{
+ RegressionCalculationHelper::tDoubleVectorPair aValues(
+ RegressionCalculationHelper::cleanup(
+ aXValues, aYValues,
+ RegressionCalculationHelper::isValidAndYPositive()));
+ m_fSign = 1.0;
+
+ size_t nMax = aValues.first.size();
+ if( nMax <= 1 ) // at least 2 points
+ {
+ aValues = RegressionCalculationHelper::cleanup(
+ aXValues, aYValues,
+ RegressionCalculationHelper::isValidAndYNegative());
+ nMax = aValues.first.size();
+ if( nMax <= 1 )
+ {
+ m_fLogSlope = std::numeric_limits<double>::quiet_NaN();
+ m_fLogIntercept = std::numeric_limits<double>::quiet_NaN();
+ m_fCorrelationCoefficient = std::numeric_limits<double>::quiet_NaN();// actual it is coefficient of determination
+ return;
+ }
+ m_fSign = -1.0;
+ }
+
+ double fAverageX = 0.0, fAverageY = 0.0;
+ double fLogIntercept = ( mForceIntercept && (m_fSign * mInterceptValue)>0 ) ? log(m_fSign * mInterceptValue) : 0.0;
+ std::vector<double> yVector;
+ yVector.resize(nMax, 0.0);
+
+ size_t i = 0;
+ for( i = 0; i < nMax; ++i )
+ {
+ double yValue = log( m_fSign *aValues.second[i] );
+ if (mForceIntercept)
+ {
+ yValue -= fLogIntercept;
+ }
+ else
+ {
+ fAverageX += aValues.first[i];
+ fAverageY += yValue;
+ }
+ yVector[i] = yValue;
+ }
+
+ const double fN = static_cast< double >( nMax );
+ fAverageX /= fN;
+ fAverageY /= fN;
+
+ double fQx = 0.0, fQy = 0.0, fQxy = 0.0;
+ for( i = 0; i < nMax; ++i )
+ {
+ double fDeltaX = aValues.first[i] - fAverageX;
+ double fDeltaY = yVector[i] - fAverageY;
+
+ fQx += fDeltaX * fDeltaX;
+ fQy += fDeltaY * fDeltaY;
+ fQxy += fDeltaX * fDeltaY;
+ }
+
+ m_fLogSlope = fQxy / fQx;
+ m_fLogIntercept = mForceIntercept ? fLogIntercept : fAverageY - m_fLogSlope * fAverageX;
+ m_fCorrelationCoefficient = fQxy / sqrt( fQx * fQy );
+}
+
+double SAL_CALL ExponentialRegressionCurveCalculator::getCurveValue( double x )
+{
+ if( ! ( std::isnan( m_fLogSlope ) ||
+ std::isnan( m_fLogIntercept )))
+ {
+ return m_fSign * exp(m_fLogIntercept + x * m_fLogSlope);
+ }
+
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+uno::Sequence< geometry::RealPoint2D > SAL_CALL ExponentialRegressionCurveCalculator::getCurveValues(
+ double min, double max, ::sal_Int32 nPointCount,
+ const uno::Reference< chart2::XScaling >& xScalingX,
+ const uno::Reference< chart2::XScaling >& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation )
+{
+ if( bMaySkipPointsInCalculation &&
+ isLinearScaling( xScalingX ) &&
+ isLogarithmicScaling( xScalingY ))
+ {
+ // optimize result
+ uno::Sequence< geometry::RealPoint2D > aResult{ { min, getCurveValue( min ) },
+ { max, getCurveValue( max ) } };
+
+ return aResult;
+ }
+
+ return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation );
+}
+
+OUString ExponentialRegressionCurveCalculator::ImplGetRepresentation(
+ const uno::Reference< util::XNumberFormatter >& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaMaxWidth /* = nullptr */ ) const
+{
+ double fIntercept = exp(m_fLogIntercept);
+ bool bHasSlope = !rtl::math::approxEqual( exp(m_fLogSlope), 1.0 );
+ bool bHasLogSlope = !rtl::math::approxEqual( fabs(m_fLogSlope), 1.0 );
+ bool bHasIntercept = !rtl::math::approxEqual( fIntercept, 1.0 ) && fIntercept != 0.0;
+
+ OUStringBuffer aBuf( mYName + " = " );
+ sal_Int32 nLineLength = aBuf.getLength();
+ sal_Int32 nValueLength=0;
+ if ( pFormulaMaxWidth && *pFormulaMaxWidth > 0 )
+ { // count characters different from coefficients
+ sal_Int32 nCharMin = nLineLength + 10 + mXName.getLength(); // 10 = "exp( ", " x )" + 2 extra characters
+ if ( m_fSign < 0.0 )
+ nCharMin += 2;
+ if ( fIntercept == 0.0 || ( !bHasSlope && m_fLogIntercept != 0.0 ) )
+ nCharMin += 3; // " + " special case where equation is written exp( a + b x )
+ if ( ( bHasIntercept || fIntercept == 0.0 || ( !bHasSlope && m_fLogIntercept != 0.0 ) ) &&
+ bHasLogSlope )
+ nValueLength = ( *pFormulaMaxWidth - nCharMin ) / 2;
+ else
+ nValueLength = *pFormulaMaxWidth - nCharMin;
+ if ( nValueLength <= 0 )
+ nValueLength = 1;
+ }
+ // temporary buffer
+ OUStringBuffer aTmpBuf("");
+ // if nValueLength not calculated then nullptr
+ sal_Int32* pValueLength = nValueLength ? &nValueLength : nullptr;
+ if ( m_fSign < 0.0 )
+ aTmpBuf.append( OUStringChar(aMinusSign) + " " );
+ if ( bHasIntercept )
+ {
+ OUString aValueString = getFormattedString( xNumFormatter, nNumberFormatKey, fIntercept, pValueLength );
+ if ( aValueString != "1" ) // aValueString may be rounded to 1 if nValueLength is small
+ {
+ aTmpBuf.append( aValueString + " " );
+ addStringToEquation( aBuf, nLineLength, aTmpBuf, pFormulaMaxWidth );
+ aTmpBuf.truncate();
+ }
+ }
+ aTmpBuf.append( "exp( " );
+ if ( !bHasIntercept )
+ {
+ if ( fIntercept == 0.0 || // underflow, a true zero is impossible
+ ( !bHasSlope && m_fLogIntercept != 0.0 ) ) // show logarithmic output, if intercept and slope both are near one
+ { // otherwise drop output of intercept, which is 1 here
+ OUString aValueString = getFormattedString( xNumFormatter, nNumberFormatKey, m_fLogIntercept, pValueLength );
+ if ( aValueString != "0" ) // aValueString may be rounded to 0 if nValueLength is small
+ {
+ aTmpBuf.append( aValueString ).append( (m_fLogSlope < 0.0) ? std::u16string_view(u" ") : std::u16string_view(u" + ") );
+ }
+ }
+ }
+ if ( m_fLogSlope < 0.0 )
+ aTmpBuf.append( OUStringChar(aMinusSign) + " " );
+ if ( bHasLogSlope )
+ {
+ OUString aValueString = getFormattedString( xNumFormatter, nNumberFormatKey, fabs(m_fLogSlope), pValueLength );
+ if ( aValueString != "1" ) // aValueString may be rounded to 1 if nValueLength is small
+ {
+ aTmpBuf.append( aValueString + " " );
+ }
+ }
+ aTmpBuf.append( mXName + " )");
+ addStringToEquation( aBuf, nLineLength, aTmpBuf, pFormulaMaxWidth );
+
+ return aBuf.makeStringAndClear();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/FillProperties.cxx b/chart2/source/tools/FillProperties.cxx
new file mode 100644
index 0000000000..ba3b63c83d
--- /dev/null
+++ b/chart2/source/tools/FillProperties.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <FillProperties.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/RectanglePoint.hpp>
+
+#include <tools/color.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+
+namespace chart
+{
+
+namespace
+{
+
+void lcl_AddPropertiesToVector_without_BitmapProperties( std::vector< css::beans::Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "FillStyle",
+ FillProperties::PROP_FILL_STYLE,
+ cppu::UnoType<drawing::FillStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillColor",
+ FillProperties::PROP_FILL_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID // "maybe auto"
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillTransparence",
+ FillProperties::PROP_FILL_TRANSPARENCE,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillTransparenceGradientName",
+ FillProperties::PROP_FILL_TRANSPARENCE_GRADIENT_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillGradientName",
+ FillProperties::PROP_FILL_GRADIENT_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillGradientStepCount",
+ FillProperties::PROP_FILL_GRADIENT_STEPCOUNT,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "FillHatchName",
+ FillProperties::PROP_FILL_HATCH_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ //bitmap properties see lcl_AddPropertiesToVector_only_BitmapProperties()
+
+ rOutProperties.emplace_back( "FillBackground",
+ FillProperties::PROP_FILL_BACKGROUND,
+ cppu::UnoType<sal_Bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+void lcl_AddPropertiesToVector_only_BitmapProperties( std::vector< css::beans::Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "FillBitmapName",
+ FillProperties::PROP_FILL_BITMAP_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapOffsetX",
+ FillProperties::PROP_FILL_BITMAP_OFFSETX,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapOffsetY",
+ FillProperties::PROP_FILL_BITMAP_OFFSETY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapPositionOffsetX",
+ FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapPositionOffsetY",
+ FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapRectanglePoint",
+ FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT,
+ cppu::UnoType<drawing::RectanglePoint>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapLogicalSize",
+ FillProperties::PROP_FILL_BITMAP_LOGICALSIZE,
+ cppu::UnoType<sal_Bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapSizeX",
+ FillProperties::PROP_FILL_BITMAP_SIZEX,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapSizeY",
+ FillProperties::PROP_FILL_BITMAP_SIZEY,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "FillBitmapMode",
+ FillProperties::PROP_FILL_BITMAP_MODE,
+ cppu::UnoType<drawing::BitmapMode>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+void lcl_AddDefaultsToMap_without_BitmapProperties(
+ ::chart::tPropertyValueMap & rOutMap )
+{
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_STYLE, drawing::FillStyle_SOLID );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_COLOR, Color(0xd9, 0xd9, 0xd9) ); // gray85
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_TRANSPARENCE, sal_Int16(0) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BACKGROUND, false );
+}
+
+void lcl_AddDefaultsToMap_only_BitmapProperties(
+ ::chart::tPropertyValueMap & rOutMap )
+{
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETX, sal_Int16(0) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_OFFSETY, sal_Int16(0) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETX, sal_Int16(0) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_POSITION_OFFSETY, sal_Int16(0) );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_RECTANGLEPOINT, drawing::RectanglePoint_MIDDLE_MIDDLE );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_LOGICALSIZE, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEX, sal_Int32(0) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_SIZEY, sal_Int32(0) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, FillProperties::PROP_FILL_BITMAP_MODE, drawing::BitmapMode_REPEAT );
+}
+
+}//end anonymous namespace
+
+void FillProperties::AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ // Fill Properties see service drawing::FillProperties
+ lcl_AddPropertiesToVector_without_BitmapProperties( rOutProperties );
+ lcl_AddPropertiesToVector_only_BitmapProperties( rOutProperties );
+}
+
+void FillProperties::AddDefaultsToMap(
+ ::chart::tPropertyValueMap & rOutMap )
+{
+ lcl_AddDefaultsToMap_without_BitmapProperties( rOutMap );
+ lcl_AddDefaultsToMap_only_BitmapProperties( rOutMap );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/FormattedStringHelper.cxx b/chart2/source/tools/FormattedStringHelper.cxx
new file mode 100644
index 0000000000..a59a76d2f5
--- /dev/null
+++ b/chart2/source/tools/FormattedStringHelper.cxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <FormattedStringHelper.hxx>
+#include <FormattedString.hxx>
+#include <com/sun/star/chart2/FormattedString.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/property.hxx>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+rtl::Reference< ::chart::FormattedString >
+ FormattedStringHelper::createFormattedString(
+ const OUString & rString
+ , const Reference< beans::XPropertySet > & xTextProperties ) noexcept
+{
+ rtl::Reference< FormattedString > xFormStr;
+ try
+ {
+ xFormStr = new FormattedString();
+
+ xFormStr->setString( rString );
+
+ // set character properties
+ comphelper::copyProperties(
+ xTextProperties, Reference< beans::XPropertySet >( static_cast<cppu::OWeakObject*>(xFormStr.get()), uno::UNO_QUERY_THROW ) );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xFormStr;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/InternalData.cxx b/chart2/source/tools/InternalData.cxx
new file mode 100644
index 0000000000..d6321d3179
--- /dev/null
+++ b/chart2/source/tools/InternalData.cxx
@@ -0,0 +1,550 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <InternalData.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+
+#include <comphelper/sequence.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+
+#ifdef DEBUG_CHART2_TOOLS
+#define DEBUG_INTERNAL_DATA 1
+#endif
+
+#ifdef DEBUG_INTERNAL_DATA
+#include <svl/gridprinter.hxx>
+#endif
+
+#include <algorithm>
+#include <iterator>
+#include <limits>
+
+using ::com::sun::star::uno::Sequence;
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+namespace
+{
+struct lcl_NumberedStringGenerator
+{
+ lcl_NumberedStringGenerator( const OUString & rStub, std::u16string_view rWildcard ) :
+ m_aStub( rStub ),
+ m_nCounter( 0 ),
+ m_nStubStartIndex( rStub.indexOf( rWildcard )),
+ m_nWildcardLength( rWildcard.size())
+ {
+ }
+ std::vector< uno::Any > operator()()
+ {
+ return { uno::Any(m_aStub.replaceAt( m_nStubStartIndex, m_nWildcardLength, OUString::number( ++m_nCounter ))) };
+ }
+private:
+ OUString m_aStub;
+ sal_Int32 m_nCounter;
+ const sal_Int32 m_nStubStartIndex;
+ const sal_Int32 m_nWildcardLength;
+};
+
+template< typename T >
+ Sequence< T > lcl_ValarrayToSequence( const std::valarray< T > & rValarray )
+{
+#if defined __GLIBCXX__ && (!defined _GLIBCXX_RELEASE || _GLIBCXX_RELEASE < 12)
+ // workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103022
+ if (!size(rValarray))
+ return Sequence<T>();
+#endif
+
+ return comphelper::containerToSequence(rValarray);
+}
+
+} // anonymous namespace
+
+InternalData::InternalData()
+ : m_nColumnCount( 0 )
+ , m_nRowCount( 0 )
+ , m_aRowLabels( 0 )
+ , m_aColumnLabels( 0 )
+{}
+
+const double fDefaultData[] = {
+ 9.10, 3.20, 4.54,
+ 2.40, 8.80, 9.65,
+ 3.10, 1.50, 3.70,
+ 4.30, 9.02, 6.20
+};
+
+void InternalData::createDefaultData()
+{
+ const sal_Int32 nRowCount = 4;
+ const sal_Int32 nColumnCount = 3;
+
+ m_nRowCount = nRowCount;
+ m_nColumnCount = nColumnCount;
+ const sal_Int32 nSize = nColumnCount * nRowCount;
+ // @todo: localize this!
+ const OUString aRowName(SchResId(STR_ROW_LABEL));
+ const OUString aColName(SchResId(STR_COLUMN_LABEL));
+
+ m_aData.resize( nSize );
+ for( sal_Int32 i=0; i<nSize; ++i )
+ m_aData[i] = fDefaultData[i];
+
+ m_aRowLabels.clear();
+ m_aRowLabels.reserve( m_nRowCount );
+ generate_n( back_inserter( m_aRowLabels ), m_nRowCount,
+ lcl_NumberedStringGenerator( aRowName, u"%ROWNUMBER" ));
+
+ m_aColumnLabels.clear();
+ m_aColumnLabels.reserve( m_nColumnCount );
+ generate_n( back_inserter( m_aColumnLabels ), m_nColumnCount,
+ lcl_NumberedStringGenerator( aColName, u"%COLUMNNUMBER" ));
+}
+
+void InternalData::setData( const Sequence< Sequence< double > >& rDataInRows )
+{
+ m_nRowCount = rDataInRows.getLength();
+ m_nColumnCount = (m_nRowCount ? rDataInRows[0].getLength() : 0);
+
+ if( m_aRowLabels.size() != static_cast< sal_uInt32 >( m_nRowCount ))
+ m_aRowLabels.resize( m_nRowCount );
+ if( m_aColumnLabels.size() != static_cast< sal_uInt32 >( m_nColumnCount ))
+ m_aColumnLabels.resize( m_nColumnCount );
+
+ m_aData.resize( m_nRowCount * m_nColumnCount );
+ // set all values to Nan
+ m_aData = std::numeric_limits<double>::quiet_NaN();
+
+ for( sal_Int32 nRow=0; nRow<m_nRowCount; ++nRow )
+ {
+ int nDataIdx = nRow*m_nColumnCount;
+ const sal_Int32 nMax = std::min( rDataInRows[nRow].getLength(), m_nColumnCount );
+ for( sal_Int32 nCol=0; nCol < nMax; ++nCol )
+ {
+ m_aData[nDataIdx] = rDataInRows[nRow][nCol];
+ nDataIdx += 1;
+ }
+ }
+}
+
+Sequence< Sequence< double > > InternalData::getData() const
+{
+ Sequence< Sequence< double > > aResult( m_nRowCount );
+ auto aResultRange = asNonConstRange(aResult);
+
+ for( sal_Int32 i=0; i<m_nRowCount; ++i )
+ aResultRange[i] = lcl_ValarrayToSequence< tDataType::value_type >(
+ m_aData[ std::slice( i*m_nColumnCount, m_nColumnCount, 1 ) ] );
+
+ return aResult;
+}
+
+Sequence< double > InternalData::getColumnValues( sal_Int32 nColumnIndex ) const
+{
+ if( nColumnIndex >= 0 && nColumnIndex < m_nColumnCount )
+ return lcl_ValarrayToSequence< tDataType::value_type >(
+ m_aData[ std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] );
+ return Sequence< double >();
+}
+Sequence< double > InternalData::getRowValues( sal_Int32 nRowIndex ) const
+{
+ if( nRowIndex >= 0 && nRowIndex < m_nRowCount )
+ return lcl_ValarrayToSequence< tDataType::value_type >(
+ m_aData[ std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ] );
+ return Sequence< double >();
+}
+
+void InternalData::setColumnValues( sal_Int32 nColumnIndex, const std::vector< double > & rNewData )
+{
+ if( nColumnIndex < 0 )
+ return;
+ enlargeData( nColumnIndex + 1, rNewData.size() );
+
+ tDataType aSlice = m_aData[ std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ];
+ for( std::vector< double >::size_type i = 0; i < rNewData.size(); ++i )
+ aSlice[i] = rNewData[i];
+ m_aData[ std::slice( nColumnIndex, m_nRowCount, m_nColumnCount ) ] = aSlice;
+}
+
+void InternalData::setRowValues( sal_Int32 nRowIndex, const std::vector< double > & rNewData )
+{
+ if( nRowIndex < 0 )
+ return;
+ enlargeData( rNewData.size(), nRowIndex+1 );
+
+ tDataType aSlice = m_aData[ std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ];
+ for( std::vector< double >::size_type i = 0; i < rNewData.size(); ++i )
+ aSlice[i] = rNewData[i];
+ m_aData[ std::slice( nRowIndex*m_nColumnCount, m_nColumnCount, 1 ) ]= aSlice;
+}
+
+void InternalData::setComplexColumnLabel( sal_Int32 nColumnIndex, std::vector< uno::Any >&& rComplexLabel )
+{
+ if( nColumnIndex < 0 )
+ return;
+ if( o3tl::make_unsigned(nColumnIndex) >= m_aColumnLabels.size() )
+ {
+ m_aColumnLabels.resize(nColumnIndex+1);
+ enlargeData( nColumnIndex+1, 0 );
+ }
+ m_aColumnLabels[nColumnIndex] = std::move(rComplexLabel);
+
+ dump();
+}
+
+void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, std::vector< uno::Any >&& rComplexLabel )
+{
+ if( nRowIndex < 0 )
+ return;
+ if( o3tl::make_unsigned(nRowIndex) >= m_aRowLabels.size() )
+ {
+ m_aRowLabels.resize(nRowIndex+1);
+ enlargeData( 0, nRowIndex+1 );
+ }
+ sal_Int32 nSize = static_cast<sal_Int32>( m_aRowLabels[nRowIndex].size() );
+ if( nSize >= 1 && !rComplexLabel.empty() )
+ {
+ m_aRowLabels[nRowIndex].resize(nSize+1);
+ m_aRowLabels[nRowIndex][nSize] = rComplexLabel[0];
+ }
+ else
+ {
+ m_aRowLabels[nRowIndex] = std::move(rComplexLabel);
+ }
+}
+
+std::vector< uno::Any > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const
+{
+ if( nColumnIndex < static_cast< sal_Int32 >( m_aColumnLabels.size() ) )
+ return m_aColumnLabels[nColumnIndex];
+ else
+ return std::vector< uno::Any >();
+}
+std::vector< uno::Any > InternalData::getComplexRowLabel( sal_Int32 nRowIndex ) const
+{
+ if( nRowIndex < static_cast< sal_Int32 >( m_aRowLabels.size() ) )
+ return m_aRowLabels[nRowIndex];
+ else
+ return std::vector< uno::Any >();
+}
+
+void InternalData::swapRowWithNext( sal_Int32 nRowIndex )
+{
+ if( nRowIndex >= m_nRowCount - 1 )
+ return;
+
+ const sal_Int32 nMax = m_nColumnCount;
+ for( sal_Int32 nColIdx=0; nColIdx<nMax; ++nColIdx )
+ {
+ size_t nIndex1 = nColIdx + nRowIndex*m_nColumnCount;
+ size_t nIndex2 = nIndex1 + m_nColumnCount;
+ std::swap(m_aData[nIndex1], m_aData[nIndex2]);
+ }
+
+ std::swap(m_aRowLabels[nRowIndex], m_aRowLabels[nRowIndex + 1]);
+}
+
+void InternalData::swapColumnWithNext( sal_Int32 nColumnIndex )
+{
+ if( nColumnIndex >= m_nColumnCount - 1 )
+ return;
+
+ const sal_Int32 nMax = m_nRowCount;
+ for( sal_Int32 nRowIdx=0; nRowIdx<nMax; ++nRowIdx )
+ {
+ size_t nIndex1 = nColumnIndex + nRowIdx*m_nColumnCount;
+ size_t nIndex2 = nIndex1 + 1;
+ std::swap(m_aData[nIndex1], m_aData[nIndex2]);
+ }
+
+ std::vector< uno::Any > aTemp( m_aColumnLabels[nColumnIndex] );
+ m_aColumnLabels[nColumnIndex] = m_aColumnLabels[nColumnIndex + 1];
+ m_aColumnLabels[nColumnIndex + 1] = aTemp;
+}
+
+bool InternalData::enlargeData( sal_Int32 nColumnCount, sal_Int32 nRowCount )
+{
+ sal_Int32 nNewColumnCount( std::max<sal_Int32>( m_nColumnCount, nColumnCount ) );
+ sal_Int32 nNewRowCount( std::max<sal_Int32>( m_nRowCount, nRowCount ) );
+ sal_Int32 nNewSize( nNewColumnCount*nNewRowCount );
+
+ bool bGrow = (nNewSize > m_nColumnCount*m_nRowCount);
+
+ if( bGrow )
+ {
+ tDataType aNewData( std::numeric_limits<double>::quiet_NaN(), nNewSize );
+ // copy old data
+ for( int nCol=0; nCol<m_nColumnCount; ++nCol )
+ static_cast< tDataType >(
+ aNewData[ std::slice( nCol, m_nRowCount, nNewColumnCount ) ] ) =
+ m_aData[ std::slice( nCol, m_nRowCount, m_nColumnCount ) ];
+
+ m_aData.resize( nNewSize );
+ m_aData = aNewData;
+ }
+ m_nColumnCount = nNewColumnCount;
+ m_nRowCount = nNewRowCount;
+ return bGrow;
+}
+
+void InternalData::insertColumn( sal_Int32 nAfterIndex )
+{
+ // note: -1 is allowed, as we insert after the given index
+ OSL_ASSERT( nAfterIndex < m_nColumnCount && nAfterIndex >= -1 );
+ if( nAfterIndex >= m_nColumnCount || nAfterIndex < -1 )
+ return;
+ sal_Int32 nNewColumnCount = m_nColumnCount + 1;
+ sal_Int32 nNewSize( nNewColumnCount * m_nRowCount );
+
+ tDataType aNewData( std::numeric_limits<double>::quiet_NaN(), nNewSize );
+
+ // copy old data
+ int nCol=0;
+ for( ; nCol<=nAfterIndex; ++nCol )
+ aNewData[ std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
+ static_cast< tDataType >(
+ m_aData[ std::slice( nCol, m_nRowCount, m_nColumnCount ) ] );
+ for( ++nCol; nCol<nNewColumnCount; ++nCol )
+ aNewData[ std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
+ static_cast< tDataType >(
+ m_aData[ std::slice( nCol - 1, m_nRowCount, m_nColumnCount ) ] );
+
+ m_nColumnCount = nNewColumnCount;
+ m_aData.resize( nNewSize );
+ m_aData = aNewData;
+
+ // labels
+ if( nAfterIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
+ m_aColumnLabels.insert( m_aColumnLabels.begin() + (nAfterIndex + 1), std::vector< uno::Any >(1) );
+
+ dump();
+}
+
+sal_Int32 InternalData::appendColumn()
+{
+ insertColumn( getColumnCount() - 1 );
+ return getColumnCount() - 1;
+}
+
+sal_Int32 InternalData::appendRow()
+{
+ insertRow( getRowCount() - 1 );
+ return getRowCount() - 1;
+}
+
+sal_Int32 InternalData::getRowCount() const
+{
+ return m_nRowCount;
+}
+
+sal_Int32 InternalData::getColumnCount() const
+{
+ return m_nColumnCount;
+}
+
+void InternalData::insertRow( sal_Int32 nAfterIndex )
+{
+ // note: -1 is allowed, as we insert after the given index
+ OSL_ASSERT( nAfterIndex < m_nRowCount && nAfterIndex >= -1 );
+ if( nAfterIndex >= m_nRowCount || nAfterIndex < -1 )
+ return;
+ sal_Int32 nNewRowCount = m_nRowCount + 1;
+ sal_Int32 nNewSize( m_nColumnCount * nNewRowCount );
+
+ tDataType aNewData( std::numeric_limits<double>::quiet_NaN(), nNewSize );
+
+ // copy old data
+ sal_Int32 nIndex = nAfterIndex + 1;
+ aNewData[ std::slice( 0, nIndex * m_nColumnCount, 1 ) ] =
+ static_cast< tDataType >(
+ m_aData[ std::slice( 0, nIndex * m_nColumnCount, 1 ) ] );
+
+ if( nIndex < m_nRowCount )
+ {
+ sal_Int32 nRemainingCount = m_nColumnCount * (m_nRowCount - nIndex);
+ aNewData[ std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] =
+ static_cast< tDataType >(
+ m_aData[ std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] );
+ }
+
+ m_nRowCount = nNewRowCount;
+ m_aData.resize( nNewSize );
+ m_aData = aNewData;
+
+ // labels
+ if( nAfterIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
+ m_aRowLabels.insert( m_aRowLabels.begin() + nIndex, std::vector< uno::Any > (1));
+
+ dump();
+}
+
+void InternalData::deleteColumn( sal_Int32 nAtIndex )
+{
+ OSL_ASSERT( nAtIndex < m_nColumnCount && nAtIndex >= 0 );
+ if( nAtIndex >= m_nColumnCount || m_nColumnCount < 1 || nAtIndex < 0 )
+ return;
+ sal_Int32 nNewColumnCount = m_nColumnCount - 1;
+ sal_Int32 nNewSize( nNewColumnCount * m_nRowCount );
+
+ tDataType aNewData( std::numeric_limits<double>::quiet_NaN(), nNewSize );
+
+ // copy old data
+ int nCol=0;
+ for( ; nCol<nAtIndex; ++nCol )
+ aNewData[ std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
+ static_cast< tDataType >(
+ m_aData[ std::slice( nCol, m_nRowCount, m_nColumnCount ) ] );
+ for( ; nCol<nNewColumnCount; ++nCol )
+ aNewData[ std::slice( nCol, m_nRowCount, nNewColumnCount ) ] =
+ static_cast< tDataType >(
+ m_aData[ std::slice( nCol + 1, m_nRowCount, m_nColumnCount ) ] );
+
+ m_nColumnCount = nNewColumnCount;
+ m_aData.resize( nNewSize );
+ m_aData = aNewData;
+
+ // labels
+ if( nAtIndex < static_cast< sal_Int32 >( m_aColumnLabels.size()))
+ m_aColumnLabels.erase( m_aColumnLabels.begin() + nAtIndex );
+
+ dump();
+}
+
+void InternalData::deleteRow( sal_Int32 nAtIndex )
+{
+ OSL_ASSERT( nAtIndex < m_nRowCount && nAtIndex >= 0 );
+ if( nAtIndex >= m_nRowCount || m_nRowCount < 1 || nAtIndex < 0 )
+ return;
+ sal_Int32 nNewRowCount = m_nRowCount - 1;
+ sal_Int32 nNewSize( m_nColumnCount * nNewRowCount );
+
+ tDataType aNewData( std::numeric_limits<double>::quiet_NaN(), nNewSize );
+
+ // copy old data
+ sal_Int32 nIndex = nAtIndex;
+ if( nIndex )
+ aNewData[ std::slice( 0, nIndex * m_nColumnCount, 1 ) ] =
+ static_cast< tDataType >(
+ m_aData[ std::slice( 0, nIndex * m_nColumnCount, 1 ) ] );
+
+ if( nIndex < nNewRowCount )
+ {
+ sal_Int32 nRemainingCount = m_nColumnCount * (nNewRowCount - nIndex);
+ aNewData[ std::slice( nIndex * m_nColumnCount, nRemainingCount, 1 ) ] =
+ static_cast< tDataType >(
+ m_aData[ std::slice( (nIndex + 1) * m_nColumnCount, nRemainingCount, 1 ) ] );
+ }
+
+ m_nRowCount = nNewRowCount;
+ m_aData.resize( nNewSize );
+ m_aData = aNewData;
+
+ // labels
+ if( nAtIndex < static_cast< sal_Int32 >( m_aRowLabels.size()))
+ m_aRowLabels.erase( m_aRowLabels.begin() + nAtIndex );
+
+ dump();
+}
+
+void InternalData::setComplexRowLabels( tVecVecAny&& rNewRowLabels )
+{
+ m_aRowLabels = std::move(rNewRowLabels);
+ sal_Int32 nNewRowCount = static_cast< sal_Int32 >( m_aRowLabels.size() );
+ if( nNewRowCount < m_nRowCount )
+ m_aRowLabels.resize( m_nRowCount );
+ else
+ enlargeData( 0, nNewRowCount );
+}
+
+const InternalData::tVecVecAny& InternalData::getComplexRowLabels() const
+{
+ return m_aRowLabels;
+}
+
+void InternalData::setComplexColumnLabels( tVecVecAny&& rNewColumnLabels )
+{
+ m_aColumnLabels = std::move(rNewColumnLabels);
+ sal_Int32 nNewColumnCount = static_cast< sal_Int32 >( m_aColumnLabels.size() );
+ if( nNewColumnCount < m_nColumnCount )
+ m_aColumnLabels.resize( m_nColumnCount );
+ else
+ enlargeData( nNewColumnCount, 0 );
+}
+
+const InternalData::tVecVecAny& InternalData::getComplexColumnLabels() const
+{
+ return m_aColumnLabels;
+}
+
+#ifdef DEBUG_INTERNAL_DATA
+void InternalData::dump() const
+{
+ // Header
+ if (!m_aColumnLabels.empty())
+ {
+ svl::GridPrinter aPrinter(m_aColumnLabels[0].size(), m_aColumnLabels.size(), true);
+ for (size_t nCol = 0; nCol < m_aColumnLabels.size(); ++nCol)
+ {
+ for (size_t nRow = 0; nRow < m_aColumnLabels[nCol].size(); ++nRow)
+ {
+ OUString aStr;
+ if (m_aColumnLabels[nCol].at(nRow) >>= aStr)
+ aPrinter.set(nRow, nCol, aStr);
+ }
+ }
+ aPrinter.print("Header");
+ }
+
+ if (!m_aRowLabels.empty())
+ {
+ svl::GridPrinter aPrinter(m_aRowLabels.size(), m_aRowLabels[0].size(), true);
+ for (size_t nRow = 0; nRow < m_aRowLabels.size(); ++nRow)
+ {
+ for (size_t nCol = 0; nCol < m_aRowLabels[nRow].size(); ++nCol)
+ {
+ OUString aStr;
+ if (m_aRowLabels[nRow].at(nCol) >>= aStr)
+ aPrinter.set(nRow, nCol, aStr);
+ }
+ }
+ aPrinter.print("Row labels");
+ }
+
+ svl::GridPrinter aPrinter(m_nRowCount, m_nColumnCount, true);
+
+ for (sal_Int32 nRow = 0; nRow < m_nRowCount; ++nRow)
+ {
+ tDataType aSlice( m_aData[ std::slice( nRow*m_nColumnCount, m_nColumnCount, 1 ) ] );
+ for (sal_Int32 nCol = 0; nCol < m_nColumnCount; ++nCol)
+ aPrinter.set(nRow, nCol, OUString::number(aSlice[nCol]));
+ }
+
+ aPrinter.print("Column data");
+}
+#else
+void InternalData::dump() const {}
+#endif
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/InternalDataProvider.cxx b/chart2/source/tools/InternalDataProvider.cxx
new file mode 100644
index 0000000000..883920daa9
--- /dev/null
+++ b/chart2/source/tools/InternalDataProvider.cxx
@@ -0,0 +1,1552 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cstddef>
+#include <iterator>
+
+#include <InternalDataProvider.hxx>
+#include <LabeledDataSequence.hxx>
+#include <DataSource.hxx>
+#include <XMLRangeHelper.hxx>
+#include <CommonFunctors.hxx>
+#include <UncachedDataSequence.hxx>
+#include <DataSourceHelper.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <DataSeries.hxx>
+
+#include <com/sun/star/chart2/data/XDataSequence.hpp>
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <comphelper/property.hxx>
+#include <o3tl/string_view.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <limits>
+#include <vector>
+#include <algorithm>
+
+namespace com::sun::star::chart2 { class XChartDocument; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+namespace
+{
+
+constexpr OUString lcl_aCategoriesRangeName = u"categories"_ustr;
+const char lcl_aCategoriesLevelRangeNamePrefix[] = "categoriesL "; //L <-> level
+const char lcl_aCategoriesPointRangeNamePrefix[] = "categoriesP "; //P <-> point
+constexpr OUString lcl_aCategoriesRoleName = u"categories"_ustr;
+const char lcl_aLabelRangePrefix[] = "label ";
+constexpr OUString lcl_aCompleteRange = u"all"_ustr;
+
+typedef std::multimap< OUString, uno::WeakReference< chart2::data::XDataSequence > >
+ lcl_tSequenceMap;
+
+std::vector< OUString > lcl_AnyToStringSequence( const std::vector< uno::Any >& aAnySeq )
+{
+ std::vector< OUString > aResult;
+ aResult.resize( aAnySeq.size() );
+ int i = 0;
+ for (const uno::Any& aAny : aAnySeq)
+ aResult[i++] = CommonFunctors::AnyToString()(aAny);
+ return aResult;
+}
+
+std::vector< uno::Any > lcl_StringToAnyVector( const css::uno::Sequence< OUString >& aStringSeq )
+{
+ std::vector< uno::Any > aResult;
+ aResult.resize( aStringSeq.getLength() );
+ int i = 0;
+ for (const OUString& aStr : aStringSeq)
+ aResult[i++] = CommonFunctors::makeAny<OUString>()(aStr);
+ return aResult;
+}
+
+struct lcl_setModified
+{
+ void operator() ( const lcl_tSequenceMap::value_type & rMapEntry )
+ {
+ // convert weak reference to reference
+ Reference< chart2::data::XDataSequence > xSeq( rMapEntry.second );
+ if( xSeq.is())
+ {
+ Reference< util::XModifiable > xMod( xSeq, uno::UNO_QUERY );
+ if( xMod.is())
+ xMod->setModified( true );
+ }
+ }
+};
+
+struct lcl_internalizeSeries
+{
+ lcl_internalizeSeries( InternalData & rInternalData,
+ InternalDataProvider & rProvider,
+ bool bConnectToModel, bool bDataInColumns ) :
+ m_rInternalData( rInternalData ),
+ m_rProvider( rProvider ),
+ m_bConnectToModel( bConnectToModel ),
+ m_bDataInColumns( bDataInColumns )
+ {}
+ void operator() ( const rtl::Reference< DataSeries > & xSeries )
+ {
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aOldSeriesData = xSeries->getDataSequences2();
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSeriesData( aOldSeriesData.size() );
+ for( std::size_t i=0; i<aOldSeriesData.size(); ++i )
+ {
+ sal_Int32 nNewIndex( m_bDataInColumns ? m_rInternalData.appendColumn() : m_rInternalData.appendRow() );
+ OUString aIdentifier( OUString::number( nNewIndex ));
+ //@todo: deal also with genericXDataSequence
+ Reference< chart2::data::XNumericalDataSequence > xValues( aOldSeriesData[i]->getValues(), uno::UNO_QUERY );
+ Reference< chart2::data::XTextualDataSequence > xLabel( aOldSeriesData[i]->getLabel(), uno::UNO_QUERY );
+ Reference< chart2::data::XDataSequence > xNewValues;
+
+ if( xValues.is() )
+ {
+ auto aValues( comphelper::sequenceToContainer<std::vector< double >>( xValues->getNumericalData()));
+ if( m_bDataInColumns )
+ m_rInternalData.setColumnValues( nNewIndex, aValues );
+ else
+ m_rInternalData.setRowValues( nNewIndex, aValues );
+ if( m_bConnectToModel )
+ {
+ xNewValues.set( m_rProvider.createDataSequenceByRangeRepresentation( aIdentifier ));
+ comphelper::copyProperties(
+ Reference< beans::XPropertySet >( xValues, uno::UNO_QUERY ),
+ Reference< beans::XPropertySet >( xNewValues, uno::UNO_QUERY ));
+ }
+ }
+
+ if( xLabel.is() )
+ {
+ if( m_bDataInColumns )
+ m_rInternalData.setComplexColumnLabel( nNewIndex, lcl_StringToAnyVector( xLabel->getTextualData() ) );
+ else
+ m_rInternalData.setComplexRowLabel( nNewIndex, lcl_StringToAnyVector( xLabel->getTextualData() ) );
+ if( m_bConnectToModel )
+ {
+ Reference< chart2::data::XDataSequence > xNewLabel(
+ m_rProvider.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix + aIdentifier ));
+ comphelper::copyProperties(
+ Reference< beans::XPropertySet >( xLabel, uno::UNO_QUERY ),
+ Reference< beans::XPropertySet >( xNewLabel, uno::UNO_QUERY ));
+ aNewSeriesData[i].set( new LabeledDataSequence( xNewValues, xNewLabel ) );
+ }
+ }
+ else
+ {
+ if( m_bConnectToModel )
+ aNewSeriesData[i].set( new LabeledDataSequence( xNewValues ) );
+ }
+ }
+ if( m_bConnectToModel )
+ xSeries->setData( aNewSeriesData );
+ }
+
+private:
+ InternalData & m_rInternalData;
+ InternalDataProvider & m_rProvider;
+ bool m_bConnectToModel;
+ bool m_bDataInColumns;
+};
+
+struct lcl_copyFromLevel
+{
+public:
+
+ explicit lcl_copyFromLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ uno::Any operator() ( const std::vector< uno::Any >& rVector )
+ {
+ uno::Any aRet;
+ if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) )
+ aRet = rVector[m_nLevel];
+ return aRet;
+ }
+
+private:
+ sal_Int32 m_nLevel;
+};
+
+struct lcl_getStringFromLevelVector
+{
+public:
+
+ explicit lcl_getStringFromLevelVector( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ OUString operator() ( const std::vector< uno::Any >& rVector )
+ {
+ OUString aString;
+ if( m_nLevel < static_cast< sal_Int32 >(rVector.size()) )
+ aString = CommonFunctors::AnyToString()(rVector[m_nLevel]);
+ return aString;
+ }
+
+private:
+ sal_Int32 m_nLevel;
+};
+
+struct lcl_setAnyAtLevel
+{
+public:
+
+ explicit lcl_setAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ std::vector< uno::Any > operator() ( const std::vector< uno::Any >& rVector, const uno::Any& rNewValue )
+ {
+ std::vector< uno::Any > aRet( rVector );
+ if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
+ aRet.resize( m_nLevel+1 );
+ aRet[ m_nLevel ]=rNewValue;
+ return aRet;
+ }
+
+private:
+ sal_Int32 m_nLevel;
+};
+
+struct lcl_setAnyAtLevelFromStringSequence
+{
+public:
+
+ explicit lcl_setAnyAtLevelFromStringSequence( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ std::vector< uno::Any > operator() ( const std::vector< uno::Any >& rVector, const OUString& rNewValue )
+ {
+ std::vector< uno::Any > aRet( rVector );
+ if( m_nLevel >= static_cast< sal_Int32 >(aRet.size()) )
+ aRet.resize( m_nLevel+1 );
+ aRet[ m_nLevel ] <<= rNewValue;
+ return aRet;
+ }
+
+private:
+ sal_Int32 m_nLevel;
+};
+
+struct lcl_insertAnyAtLevel
+{
+public:
+
+ explicit lcl_insertAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ void operator() ( std::vector< uno::Any >& rVector )
+ {
+ if( m_nLevel >= static_cast< sal_Int32 >(rVector.size()) )
+ {
+ rVector.resize( m_nLevel + 1 );
+ }
+ else
+ {
+ rVector.insert( rVector.begin() + m_nLevel, uno::Any() );
+ }
+ }
+
+private:
+ sal_Int32 m_nLevel;
+};
+
+struct lcl_removeAnyAtLevel
+{
+public:
+
+ explicit lcl_removeAnyAtLevel( sal_Int32 nLevel ) : m_nLevel( nLevel )
+ {}
+
+ void operator() ( std::vector< uno::Any >& rVector )
+ {
+ if( m_nLevel < static_cast<sal_Int32>(rVector.size()) )
+ {
+ rVector.erase(rVector.begin() + m_nLevel);
+ }
+ }
+
+private:
+ sal_Int32 m_nLevel;
+};
+
+} // anonymous namespace
+
+InternalDataProvider::InternalDataProvider()
+ : m_bDataInColumns( true )
+{}
+
+InternalDataProvider::InternalDataProvider(
+ const rtl::Reference< ChartModel > & xModel,
+ bool bConnectToModel,
+ bool bDefaultDataInColumns)
+: m_bDataInColumns( bDefaultDataInColumns )
+{
+ if (!xModel.is())
+ return;
+ try
+ {
+ rtl::Reference< Diagram > xDiagram( xModel->getFirstChartDiagram() );
+ if( xDiagram.is())
+ {
+ //data in columns?
+ {
+ OUString aRangeString;
+ bool bFirstCellAsLabel = true;
+ bool bHasCategories = true;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+ const bool bSomethingDetected(
+ DataSourceHelper::detectRangeSegmentation(
+ xModel, aRangeString, aSequenceMapping, m_bDataInColumns, bFirstCellAsLabel, bHasCategories ));
+
+ // #i120559# if no data was available, restore default
+ if(!bSomethingDetected && m_bDataInColumns != bDefaultDataInColumns)
+ {
+ m_bDataInColumns = bDefaultDataInColumns;
+ }
+ }
+
+ // categories
+ {
+ std::vector< std::vector< uno::Any > > aNewCategories;//inner count is level
+ {
+ ExplicitCategoriesProvider aExplicitCategoriesProvider(ChartModelHelper::getFirstCoordinateSystem(xModel), *xModel);
+
+ const std::vector< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() );
+ sal_Int32 nLevelCount = rSplitCategoriesList.size();
+ for( sal_Int32 nL = 0; nL<nLevelCount; nL++ )
+ {
+ Reference< chart2::data::XLabeledDataSequence > xLDS( rSplitCategoriesList[nL] );
+ if( !xLDS.is() )
+ continue;
+ Sequence< uno::Any > aDataSeq;
+ Reference< chart2::data::XDataSequence > xSeq( xLDS->getValues() );
+ if( xSeq.is() )
+ aDataSeq = xSeq->getData();
+ sal_Int32 nLength = aDataSeq.getLength();
+ sal_Int32 nCatLength = static_cast< sal_Int32 >(aNewCategories.size());
+ if( nCatLength < nLength )
+ aNewCategories.resize( nLength );
+ else if( nLength < nCatLength )
+ aDataSeq.realloc( nCatLength );
+ transform( aNewCategories.begin(), aNewCategories.end(), aDataSeq.getConstArray(),
+ aNewCategories.begin(), lcl_setAnyAtLevel(nL) );
+ }
+ if( !nLevelCount )
+ {
+ Sequence< OUString > aSimplecategories = aExplicitCategoriesProvider.getSimpleCategories();
+ sal_Int32 nLength = aSimplecategories.getLength();
+ aNewCategories.reserve( nLength );
+ for( sal_Int32 nN=0; nN<nLength; nN++)
+ {
+ aNewCategories.push_back( { uno::Any(aSimplecategories[nN]) } );
+ }
+ }
+ }
+
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexRowLabels( std::move(aNewCategories) );
+ else
+ m_aInternalData.setComplexColumnLabels( std::move(aNewCategories) );
+ if( bConnectToModel )
+ xDiagram->setCategories(
+ new LabeledDataSequence(
+ createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName ))
+ );
+ }
+
+ // data series
+ std::vector< rtl::Reference< DataSeries > > aSeriesVector( ChartModelHelper::getDataSeries( xModel ));
+ lcl_internalizeSeries ftor( m_aInternalData, *this, bConnectToModel, m_bDataInColumns );
+ for( const auto& rxScreen : aSeriesVector )
+ ftor( rxScreen );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// copy-CTOR
+InternalDataProvider::InternalDataProvider( const InternalDataProvider & rOther ) :
+ impl::InternalDataProvider_Base(rOther),
+ m_aSequenceMap( rOther.m_aSequenceMap ),
+ m_aInternalData( rOther.m_aInternalData ),
+ m_bDataInColumns( rOther.m_bDataInColumns )
+{}
+
+InternalDataProvider::~InternalDataProvider()
+{}
+
+void InternalDataProvider::addDataSequenceToMap(
+ const OUString & rRangeRepresentation,
+ const Reference< chart2::data::XDataSequence > & xSequence )
+{
+ m_aSequenceMap.emplace(
+ rRangeRepresentation,
+ uno::WeakReference< chart2::data::XDataSequence >( xSequence ));
+}
+
+void InternalDataProvider::deleteMapReferences( const OUString & rRangeRepresentation )
+{
+ // set sequence to deleted by setting its range to an empty string
+ tSequenceMapRange aRange( m_aSequenceMap.equal_range( rRangeRepresentation ));
+ for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
+ {
+ Reference< chart2::data::XDataSequence > xSeq( aIt->second );
+ if( xSeq.is())
+ {
+ Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
+ if( xNamed.is())
+ xNamed->setName( OUString());
+ }
+ }
+ // remove from map
+ m_aSequenceMap.erase( aRange.first, aRange.second );
+}
+
+void InternalDataProvider::adaptMapReferences(
+ const OUString & rOldRangeRepresentation,
+ const OUString & rNewRangeRepresentation )
+{
+ tSequenceMapRange aRange( m_aSequenceMap.equal_range( rOldRangeRepresentation ));
+ tSequenceMap aNewElements;
+ for( tSequenceMap::iterator aIt( aRange.first ); aIt != aRange.second; ++aIt )
+ {
+ Reference< chart2::data::XDataSequence > xSeq( aIt->second );
+ if( xSeq.is())
+ {
+ Reference< container::XNamed > xNamed( xSeq, uno::UNO_QUERY );
+ if( xNamed.is())
+ xNamed->setName( rNewRangeRepresentation );
+ }
+ aNewElements.emplace( rNewRangeRepresentation, aIt->second );
+ }
+ // erase map values for old index
+ m_aSequenceMap.erase( aRange.first, aRange.second );
+ // add new entries for values with new index
+ m_aSequenceMap.insert( aNewElements.begin(), aNewElements.end() );
+}
+
+void InternalDataProvider::increaseMapReferences(
+ sal_Int32 nBegin, sal_Int32 nEnd )
+{
+ for( sal_Int32 nIndex = nEnd - 1; nIndex >= nBegin; --nIndex )
+ {
+ adaptMapReferences( OUString::number( nIndex ),
+ OUString::number( nIndex + 1 ));
+ adaptMapReferences( lcl_aLabelRangePrefix + OUString::number( nIndex ),
+ lcl_aLabelRangePrefix + OUString::number( nIndex + 1 ));
+ }
+}
+
+void InternalDataProvider::decreaseMapReferences(
+ sal_Int32 nBegin, sal_Int32 nEnd )
+{
+ for( sal_Int32 nIndex = nBegin; nIndex < nEnd; ++nIndex )
+ {
+ adaptMapReferences( OUString::number( nIndex ),
+ OUString::number( nIndex - 1 ));
+ adaptMapReferences( lcl_aLabelRangePrefix + OUString::number( nIndex ),
+ lcl_aLabelRangePrefix + OUString::number( nIndex - 1 ));
+ }
+}
+
+rtl::Reference< UncachedDataSequence > InternalDataProvider::createDataSequenceAndAddToMap(
+ const OUString & rRangeRepresentation )
+{
+ rtl::Reference<UncachedDataSequence> xSeq = createDataSequenceFromArray(rRangeRepresentation, u"", u"");
+ if (xSeq.is())
+ return nullptr;
+
+ xSeq.set(new UncachedDataSequence(this, rRangeRepresentation));
+ addDataSequenceToMap(rRangeRepresentation, xSeq);
+ return xSeq;
+}
+
+rtl::Reference<UncachedDataSequence>
+InternalDataProvider::createDataSequenceFromArray( const OUString& rArrayStr, std::u16string_view rRole, std::u16string_view rRoleQualifier )
+{
+ if (rArrayStr.indexOf('{') != 0 || rArrayStr[rArrayStr.getLength()-1] != '}')
+ {
+ // Not an array string.
+ return nullptr;
+ }
+
+ bool bAllNumeric = true;
+ rtl::Reference<UncachedDataSequence> xSeq;
+
+ const sal_Unicode* p = rArrayStr.getStr();
+ const sal_Unicode* pEnd = p + rArrayStr.getLength();
+ const sal_Unicode* pElem = nullptr;
+ OUString aElem;
+
+ std::vector<OUString> aRawElems;
+ ++p; // Skip the first '{'.
+ --pEnd; // Skip the last '}'.
+ bool bInQuote = false;
+ for (; p != pEnd; ++p)
+ {
+ // Skip next "" within the title text: it's an escaped double quotation mark.
+ if (bInQuote && *p == '"' && *(p + 1) == '"')
+ {
+ if (!pElem)
+ pElem = p;
+ ++p;
+ }
+ else if (*p == '"')
+ {
+ bInQuote = !bInQuote;
+ if (bInQuote)
+ {
+ // Opening quote.
+ pElem = nullptr;
+ }
+ else
+ {
+ // Closing quote.
+ if (pElem)
+ aElem = OUString(pElem, p-pElem);
+ // Non empty string
+ if (!aElem.isEmpty())
+ bAllNumeric = false;
+ // Restore also escaped double quotation marks
+ aRawElems.push_back(aElem.replaceAll("\"\"", "\""));
+ pElem = nullptr;
+ aElem.clear();
+
+ ++p; // Skip '"'.
+ if (p == pEnd)
+ break;
+ }
+ }
+ else if (*p == ';' && !bInQuote)
+ {
+ // element separator.
+ if (pElem)
+ aElem = OUString(pElem, p-pElem);
+ aRawElems.push_back(aElem);
+ pElem = nullptr;
+ aElem.clear();
+ }
+ else if (!pElem)
+ pElem = p;
+ }
+
+ if (pElem)
+ {
+ aElem = OUString(pElem, p-pElem);
+ aRawElems.push_back(aElem);
+ }
+
+ if (rRole == u"values-y" || rRole == u"values-first" || rRole == u"values-last" ||
+ rRole == u"values-min" || rRole == u"values-max" || rRole == u"values-size" ||
+ rRole == u"error-bars-y-positive" || rRole == u"error-bars-y-negative")
+ {
+ // Column values. Append a new data column and populate it.
+
+ std::vector<double> aValues;
+ aValues.reserve(aRawElems.size());
+ for (const OUString & aRawElem : aRawElems)
+ {
+ if (aRawElem.isEmpty())
+ aValues.push_back(NAN);
+ else
+ aValues.push_back(aRawElem.toDouble());
+ }
+ sal_Int32 n = m_aInternalData.appendColumn();
+
+ m_aInternalData.setColumnValues(n, aValues);
+
+ OUString aRangeRep = OUString::number(n);
+ xSeq.set(new UncachedDataSequence(this, aRangeRep));
+ addDataSequenceToMap(aRangeRep, xSeq);
+ }
+ else if (rRole == u"values-x")
+ {
+ std::vector<double> aValues;
+ aValues.reserve(aRawElems.size());
+ if (bAllNumeric)
+ {
+ for (const OUString & aRawElem : aRawElems)
+ {
+ if (!aRawElem.isEmpty())
+ aValues.push_back(aRawElem.toDouble());
+ else
+ aValues.push_back(NAN);
+ }
+ }
+ else
+ {
+ for (size_t i = 0; i < aRawElems.size(); ++i)
+ aValues.push_back(i+1);
+ }
+
+ sal_Int32 n = m_aInternalData.appendColumn();
+ m_aInternalData.setColumnValues(n, aValues);
+
+ OUString aRangeRep = OUString::number(n);
+ xSeq.set(new UncachedDataSequence(this, aRangeRep));
+ addDataSequenceToMap(aRangeRep, xSeq);
+ }
+ else if (rRole == u"categories")
+ {
+ // Category labels.
+
+ // Store date categories as numbers.
+ bool bStoreNumeric = rRoleQualifier == u"date";
+ double fValue;
+ for (size_t i = 0; i < aRawElems.size(); ++i)
+ {
+ if (bStoreNumeric)
+ {
+ bool bGetDouble = bAllNumeric && !aRawElems[i].isEmpty();
+ fValue = bGetDouble ? aRawElems[i].toDouble() :
+ std::numeric_limits<double>::quiet_NaN();
+ }
+ std::vector<uno::Any> aLabels(1,
+ bStoreNumeric ? uno::Any(fValue) : uno::Any(aRawElems[i]));
+ m_aInternalData.setComplexRowLabel(i, std::move(aLabels));
+ }
+
+ xSeq.set(new UncachedDataSequence(this, lcl_aCategoriesRangeName));
+ addDataSequenceToMap(lcl_aCategoriesRangeName, xSeq);
+ }
+ else if (rRole == u"label")
+ {
+ // Data series label. There should be only one element. This always
+ // goes to the last data column.
+ sal_Int32 nColSize = m_aInternalData.getColumnCount();
+ if (!aRawElems.empty() && nColSize)
+ {
+ // Do not overwrite an existing label (attempted by series with no data values)
+ if (!m_aInternalData.getComplexColumnLabel(nColSize-1)[0].hasValue())
+ {
+ std::vector<uno::Any> aLabels(1, uno::Any(aRawElems[0]));
+ m_aInternalData.setComplexColumnLabel(nColSize-1, std::move(aLabels));
+ }
+
+ OUString aRangeRep = lcl_aLabelRangePrefix + OUString::number(nColSize-1);
+ xSeq.set(new UncachedDataSequence(this, aRangeRep));
+ addDataSequenceToMap(aRangeRep, xSeq);
+ }
+ }
+
+ return xSeq;
+}
+
+Reference< chart2::data::XDataSequence > InternalDataProvider::createDataSequenceAndAddToMap(
+ const OUString & rRangeRepresentation,
+ const OUString & rRole )
+{
+ rtl::Reference< UncachedDataSequence > xSeq =
+ new UncachedDataSequence( this, rRangeRepresentation, rRole );
+ addDataSequenceToMap( rRangeRepresentation, xSeq );
+ return xSeq;
+}
+
+// ____ XDataProvider ____
+sal_Bool SAL_CALL InternalDataProvider::createDataSourcePossible( const Sequence< beans::PropertyValue >& /* aArguments */ )
+{
+ return true;
+}
+
+namespace
+{
+
+sal_Int32 lcl_getInnerLevelCount( const std::vector< std::vector< uno::Any > >& rLabels )
+{
+ sal_Int32 nCount = 1;//minimum is 1!
+ for (auto const& elemLabel : rLabels)
+ {
+ nCount = std::max<sal_Int32>( elemLabel.size(), nCount );
+ }
+ return nCount;
+}
+
+}//end anonymous namespace
+
+Reference< chart2::data::XDataSource > SAL_CALL InternalDataProvider::createDataSource(
+ const Sequence< beans::PropertyValue >& aArguments )
+{
+ OUString aRangeRepresentation;
+ bool bUseColumns = true;
+ bool bFirstCellAsLabel = true;
+ bool bHasCategories = true;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+ DataSourceHelper::readArguments( aArguments, aRangeRepresentation, aSequenceMapping, bUseColumns, bFirstCellAsLabel, bHasCategories );
+
+ if( aRangeRepresentation == lcl_aCategoriesRangeName )
+ {
+ //return split complex categories if we have any:
+ std::vector< Reference< chart2::data::XLabeledDataSequence > > aComplexCategories;
+ const std::vector< std::vector< uno::Any > > & aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
+ if( bUseColumns==m_bDataInColumns )
+ {
+ sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories );
+ for( sal_Int32 nL=0; nL<nLevelCount; nL++ )
+ aComplexCategories.push_back( new LabeledDataSequence(
+ new UncachedDataSequence( this
+ , lcl_aCategoriesLevelRangeNamePrefix + OUString::number( nL )
+ , lcl_aCategoriesRoleName ) ) );
+ }
+ else
+ {
+ sal_Int32 nPointCount = m_bDataInColumns ? m_aInternalData.getRowCount() : m_aInternalData.getColumnCount();
+ for( sal_Int32 nP=0; nP<nPointCount; nP++ )
+ aComplexCategories.push_back( new LabeledDataSequence(
+ new UncachedDataSequence( this
+ , lcl_aCategoriesPointRangeNamePrefix + OUString::number( nP )
+ , lcl_aCategoriesRoleName ) ) );
+ }
+ //don't add the created sequences to the map as they are used temporarily only ...
+ return new DataSource( comphelper::containerToSequence(aComplexCategories) );
+ }
+
+ OSL_ASSERT( aRangeRepresentation == lcl_aCompleteRange );
+
+ std::vector< Reference< chart2::data::XLabeledDataSequence > > aResultLSeqVec;
+
+ // categories
+ if( bHasCategories )
+ aResultLSeqVec.push_back(
+ new LabeledDataSequence( createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName ) ) );
+
+ // data with labels
+ std::vector< Reference< chart2::data::XLabeledDataSequence > > aDataVec;
+ const sal_Int32 nCount = (bUseColumns ? m_aInternalData.getColumnCount() : m_aInternalData.getRowCount());
+ aDataVec.reserve(nCount);
+ for (sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx)
+ {
+ aDataVec.push_back(
+ new LabeledDataSequence(
+ createDataSequenceAndAddToMap( OUString::number( nIdx )),
+ createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::number( nIdx ))));
+ }
+
+ // attention: this data provider has the limitation that it stores
+ // internally if data comes from columns or rows. It is intended for
+ // creating only one used data source.
+ // @todo: add this information in the range representation strings
+ m_bDataInColumns = bUseColumns;
+
+ //reorder labeled sequences according to aSequenceMapping; ignore categories
+ for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
+ {
+ std::vector< LabeledDataSequence* >::size_type nOldIndex = aSequenceMapping[nNewIndex];
+ if( nOldIndex < aDataVec.size() )
+ {
+ if( aDataVec[nOldIndex].is() )
+ {
+ aResultLSeqVec.push_back( aDataVec[nOldIndex] );
+ aDataVec[nOldIndex] = nullptr;
+ }
+ }
+ }
+
+ //add left over data sequences to result
+ for (auto const& elem : aDataVec)
+ {
+ if( elem.is() )
+ aResultLSeqVec.push_back(elem);
+ }
+
+ return new DataSource( comphelper::containerToSequence(aResultLSeqVec) );
+}
+
+Sequence< beans::PropertyValue > SAL_CALL InternalDataProvider::detectArguments(
+ const Reference< chart2::data::XDataSource >& /* xDataSource */ )
+{
+ Sequence< beans::PropertyValue > aArguments{
+ beans::PropertyValue(
+ "CellRangeRepresentation", -1, uno::Any( lcl_aCompleteRange ),
+ beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "DataRowSource", -1, uno::Any(
+ m_bDataInColumns
+ ? css::chart::ChartDataRowSource_COLUMNS
+ : css::chart::ChartDataRowSource_ROWS ),
+ beans::PropertyState_DIRECT_VALUE ),
+ // internal data always contains labels and categories
+ beans::PropertyValue(
+ "FirstCellAsLabel", -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE ),
+ beans::PropertyValue(
+ "HasCategories", -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE )
+ };
+ // #i85913# Sequence Mapping is not needed for internal data, as it is
+ // applied to the data when the data source is created.
+
+ return aArguments;
+}
+
+sal_Bool SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString& /* aRangeRepresentation */ )
+{
+ return true;
+}
+
+Reference< chart2::data::XDataSequence > SAL_CALL InternalDataProvider::createDataSequenceByRangeRepresentation(
+ const OUString& aRangeRepresentation )
+{
+ if( aRangeRepresentation.match( lcl_aCategoriesRangeName ))
+ {
+ OSL_ASSERT( aRangeRepresentation == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
+
+ // categories
+ return createDataSequenceAndAddToMap( lcl_aCategoriesRangeName, lcl_aCategoriesRoleName );
+ }
+ else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
+ {
+ // label
+ sal_Int32 nIndex = o3tl::toInt32(aRangeRepresentation.subView( strlen(lcl_aLabelRangePrefix)));
+ return createDataSequenceAndAddToMap( lcl_aLabelRangePrefix + OUString::number( nIndex ));
+ }
+ else if ( aRangeRepresentation == "last" )
+ {
+ sal_Int32 nIndex = (m_bDataInColumns
+ ? m_aInternalData.getColumnCount()
+ : m_aInternalData.getRowCount()) - 1;
+ return createDataSequenceAndAddToMap( OUString::number( nIndex ));
+ }
+ else if( !aRangeRepresentation.isEmpty())
+ {
+ // data
+ return createDataSequenceAndAddToMap( aRangeRepresentation );
+ }
+
+ return Reference< chart2::data::XDataSequence >();
+}
+
+Reference<chart2::data::XDataSequence> SAL_CALL
+InternalDataProvider::createDataSequenceByValueArray(
+ const OUString& aRole, const OUString& aRangeRepresentation, const OUString& aRoleQualifier )
+{
+ return createDataSequenceFromArray(aRangeRepresentation, aRole, aRoleQualifier);
+}
+
+Reference< sheet::XRangeSelection > SAL_CALL InternalDataProvider::getRangeSelection()
+{
+ // there is no range selection component
+ return Reference< sheet::XRangeSelection >();
+}
+
+// ____ XInternalDataProvider ____
+sal_Bool SAL_CALL InternalDataProvider::hasDataByRangeRepresentation( const OUString& aRange )
+{
+ bool bResult = false;
+
+ if( aRange.match( lcl_aCategoriesRangeName ))
+ {
+ OSL_ASSERT( aRange == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
+ bResult = true;
+ }
+ else if( aRange.match( lcl_aLabelRangePrefix ))
+ {
+ sal_Int32 nIndex = o3tl::toInt32(aRange.subView( strlen(lcl_aLabelRangePrefix)));
+ bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount()));
+ }
+ else
+ {
+ sal_Int32 nIndex = aRange.toInt32();
+ bResult = (nIndex < (m_bDataInColumns ? m_aInternalData.getColumnCount(): m_aInternalData.getRowCount()));
+ }
+
+ return bResult;
+}
+
+Sequence< uno::Any > SAL_CALL InternalDataProvider::getDataByRangeRepresentation( const OUString& aRange )
+{
+ Sequence< uno::Any > aResult;
+
+ if( aRange.match( lcl_aLabelRangePrefix ) )
+ {
+ auto nIndex = o3tl::toUInt32(aRange.subView( strlen(lcl_aLabelRangePrefix)));
+ std::vector< uno::Any > aComplexLabel = m_bDataInColumns
+ ? m_aInternalData.getComplexColumnLabel( nIndex )
+ : m_aInternalData.getComplexRowLabel( nIndex );
+ if( !aComplexLabel.empty() )
+ aResult = comphelper::containerToSequence(aComplexLabel);
+ }
+ else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
+ {
+ auto nPointIndex = o3tl::toUInt32(aRange.subView( strlen(lcl_aCategoriesPointRangeNamePrefix) ));
+ std::vector< uno::Any > aComplexCategory = m_bDataInColumns
+ ? m_aInternalData.getComplexRowLabel( nPointIndex )
+ : m_aInternalData.getComplexColumnLabel( nPointIndex );
+ if( !aComplexCategory.empty() )
+ aResult = comphelper::containerToSequence(aComplexCategory);
+ }
+ else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
+ {
+ sal_Int32 nLevel = o3tl::toInt32(aRange.subView( strlen(lcl_aCategoriesLevelRangeNamePrefix) ));
+ const std::vector< std::vector< uno::Any > > & aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
+ if( nLevel < lcl_getInnerLevelCount( aCategories ) )
+ {
+ aResult.realloc( aCategories.size() );
+ transform( aCategories.begin(), aCategories.end(),
+ aResult.getArray(), lcl_copyFromLevel(nLevel) );
+ }
+ }
+ else if( aRange == lcl_aCategoriesRangeName )
+ {
+ const std::vector< std::vector< uno::Any > > & aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
+ sal_Int32 nLevelCount = lcl_getInnerLevelCount( aCategories );
+ if( nLevelCount == 1 )
+ {
+ aResult = getDataByRangeRepresentation( lcl_aCategoriesLevelRangeNamePrefix + OUString::number( 0 ) );
+ }
+ else
+ {
+ // Maybe this 'else' part and the functions is not necessary anymore.
+ const Sequence< OUString > aLabels = m_bDataInColumns ? getRowDescriptions() : getColumnDescriptions();
+ aResult.realloc( aLabels.getLength() );
+ std::transform( aLabels.begin(), aLabels.end(),
+ aResult.getArray(), CommonFunctors::makeAny< OUString >() );
+ }
+ }
+ else
+ {
+ sal_Int32 nIndex = aRange.toInt32();
+ if( nIndex >= 0 )
+ {
+ const Sequence< double > aData = m_bDataInColumns
+ ? m_aInternalData.getColumnValues(nIndex)
+ : m_aInternalData.getRowValues(nIndex);
+ if( aData.hasElements() )
+ {
+ aResult.realloc( aData.getLength());
+ std::transform( aData.begin(), aData.end(),
+ aResult.getArray(), CommonFunctors::makeAny< double >());
+ }
+ }
+ }
+
+ return aResult;
+}
+
+void SAL_CALL InternalDataProvider::setDataByRangeRepresentation(
+ const OUString& aRange, const Sequence< uno::Any >& aNewData )
+{
+ auto aNewVector( comphelper::sequenceToContainer<std::vector< uno::Any >>(aNewData) );
+ if( aRange.match( lcl_aLabelRangePrefix ) )
+ {
+ sal_uInt32 nIndex = o3tl::toInt32(aRange.subView( strlen(lcl_aLabelRangePrefix)));
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexColumnLabel( nIndex, std::move(aNewVector) );
+ else
+ m_aInternalData.setComplexRowLabel( nIndex, std::move(aNewVector) );
+ }
+ else if( aRange.match( lcl_aCategoriesPointRangeNamePrefix ) )
+ {
+ sal_Int32 nPointIndex = o3tl::toInt32(aRange.subView( strlen(lcl_aCategoriesLevelRangeNamePrefix)));
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexRowLabel( nPointIndex, std::move(aNewVector) );
+ else
+ m_aInternalData.setComplexColumnLabel( nPointIndex, std::move(aNewVector) );
+ }
+ else if( aRange.match( lcl_aCategoriesLevelRangeNamePrefix ) )
+ {
+ sal_Int32 nLevel = o3tl::toInt32(aRange.subView( strlen(lcl_aCategoriesLevelRangeNamePrefix)));
+ std::vector< std::vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
+
+ //ensure equal length
+ if( aNewVector.size() > aComplexCategories.size() )
+ aComplexCategories.resize( aNewVector.size() );
+ else if( aNewVector.size() < aComplexCategories.size() )
+ aNewVector.resize( aComplexCategories.size() );
+
+ transform( aComplexCategories.begin(), aComplexCategories.end(), aNewVector.begin(),
+ aComplexCategories.begin(), lcl_setAnyAtLevel(nLevel) );
+
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexRowLabels( std::move(aComplexCategories) );
+ else
+ m_aInternalData.setComplexColumnLabels( std::move(aComplexCategories) );
+ }
+ else if( aRange == lcl_aCategoriesRangeName )
+ {
+ std::vector< std::vector< uno::Any > > aComplexCategories;
+ aComplexCategories.resize( aNewVector.size() );
+ transform( aComplexCategories.begin(), aComplexCategories.end(), aNewVector.begin(),
+ aComplexCategories.begin(), lcl_setAnyAtLevel(0) );
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexRowLabels( std::move(aComplexCategories) );
+ else
+ m_aInternalData.setComplexColumnLabels( std::move(aComplexCategories) );
+ }
+ else
+ {
+ sal_Int32 nIndex = aRange.toInt32();
+ if( nIndex>=0 )
+ {
+ std::vector< double > aNewDataVec;
+ transform( aNewData.begin(), aNewData.end(),
+ back_inserter( aNewDataVec ), CommonFunctors::AnyToDouble());
+ if( m_bDataInColumns )
+ m_aInternalData.setColumnValues( nIndex, aNewDataVec );
+ else
+ m_aInternalData.setRowValues( nIndex, aNewDataVec );
+ }
+ }
+}
+
+void SAL_CALL InternalDataProvider::insertSequence( ::sal_Int32 nAfterIndex )
+{
+ if( m_bDataInColumns )
+ {
+ increaseMapReferences( nAfterIndex + 1, m_aInternalData.getColumnCount());
+ m_aInternalData.insertColumn( nAfterIndex );
+ }
+ else
+ {
+ increaseMapReferences( nAfterIndex + 1, m_aInternalData.getRowCount());
+ m_aInternalData.insertRow( nAfterIndex );
+ }
+}
+
+void SAL_CALL InternalDataProvider::deleteSequence( ::sal_Int32 nAtIndex )
+{
+ deleteMapReferences( OUString::number( nAtIndex ));
+ deleteMapReferences( lcl_aLabelRangePrefix + OUString::number( nAtIndex ));
+ if( m_bDataInColumns )
+ {
+ decreaseMapReferences( nAtIndex + 1, m_aInternalData.getColumnCount());
+ m_aInternalData.deleteColumn( nAtIndex );
+ }
+ else
+ {
+ decreaseMapReferences( nAtIndex + 1, m_aInternalData.getRowCount());
+ m_aInternalData.deleteRow( nAtIndex );
+ }
+}
+
+void SAL_CALL InternalDataProvider::appendSequence()
+{
+ if( m_bDataInColumns )
+ m_aInternalData.appendColumn();
+ else
+ m_aInternalData.appendRow();
+}
+
+void SAL_CALL InternalDataProvider::insertComplexCategoryLevel( sal_Int32 nLevel )
+{
+ OSL_ENSURE( nLevel> 0, "you can only insert category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
+ if( nLevel>0 )
+ {
+ std::vector< std::vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
+ std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_insertAnyAtLevel(nLevel) );
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexRowLabels( std::move(aComplexCategories) );
+ else
+ m_aInternalData.setComplexColumnLabels( std::move(aComplexCategories) );
+
+ tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
+ std::for_each( aRange.first, aRange.second, lcl_setModified());
+ }
+}
+void SAL_CALL InternalDataProvider::deleteComplexCategoryLevel( sal_Int32 nLevel )
+{
+ OSL_ENSURE( nLevel>0, "you can only delete category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
+ if( nLevel>0 )
+ {
+ std::vector< std::vector< uno::Any > > aComplexCategories = m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels();
+ std::for_each( aComplexCategories.begin(), aComplexCategories.end(), lcl_removeAnyAtLevel(nLevel) );
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexRowLabels( std::move(aComplexCategories) );
+ else
+ m_aInternalData.setComplexColumnLabels( std::move(aComplexCategories) );
+
+ tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
+ std::for_each( aRange.first, aRange.second, lcl_setModified());
+ }
+}
+
+void SAL_CALL InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 nAfterIndex )
+{
+ sal_Int32 nMaxRep = 0;
+ if( m_bDataInColumns )
+ {
+ m_aInternalData.insertRow( nAfterIndex );
+ nMaxRep = m_aInternalData.getColumnCount();
+ }
+ else
+ {
+ m_aInternalData.insertColumn( nAfterIndex );
+ nMaxRep = m_aInternalData.getRowCount();
+ }
+
+ // notify change to all affected ranges
+ tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( "0"));
+ tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
+ std::for_each( aBegin, aEnd, lcl_setModified());
+
+ tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
+ std::for_each( aRange.first, aRange.second, lcl_setModified());
+}
+
+void SAL_CALL InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 nAtIndex )
+{
+ sal_Int32 nMaxRep = 0;
+ if( m_bDataInColumns )
+ {
+ m_aInternalData.deleteRow( nAtIndex );
+ nMaxRep = m_aInternalData.getColumnCount();
+ }
+ else
+ {
+ m_aInternalData.deleteColumn( nAtIndex );
+ nMaxRep = m_aInternalData.getRowCount();
+ }
+
+ // notify change to all affected ranges
+ tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( "0"));
+ tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
+ std::for_each( aBegin, aEnd, lcl_setModified());
+
+ tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
+ std::for_each( aRange.first, aRange.second, lcl_setModified());
+}
+
+void SAL_CALL InternalDataProvider::swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex )
+{
+ if( m_bDataInColumns )
+ m_aInternalData.swapRowWithNext( nAtIndex );
+ else
+ m_aInternalData.swapColumnWithNext( nAtIndex );
+ sal_Int32 nMaxRep = (m_bDataInColumns
+ ? m_aInternalData.getColumnCount()
+ : m_aInternalData.getRowCount());
+
+ // notify change to all affected ranges
+ tSequenceMap::const_iterator aBegin( m_aSequenceMap.lower_bound( "0"));
+ tSequenceMap::const_iterator aEnd( m_aSequenceMap.upper_bound( OUString::number( nMaxRep )));
+ std::for_each( aBegin, aEnd, lcl_setModified());
+
+ tSequenceMapRange aRange( m_aSequenceMap.equal_range( lcl_aCategoriesRangeName ));
+ std::for_each( aRange.first, aRange.second, lcl_setModified());
+}
+
+void SAL_CALL InternalDataProvider::registerDataSequenceForChanges( const Reference< chart2::data::XDataSequence >& xSeq )
+{
+ if( xSeq.is())
+ addDataSequenceToMap( xSeq->getSourceRangeRepresentation(), xSeq );
+}
+
+// ____ XRangeXMLConversion ____
+OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& aRangeRepresentation )
+{
+ XMLRangeHelper::CellRange aRange;
+ aRange.aTableName = "local-table";
+
+ // attention: this data provider has the limitation that it stores
+ // internally if data comes from columns or rows. It is intended for
+ // creating only one used data source.
+ // @todo: add this information in the range representation strings
+ if( aRangeRepresentation.match( lcl_aCategoriesRangeName ))
+ {
+ OSL_ASSERT( aRangeRepresentation == lcl_aCategoriesRangeName );//it is not expected nor implemented that only parts of the categories are really requested
+ aRange.aUpperLeft.bIsEmpty = false;
+ if( m_bDataInColumns )
+ {
+ aRange.aUpperLeft.nColumn = 0;
+ aRange.aUpperLeft.nRow = 1;
+ aRange.aLowerRight = aRange.aUpperLeft;
+ aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
+ }
+ else
+ {
+ aRange.aUpperLeft.nColumn = 1;
+ aRange.aUpperLeft.nRow = 0;
+ aRange.aLowerRight = aRange.aUpperLeft;
+ aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
+ }
+ }
+ else if( aRangeRepresentation.match( lcl_aLabelRangePrefix ))
+ {
+ sal_Int32 nIndex = o3tl::toInt32(aRangeRepresentation.subView( strlen(lcl_aLabelRangePrefix)));
+ aRange.aUpperLeft.bIsEmpty = false;
+ aRange.aLowerRight.bIsEmpty = true;
+ if( m_bDataInColumns )
+ {
+ aRange.aUpperLeft.nColumn = nIndex + 1;
+ aRange.aUpperLeft.nRow = 0;
+ }
+ else
+ {
+ aRange.aUpperLeft.nColumn = 0;
+ aRange.aUpperLeft.nRow = nIndex + 1;
+ }
+ }
+ else if( aRangeRepresentation == lcl_aCompleteRange )
+ {
+ aRange.aUpperLeft.bIsEmpty = false;
+ aRange.aLowerRight.bIsEmpty = false;
+ aRange.aUpperLeft.nColumn = 0;
+ aRange.aUpperLeft.nRow = 0;
+ aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
+ aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
+ }
+ else
+ {
+ sal_Int32 nIndex = aRangeRepresentation.toInt32();
+ aRange.aUpperLeft.bIsEmpty = false;
+ if( m_bDataInColumns )
+ {
+ aRange.aUpperLeft.nColumn = nIndex + 1;
+ aRange.aUpperLeft.nRow = 1;
+ aRange.aLowerRight = aRange.aUpperLeft;
+ aRange.aLowerRight.nRow = m_aInternalData.getRowCount();
+ }
+ else
+ {
+ aRange.aUpperLeft.nColumn = 1;
+ aRange.aUpperLeft.nRow = nIndex + 1;
+ aRange.aLowerRight = aRange.aUpperLeft;
+ aRange.aLowerRight.nColumn = m_aInternalData.getColumnCount();
+ }
+ }
+
+ return XMLRangeHelper::getXMLStringFromCellRange( aRange );
+}
+
+OUString SAL_CALL InternalDataProvider::convertRangeFromXML( const OUString& aXMLRange )
+{
+ // Handle non-standards-conforming table:cell-range-address="PivotChart", see
+ // <https://bugs.documentfoundation.org/show_bug.cgi?id=112783> "PIVOT CHARTS: Save produces
+ // invalid file because of invalid cell address":
+ if (aXMLRange == "PivotChart") {
+ return "";
+ }
+
+ static constexpr OUString aPivotTableID(u"PT@"_ustr);
+ if (aXMLRange.startsWith(aPivotTableID))
+ return aXMLRange.copy(aPivotTableID.getLength());
+
+ XMLRangeHelper::CellRange aRange( XMLRangeHelper::getCellRangeFromXMLString( aXMLRange ));
+ if( aRange.aUpperLeft.bIsEmpty )
+ {
+ OSL_ENSURE( aRange.aLowerRight.bIsEmpty, "Weird Range" );
+ return OUString();
+ }
+
+ // "all"
+ if( !aRange.aLowerRight.bIsEmpty &&
+ ( aRange.aUpperLeft.nColumn != aRange.aLowerRight.nColumn ) &&
+ ( aRange.aUpperLeft.nRow != aRange.aLowerRight.nRow ) )
+ return lcl_aCompleteRange;
+
+ // attention: this data provider has the limitation that it stores
+ // internally if data comes from columns or rows. It is intended for
+ // creating only one used data source.
+ // @todo: add this information in the range representation strings
+
+ // data in columns
+ if( m_bDataInColumns )
+ {
+ if( aRange.aUpperLeft.nColumn == 0 )
+ return lcl_aCategoriesRangeName;
+ if( aRange.aUpperLeft.nRow == 0 )
+ return lcl_aLabelRangePrefix + OUString::number( aRange.aUpperLeft.nColumn - 1 );
+
+ return OUString::number( aRange.aUpperLeft.nColumn - 1 );
+ }
+
+ // data in rows
+ if( aRange.aUpperLeft.nRow == 0 )
+ return lcl_aCategoriesRangeName;
+ if( aRange.aUpperLeft.nColumn == 0 )
+ return lcl_aLabelRangePrefix + OUString::number( aRange.aUpperLeft.nRow - 1 );
+
+ return OUString::number( aRange.aUpperLeft.nRow - 1 );
+}
+
+namespace
+{
+
+template< class Type >
+Sequence< Sequence< Type > > lcl_convertVectorVectorToSequenceSequence( const std::vector< std::vector< Type > >& rIn )
+{
+ Sequence< Sequence< Type > > aRet;
+ sal_Int32 nOuterCount = rIn.size();
+ if( nOuterCount )
+ {
+ aRet.realloc(nOuterCount);
+ auto pRet = aRet.getArray();
+ for( sal_Int32 nN=0; nN<nOuterCount; nN++)
+ pRet[nN]= comphelper::containerToSequence( rIn[nN] );
+ }
+ return aRet;
+}
+
+template< class Type >
+std::vector< std::vector< Type > > lcl_convertSequenceSequenceToVectorVector( const Sequence< Sequence< Type > >& rIn )
+{
+ std::vector< std::vector< Type > > aRet;
+ sal_Int32 nOuterCount = rIn.getLength();
+ if( nOuterCount )
+ {
+ aRet.resize(nOuterCount);
+ for( sal_Int32 nN=0; nN<nOuterCount; nN++)
+ aRet[nN]= comphelper::sequenceToContainer<std::vector< Type >>( rIn[nN] );
+ }
+ return aRet;
+}
+
+std::vector< Sequence< OUString > > lcl_convertComplexAnyVectorToStringSequence( const std::vector< std::vector< uno::Any > >& rIn )
+{
+ std::vector< Sequence< OUString > > aRet;
+ sal_Int32 nOuterCount = rIn.size();
+ if( nOuterCount )
+ {
+ aRet.resize(nOuterCount);
+ for( sal_Int32 nN=0; nN<nOuterCount; nN++)
+ aRet[nN] = comphelper::containerToSequence(lcl_AnyToStringSequence( rIn[nN] ));
+ }
+ return aRet;
+}
+
+std::vector< std::vector< uno::Any > > lcl_convertComplexStringSequenceToAnyVector( const Sequence< Sequence< OUString > >& rIn )
+{
+ std::vector< std::vector< uno::Any > > aRet;
+ sal_Int32 nOuterCount = rIn.getLength();
+ aRet.reserve(nOuterCount);
+ for (sal_Int32 nN = 0; nN < nOuterCount; nN++)
+ aRet.push_back( lcl_StringToAnyVector( rIn[nN] ) );
+ return aRet;
+}
+
+class SplitCategoriesProvider_ForComplexDescriptions : public SplitCategoriesProvider
+{
+public:
+
+ explicit SplitCategoriesProvider_ForComplexDescriptions( const std::vector< std::vector< uno::Any > >& rComplexDescriptions )
+ : m_rComplexDescriptions( rComplexDescriptions )
+ {}
+
+ virtual sal_Int32 getLevelCount() const override;
+ virtual uno::Sequence< OUString > getStringsForLevel( sal_Int32 nIndex ) const override;
+
+private:
+ const std::vector< std::vector< uno::Any > >& m_rComplexDescriptions;
+};
+
+sal_Int32 SplitCategoriesProvider_ForComplexDescriptions::getLevelCount() const
+{
+ return lcl_getInnerLevelCount( m_rComplexDescriptions );
+}
+uno::Sequence< OUString > SplitCategoriesProvider_ForComplexDescriptions::getStringsForLevel( sal_Int32 nLevel ) const
+{
+ uno::Sequence< OUString > aResult;
+ if( nLevel < lcl_getInnerLevelCount( m_rComplexDescriptions ) )
+ {
+ aResult.realloc( m_rComplexDescriptions.size() );
+ transform( m_rComplexDescriptions.begin(), m_rComplexDescriptions.end(),
+ aResult.getArray(), lcl_getStringFromLevelVector(nLevel) );
+ }
+ return aResult;
+}
+
+}//anonymous namespace
+
+// ____ XDateCategories ____
+Sequence< double > SAL_CALL InternalDataProvider::getDateCategories()
+{
+ const std::vector< std::vector< uno::Any > > & aCategories( m_bDataInColumns ? m_aInternalData.getComplexRowLabels() : m_aInternalData.getComplexColumnLabels());
+ sal_Int32 nCount = aCategories.size();
+ Sequence< double > aDoubles( nCount );
+ auto aDoublesRange = asNonConstRange(aDoubles);
+ sal_Int32 nN=0;
+ for (auto const& category : aCategories)
+ {
+ double fValue;
+ if( category.empty() || !(category[0]>>=fValue) )
+ fValue = std::numeric_limits<double>::quiet_NaN();
+ aDoublesRange[nN++]=fValue;
+ }
+ return aDoubles;
+}
+
+void SAL_CALL InternalDataProvider::setDateCategories( const Sequence< double >& rDates )
+{
+ sal_Int32 nCount = rDates.getLength();
+ std::vector< std::vector< uno::Any > > aNewCategories;
+ aNewCategories.reserve(nCount);
+ std::vector< uno::Any > aSingleLabel(1);
+
+ for(sal_Int32 nN=0; nN<nCount; ++nN )
+ {
+ aSingleLabel[0] <<= rDates[nN];
+ aNewCategories.push_back(aSingleLabel);
+ }
+
+ if( m_bDataInColumns )
+ m_aInternalData.setComplexRowLabels( std::move(aNewCategories) );
+ else
+ m_aInternalData.setComplexColumnLabels( std::move(aNewCategories) );
+}
+
+// ____ XAnyDescriptionAccess ____
+Sequence< Sequence< uno::Any > > SAL_CALL InternalDataProvider::getAnyRowDescriptions()
+{
+ return lcl_convertVectorVectorToSequenceSequence( m_aInternalData.getComplexRowLabels() );
+}
+void SAL_CALL InternalDataProvider::setAnyRowDescriptions( const Sequence< Sequence< uno::Any > >& aRowDescriptions )
+{
+ m_aInternalData.setComplexRowLabels( lcl_convertSequenceSequenceToVectorVector( aRowDescriptions ) );
+}
+Sequence< Sequence< uno::Any > > SAL_CALL InternalDataProvider::getAnyColumnDescriptions()
+{
+ return lcl_convertVectorVectorToSequenceSequence( m_aInternalData.getComplexColumnLabels() );
+}
+void SAL_CALL InternalDataProvider::setAnyColumnDescriptions( const Sequence< Sequence< uno::Any > >& aColumnDescriptions )
+{
+ m_aInternalData.setComplexColumnLabels( lcl_convertSequenceSequenceToVectorVector( aColumnDescriptions ) );
+}
+
+// ____ XComplexDescriptionAccess ____
+Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexRowDescriptions()
+{
+ return comphelper::containerToSequence(lcl_convertComplexAnyVectorToStringSequence( m_aInternalData.getComplexRowLabels() ));
+}
+void SAL_CALL InternalDataProvider::setComplexRowDescriptions( const Sequence< Sequence< OUString > >& aRowDescriptions )
+{
+ m_aInternalData.setComplexRowLabels( lcl_convertComplexStringSequenceToAnyVector(aRowDescriptions) );
+}
+Sequence< Sequence< OUString > > SAL_CALL InternalDataProvider::getComplexColumnDescriptions()
+{
+ return comphelper::containerToSequence(lcl_convertComplexAnyVectorToStringSequence( m_aInternalData.getComplexColumnLabels() ));
+}
+void SAL_CALL InternalDataProvider::setComplexColumnDescriptions( const Sequence< Sequence< OUString > >& aColumnDescriptions )
+{
+ m_aInternalData.setComplexColumnLabels( lcl_convertComplexStringSequenceToAnyVector(aColumnDescriptions) );
+}
+
+// ____ XChartDataArray ____
+Sequence< Sequence< double > > SAL_CALL InternalDataProvider::getData()
+{
+ return m_aInternalData.getData();
+}
+
+void SAL_CALL InternalDataProvider::setData( const Sequence< Sequence< double > >& rDataInRows )
+{
+ return m_aInternalData.setData( rDataInRows );
+}
+
+void SAL_CALL InternalDataProvider::setRowDescriptions( const Sequence< OUString >& aRowDescriptions )
+{
+ std::vector< std::vector< uno::Any > > aComplexDescriptions( aRowDescriptions.getLength() );
+ transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aRowDescriptions.getConstArray(),
+ aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
+ m_aInternalData.setComplexRowLabels( std::move(aComplexDescriptions) );
+}
+
+void SAL_CALL InternalDataProvider::setColumnDescriptions( const Sequence< OUString >& aColumnDescriptions )
+{
+ std::vector< std::vector< uno::Any > > aComplexDescriptions( aColumnDescriptions.getLength() );
+ transform( aComplexDescriptions.begin(), aComplexDescriptions.end(), aColumnDescriptions.getConstArray(),
+ aComplexDescriptions.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
+ m_aInternalData.setComplexColumnLabels( std::move(aComplexDescriptions) );
+}
+
+Sequence< OUString > SAL_CALL InternalDataProvider::getRowDescriptions()
+{
+ const std::vector< std::vector< uno::Any > > & aComplexLabels( m_aInternalData.getComplexRowLabels() );
+ SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
+ return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
+}
+
+Sequence< OUString > SAL_CALL InternalDataProvider::getColumnDescriptions()
+{
+ const std::vector< std::vector< uno::Any > > & aComplexLabels( m_aInternalData.getComplexColumnLabels() );
+ SplitCategoriesProvider_ForComplexDescriptions aProvider( aComplexLabels );
+ return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider );
+}
+
+// ____ XChartData (base of XChartDataArray) ____
+void SAL_CALL InternalDataProvider::addChartDataChangeEventListener(
+ const Reference< css::chart::XChartDataChangeEventListener >& )
+{
+}
+
+void SAL_CALL InternalDataProvider::removeChartDataChangeEventListener(
+ const Reference< css::chart::XChartDataChangeEventListener >& )
+{
+}
+
+double SAL_CALL InternalDataProvider::getNotANumber()
+{
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+sal_Bool SAL_CALL InternalDataProvider::isNotANumber( double nNumber )
+{
+ return std::isnan( nNumber )
+ || std::isinf( nNumber );
+}
+// lang::XInitialization:
+void SAL_CALL InternalDataProvider::initialize(const uno::Sequence< uno::Any > & _aArguments)
+{
+ comphelper::SequenceAsHashMap aArgs(_aArguments);
+ if ( aArgs.getUnpackedValueOrDefault( "CreateDefaultData", false ) )
+ m_aInternalData.createDefaultData();
+}
+
+// ____ XCloneable ____
+Reference< util::XCloneable > SAL_CALL InternalDataProvider::createClone()
+{
+ return Reference< util::XCloneable >( new InternalDataProvider( *this ));
+}
+
+OUString SAL_CALL InternalDataProvider::getImplementationName()
+{
+ // note: in xmloff this name is used to indicate usage of own data
+ return "com.sun.star.comp.chart.InternalDataProvider";
+}
+
+sal_Bool SAL_CALL InternalDataProvider::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL InternalDataProvider::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.data.DataProvider" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart_InternalDataProvider_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::InternalDataProvider);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/LabeledDataSequence.cxx b/chart2/source/tools/LabeledDataSequence.cxx
new file mode 100644
index 0000000000..bf7b13443d
--- /dev/null
+++ b/chart2/source/tools/LabeledDataSequence.cxx
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <LabeledDataSequence.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <utility>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+LabeledDataSequence::LabeledDataSequence() :
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{}
+
+LabeledDataSequence::LabeledDataSequence(
+ uno::Reference< chart2::data::XDataSequence > xValues ) :
+ m_xData(std::move( xValues )),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ ModifyListenerHelper::addListener( m_xData, m_xModifyEventForwarder );
+}
+
+LabeledDataSequence::LabeledDataSequence(
+ uno::Reference< chart2::data::XDataSequence > xValues,
+ uno::Reference< chart2::data::XDataSequence > xLabel ) :
+ m_xData(std::move( xValues )),
+ m_xLabel(std::move( xLabel )),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ ModifyListenerHelper::addListener( m_xData, m_xModifyEventForwarder );
+ ModifyListenerHelper::addListener( m_xLabel, m_xModifyEventForwarder );
+}
+
+LabeledDataSequence::LabeledDataSequence( const LabeledDataSequence& rSource ) :
+ impl::LabeledDataSequence_Base(),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ uno::Reference< chart2::data::XDataSequence > xNewValues( rSource.m_xData );
+ uno::Reference< chart2::data::XDataSequence > xNewLabel( rSource.m_xLabel );
+
+ uno::Reference< util::XCloneable > xLabelCloneable( rSource.m_xLabel, uno::UNO_QUERY );
+ if( xLabelCloneable.is())
+ xNewLabel.set( xLabelCloneable->createClone(), uno::UNO_QUERY );
+
+ uno::Reference< util::XCloneable > xValuesCloneable( rSource.m_xData, uno::UNO_QUERY );
+ if( xValuesCloneable.is())
+ xNewValues.set( xValuesCloneable->createClone(), uno::UNO_QUERY );
+
+ m_xData = xNewValues;
+ m_xLabel = xNewLabel;
+
+ ModifyListenerHelper::addListener( m_xData, m_xModifyEventForwarder );
+ ModifyListenerHelper::addListener( m_xLabel, m_xModifyEventForwarder );
+}
+
+LabeledDataSequence::~LabeledDataSequence()
+{
+ if( m_xModifyEventForwarder.is())
+ {
+ if( m_xData.is())
+ ModifyListenerHelper::removeListener( m_xData, m_xModifyEventForwarder );
+ if( m_xLabel.is())
+ ModifyListenerHelper::removeListener( m_xLabel, m_xModifyEventForwarder );
+ }
+}
+
+// ____ XLabeledDataSequence ____
+uno::Reference< chart2::data::XDataSequence > SAL_CALL LabeledDataSequence::getValues()
+{
+ return m_xData;
+}
+
+void SAL_CALL LabeledDataSequence::setValues(
+ const uno::Reference< chart2::data::XDataSequence >& xSequence )
+{
+ if( m_xData != xSequence )
+ {
+ ModifyListenerHelper::removeListener( m_xData, m_xModifyEventForwarder );
+ m_xData = xSequence;
+ ModifyListenerHelper::addListener( m_xData, m_xModifyEventForwarder );
+ }
+}
+
+uno::Reference< chart2::data::XDataSequence > SAL_CALL LabeledDataSequence::getLabel()
+{
+ return m_xLabel;
+}
+
+void SAL_CALL LabeledDataSequence::setLabel(
+ const uno::Reference< chart2::data::XDataSequence >& xSequence )
+{
+ if( m_xLabel != xSequence )
+ {
+ ModifyListenerHelper::removeListener( m_xLabel, m_xModifyEventForwarder );
+ m_xLabel = xSequence;
+ ModifyListenerHelper::addListener( m_xLabel, m_xModifyEventForwarder );
+ }
+}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL LabeledDataSequence::createClone()
+{
+ uno::Reference< chart2::data::XDataSequence > xNewValues( m_xData );
+ uno::Reference< chart2::data::XDataSequence > xNewLabel( m_xLabel );
+
+ uno::Reference< util::XCloneable > xLabelCloneable( m_xLabel, uno::UNO_QUERY );
+ if( xLabelCloneable.is())
+ xNewLabel.set( xLabelCloneable->createClone(), uno::UNO_QUERY );
+
+ uno::Reference< util::XCloneable > xValuesCloneable( m_xData, uno::UNO_QUERY );
+ if( xValuesCloneable.is())
+ xNewValues.set( xValuesCloneable->createClone(), uno::UNO_QUERY );
+
+ return uno::Reference< util::XCloneable >(
+ new LabeledDataSequence( xNewValues, xNewLabel ) );
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL LabeledDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL LabeledDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+OUString SAL_CALL LabeledDataSequence::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.LabeledDataSequence";
+}
+
+sal_Bool SAL_CALL LabeledDataSequence::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL LabeledDataSequence::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.data.LabeledDataSequence" };
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_LabeledDataSequence_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::LabeledDataSequence );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/LegendHelper.cxx b/chart2/source/tools/LegendHelper.cxx
new file mode 100644
index 0000000000..2c52f13639
--- /dev/null
+++ b/chart2/source/tools/LegendHelper.cxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <LegendHelper.hxx>
+#include <Legend.hxx>
+#include <ChartModel.hxx>
+#include <Diagram.hxx>
+#include <com/sun/star/chart/ChartLegendExpansion.hpp>
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+rtl::Reference< Legend > LegendHelper::showLegend( ChartModel& rModel
+ , const uno::Reference< uno::XComponentContext >& xContext )
+{
+ rtl::Reference< Legend > xLegend = LegendHelper::getLegend( rModel, xContext, true );
+ if( xLegend.is())
+ {
+ xLegend->setPropertyValue( "Show", uno::Any(true) );
+
+ chart2::RelativePosition aRelativePosition;
+ if( !(xLegend->getPropertyValue( "RelativePosition") >>= aRelativePosition) )
+ {
+ chart2::LegendPosition ePos = chart2::LegendPosition_LINE_END;
+ if( !(xLegend->getPropertyValue( "AnchorPosition") >>= ePos ) )
+ xLegend->setPropertyValue( "AnchorPosition", uno::Any( ePos ));
+
+ css::chart::ChartLegendExpansion eExpansion =
+ ( ePos == chart2::LegendPosition_LINE_END ||
+ ePos == chart2::LegendPosition_LINE_START )
+ ? css::chart::ChartLegendExpansion_HIGH
+ : css::chart::ChartLegendExpansion_WIDE;
+ if( !(xLegend->getPropertyValue( "Expansion") >>= eExpansion ) )
+ xLegend->setPropertyValue( "Expansion", uno::Any( eExpansion ));
+
+ xLegend->setPropertyValue( "RelativePosition", uno::Any());
+ }
+
+ }
+ return xLegend;
+}
+
+void LegendHelper::hideLegend( ChartModel& rModel )
+{
+ rtl::Reference< Legend > xLegend = LegendHelper::getLegend( rModel, nullptr );
+ if( xLegend.is())
+ {
+ xLegend->setPropertyValue( "Show", uno::Any(false) );
+ }
+}
+
+rtl::Reference< Legend > LegendHelper::getLegend(
+ ChartModel& rModel
+ , const uno::Reference< uno::XComponentContext >& xContext
+ , bool bCreate )
+{
+ rtl::Reference< Legend > xResult;
+
+ try
+ {
+ rtl::Reference< Diagram > xDia( rModel.getFirstChartDiagram());
+ if( xDia.is() )
+ {
+ xResult = xDia->getLegend2();
+ if( bCreate && !xResult.is() && xContext.is() )
+ {
+ xResult = new Legend();
+ xDia->setLegend( xResult );
+ }
+ }
+ else if(bCreate)
+ {
+ OSL_FAIL("need diagram for creation of legend");
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+bool LegendHelper::hasLegend( const rtl::Reference< Diagram > & xDiagram )
+{
+ bool bReturn = false;
+ if( xDiagram.is())
+ {
+ uno::Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY );
+ if( xLegendProp.is())
+ xLegendProp->getPropertyValue( "Show") >>= bReturn;
+ }
+
+ return bReturn;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/LifeTime.cxx b/chart2/source/tools/LifeTime.cxx
new file mode 100644
index 0000000000..45550b93ef
--- /dev/null
+++ b/chart2/source/tools/LifeTime.cxx
@@ -0,0 +1,430 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <LifeTime.hxx>
+#include <osl/diagnose.h>
+
+#include <com/sun/star/document/XStorageChangeListener.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/util/CloseVetoException.hpp>
+#include <com/sun/star/util/XCloseListener.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+
+namespace apphelper
+{
+
+LifeTimeManager::LifeTimeManager( lang::XComponent* pComponent )
+ : m_pComponent(pComponent)
+{
+ m_bDisposed = false;
+ m_bInDispose = false;
+ m_nAccessCount = 0;
+ m_nLongLastingCallCount = 0;
+ m_aNoAccessCountCondition.set();
+ m_aNoLongLastingCallCountCondition.set();
+}
+
+LifeTimeManager::~LifeTimeManager()
+{
+}
+
+bool LifeTimeManager::impl_isDisposed( bool bAssert )
+{
+ if( m_bDisposed || m_bInDispose )
+ {
+ if( bAssert )
+ {
+ OSL_FAIL( "This component is already disposed " );
+ }
+ return true;
+ }
+ return false;
+}
+
+bool LifeTimeManager::impl_canStartApiCall()
+{
+ if( impl_isDisposed() )
+ return false; //behave passive if already disposed
+
+ //mutex is acquired
+ return true;
+}
+
+void LifeTimeManager::impl_registerApiCall(bool bLongLastingCall)
+{
+ //only allowed if not disposed
+ //do not acquire the mutex here because it will be acquired already
+ m_nAccessCount++;
+ if(m_nAccessCount==1)
+ //@todo? is it ok to wake some threads here while we have acquired the mutex?
+ m_aNoAccessCountCondition.reset();
+
+ if(bLongLastingCall)
+ m_nLongLastingCallCount++;
+ if(m_nLongLastingCallCount==1)
+ m_aNoLongLastingCallCountCondition.reset();
+}
+
+void LifeTimeManager::impl_unregisterApiCall(std::unique_lock<std::mutex>& rGuard, bool bLongLastingCall)
+{
+ //Mutex needs to be acquired exactly once
+ //mutex may be released inbetween in special case of impl_apiCallCountReachedNull()
+
+ OSL_ENSURE( m_nAccessCount>0, "access count mismatch" );
+ m_nAccessCount--;
+ if(bLongLastingCall)
+ m_nLongLastingCallCount--;
+ if( m_nLongLastingCallCount==0 )
+ {
+ m_aNoLongLastingCallCountCondition.set();
+ }
+ if( m_nAccessCount== 0)
+ {
+ m_aNoAccessCountCondition.set();
+ impl_apiCallCountReachedNull(rGuard);
+
+ }
+}
+
+bool LifeTimeManager::dispose()
+{
+ //hold no mutex
+ {
+ std::unique_lock aGuard( m_aAccessMutex );
+
+ if( m_bDisposed || m_bInDispose )
+ {
+ SAL_WARN("chart2", "This component is already disposed " );
+ return false; //behave passive if already disposed
+ }
+
+ m_bInDispose = true;
+ //adding any listener is not allowed anymore
+ //new calls will not be accepted
+ //still running calls have the freedom to finish their work without crash
+
+ uno::Reference< lang::XComponent > xComponent(m_pComponent);
+ if(xComponent.is())
+ {
+ // notify XCLoseListeners
+ lang::EventObject aEvent( xComponent );
+ m_aCloseListeners.disposeAndClear( aGuard, aEvent );
+ m_aModifyListeners.disposeAndClear( aGuard, aEvent );
+ m_aStorageChangeListeners.disposeAndClear( aGuard, aEvent );
+ m_aEventListeners.disposeAndClear( aGuard, aEvent );
+ m_aSelectionChangeListeners.disposeAndClear( aGuard, aEvent );
+ }
+
+ OSL_ENSURE( !m_bDisposed, "dispose was called already" );
+ m_bDisposed = true;
+ }
+ //no mutex is acquired
+
+ //wait until all still running calls have finished
+ //the accessCount cannot grow anymore, because all calls will return after checking m_bDisposed
+ m_aNoAccessCountCondition.wait();
+
+ //we are the only ones working on our data now
+
+ return true;
+ //--release all resources and references after calling this method successful
+}
+
+CloseableLifeTimeManager::CloseableLifeTimeManager( css::util::XCloseable* pCloseable
+ , css::lang::XComponent* pComponent )
+ : LifeTimeManager( pComponent )
+ , m_pCloseable(pCloseable)
+{
+ m_bClosed = false;
+ m_bInTryClose = false;
+ m_bOwnership = false;
+ m_aEndTryClosingCondition.set();
+}
+
+CloseableLifeTimeManager::~CloseableLifeTimeManager()
+{
+}
+
+bool CloseableLifeTimeManager::impl_isDisposedOrClosed( bool bAssert )
+{
+ if( impl_isDisposed( bAssert ) )
+ return true;
+
+ if( m_bClosed )
+ {
+ if( bAssert )
+ {
+ OSL_FAIL( "This object is already closed" );
+ }
+ return true;
+ }
+ return false;
+}
+
+bool CloseableLifeTimeManager::g_close_startTryClose(bool bDeliverOwnership)
+{
+ //no mutex is allowed to be acquired
+ {
+ std::unique_lock aGuard( m_aAccessMutex );
+ if( impl_isDisposedOrClosed(false) )
+ return false;
+
+ //Mutex needs to be acquired exactly once; will be released inbetween
+ if( !impl_canStartApiCall() )
+ return false;
+ //mutex is acquired
+
+ //not closed already -> we try to close again
+ m_bInTryClose = true;
+ m_aEndTryClosingCondition.reset();
+
+ impl_registerApiCall(false);
+ }
+
+ //no mutex is acquired
+
+ //only remove listener calls will be worked on until end of tryclose
+ //all other new calls will wait till end of try close // @todo? is that really ok
+
+ //?? still running calls have the freedom to finish their work without crash
+
+ try
+ {
+ uno::Reference< util::XCloseable > xCloseable(m_pCloseable);
+ if(xCloseable.is())
+ {
+ std::unique_lock aGuard( m_aAccessMutex );
+ //--call queryClosing on all registered close listeners
+ if( m_aCloseListeners.getLength(aGuard) )
+ {
+ lang::EventObject aEvent( xCloseable );
+ m_aCloseListeners.forEach(aGuard,
+ [&aEvent, bDeliverOwnership](const uno::Reference<util::XCloseListener>& l)
+ {
+ l->queryClosing(aEvent, bDeliverOwnership);
+ });
+ }
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ //no mutex is acquired
+ g_close_endTryClose(bDeliverOwnership);
+ throw;
+ }
+ return true;
+}
+
+void CloseableLifeTimeManager::g_close_endTryClose(bool bDeliverOwnership )
+{
+ //this method is called, if the try to close was not successful
+ std::unique_lock aGuard( m_aAccessMutex );
+ impl_setOwnership( bDeliverOwnership, false );
+
+ m_bInTryClose = false;
+ m_aEndTryClosingCondition.set();
+
+ //Mutex needs to be acquired exactly once
+ //mutex may be released inbetween in special case of impl_apiCallCountReachedNull()
+ impl_unregisterApiCall(aGuard, false);
+}
+
+void CloseableLifeTimeManager::g_close_isNeedToCancelLongLastingCalls( bool bDeliverOwnership, util::CloseVetoException const & ex )
+{
+ //this method is called when no closelistener has had a veto during queryclosing
+ //the method returns false, if nothing stands against closing anymore
+ //it returns true, if some longlasting calls are running, which might be cancelled
+ //it throws the given exception, if long calls are running but not cancelable
+
+ std::unique_lock aGuard( m_aAccessMutex );
+ //this count cannot grow after try of close has started, because we wait in all those methods for end of try closing
+ if( !m_nLongLastingCallCount )
+ return;
+
+ impl_setOwnership( bDeliverOwnership, true );
+
+ m_bInTryClose = false;
+ m_aEndTryClosingCondition.set();
+
+ //Mutex needs to be acquired exactly once
+ //mutex may be released inbetween in special case of impl_apiCallCountReachedNull()
+ impl_unregisterApiCall(aGuard, false);
+
+ throw ex;
+}
+
+void CloseableLifeTimeManager::g_close_endTryClose_doClose()
+{
+ //this method is called, if the try to close was successful
+ std::unique_lock aGuard( m_aAccessMutex );
+
+ m_bInTryClose = false;
+ m_aEndTryClosingCondition.set();
+
+ //Mutex needs to be acquired exactly once
+ //mutex may be released inbetween in special case of impl_apiCallCountReachedNull()
+ impl_unregisterApiCall(aGuard, false);
+ impl_doClose(aGuard);
+}
+
+void CloseableLifeTimeManager::impl_setOwnership( bool bDeliverOwnership, bool bMyVeto )
+{
+ m_bOwnership = bDeliverOwnership && bMyVeto;
+}
+
+void CloseableLifeTimeManager::impl_apiCallCountReachedNull(std::unique_lock<std::mutex>& rGuard)
+{
+ //Mutex needs to be acquired exactly once
+ //mutex will be released inbetween in impl_doClose()
+ if( m_pCloseable && m_bOwnership )
+ impl_doClose(rGuard);
+}
+
+void CloseableLifeTimeManager::impl_doClose(std::unique_lock<std::mutex>& rGuard)
+{
+ //Mutex needs to be acquired exactly once before calling impl_doClose()
+
+ if(m_bClosed)
+ return; //behave as passive as possible, if disposed or closed already
+ if( m_bDisposed || m_bInDispose )
+ return; //behave as passive as possible, if disposed or closed already
+
+ m_bClosed = true;
+
+ uno::Reference< util::XCloseable > xCloseable;
+ xCloseable.set(m_pCloseable);
+ try
+ {
+ if(xCloseable.is())
+ {
+ //--call notifyClosing on all registered close listeners
+ if( m_aCloseListeners.getLength(rGuard) )
+ {
+ lang::EventObject aEvent( xCloseable );
+ m_aCloseListeners.notifyEach(rGuard, &util::XCloseListener::notifyClosing, aEvent);
+ }
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ rGuard.unlock();
+ if(xCloseable.is())
+ {
+ uno::Reference< lang::XComponent > xComponent( xCloseable, uno::UNO_QUERY );
+ if(xComponent.is())
+ {
+ OSL_ENSURE( m_bClosed, "a not closed component will be disposed " );
+ xComponent->dispose();
+ }
+ }
+ rGuard.lock();
+}
+
+void CloseableLifeTimeManager::g_addCloseListener( const uno::Reference< util::XCloseListener > & xListener )
+{
+ std::unique_lock aGuard( m_aAccessMutex );
+ //Mutex needs to be acquired exactly once; will be released inbetween
+ if( !impl_canStartApiCall() )
+ return;
+ //mutex is acquired
+
+ m_aCloseListeners.addInterface( aGuard, xListener );
+ m_bOwnership = false;
+}
+
+bool CloseableLifeTimeManager::impl_canStartApiCall()
+{
+ //Mutex needs to be acquired exactly once before calling this method
+ //the mutex will be released inbetween and reacquired
+
+ if( impl_isDisposed() )
+ return false; //behave passive if already disposed
+ if( m_bClosed )
+ return false; //behave passive if closing is already done
+
+ //during try-close most calls need to wait for the decision
+ while( m_bInTryClose )
+ {
+ //if someone tries to close this object at the moment
+ //we need to wait for his end because the result of the preceding call
+ //is relevant for our behaviour here
+
+ m_aAccessMutex.unlock();
+ m_aEndTryClosingCondition.wait(); //@todo??? this may block??? try closing
+ m_aAccessMutex.lock();
+ if( m_bDisposed || m_bInDispose || m_bClosed )
+ return false; //return if closed already
+ }
+ //mutex is acquired
+ return true;
+}
+
+bool LifeTimeGuard::startApiCall(bool bLongLastingCall)
+{
+ //Mutex needs to be acquired exactly once; will be released inbetween
+ //mutex is required due to constructor of LifeTimeGuard
+
+ OSL_ENSURE( !m_bCallRegistered, "this method is only allowed ones" );
+ if(m_bCallRegistered)
+ return false;
+
+ //Mutex needs to be acquired exactly once; will be released inbetween
+ if( !m_rManager.impl_canStartApiCall() )
+ return false;
+ //mutex is acquired
+
+ m_bCallRegistered = true;
+ m_bLongLastingCallRegistered = bLongLastingCall;
+ m_rManager.impl_registerApiCall(bLongLastingCall);
+ return true;
+}
+
+LifeTimeGuard::~LifeTimeGuard()
+{
+ try
+ {
+ //do acquire the mutex if it was cleared before
+ if (!m_guard.owns_lock())
+ m_guard.lock();
+ if(m_bCallRegistered)
+ {
+ //Mutex needs to be acquired exactly once
+ //mutex may be released inbetween in special case of impl_apiCallCountReachedNull()
+ m_rManager.impl_unregisterApiCall(m_guard, m_bLongLastingCallRegistered);
+ }
+ }
+ catch( uno::Exception& ex )
+ {
+ //@todo ? allow a uno::RuntimeException from dispose to travel through??
+ ex.Context.is(); //to avoid compilation warnings
+ }
+}
+
+}//end namespace apphelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/LinePropertiesHelper.cxx b/chart2/source/tools/LinePropertiesHelper.cxx
new file mode 100644
index 0000000000..b3c5fc6ccf
--- /dev/null
+++ b/chart2/source/tools/LinePropertiesHelper.cxx
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <LinePropertiesHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/drawing/LineCap.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/color.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+
+namespace chart
+{
+
+void LinePropertiesHelper::AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ // Line Properties see service drawing::LineProperties
+ rOutProperties.emplace_back( "LineStyle",
+ PROP_LINE_STYLE,
+ cppu::UnoType<drawing::LineStyle>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "LineDash",
+ PROP_LINE_DASH,
+ cppu::UnoType<drawing::LineDash>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+//not in service description
+ rOutProperties.emplace_back( "LineDashName",
+ PROP_LINE_DASH_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "LineColor",
+ PROP_LINE_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "LineTransparence",
+ PROP_LINE_TRANSPARENCE,
+ cppu::UnoType<sal_Int16>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "LineWidth",
+ PROP_LINE_WIDTH,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "LineJoint",
+ PROP_LINE_JOINT,
+ cppu::UnoType<drawing::LineJoint>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "LineCap",
+ PROP_LINE_CAP,
+ cppu::UnoType<drawing::LineCap>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+void LinePropertiesHelper::AddDefaultsToMap(
+ ::chart::tPropertyValueMap & rOutMap )
+{
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LINE_STYLE, drawing::LineStyle_SOLID );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LINE_WIDTH, sal_Int32(0) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LINE_COLOR, COL_BLACK );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LINE_TRANSPARENCE, sal_Int16(0) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LINE_JOINT, drawing::LineJoint_ROUND );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_LINE_CAP, drawing::LineCap_BUTT );
+}
+
+bool LinePropertiesHelper::IsLineVisible( const css::uno::Reference<
+ css::beans::XPropertySet >& xLineProperties )
+{
+ bool bRet = false;
+ try
+ {
+ if( xLineProperties.is() )
+ {
+ drawing::LineStyle aLineStyle(drawing::LineStyle_SOLID);
+ xLineProperties->getPropertyValue( "LineStyle" ) >>= aLineStyle;
+ if( aLineStyle != drawing::LineStyle_NONE )
+ {
+ sal_Int16 nLineTransparence=0;
+ xLineProperties->getPropertyValue( "LineTransparence" ) >>= nLineTransparence;
+ if(nLineTransparence!=100)
+ {
+ bRet = true;
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return bRet;
+}
+
+void LinePropertiesHelper::SetLineVisible( const css::uno::Reference<
+ css::beans::XPropertySet >& xLineProperties )
+{
+ try
+ {
+ if( xLineProperties.is() )
+ {
+ drawing::LineStyle aLineStyle(drawing::LineStyle_SOLID);
+ xLineProperties->getPropertyValue( "LineStyle" ) >>= aLineStyle;
+ if( aLineStyle == drawing::LineStyle_NONE )
+ xLineProperties->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_SOLID ) );
+
+ sal_Int16 nLineTransparence=0;
+ xLineProperties->getPropertyValue( "LineTransparence" ) >>= nLineTransparence;
+ if(nLineTransparence==100)
+ xLineProperties->setPropertyValue( "LineTransparence", uno::Any( sal_Int16(0) ) );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void LinePropertiesHelper::SetLineInvisible( const css::uno::Reference<
+ css::beans::XPropertySet >& xLineProperties )
+{
+ try
+ {
+ if( xLineProperties.is() )
+ {
+ drawing::LineStyle aLineStyle(drawing::LineStyle_SOLID);
+ xLineProperties->getPropertyValue( "LineStyle" ) >>= aLineStyle;
+ if( aLineStyle != drawing::LineStyle_NONE )
+ xLineProperties->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE ) );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void LinePropertiesHelper::SetLineColor( const css::uno::Reference<
+ css::beans::XPropertySet >& xLineProperties, sal_Int32 nColor )
+{
+ try
+ {
+ if( xLineProperties.is() )
+ {
+ xLineProperties->setPropertyValue( "LineColor", uno::Any( nColor ) );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/LinearRegressionCurveCalculator.cxx b/chart2/source/tools/LinearRegressionCurveCalculator.cxx
new file mode 100644
index 0000000000..ee836555b1
--- /dev/null
+++ b/chart2/source/tools/LinearRegressionCurveCalculator.cxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <LinearRegressionCurveCalculator.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+LinearRegressionCurveCalculator::LinearRegressionCurveCalculator()
+{}
+
+LinearRegressionCurveCalculator::~LinearRegressionCurveCalculator()
+{}
+
+void LinearRegressionCurveCalculator::setRegressionProperties(
+ sal_Int32 /*aDegree*/,
+ sal_Bool aForceIntercept,
+ double aInterceptValue,
+ sal_Int32 aPeriod,
+ sal_Int32 /*nMovingType*/)
+{
+ PolynomialRegressionCurveCalculator::setRegressionProperties(
+ 1,
+ aForceIntercept,
+ aInterceptValue,
+ aPeriod,
+ 0);
+}
+
+uno::Sequence< geometry::RealPoint2D > SAL_CALL LinearRegressionCurveCalculator::getCurveValues(
+ double min, double max, ::sal_Int32 nPointCount,
+ const uno::Reference< chart2::XScaling >& xScalingX,
+ const uno::Reference< chart2::XScaling >& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation )
+{
+ if( bMaySkipPointsInCalculation &&
+ isLinearScaling( xScalingX ) &&
+ isLinearScaling( xScalingY ))
+ {
+ // optimize result
+ uno::Sequence< geometry::RealPoint2D > aResult{ { min, getCurveValue( min ) },
+ { max, getCurveValue( max ) } };
+
+ return aResult;
+ }
+ return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/LogarithmicRegressionCurveCalculator.cxx b/chart2/source/tools/LogarithmicRegressionCurveCalculator.cxx
new file mode 100644
index 0000000000..5e68235d14
--- /dev/null
+++ b/chart2/source/tools/LogarithmicRegressionCurveCalculator.cxx
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <LogarithmicRegressionCurveCalculator.hxx>
+#include <RegressionCalculationHelper.hxx>
+#include <SpecialCharacters.hxx>
+
+#include <rtl/math.hxx>
+#include <rtl/ustrbuf.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+LogarithmicRegressionCurveCalculator::LogarithmicRegressionCurveCalculator() :
+ m_fSlope( std::numeric_limits<double>::quiet_NaN() ),
+ m_fIntercept( std::numeric_limits<double>::quiet_NaN() )
+{
+}
+
+LogarithmicRegressionCurveCalculator::~LogarithmicRegressionCurveCalculator()
+{}
+
+// ____ XRegressionCurve ____
+void SAL_CALL LogarithmicRegressionCurveCalculator::recalculateRegression(
+ const uno::Sequence< double >& aXValues,
+ const uno::Sequence< double >& aYValues )
+{
+ RegressionCalculationHelper::tDoubleVectorPair aValues(
+ RegressionCalculationHelper::cleanup(
+ aXValues, aYValues,
+ RegressionCalculationHelper::isValidAndXPositive()));
+
+ const size_t nMax = aValues.first.size();
+ if( nMax <= 1 ) // at least 2 points
+ {
+ m_fSlope = std::numeric_limits<double>::quiet_NaN();
+ m_fIntercept = std::numeric_limits<double>::quiet_NaN();
+ m_fCorrelationCoefficient = std::numeric_limits<double>::quiet_NaN();
+ return;
+ }
+
+ double fAverageX = 0.0, fAverageY = 0.0;
+ size_t i = 0;
+ for( i = 0; i < nMax; ++i )
+ {
+ fAverageX += log( aValues.first[i] );
+ fAverageY += aValues.second[i];
+ }
+
+ const double fN = static_cast< double >( nMax );
+ fAverageX /= fN;
+ fAverageY /= fN;
+
+ double fQx = 0.0, fQy = 0.0, fQxy = 0.0;
+ for( i = 0; i < nMax; ++i )
+ {
+ double fDeltaX = log( aValues.first[i] ) - fAverageX;
+ double fDeltaY = aValues.second[i] - fAverageY;
+
+ fQx += fDeltaX * fDeltaX;
+ fQy += fDeltaY * fDeltaY;
+ fQxy += fDeltaX * fDeltaY;
+ }
+
+ m_fSlope = fQxy / fQx;
+ m_fIntercept = fAverageY - m_fSlope * fAverageX;
+ m_fCorrelationCoefficient = fQxy / sqrt( fQx * fQy );
+}
+
+double SAL_CALL LogarithmicRegressionCurveCalculator::getCurveValue( double x )
+{
+ if( ! ( std::isnan( m_fSlope ) ||
+ std::isnan( m_fIntercept )))
+ {
+ return m_fSlope * log( x ) + m_fIntercept;
+ }
+
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+uno::Sequence< geometry::RealPoint2D > SAL_CALL LogarithmicRegressionCurveCalculator::getCurveValues(
+ double min, double max, ::sal_Int32 nPointCount,
+ const uno::Reference< chart2::XScaling >& xScalingX,
+ const uno::Reference< chart2::XScaling >& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation )
+{
+ if( bMaySkipPointsInCalculation &&
+ isLogarithmicScaling( xScalingX ) &&
+ isLinearScaling( xScalingY ))
+ {
+ // optimize result
+ uno::Sequence< geometry::RealPoint2D > aResult{ { min, getCurveValue( min ) },
+ { max, getCurveValue( max ) } };
+
+ return aResult;
+ }
+ return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation );
+}
+
+OUString LogarithmicRegressionCurveCalculator::ImplGetRepresentation(
+ const uno::Reference< util::XNumberFormatter >& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaMaxWidth /* = nullptr */ ) const
+{
+ bool bHasSlope = !rtl::math::approxEqual( fabs( m_fSlope ), 1.0 );
+ OUStringBuffer aBuf( mYName + " = " );
+ sal_Int32 nLineLength = aBuf.getLength();
+ sal_Int32 nValueLength=0;
+ if ( pFormulaMaxWidth && *pFormulaMaxWidth > 0 ) // count nValueLength
+ {
+ sal_Int32 nCharMin = nLineLength + 6 + mXName.getLength(); // 6 = "ln(x)" + 2 extra characters
+ if( m_fSlope < 0.0 )
+ nCharMin += 2; // "- "
+ if( m_fSlope != 0.0 && m_fIntercept != 0.0 )
+ {
+ nCharMin += 3; // " + "
+ if ( bHasSlope )
+ nValueLength = (*pFormulaMaxWidth - nCharMin) / 2;
+ }
+ if ( nValueLength == 0 ) // not yet calculated
+ nValueLength = *pFormulaMaxWidth - nCharMin;
+ if ( nValueLength <= 0 )
+ nValueLength = 1;
+ }
+
+ // temporary buffer
+ OUStringBuffer aTmpBuf("");
+ // if nValueLength not calculated then nullptr
+ sal_Int32* pValueLength = nValueLength ? &nValueLength : nullptr;
+ if( m_fSlope != 0.0 ) // add slope value
+ {
+ if( m_fSlope < 0.0 )
+ {
+ aTmpBuf.append( OUStringChar(aMinusSign) + " " );
+ }
+ if( bHasSlope )
+ {
+ OUString aValueString = getFormattedString( xNumFormatter, nNumberFormatKey, fabs(m_fSlope), pValueLength );
+ if ( aValueString != "1" ) // aValueString may be rounded to 1 if nValueLength is small
+ {
+ aTmpBuf.append( aValueString + " " );
+ }
+ }
+ aTmpBuf.append( "ln(" + mXName + ") " );
+ addStringToEquation( aBuf, nLineLength, aTmpBuf, pFormulaMaxWidth );
+ aTmpBuf.truncate();
+
+ if( m_fIntercept > 0.0 )
+ aTmpBuf.append( "+ " );
+ }
+ // add intercept value
+ if( m_fIntercept < 0.0 )
+ aTmpBuf.append( OUStringChar(aMinusSign) + " " );
+ OUString aValueString = getFormattedString( xNumFormatter, nNumberFormatKey, fabs(m_fIntercept), pValueLength );
+ if ( aValueString != "0" ) // aValueString may be rounded to 0 if nValueLength is small
+ {
+ aTmpBuf.append( aValueString );
+ addStringToEquation( aBuf, nLineLength, aTmpBuf, pFormulaMaxWidth );
+ }
+
+ if ( std::u16string_view(aBuf) == Concat2View(mYName + " = ") )
+ aBuf.append( "0" );
+
+ return aBuf.makeStringAndClear();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/MeanValueRegressionCurveCalculator.cxx b/chart2/source/tools/MeanValueRegressionCurveCalculator.cxx
new file mode 100644
index 0000000000..aefd3f8f05
--- /dev/null
+++ b/chart2/source/tools/MeanValueRegressionCurveCalculator.cxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <MeanValueRegressionCurveCalculator.hxx>
+
+#include <osl/diagnose.h>
+
+#include <cmath>
+#include <limits>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+MeanValueRegressionCurveCalculator::MeanValueRegressionCurveCalculator() :
+ m_fMeanValue( std::numeric_limits<double>::quiet_NaN() )
+{
+}
+
+MeanValueRegressionCurveCalculator::~MeanValueRegressionCurveCalculator()
+{}
+
+// ____ XRegressionCurveCalculator ____
+void SAL_CALL MeanValueRegressionCurveCalculator::recalculateRegression(
+ const uno::Sequence< double >& /*aXValues*/,
+ const uno::Sequence< double >& aYValues )
+{
+ const sal_Int32 nDataLength = aYValues.getLength();
+ sal_Int32 nMax = nDataLength;
+ double fSumY = 0.0;
+ const double * pY = aYValues.getConstArray();
+
+ for( sal_Int32 i = 0; i < nDataLength; ++i )
+ {
+ if( std::isnan( pY[i] ) ||
+ std::isinf( pY[i] ))
+ --nMax;
+ else
+ fSumY += pY[i];
+ }
+
+ m_fCorrelationCoefficient = 0.0;
+
+ if( nMax == 0 )
+ {
+ m_fMeanValue = std::numeric_limits<double>::quiet_NaN();
+ }
+ else
+ {
+ m_fMeanValue = fSumY / static_cast< double >( nMax );
+
+ // correlation coefficient: standard deviation
+ if( nMax > 1 )
+ {
+ double fErrorSum = 0.0;
+ for( sal_Int32 i = 0; i < nDataLength; ++i )
+ {
+ if( !std::isnan( pY[i] ) &&
+ !std::isinf( pY[i] ))
+ {
+ double v = m_fMeanValue - pY[i];
+ fErrorSum += (v*v);
+ }
+ }
+ OSL_ASSERT( fErrorSum >= 0.0 );
+ m_fCorrelationCoefficient = sqrt( fErrorSum / (nMax - 1 ));
+ }
+ }
+}
+
+double SAL_CALL MeanValueRegressionCurveCalculator::getCurveValue( double /*x*/ )
+{
+ return m_fMeanValue;
+}
+
+uno::Sequence< geometry::RealPoint2D > SAL_CALL MeanValueRegressionCurveCalculator::getCurveValues(
+ double min, double max, ::sal_Int32 nPointCount,
+ const uno::Reference< chart2::XScaling >& xScalingX,
+ const uno::Reference< chart2::XScaling >& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation )
+{
+ if( bMaySkipPointsInCalculation )
+ {
+ // optimize result
+ uno::Sequence< geometry::RealPoint2D > aResult{ { min, m_fMeanValue },
+ { max, m_fMeanValue } };
+
+ return aResult;
+ }
+ return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation );
+}
+
+OUString MeanValueRegressionCurveCalculator::ImplGetRepresentation(
+ const uno::Reference< util::XNumberFormatter >& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaLength /* = nullptr */ ) const
+{
+ OUString aBuf(mYName + " = ");
+ if ( pFormulaLength )
+ {
+ *pFormulaLength -= aBuf.getLength();
+ if ( *pFormulaLength <= 0 )
+ return "###";
+ }
+ return ( aBuf + getFormattedString( xNumFormatter, nNumberFormatKey, m_fMeanValue, pFormulaLength ) );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/MediaDescriptorHelper.cxx b/chart2/source/tools/MediaDescriptorHelper.cxx
new file mode 100644
index 0000000000..bd217b0fbf
--- /dev/null
+++ b/chart2/source/tools/MediaDescriptorHelper.cxx
@@ -0,0 +1,225 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <MediaDescriptorHelper.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+
+using namespace ::com::sun::star;
+
+namespace apphelper
+{
+
+MediaDescriptorHelper::MediaDescriptorHelper( const uno::Sequence<
+ beans::PropertyValue > & rMediaDescriptor )
+ : m_aModelProperties(rMediaDescriptor.getLength())
+{
+ auto aModelPropertiesRange = asNonConstRange(m_aModelProperties);
+ css::uno::Sequence< css::beans::PropertyValue >
+ aRegularProperties(rMediaDescriptor.getLength()); //these are the properties which are described in service com.sun.star.document.MediaDescriptor and not marked as deprecated
+ auto aRegularPropertiesRange = asNonConstRange(aRegularProperties);
+ impl_init();
+ sal_Int32 nRegularCount = 0;
+ sal_Int32 nModelCount = 0;
+
+ auto addRegularProp = [&aRegularPropertiesRange, &nRegularCount](const beans::PropertyValue& rRegularProp)
+ {
+ aRegularPropertiesRange[nRegularCount] = rRegularProp;
+ ++nRegularCount;
+ };
+ auto addModelProp = [&aModelPropertiesRange, &nModelCount, &addRegularProp](const beans::PropertyValue& rModelProp)
+ {
+ addRegularProp(rModelProp);
+ aModelPropertiesRange[nModelCount] = rModelProp;
+ ++nModelCount;
+ };
+
+ //read given rMediaDescriptor and store in internal structures:
+ for( const beans::PropertyValue& rProp : rMediaDescriptor)
+ {
+ if (rProp.Name == "AsTemplate")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "Author")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "CharacterSet")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "Comment")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "ComponentData")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "FilterData")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "FilterName")
+ {
+ ISSET_FilterName = rProp.Value >>= FilterName;
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "FilterOptions")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "FrameName")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "Hidden")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "HierarchicalDocumentName")
+ {
+ rProp.Value >>= HierarchicalDocumentName;
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "OutputStream")
+ {
+ ISSET_OutputStream = rProp.Value >>= OutputStream;
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "InputStream")
+ {
+ ISSET_InputStream = rProp.Value >>= InputStream;
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "InteractionHandler")
+ {
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "JumpMark")
+ {
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "MediaType")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "OpenNewView")
+ {
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "Overwrite")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "Password")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "PosSize")
+ {
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "PostData")
+ {
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "Preview")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "ReadOnly")
+ {
+ rProp.Value >>= ReadOnly;
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "Referer")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "SetEmbedded")
+ {
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "Silent")
+ {
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "StatusIndicator")
+ {
+ addRegularProp(rProp);
+ }
+ else if (rProp.Name == "Storage")
+ {
+ ISSET_Storage = rProp.Value >>= Storage;
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "Stream")
+ {
+ ISSET_Stream = rProp.Value >>= Stream;
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "Unpacked")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "URL")
+ {
+ ISSET_URL = rProp.Value >>= URL;
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "Version")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "ViewData")
+ {
+ addModelProp(rProp);
+ }
+ else if (rProp.Name == "ViewId")
+ {
+ addModelProp(rProp);
+ }
+ }
+
+ aRegularProperties.realloc(nRegularCount);
+ m_aModelProperties.realloc(nModelCount);
+}
+
+void MediaDescriptorHelper::impl_init()
+{
+ ISSET_FilterName = false;
+
+ ISSET_OutputStream = false;
+ ISSET_InputStream = false;
+
+ ReadOnly = false;
+ ISSET_URL = false;
+
+ ISSET_Storage = false;
+ ISSET_Stream = false;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ModifyListenerCallBack.cxx b/chart2/source/tools/ModifyListenerCallBack.cxx
new file mode 100644
index 0000000000..037ee7a782
--- /dev/null
+++ b/chart2/source/tools/ModifyListenerCallBack.cxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ModifyListenerCallBack.hxx>
+#include <comphelper/compbase.hxx>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+
+namespace chart {
+
+typedef comphelper::WeakComponentImplHelper< css::util::XModifyListener >
+ ModifyListenerCallBack_Base;
+
+class ModifyListenerCallBack_impl
+ : public ModifyListenerCallBack_Base
+{
+public:
+ explicit ModifyListenerCallBack_impl( const Link<void*,void>& rCallBack );
+
+ void startListening( const Reference< util::XModifyBroadcaster >& xBroadcaster );
+ void stopListening();
+
+ //XModifyListener
+ virtual void SAL_CALL modified( const lang::EventObject& aEvent ) override;
+
+ //XEventListener
+ virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
+
+ using ::comphelper::WeakComponentImplHelperBase::disposing;
+
+private:
+ Link<void*,void> m_aLink;//will be called on modify
+ Reference< util::XModifyBroadcaster > m_xBroadcaster;//broadcaster to listen at
+};
+
+ModifyListenerCallBack_impl::ModifyListenerCallBack_impl( const Link<void*,void>& rCallBack )
+ : m_aLink( rCallBack )
+{
+}
+
+//XModifyListener
+void SAL_CALL ModifyListenerCallBack_impl::modified( const lang::EventObject& /*aEvent*/ )
+{
+ m_aLink.Call(nullptr);
+}
+
+//XEventListener
+void SAL_CALL ModifyListenerCallBack_impl::disposing( const lang::EventObject& /*Source*/ )
+{
+ m_xBroadcaster.clear();
+}
+
+void ModifyListenerCallBack_impl::startListening( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyBroadcaster >& xBroadcaster )
+{
+ if( m_xBroadcaster == xBroadcaster )
+ return;
+
+ stopListening();
+ m_xBroadcaster = xBroadcaster;
+ if( m_xBroadcaster.is() )
+ m_xBroadcaster->addModifyListener( this );
+}
+void ModifyListenerCallBack_impl::stopListening()
+{
+ if( m_xBroadcaster.is() )
+ {
+ m_xBroadcaster->removeModifyListener( this );
+ m_xBroadcaster.clear();
+ }
+}
+
+ModifyListenerCallBack::ModifyListenerCallBack( const Link<void*,void>& rCallBack )
+ : pModifyListener_impl( new ModifyListenerCallBack_impl(rCallBack) )
+ , m_xModifyListener( pModifyListener_impl )
+{
+}
+
+ModifyListenerCallBack::~ModifyListenerCallBack()
+{
+ stopListening();
+}
+
+void ModifyListenerCallBack::startListening( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyBroadcaster >& xBroadcaster )
+{
+ pModifyListener_impl->startListening( xBroadcaster );
+}
+void ModifyListenerCallBack::stopListening()
+{
+ pModifyListener_impl->stopListening();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ModifyListenerHelper.cxx b/chart2/source/tools/ModifyListenerHelper.cxx
new file mode 100644
index 0000000000..507e79fa32
--- /dev/null
+++ b/chart2/source/tools/ModifyListenerHelper.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ModifyListenerHelper.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+ModifyEventForwarder::ModifyEventForwarder()
+{
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL ModifyEventForwarder::addModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ std::unique_lock aGuard(m_aMutex);
+
+ m_aModifyListeners.addInterface( aGuard, aListener );
+}
+
+void SAL_CALL ModifyEventForwarder::removeModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ std::unique_lock aGuard(m_aMutex);
+
+ m_aModifyListeners.removeInterface( aGuard, aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL ModifyEventForwarder::modified( const lang::EventObject& aEvent )
+{
+ std::unique_lock aGuard(m_aMutex);
+
+ if( m_aModifyListeners.getLength(aGuard) == 0 )
+ return;
+
+ m_aModifyListeners.notifyEach( aGuard, &util::XModifyListener::modified, aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL ModifyEventForwarder::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ WeakComponentImplHelperBase ____
+void ModifyEventForwarder::disposing(std::unique_lock<std::mutex>& rGuard)
+{
+ // dispose was called at this
+ m_aModifyListeners.disposeAndClear( rGuard, lang::EventObject( static_cast<cppu::OWeakObject*>(this) ) );
+}
+
+} // namespace chart::ModifyListenerHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/MovingAverageRegressionCurveCalculator.cxx b/chart2/source/tools/MovingAverageRegressionCurveCalculator.cxx
new file mode 100644
index 0000000000..f71262f738
--- /dev/null
+++ b/chart2/source/tools/MovingAverageRegressionCurveCalculator.cxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <MovingAverageRegressionCurveCalculator.hxx>
+#include <RegressionCalculationHelper.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+
+#include <algorithm>
+#include <limits>
+
+#include <com/sun/star/chart2/MovingAverageType.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+namespace chart
+{
+
+MovingAverageRegressionCurveCalculator::MovingAverageRegressionCurveCalculator()
+{}
+
+MovingAverageRegressionCurveCalculator::~MovingAverageRegressionCurveCalculator()
+{}
+
+// ____ XRegressionCurveCalculator ____
+void SAL_CALL MovingAverageRegressionCurveCalculator::recalculateRegression(
+ const uno::Sequence< double >& aXValues,
+ const uno::Sequence< double >& aYValues )
+{
+ m_fCorrelationCoefficient = std::numeric_limits<double>::quiet_NaN();
+
+ RegressionCalculationHelper::tDoubleVectorPair aValues(
+ RegressionCalculationHelper::cleanup(
+ aXValues, aYValues,
+ RegressionCalculationHelper::isValid()));
+
+ aYList.clear();
+ aXList.clear();
+
+ // For formulas, see
+ // https://docs.oasis-open.org/office/OpenDocument/v1.3/cs02/part3-schema/OpenDocument-v1.3-cs02-part3-schema.html#property-chart_regression-moving-type
+
+ switch (mnMovingType)
+ {
+ case MovingAverageType::Central:
+ {
+
+ calculateValuesCentral(std::move(aValues));
+ break;
+ }
+
+ case MovingAverageType::AveragedAbscissa:
+ {
+ calculateValues(std::move(aValues), true);
+ break;
+ }
+ case MovingAverageType::Prior:
+ default:
+ {
+ calculateValues(std::move(aValues), false);
+ break;
+ }
+ }
+}
+
+void MovingAverageRegressionCurveCalculator::calculateValuesCentral(
+ RegressionCalculationHelper::tDoubleVectorPair aValues)
+{
+ const size_t aSize = aValues.first.size();
+ if (aSize == 0)
+ return;
+ for (size_t i = mPeriod - 1; i < aSize; ++i)
+ {
+ double yAvg = 0.0;
+
+ for (sal_Int32 j = 0; j < mPeriod; j++)
+ {
+ yAvg += aValues.second[i - j];
+ }
+ yAvg /= mPeriod;
+ aYList.push_back(yAvg);
+ }
+ sal_Int32 nPeriodLocal = (mPeriod % 2 == 0) ? (mPeriod / 2) : ((mPeriod - 1) / 2);
+ for (size_t i = nPeriodLocal; i < aSize - 1; ++i)
+ {
+ double x = aValues.first[i];
+ aXList.push_back(x);
+ }
+}
+
+void MovingAverageRegressionCurveCalculator::calculateValues(
+ RegressionCalculationHelper::tDoubleVectorPair aValues, bool bUseXAvg)
+{
+ const size_t aSize = aValues.first.size();
+ for (size_t i = mPeriod - 1; i < aSize; ++i)
+ {
+ double xAvg = 0.0;
+ double yAvg = 0.0;
+
+ for (sal_Int32 j = 0; j < mPeriod; j++)
+ {
+ xAvg += aValues.first[i - j];
+ yAvg += aValues.second[i - j];
+ }
+ yAvg /= mPeriod;
+ xAvg /= mPeriod;
+
+ aYList.push_back(yAvg);
+ if (bUseXAvg)
+ {
+ aXList.push_back(xAvg);
+ }
+ else
+ {
+ double x = aValues.first[i];
+ aXList.push_back(x);
+ }
+ }
+}
+
+double SAL_CALL MovingAverageRegressionCurveCalculator::getCurveValue( double /*x*/ )
+{
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+uno::Sequence< geometry::RealPoint2D > SAL_CALL MovingAverageRegressionCurveCalculator::getCurveValues(
+ double /*min*/, double /*max*/, sal_Int32 /*nPointCount*/,
+ const uno::Reference< chart2::XScaling >& /*xScalingX*/,
+ const uno::Reference< chart2::XScaling >& /*xScalingY*/,
+ sal_Bool /*bMaySkipPointsInCalculation*/ )
+{
+ size_t nSize = std::min(aXList.size(), aYList.size());
+ uno::Sequence< geometry::RealPoint2D > aResult( nSize );
+ std::transform(aXList.begin(), aXList.begin() + nSize, aYList.begin(), aResult.getArray(),
+ [](const auto& x, const auto& y) { return geometry::RealPoint2D(x, y); });
+ return aResult;
+}
+
+OUString MovingAverageRegressionCurveCalculator::ImplGetRepresentation(
+ const uno::Reference< util::XNumberFormatter >& /*xNumFormatter*/,
+ sal_Int32 /*nNumberFormatKey*/, sal_Int32* /*pFormulaLength = nullptr */ ) const
+{
+ OUString aRet = SchResId( STR_OBJECT_MOVING_AVERAGE_WITH_PARAMETERS );
+ // change text for Moving Average
+ OUString aWildcard( "%PERIOD" );
+ sal_Int32 nIndex = aRet.indexOf( aWildcard );
+ if( nIndex != -1 )
+ { // replace period
+ aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), OUString::number(mPeriod) );
+ }
+ return aRet;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/NameContainer.cxx b/chart2/source/tools/NameContainer.cxx
new file mode 100644
index 0000000000..23e0a2821d
--- /dev/null
+++ b/chart2/source/tools/NameContainer.cxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <NameContainer.hxx>
+
+#include <com/sun/star/uno/Any.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+namespace chart
+{
+
+
+NameContainer::NameContainer()
+{
+}
+
+NameContainer::NameContainer( const NameContainer & rOther )
+ : impl::NameContainer_Base(rOther)
+ , m_aMap( rOther.m_aMap )
+{
+}
+
+NameContainer::~NameContainer()
+{
+}
+
+//XServiceInfo
+OUString SAL_CALL NameContainer::getImplementationName()
+{
+ return "com.sun.star.comp.chart.XMLNameSpaceMap";
+}
+
+sal_Bool SAL_CALL NameContainer::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SAL_CALL NameContainer::getSupportedServiceNames()
+{
+ return { "com.sun.star.xml.NamespaceMap" };
+}
+
+// XNameContainer
+void SAL_CALL NameContainer::insertByName( const OUString& rName, const Any& rElement )
+{
+ if( m_aMap.find( rName ) != m_aMap.end() )
+ throw container::ElementExistException();
+ m_aMap.emplace( rName, rElement );
+}
+
+void SAL_CALL NameContainer::removeByName( const OUString& Name )
+{
+ tContentMap::iterator aIt( m_aMap.find( Name ));
+ if( aIt == m_aMap.end())
+ throw container::NoSuchElementException();
+ m_aMap.erase( aIt );
+}
+
+// XNameReplace
+void SAL_CALL NameContainer::replaceByName( const OUString& rName, const Any& rElement )
+{
+ tContentMap::iterator aIt( m_aMap.find( rName ));
+ if( aIt == m_aMap.end() )
+ throw container::NoSuchElementException();
+ aIt->second = rElement;
+}
+
+// XNameAccess
+Any SAL_CALL NameContainer::getByName( const OUString& rName )
+{
+ tContentMap::iterator aIter( m_aMap.find( rName ) );
+ if( aIter == m_aMap.end() )
+ throw container::NoSuchElementException();
+ return aIter->second;
+}
+
+Sequence< OUString > SAL_CALL NameContainer::getElementNames()
+{
+ return comphelper::mapKeysToSequence(m_aMap);
+}
+
+sal_Bool SAL_CALL NameContainer::hasByName( const OUString& rName )
+{
+ return ( m_aMap.find( rName ) != m_aMap.end() );
+}
+
+// XElementAccess
+sal_Bool SAL_CALL NameContainer::hasElements()
+{
+ return ! m_aMap.empty();
+}
+
+uno::Type SAL_CALL NameContainer::getElementType()
+{
+ return ::cppu::UnoType<OUString>::get();
+}
+
+// XCloneable
+uno::Reference< util::XCloneable > SAL_CALL NameContainer::createClone()
+{
+ return uno::Reference< util::XCloneable >( new NameContainer( *this ));
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/NumberFormatterWrapper.cxx b/chart2/source/tools/NumberFormatterWrapper.cxx
new file mode 100644
index 0000000000..e00df1fae0
--- /dev/null
+++ b/chart2/source/tools/NumberFormatterWrapper.cxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <NumberFormatterWrapper.hxx>
+#include <svl/numformat.hxx>
+#include <svl/numuno.hxx>
+#include <tools/color.hxx>
+#include <com/sun/star/util/Date.hpp>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+FixedNumberFormatter::FixedNumberFormatter(
+ const uno::Reference< util::XNumberFormatsSupplier >& xSupplier
+ , sal_Int32 nNumberFormatKey )
+ : m_aNumberFormatterWrapper(xSupplier)
+ , m_nNumberFormatKey( nNumberFormatKey )
+{
+}
+
+FixedNumberFormatter::~FixedNumberFormatter()
+{
+}
+
+OUString FixedNumberFormatter::getFormattedString( double fValue, Color& rLabelColor, bool& rbColorChanged ) const
+{
+ return m_aNumberFormatterWrapper.getFormattedString(
+ m_nNumberFormatKey, fValue, rLabelColor, rbColorChanged );
+}
+
+NumberFormatterWrapper::NumberFormatterWrapper( const uno::Reference< util::XNumberFormatsSupplier >& xSupplier )
+ : m_xNumberFormatsSupplier(xSupplier)
+ , m_pNumberFormatter(nullptr)
+
+{
+ uno::Reference<beans::XPropertySet> xProp(m_xNumberFormatsSupplier,uno::UNO_QUERY);
+ OUString sNullDate( "NullDate" );
+ if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(sNullDate) )
+ m_aNullDate = xProp->getPropertyValue(sNullDate);
+ SvNumberFormatsSupplierObj* pSupplierObj = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( xSupplier );
+ if( pSupplierObj )
+ m_pNumberFormatter = pSupplierObj->GetNumberFormatter();
+ SAL_WARN_IF(!m_pNumberFormatter,"chart2.tools","need a numberformatter");
+}
+
+NumberFormatterWrapper::~NumberFormatterWrapper()
+{
+}
+
+namespace
+{
+ bool getDate(const css::uno::Any& rAny, util::Date& rDate)
+ {
+ if (rAny >>= rDate)
+ return true;
+ util::DateTime aUtilDateTime;
+ if (rAny >>= aUtilDateTime)
+ {
+ rDate.Day = aUtilDateTime.Day;
+ rDate.Month = aUtilDateTime.Month;
+ rDate.Year = aUtilDateTime.Year;
+ return true;
+ }
+ SAL_WARN("chart2.tools", "neither a util::Date nor a util::DateTime");
+ return false;
+ }
+}
+
+Date NumberFormatterWrapper::getNullDate() const
+{
+ Date aRet(30,12,1899);
+
+ util::Date aUtilDate;
+ if (m_aNullDate.hasValue() && getDate(m_aNullDate, aUtilDate))
+ {
+ aRet = Date(aUtilDate.Day,aUtilDate.Month,aUtilDate.Year);
+ }
+ else if( m_pNumberFormatter )
+ {
+ aRet = m_pNumberFormatter->GetNullDate();
+ }
+ return aRet;
+}
+
+OUString NumberFormatterWrapper::getFormattedString( sal_Int32 nNumberFormatKey, double fValue,
+ Color& rLabelColor, bool& rbColorChanged ) const
+{
+ OUString aText;
+ const Color* pTextColor = nullptr;
+ if( !m_pNumberFormatter )
+ {
+ OSL_FAIL("Need a NumberFormatter");
+ return aText;
+ }
+ // i99104 handle null date correctly
+ sal_Int16 nYear = 1899;
+ sal_uInt16 nDay = 30,nMonth = 12;
+ if ( m_aNullDate.hasValue() )
+ {
+ const Date& rDate = m_pNumberFormatter->GetNullDate();
+ nYear = rDate.GetYear();
+ nMonth = rDate.GetMonth();
+ nDay = rDate.GetDay();
+ util::Date aNewNullDate;
+ if (getDate(m_aNullDate, aNewNullDate))
+ m_pNumberFormatter->ChangeNullDate(aNewNullDate.Day,aNewNullDate.Month,aNewNullDate.Year);
+ }
+ // tdf#130969: use UNLIMITED_PRECISION in case of GENERAL Number Format
+ if( m_pNumberFormatter->GetStandardPrec() != SvNumberFormatter::UNLIMITED_PRECISION )
+ m_pNumberFormatter->ChangeStandardPrec(SvNumberFormatter::UNLIMITED_PRECISION);
+ m_pNumberFormatter->GetOutputString(fValue, nNumberFormatKey, aText, &pTextColor);
+ if ( m_aNullDate.hasValue() )
+ {
+ m_pNumberFormatter->ChangeNullDate(nDay,nMonth,nYear);
+ }
+
+ if(pTextColor)
+ {
+ rbColorChanged = true;
+ rLabelColor = *pTextColor;
+ }
+ else
+ rbColorChanged = false;
+
+ return aText;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/OPropertySet.cxx b/chart2/source/tools/OPropertySet.cxx
new file mode 100644
index 0000000000..29e7298974
--- /dev/null
+++ b/chart2/source/tools/OPropertySet.cxx
@@ -0,0 +1,465 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <OPropertySet.hxx>
+#include <CloneHelper.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/style/XStyle.hpp>
+
+#include <algorithm>
+#include <memory>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+using ::osl::MutexGuard;
+
+// needed for MS compiler
+using ::cppu::OBroadcastHelper;
+using ::cppu::OPropertySetHelper;
+
+namespace property
+{
+
+OPropertySet::OPropertySet( ) :
+ OBroadcastHelper( m_aMutex ),
+ // the following causes a warning; there seems to be no way to avoid it
+ OPropertySetHelper( static_cast< OBroadcastHelper & >( *this )),
+ m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault(false)
+{
+}
+
+OPropertySet::OPropertySet( const OPropertySet & rOther ) :
+ OBroadcastHelper( m_aMutex ),
+ // the following causes a warning; there seems to be no way to avoid it
+ OPropertySetHelper( static_cast< OBroadcastHelper & >( *this )),
+ css::lang::XTypeProvider(),
+ css::beans::XPropertyState(),
+ css::beans::XMultiPropertyStates(),
+ css::style::XStyleSupplier(),
+ m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault(false)
+{
+ MutexGuard aGuard( m_aMutex );
+
+ m_aProperties = rOther.m_aProperties;
+
+ // clone interface properties
+ for(auto& rProp : m_aProperties)
+ {
+ if( rProp.second.hasValue() &&
+ rProp.second.getValueType().getTypeClass() == uno::TypeClass_INTERFACE )
+ {
+ Reference< util::XCloneable > xCloneable;
+ if( rProp.second >>= xCloneable )
+ rProp.second <<= xCloneable->createClone();
+ }
+ }
+
+ m_xStyle.set( ::chart::CloneHelper::CreateRefClone< style::XStyle >()( rOther.m_xStyle ));
+}
+
+void OPropertySet::SetNewValuesExplicitlyEvenIfTheyEqualDefault()
+{
+ m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault = true;
+}
+
+OPropertySet::~OPropertySet()
+{}
+
+Any SAL_CALL OPropertySet::queryInterface( const uno::Type& aType )
+{
+ return ::cppu::queryInterface(
+ aType,
+ static_cast< lang::XTypeProvider * >( this ),
+ static_cast< beans::XPropertySet * >( this ),
+ static_cast< beans::XMultiPropertySet * >( this ),
+ static_cast< beans::XFastPropertySet * >( this ),
+ static_cast< beans::XPropertyState * >( this ),
+ static_cast< beans::XMultiPropertyStates * >( this ),
+ static_cast< style::XStyleSupplier * >( this ) );
+}
+
+// ____ XTypeProvider ____
+Sequence< uno::Type > SAL_CALL
+ OPropertySet::getTypes()
+{
+ static const Sequence< uno::Type > aTypeList{
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<beans::XPropertySet>::get(),
+ cppu::UnoType<beans::XMultiPropertySet>::get(),
+ cppu::UnoType<beans::XFastPropertySet>::get(),
+ cppu::UnoType<beans::XPropertyState>::get(),
+ cppu::UnoType<beans::XMultiPropertyStates>::get(),
+ cppu::UnoType<style::XStyleSupplier>::get() };
+
+ return aTypeList;
+}
+
+Sequence< sal_Int8 > SAL_CALL
+ OPropertySet::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// ____ XPropertyState ____
+beans::PropertyState SAL_CALL
+ OPropertySet::getPropertyState( const OUString& PropertyName )
+{
+ cppu::IPropertyArrayHelper & rPH = getInfoHelper();
+
+ return GetPropertyStateByHandle(
+ rPH.getHandleByName( PropertyName ));
+}
+
+Sequence< beans::PropertyState > SAL_CALL
+ OPropertySet::getPropertyStates( const Sequence< OUString >& aPropertyName )
+{
+ cppu::IPropertyArrayHelper & rPH = getInfoHelper();
+
+ std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[ aPropertyName.getLength() ]);
+ rPH.fillHandles( pHandles.get(), aPropertyName );
+
+ std::vector< sal_Int32 > aHandles( pHandles.get(), pHandles.get() + aPropertyName.getLength());
+ pHandles.reset();
+
+ return GetPropertyStatesByHandle( aHandles );
+}
+
+void SAL_CALL
+ OPropertySet::setPropertyToDefault( const OUString& PropertyName )
+{
+ cppu::IPropertyArrayHelper & rPH = getInfoHelper();
+
+ SetPropertyToDefault( rPH.getHandleByName( PropertyName ));
+ firePropertyChangeEvent();
+}
+
+Any SAL_CALL
+ OPropertySet::getPropertyDefault( const OUString& aPropertyName )
+{
+ cppu::IPropertyArrayHelper & rPH = getInfoHelper();
+
+ Any any;
+ GetDefaultValue( rPH.getHandleByName( aPropertyName ), any );
+ return any;
+}
+
+// ____ XMultiPropertyStates ____
+
+// Note: getPropertyStates() is already implemented in XPropertyState with the
+// same signature
+
+void SAL_CALL
+ OPropertySet::setAllPropertiesToDefault()
+{
+ SetAllPropertiesToDefault();
+ firePropertyChangeEvent();
+}
+
+void SAL_CALL
+ OPropertySet::setPropertiesToDefault( const Sequence< OUString >& aPropertyNames )
+{
+ cppu::IPropertyArrayHelper & rPH = getInfoHelper();
+
+ std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[ aPropertyNames.getLength() ]);
+ rPH.fillHandles( pHandles.get(), aPropertyNames );
+
+ std::vector< sal_Int32 > aHandles( pHandles.get(), pHandles.get() + aPropertyNames.getLength());
+ pHandles.reset();
+
+ SetPropertiesToDefault( aHandles );
+}
+
+Sequence< Any > SAL_CALL
+ OPropertySet::getPropertyDefaults( const Sequence< OUString >& aPropertyNames )
+{
+ ::cppu::IPropertyArrayHelper & rPH = getInfoHelper();
+ const sal_Int32 nElements = aPropertyNames.getLength();
+
+ Sequence< Any > aResult( nElements );
+ Any * pResultArray = aResult.getArray();
+ sal_Int32 nI = 0;
+
+ for( ; nI < nElements; ++nI )
+ {
+ GetDefaultValue(
+ rPH.getHandleByName( aPropertyNames[ nI ] ),
+ pResultArray[ nI ]);
+ }
+
+ return aResult;
+}
+
+sal_Bool SAL_CALL OPropertySet::convertFastPropertyValue
+ ( Any & rConvertedValue,
+ Any & rOldValue,
+ sal_Int32 nHandle,
+ const Any& rValue )
+{
+ getFastPropertyValue( rOldValue, nHandle );
+ //accept longs also for short values
+ {
+ sal_Int16 nValue;
+ if( (rOldValue>>=nValue) && !(rValue>>=nValue) )
+ {
+ sal_Int32 n32Value = 0;
+ if( rValue>>=n32Value )
+ {
+ rConvertedValue <<= static_cast<sal_Int16>(n32Value);
+ return true;
+ }
+
+ sal_Int64 n64Value = 0;
+ if( rValue>>=n64Value )
+ {
+ rConvertedValue <<= static_cast<sal_Int16>(n64Value);
+ return true;
+ }
+ }
+ }
+ rConvertedValue = rValue;
+ if( !m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault && rOldValue == rConvertedValue )
+ return false;//no change necessary
+ return true;
+}
+
+void SAL_CALL OPropertySet::setFastPropertyValue_NoBroadcast
+ ( sal_Int32 nHandle,
+ const Any& rValue )
+{
+#if OSL_DEBUG_LEVEL > 0
+ if( rValue.hasValue())
+ {
+ cppu::IPropertyArrayHelper & rPH = getInfoHelper();
+ OUString aName;
+ rPH.fillPropertyMembersByHandle( &aName, nullptr, nHandle );
+ OSL_ENSURE( rValue.isExtractableTo( rPH.getPropertyByName( aName ).Type ),
+ "Property type is wrong" );
+ }
+#endif
+
+ Any aDefault;
+ try
+ {
+ GetDefaultValue( nHandle, aDefault );
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ aDefault.clear();
+ }
+ if( !m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault && aDefault.hasValue() && aDefault == rValue ) //#i98893# don't export defaults to file
+ SetPropertyToDefault( nHandle );
+ else
+ SetPropertyValueByHandle( nHandle, rValue );
+}
+
+void SAL_CALL OPropertySet::getFastPropertyValue
+ ( Any& rValue,
+ sal_Int32 nHandle ) const
+{
+ if( GetPropertyValueByHandle( rValue, nHandle ))
+ return;
+
+ // property was not set -> try style
+ uno::Reference< beans::XFastPropertySet > xStylePropSet( m_xStyle, uno::UNO_QUERY );
+ if( xStylePropSet.is() )
+ {
+#ifdef DBG_UTIL
+ {
+ // check if the handle of the style points to the same property
+ // name as the handle in this property set
+ uno::Reference< beans::XPropertySet > xPropSet( xStylePropSet, uno::UNO_QUERY );
+ if( xPropSet.is())
+ {
+ uno::Reference< beans::XPropertySetInfo > xInfo = xPropSet->getPropertySetInfo();
+ if( xInfo.is() )
+ {
+ // for some reason the virtual method getInfoHelper() is
+ // not const
+ ::cppu::IPropertyArrayHelper & rPH =
+ const_cast< OPropertySet * >( this )->getInfoHelper();
+
+ // find the Property with Handle nHandle in Style
+ Sequence< beans::Property > aProps( xInfo->getProperties() );
+ sal_Int32 nI = aProps.getLength() - 1;
+ while( ( nI >= 0 ) && nHandle != aProps[ nI ].Handle )
+ --nI;
+
+ if( nI >= 0 ) // => nHandle == aProps[nI].Handle
+ {
+ // check whether the handle in this property set is
+ // the same as the one in the style
+ beans::Property aProp( rPH.getPropertyByName( aProps[ nI ].Name ) );
+ OSL_ENSURE( nHandle == aProp.Handle,
+ "HandleCheck: Handles for same property differ!" );
+
+ if( nHandle == aProp.Handle )
+ {
+ OSL_ENSURE( aProp.Type == aProps[nI].Type,
+ "HandleCheck: Types differ!" );
+ OSL_ENSURE( aProp.Attributes == aProps[nI].Attributes,
+ "HandleCheck: Attributes differ!" );
+ }
+ }
+ else
+ {
+ OSL_FAIL( "HandleCheck: Handle not found in Style" );
+ }
+ }
+ else
+ OSL_FAIL( "HandleCheck: Invalid XPropertySetInfo returned" );
+ }
+ else
+ OSL_FAIL( "HandleCheck: XPropertySet not supported" );
+ }
+#endif
+ rValue = xStylePropSet->getFastPropertyValue( nHandle );
+ }
+ else
+ {
+ // there is no style (or the style does not support XFastPropertySet)
+ // => take the default value
+ try
+ {
+ GetDefaultValue( nHandle, rValue );
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ rValue.clear();
+ }
+ }
+}
+
+void OPropertySet::firePropertyChangeEvent()
+{
+ // nothing in base class
+}
+
+// ____ XStyleSupplier ____
+Reference< style::XStyle > SAL_CALL OPropertySet::getStyle()
+{
+ return m_xStyle;
+}
+
+void SAL_CALL OPropertySet::setStyle( const Reference< style::XStyle >& xStyle )
+{
+ if( ! SetStyle( xStyle ))
+ throw lang::IllegalArgumentException(
+ "Empty Style",
+ static_cast< beans::XPropertySet * >( this ),
+ 0 );
+}
+
+// ____ XMultiPropertySet ____
+void SAL_CALL OPropertySet::setPropertyValues(
+ const Sequence< OUString >& PropertyNames, const Sequence< Any >& Values )
+{
+ ::cppu::OPropertySetHelper::setPropertyValues( PropertyNames, Values );
+
+ firePropertyChangeEvent();
+}
+
+// ____ XFastPropertySet ____
+void SAL_CALL OPropertySet::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue )
+{
+ ::cppu::OPropertySetHelper::setFastPropertyValue( nHandle, rValue );
+
+ firePropertyChangeEvent();
+}
+
+beans::PropertyState OPropertySet::GetPropertyStateByHandle( sal_Int32 nHandle ) const
+{
+ if( m_aProperties.end() == m_aProperties.find( nHandle ))
+ return beans::PropertyState_DEFAULT_VALUE;
+ return beans::PropertyState_DIRECT_VALUE;
+}
+
+Sequence< beans::PropertyState > OPropertySet::GetPropertyStatesByHandle(
+ const std::vector< sal_Int32 > & aHandles ) const
+{
+ Sequence< beans::PropertyState > aResult( aHandles.size());
+
+ std::transform( aHandles.begin(), aHandles.end(),
+ aResult.getArray(),
+ [this](sal_Int32 nHandle) { return GetPropertyStateByHandle(nHandle); });
+
+ return aResult;
+}
+
+void OPropertySet::SetPropertyToDefault( sal_Int32 nHandle )
+{
+ auto aFoundIter( m_aProperties.find( nHandle ) );
+
+ if( m_aProperties.end() != aFoundIter )
+ {
+ m_aProperties.erase( aFoundIter );
+ }
+}
+
+void OPropertySet::SetPropertiesToDefault(
+ const std::vector< sal_Int32 > & aHandles )
+{
+ for(auto nHandle : aHandles)
+ m_aProperties.erase(nHandle);
+}
+
+void OPropertySet::SetAllPropertiesToDefault()
+{
+ m_aProperties.clear();
+}
+
+bool OPropertySet::GetPropertyValueByHandle(
+ Any & rValue,
+ sal_Int32 nHandle ) const
+{
+ bool bResult = false;
+
+ auto aFoundIter( m_aProperties.find( nHandle ) );
+
+ if( m_aProperties.end() != aFoundIter )
+ {
+ rValue = (*aFoundIter).second;
+ bResult = true;
+ }
+
+ return bResult;
+}
+
+void OPropertySet::SetPropertyValueByHandle(
+ sal_Int32 nHandle, const Any & rValue )
+{
+ m_aProperties[ nHandle ] = rValue;
+}
+
+bool OPropertySet::SetStyle( const Reference< style::XStyle > & xStyle )
+{
+ if( ! xStyle.is())
+ return false;
+
+ m_xStyle = xStyle;
+ return true;
+}
+
+
+} // namespace property
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ObjectIdentifier.cxx b/chart2/source/tools/ObjectIdentifier.cxx
new file mode 100644
index 0000000000..6e7631c8a9
--- /dev/null
+++ b/chart2/source/tools/ObjectIdentifier.cxx
@@ -0,0 +1,1405 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cstddef>
+#include <map>
+
+#include <ObjectIdentifier.hxx>
+#include <TitleHelper.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartType.hxx>
+#include <GridProperties.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <servicenames_charttypes.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <unonames.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <DataSeries.hxx>
+#include <RegressionCurveModel.hxx>
+
+#include <com/sun/star/chart2/XAxis.hpp>
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+
+#include <rtl/ustrbuf.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <o3tl/safeint.hxx>
+#include <o3tl/string_view.hxx>
+#include <utility>
+
+namespace com::sun::star::drawing { class XShape; }
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+
+constexpr OUString m_aMultiClick = u"MultiClick"_ustr;
+constexpr OUString m_aDragMethodEquals = u"DragMethod="_ustr;
+constexpr OUString m_aDragParameterEquals = u"DragParameter="_ustr;
+constexpr OUString m_aProtocol = u"CID/"_ustr;
+constexpr OUString m_aPieSegmentDragMethodServiceName(u"PieSegmentDragging"_ustr);
+
+namespace
+{
+
+OUString lcl_createClassificationStringForType( ObjectType eObjectType
+ , std::u16string_view rDragMethodServiceName
+ , std::u16string_view rDragParameterString
+ )
+{
+ OUStringBuffer aRet;
+ switch( eObjectType )
+ {
+ //these object types are all selected only after their parents was selected before
+ case OBJECTTYPE_LEGEND_ENTRY: //parent is intended to be OBJECTTYPE_LEGEND
+ case OBJECTTYPE_DATA_POINT: //parent is intended to be OBJECTTYPE_DATA_SERIES
+ case OBJECTTYPE_DATA_LABEL: //parent is intended to be OBJECTTYPE_DATA_LABELS
+ case OBJECTTYPE_DATA_ERRORS_X: //parent is intended to be OBJECTTYPE_DATA_ERRORS
+ case OBJECTTYPE_DATA_ERRORS_Y: //parent is intended to be OBJECTTYPE_DATA_ERRORS
+ case OBJECTTYPE_DATA_ERRORS_Z: //parent is intended to be OBJECTTYPE_DATA_ERRORS
+ aRet=m_aMultiClick;
+ break;
+ default:
+ break;//empty string
+ }
+ if( !rDragMethodServiceName.empty() )
+ {
+ if( !aRet.isEmpty() )
+ aRet.append(":");
+ aRet.append( OUString::Concat(m_aDragMethodEquals) + rDragMethodServiceName );
+
+ if( !rDragParameterString.empty() )
+ {
+ if( !aRet.isEmpty() )
+ aRet.append(":");
+ aRet.append( OUString::Concat(m_aDragParameterEquals) + rDragParameterString );
+ }
+ }
+ return aRet.makeStringAndClear();
+}
+
+typedef std::map< TitleHelper::eTitleType, OUString > tTitleMap;
+const tTitleMap& lcl_getTitleMap()
+{
+ //maps the title type to the ParentParticle for that title
+ static tTitleMap s_aTitleMap{
+ {TitleHelper::MAIN_TITLE, ""},
+ {TitleHelper::SUB_TITLE, "D=0"},
+ {TitleHelper::X_AXIS_TITLE, "D=0:CS=0:Axis=0,0"},
+ {TitleHelper::Y_AXIS_TITLE, "D=0:CS=0:Axis=1,0"},
+ {TitleHelper::Z_AXIS_TITLE, "D=0:CS=0:Axis=2,0"},
+ {TitleHelper::SECONDARY_X_AXIS_TITLE, "D=0:CS=0:Axis=0,1"},
+ {TitleHelper::SECONDARY_Y_AXIS_TITLE, "D=0:CS=0:Axis=1,1"}};
+ return s_aTitleMap;
+}
+
+OUString lcl_getTitleParentParticle( TitleHelper::eTitleType aTitleType )
+{
+ OUString aRet;
+
+ const tTitleMap& rMap = lcl_getTitleMap();
+ tTitleMap::const_iterator aIt( rMap.find( aTitleType ) );
+ if( aIt != rMap.end())
+ aRet = (*aIt).second;
+
+ return aRet;
+}
+
+rtl::Reference<ChartType> lcl_getFirstStockChartType( const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ if(!xDiagram.is())
+ return nullptr;
+
+ //iterate through all coordinate systems
+
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysList( xDiagram->getBaseCoordinateSystems() );
+ for( rtl::Reference< BaseCoordinateSystem > const & coords : aCooSysList )
+ {
+ //iterate through all chart types in the current coordinate system
+ for( rtl::Reference< ChartType > const & xChartType : coords->getChartTypes2() )
+ {
+ OUString aChartType = xChartType->getChartType();
+ if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
+ return xChartType;
+ }
+ }
+ return nullptr;
+}
+
+std::u16string_view lcl_getIndexStringAfterString( std::u16string_view rString, std::u16string_view rSearchString )
+{
+ size_t nIndexStart = rString.rfind( rSearchString );
+ if( nIndexStart == std::u16string_view::npos )
+ return std::u16string_view();
+ nIndexStart += rSearchString.size();
+ size_t nIndexEnd = rString.size();
+ size_t nNextColon = rString.find( ':', nIndexStart );
+ if( nNextColon != std::u16string_view::npos )
+ nIndexEnd = nNextColon;
+ return rString.substr(nIndexStart,nIndexEnd-nIndexStart);
+}
+
+sal_Int32 lcl_StringToIndex( std::u16string_view rIndexString )
+{
+ sal_Int32 nRet = -1;
+ if( !rIndexString.empty() )
+ {
+ nRet = o3tl::toInt32(rIndexString);
+ if( nRet < -1 )
+ nRet = -1;
+ }
+ return nRet;
+}
+
+void lcl_parseCooSysIndices( sal_Int32& rnDiagram, sal_Int32& rnCooSys, std::u16string_view rString )
+{
+ rnDiagram = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, u"D=" ) );
+ rnCooSys = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, u"CS=" ) );
+}
+
+void lcl_parseAxisIndices( sal_Int32& rnDimensionIndex, sal_Int32& rnAxisIndex, std::u16string_view rString )
+{
+ std::u16string_view aAxisIndexString = lcl_getIndexStringAfterString( rString, u":Axis=" );
+ sal_Int32 nCharacterIndex=0;
+ rnDimensionIndex = lcl_StringToIndex( o3tl::getToken(aAxisIndexString, 0, ',', nCharacterIndex ) );
+ rnAxisIndex = lcl_StringToIndex( o3tl::getToken(aAxisIndexString, 0, ',', nCharacterIndex ) );
+}
+
+void lcl_parseGridIndices( sal_Int32& rnSubGridIndex, std::u16string_view rString )
+{
+ rnSubGridIndex = -1;
+ rnSubGridIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, u":SubGrid=" ) );
+}
+
+void lcl_parseSeriesIndices( sal_Int32& rnChartTypeIndex, sal_Int32& rnSeriesIndex, sal_Int32& rnPointIndex, std::u16string_view rString )
+{
+ rnChartTypeIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, u"CT=" ) );
+ rnSeriesIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, u"Series=" ) );
+ rnPointIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, u"Point=" ) );
+}
+
+void lcl_getDiagramAndCooSys( std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel
+ , rtl::Reference< Diagram >& xDiagram
+ , rtl::Reference< BaseCoordinateSystem >& xCooSys )
+{
+ sal_Int32 nDiagramIndex = -1;
+ sal_Int32 nCooSysIndex = -1;
+ lcl_parseCooSysIndices( nDiagramIndex, nCooSysIndex, rObjectCID );
+ xDiagram = xChartModel->getFirstChartDiagram();//todo use nDiagramIndex when more than one diagram is possible in future
+ if( !xDiagram.is() )
+ return;
+
+ if( nCooSysIndex > -1 )
+ {
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > aCooSysList( xDiagram->getBaseCoordinateSystems() );
+ if( o3tl::make_unsigned(nCooSysIndex) < aCooSysList.size() )
+ xCooSys = aCooSysList[nCooSysIndex];
+ }
+}
+
+} //anonymous namespace
+
+ObjectIdentifier::ObjectIdentifier()
+{
+}
+
+ObjectIdentifier::ObjectIdentifier( OUString aObjectCID )
+ :m_aObjectCID(std::move( aObjectCID ))
+{
+}
+
+ObjectIdentifier::ObjectIdentifier( const Reference< drawing::XShape >& rxShape )
+ : m_xAdditionalShape( rxShape )
+{
+}
+
+ObjectIdentifier::ObjectIdentifier( const Any& rAny )
+{
+ const uno::Type& rType = rAny.getValueType();
+ if ( rType == cppu::UnoType<OUString>::get() )
+ {
+ rAny >>= m_aObjectCID;
+ }
+ else if ( rType == cppu::UnoType< drawing::XShape >::get() )
+ {
+ rAny >>= m_xAdditionalShape;
+ }
+}
+
+bool ObjectIdentifier::operator==( const ObjectIdentifier& rOID ) const
+{
+ return areIdenticalObjects( m_aObjectCID, rOID.m_aObjectCID ) &&
+ ( m_xAdditionalShape == rOID.m_xAdditionalShape );
+}
+
+bool ObjectIdentifier::operator!=( const ObjectIdentifier& rOID ) const
+{
+ return !operator==( rOID );
+}
+
+bool ObjectIdentifier::operator<( const ObjectIdentifier& rOID ) const
+{
+ bool bReturn = false;
+ if ( !(m_aObjectCID.isEmpty() || rOID.m_aObjectCID.isEmpty()) )
+ {
+ bReturn = ( m_aObjectCID.compareTo( rOID.m_aObjectCID ) < 0 );
+ }
+ else if ( !m_aObjectCID.isEmpty() )
+ {
+ bReturn = true;
+ }
+ else if ( !rOID.m_aObjectCID.isEmpty() )
+ {
+ bReturn = false;
+ }
+ else if ( m_xAdditionalShape.is() && rOID.m_xAdditionalShape.is() )
+ {
+ bReturn = ( m_xAdditionalShape < rOID.m_xAdditionalShape );
+ }
+ return bReturn;
+}
+
+OUString ObjectIdentifier::createClassifiedIdentifierForObject(
+ const rtl::Reference< ::chart::Title >& xTitle
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ TitleHelper::eTitleType aTitleType;
+ OUString aRet;
+ const std::u16string_view aObjectID;
+ const std::u16string_view aDragMethodServiceName;
+ const std::u16string_view aDragParameterString;
+ if( TitleHelper::getTitleType( aTitleType, xTitle, xChartModel ) )
+ {
+ enum ObjectType eObjectType = OBJECTTYPE_TITLE;
+ OUString aParentParticle = lcl_getTitleParentParticle( aTitleType );
+ aRet = ObjectIdentifier::createClassifiedIdentifierWithParent(
+ eObjectType, aObjectID, aParentParticle, aDragMethodServiceName, aDragParameterString );
+ }
+ return aRet;
+}
+
+OUString ObjectIdentifier::createClassifiedIdentifierForObject(
+ const Reference< uno::XInterface >& xObject
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ OUString aRet;
+
+ enum ObjectType eObjectType = OBJECTTYPE_UNKNOWN;
+ const std::u16string_view aObjectID;
+ OUString aParentParticle;
+ const std::u16string_view aDragMethodServiceName;
+ const std::u16string_view aDragParameterString;
+
+ try
+ {
+ //title
+ if( ::chart::Title* pTitle = dynamic_cast<::chart::Title*>(xObject.get()) )
+ return createClassifiedIdentifierForObject(rtl::Reference<Title>(pTitle), xChartModel);
+
+ uno::Reference<chart2::XDataTable> xDataTable(xObject, uno::UNO_QUERY);
+ if (xDataTable.is())
+ {
+ return createClassifiedIdentifierForParticle(createParticleForDataTable(xChartModel));
+ }
+
+ //axis
+ rtl::Reference< Axis > xAxis = dynamic_cast<Axis*>( xObject.get() );
+ if( xAxis.is() )
+ {
+ rtl::Reference<Diagram> xDiagram = xChartModel->getFirstChartDiagram();
+ rtl::Reference< BaseCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( xAxis, xDiagram ) );
+ OUString aCooSysParticle( createParticleForCoordinateSystem( xCooSys, xChartModel ) );
+ sal_Int32 nDimensionIndex=-1;
+ sal_Int32 nAxisIndex=-1;
+ AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex );
+ OUString aAxisParticle( createParticleForAxis( nDimensionIndex, nAxisIndex ) );
+ return createClassifiedIdentifierForParticles( aCooSysParticle, aAxisParticle );
+ }
+
+ //legend
+ Reference< XLegend > xLegend( xObject, uno::UNO_QUERY );
+ if( xLegend.is() )
+ {
+ return createClassifiedIdentifierForParticle( createParticleForLegend( xChartModel ) );
+ }
+
+ //diagram
+ Reference< XDiagram > xDiagram( xObject, uno::UNO_QUERY );
+ if( xDiagram.is() )
+ {
+ return createClassifiedIdentifierForParticle( createParticleForDiagram() );
+ }
+
+ //todo
+ //XDataSeries
+ //CooSys
+ //charttype
+ //datapoint?
+ //Gridproperties
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ if( eObjectType != OBJECTTYPE_UNKNOWN )
+ {
+ aRet = ObjectIdentifier::createClassifiedIdentifierWithParent(
+ eObjectType, aObjectID, aParentParticle, aDragMethodServiceName, aDragParameterString );
+ }
+ else
+ {
+ OSL_FAIL("give object could not be identified in createClassifiedIdentifierForObject");
+ }
+
+ return aRet;
+}
+
+OUString ObjectIdentifier::createClassifiedIdentifierForObject(
+ const rtl::Reference< Legend >& xLegend
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ try
+ {
+ if( xLegend.is() )
+ {
+ return createClassifiedIdentifierForParticle( createParticleForLegend( xChartModel ) );
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ OSL_FAIL("give object could not be identified in createClassifiedIdentifierForObject");
+
+ return OUString();
+}
+
+OUString ObjectIdentifier::createClassifiedIdentifierForObject(
+ const rtl::Reference<::chart::Axis>& xAxis
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ try
+ {
+ //axis
+ if( xAxis.is() )
+ {
+ rtl::Reference<Diagram> xDiagram = xChartModel->getFirstChartDiagram();
+ rtl::Reference< BaseCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( xAxis, xDiagram ) );
+ OUString aCooSysParticle( createParticleForCoordinateSystem( xCooSys, xChartModel ) );
+ sal_Int32 nDimensionIndex=-1;
+ sal_Int32 nAxisIndex=-1;
+ AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex );
+ OUString aAxisParticle( createParticleForAxis( nDimensionIndex, nAxisIndex ) );
+ return createClassifiedIdentifierForParticles( aCooSysParticle, aAxisParticle );
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ OSL_FAIL("give object could not be identified in createClassifiedIdentifierForObject");
+
+ return OUString();
+}
+
+OUString ObjectIdentifier::createClassifiedIdentifierForParticle(
+ std::u16string_view rParticle )
+{
+ return ObjectIdentifier::createClassifiedIdentifierForParticles( rParticle, u"" );
+}
+
+OUString ObjectIdentifier::createClassifiedIdentifierForParticles(
+ std::u16string_view rParentParticle
+ , std::u16string_view rChildParticle
+ , std::u16string_view rDragMethodServiceName
+ , std::u16string_view rDragParameterString )
+{
+ ObjectType eObjectType( ObjectIdentifier::getObjectType( rChildParticle ) );
+ if( eObjectType == OBJECTTYPE_UNKNOWN )
+ eObjectType = ObjectIdentifier::getObjectType( rParentParticle );
+
+ OUStringBuffer aRet( m_aProtocol +
+ lcl_createClassificationStringForType( eObjectType, rDragMethodServiceName, rDragParameterString ));
+ if(aRet.getLength() > m_aProtocol.getLength())
+ aRet.append("/");
+
+ if(!rParentParticle.empty())
+ {
+ aRet.append(rParentParticle);
+ if( !rChildParticle.empty() )
+ aRet.append(":");
+ }
+ aRet.append(rChildParticle);
+
+ return aRet.makeStringAndClear();
+}
+
+OUString ObjectIdentifier::createParticleForDiagram()
+{
+ //TODO: if more than one diagram is implemented, add the correct diagram index here
+ return "D=0";
+}
+
+OUString ObjectIdentifier::createParticleForCoordinateSystem(
+ const rtl::Reference< BaseCoordinateSystem >& xCooSys
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ OUString aRet;
+
+ rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
+ if( xDiagram.is() )
+ {
+ std::size_t nCooSysIndex = 0;
+ const std::vector< rtl::Reference< BaseCoordinateSystem > > & aCooSysList( xDiagram->getBaseCoordinateSystems() );
+ for( ; nCooSysIndex < aCooSysList.size(); ++nCooSysIndex )
+ {
+ if( xCooSys == aCooSysList[nCooSysIndex] )
+ {
+ aRet = ObjectIdentifier::createParticleForDiagram() + ":CS=" + OUString::number( nCooSysIndex );
+ break;
+ }
+ }
+ }
+
+ return aRet;
+}
+
+OUString ObjectIdentifier::createParticleForAxis(
+ sal_Int32 nDimensionIndex
+ , sal_Int32 nAxisIndex )
+{
+ return "Axis=" +
+ OUString::number( nDimensionIndex ) +
+ "," +
+ OUString::number( nAxisIndex );
+}
+
+OUString ObjectIdentifier::createParticleForGrid(
+ sal_Int32 nDimensionIndex
+ , sal_Int32 nAxisIndex )
+{
+ OUString aRet = "Axis=" + OUString::number( nDimensionIndex )
+ + "," + OUString::number( nAxisIndex ) + ":Grid=0";
+
+ return aRet;
+}
+
+OUString ObjectIdentifier::createClassifiedIdentifierForGrid(
+ const Reference< XAxis >& xAxis
+ , const rtl::Reference<::chart::ChartModel>& xChartModel
+ , sal_Int32 nSubGridIndex )
+{
+ //-1: main grid, 0: first subgrid etc
+
+ OUString aAxisCID( createClassifiedIdentifierForObject( xAxis, xChartModel ) );
+ OUString aGridCID( addChildParticle( aAxisCID
+ , createChildParticleWithIndex( OBJECTTYPE_GRID, 0 ) ) );
+ if( nSubGridIndex >= 0 )
+ {
+ aGridCID = addChildParticle( aGridCID
+ , createChildParticleWithIndex( OBJECTTYPE_SUBGRID, 0 ) );
+ }
+ return aGridCID;
+}
+
+OUString ObjectIdentifier::createParticleForSeries(
+ sal_Int32 nDiagramIndex, sal_Int32 nCooSysIndex
+ , sal_Int32 nChartTypeIndex, sal_Int32 nSeriesIndex )
+{
+ return
+ "D=" + OUString::number( nDiagramIndex ) +
+ ":CS=" + OUString::number( nCooSysIndex ) +
+ ":CT=" + OUString::number( nChartTypeIndex ) +
+ ":" + getStringForType( OBJECTTYPE_DATA_SERIES ) + "=" +
+ OUString::number( nSeriesIndex );
+}
+
+
+OUString ObjectIdentifier::createParticleForLegend(
+ const rtl::Reference<::chart::ChartModel>& )
+{
+ //todo: if more than one diagram is implemented, find the correct diagram which is owner of the given legend
+
+ return ObjectIdentifier::createParticleForDiagram() + ":" + getStringForType( OBJECTTYPE_LEGEND ) + "=";
+}
+
+OUString ObjectIdentifier::createParticleForDataTable(const rtl::Reference<::chart::ChartModel>& /* xChartModel */)
+{
+ return ObjectIdentifier::createParticleForDiagram() + ":" + getStringForType(OBJECTTYPE_DATA_TABLE) + "=";
+}
+
+OUString ObjectIdentifier::createClassifiedIdentifier(
+ enum ObjectType eObjectType //e.g. OBJECTTYPE_DATA_SERIES
+ , std::u16string_view rParticleID )//e.g. SeriesID
+{
+ return createClassifiedIdentifierWithParent(
+ eObjectType, rParticleID, u"" );
+}
+
+OUString ObjectIdentifier::createClassifiedIdentifierWithParent(
+ enum ObjectType eObjectType //e.g. OBJECTTYPE_DATA_POINT or OBJECTTYPE_GRID
+ , std::u16string_view rParticleID //e.g. Point Index or SubGrid Index
+ , std::u16string_view rParentPartical //e.g. "Series=SeriesID" or "Grid=GridId"
+ , std::u16string_view rDragMethodServiceName
+ , std::u16string_view rDragParameterString
+ )
+ //, bool bIsMultiClickObject ) //e.g. true
+{
+ //e.g. "MultiClick/Series=2:Point=34"
+
+ OUStringBuffer aRet( m_aProtocol +
+ lcl_createClassificationStringForType( eObjectType, rDragMethodServiceName, rDragParameterString ));
+ if(aRet.getLength() > m_aProtocol.getLength())
+ aRet.append("/");
+ aRet.append(rParentPartical);
+ if(!rParentPartical.empty())
+ aRet.append(":");
+
+ aRet.append(getStringForType( eObjectType ) + "=" + rParticleID);
+
+ return aRet.makeStringAndClear();
+}
+
+const OUString& ObjectIdentifier::getPieSegmentDragMethodServiceName()
+{
+ return m_aPieSegmentDragMethodServiceName;
+}
+
+OUString ObjectIdentifier::createPieSegmentDragParameterString(
+ sal_Int32 nOffsetPercent
+ , const awt::Point& rMinimumPosition
+ , const awt::Point& rMaximumPosition )
+{
+ OUString aRet = OUString::number( nOffsetPercent )
+ + "," + OUString::number( rMinimumPosition.X )
+ + "," + OUString::number( rMinimumPosition.Y )
+ + "," + OUString::number( rMaximumPosition.X )
+ + "," + OUString::number( rMaximumPosition.Y );
+ return aRet;
+}
+
+bool ObjectIdentifier::parsePieSegmentDragParameterString(
+ std::u16string_view rDragParameterString
+ , sal_Int32& rOffsetPercent
+ , awt::Point& rMinimumPosition
+ , awt::Point& rMaximumPosition )
+{
+ sal_Int32 nCharacterIndex = 0;
+
+ std::u16string_view aValueString( o3tl::getToken(rDragParameterString, 0, ',', nCharacterIndex ) );
+ rOffsetPercent = o3tl::toInt32(aValueString);
+ if( nCharacterIndex < 0 )
+ return false;
+
+ aValueString = o3tl::getToken(rDragParameterString, 0, ',', nCharacterIndex );
+ rMinimumPosition.X = o3tl::toInt32(aValueString);
+ if( nCharacterIndex < 0 )
+ return false;
+
+ aValueString = o3tl::getToken(rDragParameterString, 0, ',', nCharacterIndex );
+ rMinimumPosition.Y = o3tl::toInt32(aValueString);
+ if( nCharacterIndex < 0 )
+ return false;
+
+ aValueString = o3tl::getToken(rDragParameterString, 0, ',', nCharacterIndex );
+ rMaximumPosition.X = o3tl::toInt32(aValueString);
+ if( nCharacterIndex < 0 )
+ return false;
+
+ aValueString = o3tl::getToken(rDragParameterString, 0, ',', nCharacterIndex );
+ rMaximumPosition.Y = o3tl::toInt32(aValueString);
+ return nCharacterIndex >= 0;
+}
+
+std::u16string_view ObjectIdentifier::getDragMethodServiceName( std::u16string_view rCID )
+{
+ std::u16string_view aRet;
+
+ size_t nIndexStart = rCID.find( m_aDragMethodEquals );
+ if( nIndexStart != std::u16string_view::npos )
+ {
+ nIndexStart = rCID.find( '=', nIndexStart );
+ if( nIndexStart != std::u16string_view::npos )
+ {
+ nIndexStart++;
+ size_t nNextSlash = rCID.find( '/', nIndexStart );
+ if( nNextSlash != std::u16string_view::npos )
+ {
+ sal_Int32 nIndexEnd = nNextSlash;
+ size_t nNextColon = rCID.find( ':', nIndexStart );
+ if( nNextColon == std::u16string_view::npos || nNextColon < nNextSlash )
+ nIndexEnd = nNextColon;
+ aRet = rCID.substr(nIndexStart,nIndexEnd-nIndexStart);
+ }
+ }
+ }
+ return aRet;
+}
+
+std::u16string_view ObjectIdentifier::getDragParameterString( std::u16string_view rCID )
+{
+ std::u16string_view aRet;
+
+ size_t nIndexStart = rCID.find( m_aDragParameterEquals );
+ if( nIndexStart != std::u16string_view::npos )
+ {
+ nIndexStart = rCID.find( '=', nIndexStart );
+ if( nIndexStart != std::u16string_view::npos )
+ {
+ nIndexStart++;
+ size_t nNextSlash = rCID.find( '/', nIndexStart );
+ if( nNextSlash != std::u16string_view::npos )
+ {
+ sal_Int32 nIndexEnd = nNextSlash;
+ size_t nNextColon = rCID.find( ':', nIndexStart );
+ if( nNextColon == std::u16string_view::npos || nNextColon < nNextSlash )
+ nIndexEnd = nNextColon;
+ aRet = rCID.substr(nIndexStart,nIndexEnd-nIndexStart);
+ }
+ }
+ }
+ return aRet;
+}
+
+bool ObjectIdentifier::isDragableObject( std::u16string_view rClassifiedIdentifier )
+{
+ bool bReturn = false;
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( rClassifiedIdentifier );
+ switch( eObjectType )
+ {
+ case OBJECTTYPE_TITLE:
+ case OBJECTTYPE_LEGEND:
+ case OBJECTTYPE_DIAGRAM:
+ case OBJECTTYPE_DATA_LABEL:
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ //case OBJECTTYPE_DIAGRAM_WALL:
+ bReturn = true;
+ break;
+ default:
+ std::u16string_view aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( rClassifiedIdentifier ) );
+ bReturn = !aDragMethodServiceName.empty();
+ break;
+ }
+ return bReturn;
+}
+
+bool ObjectIdentifier::isDragableObject() const
+{
+ bool bReturn = false;
+ if ( isAutoGeneratedObject() )
+ {
+ bReturn = isDragableObject( m_aObjectCID );
+ }
+ else if ( isAdditionalShape() )
+ {
+ bReturn = true;
+ }
+ return bReturn;
+}
+
+bool ObjectIdentifier::isRotateableObject( std::u16string_view rClassifiedIdentifier )
+{
+ bool bReturn = false;
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( rClassifiedIdentifier );
+ switch( eObjectType )
+ {
+ case OBJECTTYPE_DIAGRAM:
+ //case OBJECTTYPE_DIAGRAM_WALL:
+ bReturn = true;
+ break;
+ default:
+ bReturn = false;
+ break;
+ }
+ return bReturn;
+}
+
+bool ObjectIdentifier::isMultiClickObject( std::u16string_view rClassifiedIdentifier )
+{
+ //the name of a shape is it's ClassifiedIdentifier
+
+ //a MultiClickObject is an object that is selectable by more than one click only ;
+ //before a MultiClickObject can be selected it is necessary that a named parent group object
+ //was selected before;
+
+ //!!!!! by definition the name of a MultiClickObject starts with "CID/MultiClick:"
+ bool bRet = o3tl::starts_with(rClassifiedIdentifier.substr( m_aProtocol.getLength() ), m_aMultiClick);
+ return bRet;
+}
+
+bool ObjectIdentifier::areSiblings( std::u16string_view rCID1, std::u16string_view rCID2 )
+{
+ bool bRet=false;
+ size_t nLastSign1 = rCID1.rfind( '=' );
+ size_t nLastSign2 = rCID2.rfind( '=' );
+ if( nLastSign1 == rCID1.find( '=' ) )//CID cannot be sibling if only one "=" occurs
+ bRet=false;
+ else if( nLastSign2 == rCID2.find( '=' ) )//CID cannot be sibling if only one "=" occurs
+ bRet=false;
+ else if( ObjectIdentifier::areIdenticalObjects( rCID1, rCID2 ) )
+ bRet=false;
+ else
+ {
+ std::u16string_view aParent1( ObjectIdentifier::getFullParentParticle( rCID1 ) );
+ if( !aParent1.empty() )
+ {
+ std::u16string_view aParent2( ObjectIdentifier::getFullParentParticle( rCID2 ) );
+ bRet=aParent1 == aParent2;
+ }
+ //legend entries are special:
+ if(!bRet)
+ {
+ if( getObjectType(rCID1) == OBJECTTYPE_LEGEND_ENTRY
+ && getObjectType(rCID2) == OBJECTTYPE_LEGEND_ENTRY )
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+bool ObjectIdentifier::areIdenticalObjects( std::u16string_view rCID1, std::u16string_view rCID2 )
+{
+ if( rCID1 == rCID2 )
+ return true;
+ //draggable pie or donut segments need special treatment, as their CIDs do change with offset
+ {
+ if( rCID1.find( m_aPieSegmentDragMethodServiceName ) == std::u16string_view::npos
+ || rCID2.find( m_aPieSegmentDragMethodServiceName ) == std::u16string_view::npos )
+ return false;
+
+ OUString aID1( ObjectIdentifier::getObjectID( rCID1 ) );
+ OUString aID2( ObjectIdentifier::getObjectID( rCID2 ) );
+ if( !aID1.isEmpty() && aID1 == aID2 )
+ return true;
+ }
+ return false;
+}
+
+OUString ObjectIdentifier::getStringForType( ObjectType eObjectType )
+{
+ OUString aRet;
+ switch( eObjectType )
+ {
+ case OBJECTTYPE_PAGE:
+ aRet="Page";
+ break;
+ case OBJECTTYPE_TITLE:
+ aRet="Title";
+ break;
+ case OBJECTTYPE_LEGEND:
+ aRet="Legend";
+ break;
+ case OBJECTTYPE_LEGEND_ENTRY:
+ aRet="LegendEntry";
+ break;
+ case OBJECTTYPE_DIAGRAM:
+ aRet="D";
+ break;
+ case OBJECTTYPE_DIAGRAM_WALL:
+ aRet="DiagramWall";
+ break;
+ case OBJECTTYPE_DIAGRAM_FLOOR:
+ aRet="DiagramFloor";
+ break;
+ case OBJECTTYPE_AXIS:
+ aRet="Axis";
+ break;
+ case OBJECTTYPE_AXIS_UNITLABEL:
+ aRet="AxisUnitLabel";
+ break;
+ case OBJECTTYPE_GRID:
+ aRet="Grid";
+ break;
+ case OBJECTTYPE_SUBGRID:
+ aRet="SubGrid";
+ break;
+ case OBJECTTYPE_DATA_SERIES:
+ aRet="Series";
+ break;
+ case OBJECTTYPE_DATA_POINT:
+ aRet="Point";
+ break;
+ case OBJECTTYPE_DATA_LABELS:
+ aRet="DataLabels";
+ break;
+ case OBJECTTYPE_DATA_LABEL:
+ aRet="DataLabel";
+ break;
+ case OBJECTTYPE_DATA_ERRORS_X:
+ aRet="ErrorsX";
+ break;
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ aRet="ErrorsY";
+ break;
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ aRet="ErrorsZ";
+ break;
+ case OBJECTTYPE_DATA_CURVE:
+ aRet="Curve";
+ break;
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ aRet="Equation";
+ break;
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ aRet="Average";
+ break;
+ case OBJECTTYPE_DATA_STOCK_RANGE:
+ aRet="StockRange";
+ break;
+ case OBJECTTYPE_DATA_STOCK_LOSS:
+ aRet="StockLoss";
+ break;
+ case OBJECTTYPE_DATA_STOCK_GAIN:
+ aRet="StockGain";
+ break;
+ case OBJECTTYPE_DATA_TABLE:
+ aRet="DataTable";
+ break;
+ default: //OBJECTTYPE_UNKNOWN
+ ;
+ }
+ return aRet;
+}
+
+ObjectType ObjectIdentifier::getObjectType( std::u16string_view aCID )
+{
+ ObjectType eRet;
+ size_t nLastSign = aCID.rfind( ':' );//last sign before the type string
+ if(nLastSign == std::u16string_view::npos)
+ nLastSign = aCID.rfind( '/' );
+ if(nLastSign == std::u16string_view::npos)
+ {
+ size_t nEndIndex = aCID.rfind( '=' );
+ if(nEndIndex == std::u16string_view::npos)
+ return OBJECTTYPE_UNKNOWN;
+ nLastSign = 0;
+ }
+ if( nLastSign>0 )
+ nLastSign++;
+
+ aCID = aCID.substr(nLastSign);
+ if( o3tl::starts_with(aCID, u"Page") )
+ eRet = OBJECTTYPE_PAGE;
+ else if( o3tl::starts_with(aCID, u"Title") )
+ eRet = OBJECTTYPE_TITLE;
+ else if( o3tl::starts_with(aCID, u"LegendEntry") )
+ eRet = OBJECTTYPE_LEGEND_ENTRY;
+ else if( o3tl::starts_with(aCID, u"Legend") )
+ eRet = OBJECTTYPE_LEGEND;
+ else if( o3tl::starts_with(aCID, u"DiagramWall") )
+ eRet = OBJECTTYPE_DIAGRAM_WALL;
+ else if( o3tl::starts_with(aCID, u"DiagramFloor") )
+ eRet = OBJECTTYPE_DIAGRAM_FLOOR;
+ else if( o3tl::starts_with(aCID, u"D=") )
+ eRet = OBJECTTYPE_DIAGRAM;
+ else if( o3tl::starts_with(aCID, u"AxisUnitLabel") )
+ eRet = OBJECTTYPE_AXIS_UNITLABEL;
+ else if( o3tl::starts_with(aCID, u"Axis") )
+ eRet = OBJECTTYPE_AXIS;
+ else if( o3tl::starts_with(aCID, u"Grid") )
+ eRet = OBJECTTYPE_GRID;
+ else if( o3tl::starts_with(aCID, u"SubGrid") )
+ eRet = OBJECTTYPE_SUBGRID;
+ else if( o3tl::starts_with(aCID, u"Series") )
+ eRet = OBJECTTYPE_DATA_SERIES;
+ else if( o3tl::starts_with(aCID, u"Point") )
+ eRet = OBJECTTYPE_DATA_POINT;
+ else if( o3tl::starts_with(aCID, u"DataLabels") )
+ eRet = OBJECTTYPE_DATA_LABELS;
+ else if( o3tl::starts_with(aCID, u"DataLabel") )
+ eRet = OBJECTTYPE_DATA_LABEL;
+ else if( o3tl::starts_with(aCID, u"ErrorsX") )
+ eRet = OBJECTTYPE_DATA_ERRORS_X;
+ else if( o3tl::starts_with(aCID, u"ErrorsY") )
+ eRet = OBJECTTYPE_DATA_ERRORS_Y;
+ else if( o3tl::starts_with(aCID, u"ErrorsZ") )
+ eRet = OBJECTTYPE_DATA_ERRORS_Z;
+ else if( o3tl::starts_with(aCID, u"Curve") )
+ eRet = OBJECTTYPE_DATA_CURVE;
+ else if( o3tl::starts_with(aCID, u"Equation") )
+ eRet = OBJECTTYPE_DATA_CURVE_EQUATION;
+ else if( o3tl::starts_with(aCID, u"Average") )
+ eRet = OBJECTTYPE_DATA_AVERAGE_LINE;
+ else if( o3tl::starts_with(aCID, u"StockRange") )
+ eRet = OBJECTTYPE_DATA_STOCK_RANGE;
+ else if( o3tl::starts_with(aCID, u"StockLoss") )
+ eRet = OBJECTTYPE_DATA_STOCK_LOSS;
+ else if( o3tl::starts_with(aCID, u"StockGain") )
+ eRet = OBJECTTYPE_DATA_STOCK_GAIN;
+ else if( o3tl::starts_with(aCID, u"DataTable") )
+ eRet = OBJECTTYPE_DATA_TABLE;
+ else
+ eRet = OBJECTTYPE_UNKNOWN;
+
+ return eRet;
+}
+
+ObjectType ObjectIdentifier::getObjectType() const
+{
+ ObjectType eObjectType( OBJECTTYPE_UNKNOWN );
+ if ( isAutoGeneratedObject() )
+ {
+ eObjectType = getObjectType( m_aObjectCID );
+ }
+ else if ( isAdditionalShape() )
+ {
+ eObjectType = OBJECTTYPE_SHAPE;
+ }
+ return eObjectType;
+}
+
+OUString ObjectIdentifier::createDataCurveCID(
+ std::u16string_view rSeriesParticle
+ , sal_Int32 nCurveIndex
+ , bool bAverageLine )
+{
+ OUString aParticleID( OUString::number( nCurveIndex ) );
+ ObjectType eType = bAverageLine ? OBJECTTYPE_DATA_AVERAGE_LINE : OBJECTTYPE_DATA_CURVE;
+ return createClassifiedIdentifierWithParent( eType, aParticleID, rSeriesParticle );
+}
+
+OUString ObjectIdentifier::createDataCurveEquationCID(
+ std::u16string_view rSeriesParticle
+ , sal_Int32 nCurveIndex )
+{
+ OUString aParticleID( OUString::number( nCurveIndex ) );
+ return createClassifiedIdentifierWithParent( OBJECTTYPE_DATA_CURVE_EQUATION, aParticleID, rSeriesParticle );
+}
+
+OUString ObjectIdentifier::addChildParticle( std::u16string_view rParticle, std::u16string_view rChildParticle )
+{
+ OUStringBuffer aRet(rParticle);
+
+ if( !aRet.isEmpty() && !rChildParticle.empty() )
+ aRet.append(":");
+ if( !rChildParticle.empty() )
+ aRet.append(rChildParticle);
+
+ return aRet.makeStringAndClear();
+}
+
+OUString ObjectIdentifier::createChildParticleWithIndex( ObjectType eObjectType, sal_Int32 nIndex )
+{
+ OUStringBuffer aRet( getStringForType( eObjectType ) );
+ if( !aRet.isEmpty() )
+ {
+ aRet.append("=" + OUString::number(nIndex));
+ }
+ return aRet.makeStringAndClear();
+}
+
+sal_Int32 ObjectIdentifier::getIndexFromParticleOrCID( std::u16string_view rParticleOrCID )
+{
+ const std::u16string_view aIndexString = lcl_getIndexStringAfterString( rParticleOrCID, u"=" );
+ return lcl_StringToIndex( o3tl::getToken(aIndexString, 0, ',' ) );
+}
+
+OUString ObjectIdentifier::createSeriesSubObjectStub( ObjectType eSubObjectType
+ , std::u16string_view rSeriesParticle
+ , std::u16string_view rDragMethodServiceName
+ , std::u16string_view rDragParameterString )
+{
+ OUString aChildParticle = getStringForType( eSubObjectType ) + "=";
+
+ return createClassifiedIdentifierForParticles(
+ rSeriesParticle, aChildParticle
+ , rDragMethodServiceName, rDragParameterString );
+}
+
+OUString ObjectIdentifier::createPointCID( std::u16string_view rPointCID_Stub, sal_Int32 nIndex )
+{
+ return rPointCID_Stub + OUString::number( nIndex );
+}
+
+std::u16string_view ObjectIdentifier::getParticleID( std::u16string_view rCID )
+{
+ std::u16string_view aRet;
+ size_t nLast = rCID.rfind('=');
+ if(nLast != std::u16string_view::npos)
+ aRet = rCID.substr(++nLast);
+ return aRet;
+}
+
+std::u16string_view ObjectIdentifier::getFullParentParticle( std::u16string_view rCID )
+{
+ std::u16string_view aRet;
+
+ size_t nStartPos = rCID.rfind('/');
+ if( nStartPos != std::u16string_view::npos )
+ {
+ nStartPos++;
+ size_t nEndPos = rCID.rfind(':');
+ if( nEndPos != std::u16string_view::npos && nStartPos < nEndPos )
+ {
+ aRet = rCID.substr(nStartPos,nEndPos-nStartPos);
+ }
+ }
+
+ return aRet;
+}
+
+OUString ObjectIdentifier::getObjectID( std::u16string_view rCID )
+{
+ OUString aRet;
+
+ size_t nStartPos = rCID.rfind('/');
+ if( nStartPos != std::u16string_view::npos )
+ {
+ nStartPos++;
+ size_t nEndPos = rCID.size();
+ aRet = rCID.substr(nStartPos,nEndPos-nStartPos);
+ }
+
+ return aRet;
+}
+
+bool ObjectIdentifier::isCID( std::u16string_view rName )
+{
+ return !rName.empty() && o3tl::starts_with( rName, m_aProtocol );
+}
+
+Reference< beans::XPropertySet > ObjectIdentifier::getObjectPropertySet(
+ std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ //return the model object that is indicated by rObjectCID
+ if(rObjectCID.empty())
+ return nullptr;
+ if(!xChartModel.is())
+ return nullptr;
+
+ Reference< beans::XPropertySet > xObjectProperties;
+ try
+ {
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( rObjectCID );
+ std::u16string_view aParticleID = ObjectIdentifier::getParticleID( rObjectCID );
+
+ rtl::Reference< Diagram > xDiagram;
+ rtl::Reference< BaseCoordinateSystem > xCooSys;
+ lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys );
+
+ switch(eObjectType)
+ {
+ case OBJECTTYPE_PAGE:
+ {
+ xObjectProperties.set( xChartModel->getPageBackground() );
+ }
+ break;
+ case OBJECTTYPE_TITLE:
+ {
+ TitleHelper::eTitleType aTitleType = getTitleTypeForCID( rObjectCID );
+ rtl::Reference< Title > xTitle( TitleHelper::getTitle( aTitleType, xChartModel ) );
+ xObjectProperties = xTitle;
+ }
+ break;
+ case OBJECTTYPE_LEGEND:
+ {
+ if( xDiagram.is() )
+ xObjectProperties.set( xDiagram->getLegend(), uno::UNO_QUERY );
+ }
+ break;
+ case OBJECTTYPE_LEGEND_ENTRY:
+ break;
+ case OBJECTTYPE_DIAGRAM:
+ {
+ xObjectProperties = xDiagram;
+ }
+ break;
+ case OBJECTTYPE_DIAGRAM_WALL:
+ {
+ if( xDiagram.is() )
+ xObjectProperties.set( xDiagram->getWall() );
+ }
+ break;
+ case OBJECTTYPE_DIAGRAM_FLOOR:
+ {
+ if( xDiagram.is() )
+ xObjectProperties.set( xDiagram->getFloor() );
+ }
+ break;
+ case OBJECTTYPE_AXIS:
+ {
+ sal_Int32 nDimensionIndex = -1;
+ sal_Int32 nAxisIndex = -1;
+ lcl_parseAxisIndices( nDimensionIndex, nAxisIndex, rObjectCID );
+
+ rtl::Reference< Axis > xAxis =
+ AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys );
+ if( xAxis.is() )
+ xObjectProperties = xAxis;
+ }
+ break;
+ case OBJECTTYPE_AXIS_UNITLABEL:
+ break;
+ case OBJECTTYPE_GRID:
+ case OBJECTTYPE_SUBGRID:
+ {
+ sal_Int32 nDimensionIndex = -1;
+ sal_Int32 nAxisIndex = -1;
+ lcl_parseAxisIndices( nDimensionIndex, nAxisIndex, rObjectCID );
+
+ sal_Int32 nSubGridIndex = -1;
+ lcl_parseGridIndices( nSubGridIndex, rObjectCID );
+
+ xObjectProperties = AxisHelper::getGridProperties( xCooSys , nDimensionIndex, nAxisIndex, nSubGridIndex );
+ }
+ break;
+ case OBJECTTYPE_DATA_LABELS:
+ case OBJECTTYPE_DATA_SERIES:
+ {
+ rtl::Reference< DataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID(
+ rObjectCID, xChartModel ) );
+ if( xSeries.is() )
+ xObjectProperties = xSeries;
+
+ break;
+ }
+ case OBJECTTYPE_DATA_LABEL:
+ case OBJECTTYPE_DATA_POINT:
+ {
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID(
+ rObjectCID, xChartModel );
+ if(xSeries.is())
+ {
+ sal_Int32 nIndex = o3tl::toInt32(aParticleID);
+ xObjectProperties = xSeries->getDataPointByIndex( nIndex );
+ }
+ break;
+ }
+ case OBJECTTYPE_DATA_ERRORS_X:
+ case OBJECTTYPE_DATA_ERRORS_Y:
+ case OBJECTTYPE_DATA_ERRORS_Z:
+ {
+ rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID(
+ rObjectCID, xChartModel );
+ if(xSeries.is())
+ {
+ Reference< beans::XPropertySet > xErrorBarProp;
+ OUString errorBar;
+
+ if ( eObjectType == OBJECTTYPE_DATA_ERRORS_X)
+ errorBar = CHART_UNONAME_ERRORBAR_X;
+ else if (eObjectType == OBJECTTYPE_DATA_ERRORS_Y)
+ errorBar = CHART_UNONAME_ERRORBAR_Y;
+ else
+ errorBar = "ErrorBarZ";
+
+ xSeries->getPropertyValue( errorBar ) >>= xErrorBarProp;
+ xObjectProperties = xErrorBarProp;
+ }
+ break;
+ }
+ case OBJECTTYPE_DATA_AVERAGE_LINE:
+ case OBJECTTYPE_DATA_CURVE:
+ case OBJECTTYPE_DATA_CURVE_EQUATION:
+ {
+ rtl::Reference< DataSeries > xRegressionContainer = ObjectIdentifier::getDataSeriesForCID(
+ rObjectCID, xChartModel );
+ if(xRegressionContainer.is())
+ {
+ sal_Int32 nIndex = o3tl::toInt32(aParticleID);
+ const std::vector< rtl::Reference< RegressionCurveModel > > & aCurveList =
+ xRegressionContainer->getRegressionCurves2();
+ if( nIndex >= 0 && o3tl::make_unsigned(nIndex) < aCurveList.size() )
+ {
+ if( eObjectType == OBJECTTYPE_DATA_CURVE_EQUATION )
+ xObjectProperties = aCurveList[nIndex]->getEquationProperties();
+ else
+ xObjectProperties = aCurveList[nIndex];
+ }
+ }
+ break;
+ }
+ case OBJECTTYPE_DATA_STOCK_RANGE:
+ break;
+ case OBJECTTYPE_DATA_STOCK_LOSS:
+ {
+ rtl::Reference<ChartType> xChartType( lcl_getFirstStockChartType( xChartModel ) );
+ if(xChartType.is())
+ xChartType->getPropertyValue( "BlackDay" ) >>= xObjectProperties;
+ }
+ break;
+ case OBJECTTYPE_DATA_STOCK_GAIN:
+ {
+ rtl::Reference<ChartType> xChartType( lcl_getFirstStockChartType( xChartModel ) );
+ if(xChartType.is())
+ xChartType->getPropertyValue( "WhiteDay" ) >>= xObjectProperties;
+ }
+ break;
+ case OBJECTTYPE_DATA_TABLE:
+ {
+ if (xDiagram.is())
+ xObjectProperties.set(xDiagram->getDataTable(), uno::UNO_QUERY);
+ }
+ break;
+ break;
+ default: //OBJECTTYPE_UNKNOWN
+ break;
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return xObjectProperties;
+}
+
+rtl::Reference< Axis > ObjectIdentifier::getAxisForCID(
+ std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ rtl::Reference< Diagram > xDiagram;
+ rtl::Reference< BaseCoordinateSystem > xCooSys;
+ lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys );
+
+ sal_Int32 nDimensionIndex = -1;
+ sal_Int32 nAxisIndex = -1;
+ lcl_parseAxisIndices( nDimensionIndex, nAxisIndex, rObjectCID );
+
+ return AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys );
+}
+
+rtl::Reference< DataSeries > ObjectIdentifier::getDataSeriesForCID(
+ std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ rtl::Reference< Diagram > xDiagram;
+ rtl::Reference< BaseCoordinateSystem > xCooSys;
+ lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys );
+
+ sal_Int32 nChartTypeIndex = -1;
+ sal_Int32 nSeriesIndex = -1;
+ sal_Int32 nPointIndex = -1;
+ lcl_parseSeriesIndices( nChartTypeIndex, nSeriesIndex, nPointIndex, rObjectCID );
+
+ rtl::Reference< DataSeries > xSeries;
+ if (xDiagram)
+ {
+ rtl::Reference< ChartType > xDataSeriesContainer( xDiagram->getChartTypeByIndex( nChartTypeIndex ) );
+ if( xDataSeriesContainer.is() )
+ {
+ const std::vector< rtl::Reference< DataSeries > > & aDataSeriesSeq( xDataSeriesContainer->getDataSeries2() );
+ if( nSeriesIndex >= 0 && o3tl::make_unsigned(nSeriesIndex) < aDataSeriesSeq.size() )
+ xSeries = aDataSeriesSeq[nSeriesIndex];
+ }
+ }
+ return xSeries;
+}
+
+rtl::Reference< Diagram > ObjectIdentifier::getDiagramForCID(
+ std::u16string_view rObjectCID
+ , const rtl::Reference<::chart::ChartModel>& xChartModel )
+{
+ rtl::Reference< Diagram > xDiagram;
+ rtl::Reference< BaseCoordinateSystem > xCooSys;
+ lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys );
+
+ return xDiagram;
+}
+
+TitleHelper::eTitleType ObjectIdentifier::getTitleTypeForCID( std::u16string_view rCID )
+{
+ TitleHelper::eTitleType eRet( TitleHelper::MAIN_TITLE );
+
+ std::u16string_view aParentParticle = ObjectIdentifier::getFullParentParticle( rCID );
+ const tTitleMap& rMap = lcl_getTitleMap();
+ tTitleMap::const_iterator aIt = std::find_if(rMap.begin(), rMap.end(),
+ [&aParentParticle](tTitleMap::const_reference rEntry) { return aParentParticle == rEntry.second; });
+ if (aIt != rMap.end())
+ eRet = (*aIt).first;
+
+ return eRet;
+}
+
+OUString ObjectIdentifier::getSeriesParticleFromCID( std::u16string_view rCID )
+{
+ sal_Int32 nDiagramIndex = -1;
+ sal_Int32 nCooSysIndex = -1;
+ lcl_parseCooSysIndices( nDiagramIndex, nCooSysIndex, rCID );
+
+ sal_Int32 nChartTypeIndex = -1;
+ sal_Int32 nSeriesIndex = -1;
+ sal_Int32 nPointIndex = -1;
+ lcl_parseSeriesIndices( nChartTypeIndex, nSeriesIndex, nPointIndex, rCID );
+
+ return ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCooSysIndex, nChartTypeIndex, nSeriesIndex );
+}
+
+OUString ObjectIdentifier::getMovedSeriesCID( std::u16string_view rObjectCID, bool bForward )
+{
+ sal_Int32 nDiagramIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, u"CID/D=" ) );
+ sal_Int32 nCooSysIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, u"CS=" ) );
+ sal_Int32 nChartTypeIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, u"CT=" ) );
+ sal_Int32 nSeriesIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, u"Series=" ) );
+
+ if( bForward )
+ nSeriesIndex--;
+ else
+ nSeriesIndex++;
+
+ OUString aRet = ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCooSysIndex, nChartTypeIndex, nSeriesIndex );
+ return ObjectIdentifier::createClassifiedIdentifierForParticle( aRet );
+}
+
+bool ObjectIdentifier::isValid() const
+{
+ return ( isAutoGeneratedObject() || isAdditionalShape() );
+}
+
+bool ObjectIdentifier::isAutoGeneratedObject() const
+{
+ return ( !m_aObjectCID.isEmpty() );
+}
+
+bool ObjectIdentifier::isAdditionalShape() const
+{
+ return m_xAdditionalShape.is();
+}
+
+Any ObjectIdentifier::getAny() const
+{
+ Any aAny;
+ if ( isAutoGeneratedObject() )
+ {
+ aAny <<= getObjectCID();
+ }
+ else if ( isAdditionalShape() )
+ {
+ aAny <<= getAdditionalShape();
+ }
+ return aAny;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx b/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx
new file mode 100644
index 0000000000..f8921d73c2
--- /dev/null
+++ b/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx
@@ -0,0 +1,392 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PolynomialRegressionCurveCalculator.hxx>
+#include <RegressionCalculationHelper.hxx>
+
+#include <cmath>
+#include <limits>
+#include <rtl/math.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <SpecialCharacters.hxx>
+
+using namespace com::sun::star;
+
+namespace chart
+{
+
+static double lcl_GetDotProduct(std::vector<double>& aVec1, std::vector<double>& aVec2)
+{
+ double fResult = 0.0;
+ assert(aVec1.size() == aVec2.size());
+ for (size_t i = 0; i < aVec1.size(); ++i)
+ fResult += aVec1[i] * aVec2[i];
+ return fResult;
+}
+
+PolynomialRegressionCurveCalculator::PolynomialRegressionCurveCalculator()
+{}
+
+PolynomialRegressionCurveCalculator::~PolynomialRegressionCurveCalculator()
+{}
+
+void PolynomialRegressionCurveCalculator::computeCorrelationCoefficient(
+ RegressionCalculationHelper::tDoubleVectorPair& rValues,
+ const sal_Int32 aNoValues,
+ double yAverage )
+{
+ double aSumError = 0.0;
+ double aSumTotal = 0.0;
+ double aSumYpred2 = 0.0;
+
+ for( sal_Int32 i = 0; i < aNoValues; i++ )
+ {
+ double xValue = rValues.first[i];
+ double yActual = rValues.second[i];
+ double yPredicted = getCurveValue( xValue );
+ aSumTotal += (yActual - yAverage) * (yActual - yAverage);
+ aSumError += (yActual - yPredicted) * (yActual - yPredicted);
+ if(mForceIntercept)
+ aSumYpred2 += (yPredicted - mInterceptValue) * (yPredicted - mInterceptValue);
+ }
+
+ double aRSquared = 0.0;
+ if(mForceIntercept)
+ {
+ if (auto const div = aSumError + aSumYpred2)
+ {
+ aRSquared = aSumYpred2 / div;
+ }
+ }
+ else if (aSumTotal != 0.0)
+ {
+ aRSquared = 1.0 - (aSumError / aSumTotal);
+ }
+
+ if (aRSquared > 0.0)
+ m_fCorrelationCoefficient = std::sqrt(aRSquared);
+ else
+ m_fCorrelationCoefficient = 0.0;
+}
+
+// ____ XRegressionCurveCalculator ____
+void SAL_CALL PolynomialRegressionCurveCalculator::recalculateRegression(
+ const uno::Sequence< double >& aXValues,
+ const uno::Sequence< double >& aYValues )
+{
+ m_fCorrelationCoefficient = std::numeric_limits<double>::quiet_NaN();
+
+ RegressionCalculationHelper::tDoubleVectorPair aValues(
+ RegressionCalculationHelper::cleanup( aXValues, aYValues, RegressionCalculationHelper::isValid()));
+
+ const sal_Int32 aNoValues = aValues.first.size();
+
+ const sal_Int32 aNoPowers = mForceIntercept ? mDegree : mDegree + 1;
+
+ mCoefficients.clear();
+ mCoefficients.resize(aNoPowers, 0.0);
+
+ double yAverage = 0.0;
+
+ std::vector<double> yVector;
+ yVector.resize(aNoValues, 0.0);
+
+ for(sal_Int32 i = 0; i < aNoValues; i++)
+ {
+ double yValue = aValues.second[i];
+ if (mForceIntercept)
+ yValue -= mInterceptValue;
+ yVector[i] = yValue;
+ yAverage += yValue;
+ }
+ if (aNoValues != 0)
+ {
+ yAverage /= aNoValues;
+ }
+
+ // Special case for single variable regression like in LINEST
+ // implementation in Calc.
+ if (mDegree == 1)
+ {
+ std::vector<double> xVector;
+ xVector.resize(aNoValues, 0.0);
+ double xAverage = 0.0;
+
+ for(sal_Int32 i = 0; i < aNoValues; ++i)
+ {
+ double xValue = aValues.first[i];
+ xVector[i] = xValue;
+ xAverage += xValue;
+ }
+ if (aNoValues != 0)
+ {
+ xAverage /= aNoValues;
+ }
+
+ if (!mForceIntercept)
+ {
+ for (sal_Int32 i = 0; i < aNoValues; ++i)
+ {
+ xVector[i] -= xAverage;
+ yVector[i] -= yAverage;
+ }
+ }
+ double fSumXY = lcl_GetDotProduct(xVector, yVector);
+ double fSumX2 = lcl_GetDotProduct(xVector, xVector);
+
+ double fSlope = fSumXY / fSumX2;
+
+ if (!mForceIntercept)
+ {
+ mInterceptValue = ::rtl::math::approxSub(yAverage, fSlope * xAverage);
+ mCoefficients[0] = mInterceptValue;
+ mCoefficients[1] = fSlope;
+ }
+ else
+ {
+ mCoefficients[0] = fSlope;
+ mCoefficients.insert(mCoefficients.begin(), mInterceptValue);
+ }
+
+ computeCorrelationCoefficient(aValues, aNoValues, yAverage);
+ return;
+ }
+
+ std::vector<double> aQRTransposed;
+ aQRTransposed.resize(aNoValues * aNoPowers, 0.0);
+
+ for(sal_Int32 j = 0; j < aNoPowers; j++)
+ {
+ sal_Int32 aPower = mForceIntercept ? j+1 : j;
+ sal_Int32 aColumnIndex = j * aNoValues;
+ for(sal_Int32 i = 0; i < aNoValues; i++)
+ {
+ double xValue = aValues.first[i];
+ aQRTransposed[i + aColumnIndex] = std::pow(xValue, static_cast<int>(aPower));
+ }
+ }
+
+ // QR decomposition - based on org.apache.commons.math.linear.QRDecomposition from apache commons math (ASF)
+ sal_Int32 aMinorSize = std::min(aNoValues, aNoPowers);
+
+ std::vector<double> aDiagonal;
+ aDiagonal.resize(aMinorSize, 0.0);
+
+ // Calculate Householder reflectors
+ for (sal_Int32 aMinor = 0; aMinor < aMinorSize; aMinor++)
+ {
+ double aNormSqr = 0.0;
+ for (sal_Int32 x = aMinor; x < aNoValues; x++)
+ {
+ double c = aQRTransposed[x + aMinor * aNoValues];
+ aNormSqr += c * c;
+ }
+
+ double a;
+
+ if (aQRTransposed[aMinor + aMinor * aNoValues] > 0.0)
+ a = -std::sqrt(aNormSqr);
+ else
+ a = std::sqrt(aNormSqr);
+
+ aDiagonal[aMinor] = a;
+
+ if (a != 0.0)
+ {
+ aQRTransposed[aMinor + aMinor * aNoValues] -= a;
+
+ for (sal_Int32 aColumn = aMinor + 1; aColumn < aNoPowers; aColumn++)
+ {
+ double alpha = 0.0;
+ for (sal_Int32 aRow = aMinor; aRow < aNoValues; aRow++)
+ {
+ alpha -= aQRTransposed[aRow + aColumn * aNoValues] * aQRTransposed[aRow + aMinor * aNoValues];
+ }
+ alpha /= a * aQRTransposed[aMinor + aMinor * aNoValues];
+
+ for (sal_Int32 aRow = aMinor; aRow < aNoValues; aRow++)
+ {
+ aQRTransposed[aRow + aColumn * aNoValues] -= alpha * aQRTransposed[aRow + aMinor * aNoValues];
+ }
+ }
+ }
+ }
+
+ // Solve the linear equation
+ for (sal_Int32 aMinor = 0; aMinor < aMinorSize; aMinor++)
+ {
+ double aDotProduct = 0;
+
+ for (sal_Int32 aRow = aMinor; aRow < aNoValues; aRow++)
+ {
+ aDotProduct += yVector[aRow] * aQRTransposed[aRow + aMinor * aNoValues];
+ }
+ aDotProduct /= aDiagonal[aMinor] * aQRTransposed[aMinor + aMinor * aNoValues];
+
+ for (sal_Int32 aRow = aMinor; aRow < aNoValues; aRow++)
+ {
+ yVector[aRow] += aDotProduct * aQRTransposed[aRow + aMinor * aNoValues];
+ }
+
+ }
+
+ for (sal_Int32 aRow = aDiagonal.size() - 1; aRow >= 0; aRow--)
+ {
+ yVector[aRow] /= aDiagonal[aRow];
+ double yRow = yVector[aRow];
+ mCoefficients[aRow] = yRow;
+
+ for (sal_Int32 i = 0; i < aRow; i++)
+ {
+ yVector[i] -= yRow * aQRTransposed[i + aRow * aNoValues];
+ }
+ }
+
+ if(mForceIntercept)
+ {
+ mCoefficients.insert(mCoefficients.begin(), mInterceptValue);
+ }
+
+ // Calculate correlation coefficient
+ computeCorrelationCoefficient(aValues, aNoValues, yAverage);
+}
+
+double SAL_CALL PolynomialRegressionCurveCalculator::getCurveValue( double x )
+{
+ if (mCoefficients.empty())
+ return std::numeric_limits<double>::quiet_NaN();
+
+ sal_Int32 aNoCoefficients = static_cast<sal_Int32>(mCoefficients.size());
+
+ // Horner's method
+ double fResult = 0.0;
+ for (sal_Int32 i = aNoCoefficients - 1; i >= 0; i--)
+ {
+ fResult = mCoefficients[i] + (x * fResult);
+ }
+ return fResult;
+}
+
+OUString PolynomialRegressionCurveCalculator::ImplGetRepresentation(
+ const uno::Reference< util::XNumberFormatter >& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaMaxWidth /* = nullptr */ ) const
+{
+ OUStringBuffer aBuf( mYName + " = " );
+
+ sal_Int32 nValueLength=0;
+ sal_Int32 aLastIndex = mCoefficients.size() - 1;
+
+ if ( pFormulaMaxWidth && *pFormulaMaxWidth > 0 )
+ {
+ sal_Int32 nCharMin = aBuf.getLength(); // count characters different from coefficients
+ double nCoefficients = aLastIndex + 1.0; // number of coefficients
+ for (sal_Int32 i = aLastIndex; i >= 0; i--)
+ {
+ double aValue = mCoefficients[i];
+ if ( aValue == 0.0 )
+ { // do not count coefficient if it is 0
+ nCoefficients --;
+ continue;
+ }
+ if ( rtl::math::approxEqual( fabs( aValue ) , 1.0 ) )
+ { // do not count coefficient if it is 1
+ nCoefficients --;
+ if ( i == 0 ) // intercept = 1
+ nCharMin ++;
+ }
+ if ( i != aLastIndex )
+ nCharMin += 3; // " + "
+ if ( i > 0 )
+ {
+ nCharMin += mXName.getLength() + 1; // " x"
+ if ( i > 1 )
+ nCharMin +=1; // "^i"
+ if ( i >= 10 )
+ nCharMin ++; // 2 digits for i
+ }
+ }
+ nValueLength = ( *pFormulaMaxWidth - nCharMin ) / nCoefficients;
+ if ( nValueLength <= 0 )
+ nValueLength = 1;
+ }
+
+ bool bFindValue = false;
+ sal_Int32 nLineLength = aBuf.getLength();
+ for (sal_Int32 i = aLastIndex; i >= 0; i--)
+ {
+ double aValue = mCoefficients[i];
+ OUStringBuffer aTmpBuf(""); // temporary buffer
+ if (aValue == 0.0)
+ {
+ continue;
+ }
+ else if (aValue < 0.0)
+ {
+ if ( bFindValue ) // if it is not the first aValue
+ aTmpBuf.append( " " );
+ aTmpBuf.append( OUStringChar(aMinusSign) + " ");
+ aValue = - aValue;
+ }
+ else
+ {
+ if ( bFindValue ) // if it is not the first aValue
+ aTmpBuf.append( " + " );
+ }
+ bFindValue = true;
+
+ // if nValueLength not calculated then nullptr
+ sal_Int32* pValueLength = nValueLength ? &nValueLength : nullptr;
+ OUString aValueString = getFormattedString( xNumFormatter, nNumberFormatKey, aValue, pValueLength );
+ if ( i == 0 || aValueString != "1" ) // aValueString may be rounded to 1 if nValueLength is small
+ {
+ aTmpBuf.append( aValueString );
+ if ( i > 0 ) // insert blank between coefficient and x
+ aTmpBuf.append( " " );
+ }
+
+ if(i > 0)
+ {
+ aTmpBuf.append( mXName );
+ if (i > 1)
+ {
+ if (i < 10) // simple case if only one digit
+ aTmpBuf.append( aSuperscriptFigures[ i ] );
+ else
+ {
+ OUString aValueOfi = OUString::number( i );
+ for ( sal_Int32 n = 0; n < aValueOfi.getLength() ; n++ )
+ {
+ sal_Int32 nIndex = aValueOfi[n] - u'0';
+ aTmpBuf.append( aSuperscriptFigures[ nIndex ] );
+ }
+ }
+ }
+ }
+ addStringToEquation( aBuf, nLineLength, aTmpBuf, pFormulaMaxWidth );
+ }
+ if ( std::u16string_view(aBuf) == Concat2View( mYName + " = ") )
+ aBuf.append( "0" );
+
+ return aBuf.makeStringAndClear();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/PopupRequest.cxx b/chart2/source/tools/PopupRequest.cxx
new file mode 100644
index 0000000000..70dd65b783
--- /dev/null
+++ b/chart2/source/tools/PopupRequest.cxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <PopupRequest.hxx>
+
+using namespace css;
+
+namespace chart
+{
+PopupRequest::PopupRequest() {}
+
+PopupRequest::~PopupRequest() {}
+
+// ____ XRequestCallback ____
+
+void SAL_CALL PopupRequest::addCallback(const uno::Reference<awt::XCallback>& xCallback,
+ const uno::Any& /*aData*/)
+{
+ m_xCallback = xCallback;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/PotentialRegressionCurveCalculator.cxx b/chart2/source/tools/PotentialRegressionCurveCalculator.cxx
new file mode 100644
index 0000000000..504048641b
--- /dev/null
+++ b/chart2/source/tools/PotentialRegressionCurveCalculator.cxx
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PotentialRegressionCurveCalculator.hxx>
+#include <RegressionCalculationHelper.hxx>
+#include <SpecialCharacters.hxx>
+
+#include <limits>
+#include <rtl/math.hxx>
+#include <rtl/ustrbuf.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+PotentialRegressionCurveCalculator::PotentialRegressionCurveCalculator()
+ : m_fSlope(std::numeric_limits<double>::quiet_NaN())
+ , m_fIntercept(std::numeric_limits<double>::quiet_NaN())
+ , m_fSign(1.0)
+{
+}
+
+PotentialRegressionCurveCalculator::~PotentialRegressionCurveCalculator()
+{}
+
+// ____ XRegressionCurveCalculator ____
+void SAL_CALL PotentialRegressionCurveCalculator::recalculateRegression(
+ const uno::Sequence< double >& aXValues,
+ const uno::Sequence< double >& aYValues )
+{
+ RegressionCalculationHelper::tDoubleVectorPair aValues(
+ RegressionCalculationHelper::cleanup(
+ aXValues, aYValues,
+ RegressionCalculationHelper::isValidAndBothPositive()));
+ m_fSign = 1.0;
+
+ size_t nMax = aValues.first.size();
+ if( nMax <= 1 ) // at least 2 points
+ {
+ aValues = RegressionCalculationHelper::cleanup(
+ aXValues, aYValues,
+ RegressionCalculationHelper::isValidAndXPositiveAndYNegative());
+ nMax = aValues.first.size();
+ if( nMax <= 1 )
+ {
+ m_fSlope = std::numeric_limits<double>::quiet_NaN();
+ m_fIntercept = std::numeric_limits<double>::quiet_NaN();
+ m_fCorrelationCoefficient = std::numeric_limits<double>::quiet_NaN();
+ return;
+ }
+ m_fSign = -1.0;
+ }
+
+ double fAverageX = 0.0, fAverageY = 0.0;
+ size_t i = 0;
+ for( i = 0; i < nMax; ++i )
+ {
+ fAverageX += log( aValues.first[i] );
+ fAverageY += log( m_fSign * aValues.second[i] );
+ }
+
+ const double fN = static_cast< double >( nMax );
+ fAverageX /= fN;
+ fAverageY /= fN;
+
+ double fQx = 0.0, fQy = 0.0, fQxy = 0.0;
+ for( i = 0; i < nMax; ++i )
+ {
+ double fDeltaX = log( aValues.first[i] ) - fAverageX;
+ double fDeltaY = log( m_fSign * aValues.second[i] ) - fAverageY;
+
+ fQx += fDeltaX * fDeltaX;
+ fQy += fDeltaY * fDeltaY;
+ fQxy += fDeltaX * fDeltaY;
+ }
+
+ m_fSlope = fQxy / fQx;
+ m_fIntercept = fAverageY - m_fSlope * fAverageX;
+ m_fCorrelationCoefficient = fQxy / sqrt( fQx * fQy );
+
+ m_fIntercept = m_fSign * exp( m_fIntercept );
+}
+
+double SAL_CALL PotentialRegressionCurveCalculator::getCurveValue( double x )
+{
+ if( ! ( std::isnan( m_fSlope ) ||
+ std::isnan( m_fIntercept )))
+ {
+ return m_fIntercept * pow( x, m_fSlope );
+ }
+
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+uno::Sequence< geometry::RealPoint2D > SAL_CALL PotentialRegressionCurveCalculator::getCurveValues(
+ double min, double max, ::sal_Int32 nPointCount,
+ const uno::Reference< chart2::XScaling >& xScalingX,
+ const uno::Reference< chart2::XScaling >& xScalingY,
+ sal_Bool bMaySkipPointsInCalculation )
+{
+ if( bMaySkipPointsInCalculation &&
+ isLogarithmicScaling( xScalingX ) &&
+ isLogarithmicScaling( xScalingY ))
+ {
+ // optimize result
+ uno::Sequence< geometry::RealPoint2D > aResult{ { min, getCurveValue( min ) },
+ { max, getCurveValue( max ) } };
+
+ return aResult;
+ }
+ return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation );
+}
+
+OUString PotentialRegressionCurveCalculator::ImplGetRepresentation(
+ const uno::Reference< util::XNumberFormatter >& xNumFormatter,
+ sal_Int32 nNumberFormatKey, sal_Int32* pFormulaMaxWidth /* = nullptr */ ) const
+{
+ bool bHasIntercept = !rtl::math::approxEqual( fabs(m_fIntercept), 1.0 );
+ OUStringBuffer aBuf( mYName + " = " );
+ sal_Int32 nLineLength = aBuf.getLength();
+ sal_Int32 nValueLength=0;
+ if ( pFormulaMaxWidth && *pFormulaMaxWidth > 0 ) // count nValueLength
+ {
+ sal_Int32 nCharMin = nLineLength + mXName.getLength() + 3; // 3 = "^" + 2 extra characters
+ if ( m_fIntercept != 0.0 && m_fSlope != 0.0 )
+ {
+ if ( m_fIntercept < 0.0 )
+ nCharMin += 2; // "- "
+ if ( bHasIntercept )
+ nValueLength = (*pFormulaMaxWidth - nCharMin) / 2;
+ }
+ if ( nValueLength == 0 ) // not yet calculated
+ nValueLength = *pFormulaMaxWidth - nCharMin;
+ if ( nValueLength <= 0 )
+ nValueLength = 1;
+ }
+
+ if( m_fIntercept == 0.0 )
+ {
+ aBuf.append( '0' );
+ }
+ else
+ {
+ // temporary buffer
+ OUStringBuffer aTmpBuf("");
+ // if nValueLength not calculated then nullptr
+ sal_Int32* pValueLength = nValueLength ? &nValueLength : nullptr;
+ if ( m_fIntercept < 0.0 ) // add intercept value
+ aTmpBuf.append( OUStringChar(aMinusSign) + " " );
+ if( bHasIntercept )
+ {
+ OUString aValueString = getFormattedString( xNumFormatter, nNumberFormatKey, fabs(m_fIntercept), pValueLength );
+ if ( aValueString != "1" ) // aValueString may be rounded to 1 if nValueLength is small
+ {
+ aTmpBuf.append( aValueString + " " );
+ }
+ }
+ if( m_fSlope != 0.0 ) // add slope value
+ {
+ aTmpBuf.append( mXName + "^" +
+ getFormattedString( xNumFormatter, nNumberFormatKey, m_fSlope, pValueLength ));
+ }
+ addStringToEquation( aBuf, nLineLength, aTmpBuf, pFormulaMaxWidth );
+ }
+
+ return aBuf.makeStringAndClear();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/PropertyHelper.cxx b/chart2/source/tools/PropertyHelper.cxx
new file mode 100644
index 0000000000..48e21eccaf
--- /dev/null
+++ b/chart2/source/tools/PropertyHelper.cxx
@@ -0,0 +1,312 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PropertyHelper.hxx>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <docmodel/uno/UnoGradientTools.hxx>
+#include <comphelper/sequence.hxx>
+#include <osl/diagnose.h>
+#include <comphelper/diagnose_ex.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <utility>
+#include <vector>
+#include <algorithm>
+#include <iterator>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+struct lcl_EqualsElement
+{
+ explicit lcl_EqualsElement( Any rValue, const Reference< container::XNameAccess > & xAccess )
+ : m_aValue(std::move( rValue )), m_xAccess( xAccess )
+ {
+ OSL_ASSERT( m_xAccess.is());
+ }
+
+ bool operator() ( const OUString & rName )
+ {
+ try
+ {
+ return (m_xAccess->getByName( rName ) == m_aValue);
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return false;
+ }
+
+private:
+ Any m_aValue;
+ Reference< container::XNameAccess > m_xAccess;
+};
+
+struct lcl_StringMatches
+{
+ explicit lcl_StringMatches( OUString aCmpStr ) :
+ m_aCmpStr(std::move( aCmpStr ))
+ {}
+
+ bool operator() ( std::u16string_view rStr )
+ {
+ return o3tl::starts_with( rStr, m_aCmpStr );
+ }
+
+private:
+ OUString m_aCmpStr;
+};
+
+struct lcl_OUStringRestToInt32
+{
+ explicit lcl_OUStringRestToInt32( sal_Int32 nPrefixLength ) :
+ m_nPrefixLength( nPrefixLength )
+ {}
+ sal_Int32 operator() ( std::u16string_view rStr )
+ {
+ if( m_nPrefixLength > static_cast<sal_Int32>(rStr.size()) )
+ return 0;
+ return o3tl::toInt32(rStr.substr( m_nPrefixLength ));
+ }
+private:
+ sal_Int32 m_nPrefixLength;
+};
+
+/** adds a fill gradient, fill hatch, fill bitmap, fill transparency gradient,
+ line dash or line marker to the corresponding name container with a unique
+ name.
+
+ @param rPrefix
+ The prefix used for automated name generation.
+
+ @param rPreferredName
+ If this string is not empty it is used as name if it is unique in the
+ table. Otherwise a new name is generated using pPrefix.
+
+ @return the new name under which the property was stored in the table
+*/
+OUString lcl_addNamedPropertyUniqueNameToTable(
+ const Any & rValue,
+ const Reference< container::XNameContainer > & xNameContainer,
+ const OUString & rPrefix,
+ const OUString & rPreferredName )
+{
+ if( ! xNameContainer.is() ||
+ ! rValue.hasValue() )
+ return rPreferredName;
+
+ Any aValue(rValue);
+
+ if ( rValue.has<css::awt::Gradient>())
+ {
+ // tdf#158421 the lists for Gradients needs awt::Gradient2
+ // as type, convert input data if needed (and warn about it,
+ // the caller should be changed to offer the needed type)
+ SAL_WARN("chart2","input value needs to be awt::Gradient2");
+ const basegfx::BGradient aTemp(model::gradient::getFromAny(rValue));
+ aValue <<= model::gradient::createUnoGradient2(aTemp);
+ }
+
+ if ( aValue.getValueType() != xNameContainer->getElementType())
+ return rPreferredName;
+
+ try
+ {
+ Reference< container::XNameAccess > xNameAccess( xNameContainer, uno::UNO_QUERY_THROW );
+ const uno::Sequence<OUString> aElementNames = xNameAccess->getElementNames();
+ auto it = std::find_if( aElementNames.begin(), aElementNames.end(), lcl_EqualsElement( aValue, xNameAccess ));
+
+ // element found => return name
+ if( it != aElementNames.end())
+ return *it;
+
+ // element not found in container
+ OUString aUniqueName;
+
+ // check if preferred name is already used
+ if( !rPreferredName.isEmpty())
+ {
+ auto aIt = std::find( aElementNames.begin(), aElementNames.end(), rPreferredName );
+ if( aIt == aElementNames.end())
+ aUniqueName = rPreferredName;
+ }
+
+ if( aUniqueName.isEmpty())
+ {
+ auto aNames( comphelper::sequenceToContainer<std::vector< OUString >>( aElementNames ));
+ // create a unique id using the prefix plus a number
+ std::vector< sal_Int32 > aNumbers;
+ std::vector< OUString >::iterator aNonConstIt(
+ std::partition( aNames.begin(), aNames.end(), lcl_StringMatches( rPrefix )));
+ std::transform( aNames.begin(), aNonConstIt,
+ back_inserter( aNumbers ),
+ lcl_OUStringRestToInt32( rPrefix.getLength() ));
+ std::vector< sal_Int32 >::const_iterator aMaxIt(
+ std::max_element( aNumbers.begin(), aNumbers.end()));
+
+ sal_Int32 nIndex = 1;
+ if( aMaxIt != aNumbers.end())
+ nIndex = (*aMaxIt) + 1;
+
+ aUniqueName = rPrefix + OUString::number( nIndex );
+ }
+
+ OSL_ASSERT( !aUniqueName.isEmpty());
+ xNameContainer->insertByName( aUniqueName, aValue );
+ return aUniqueName;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return rPreferredName;
+}
+
+} // anonymous namespace
+
+namespace chart::PropertyHelper
+{
+
+OUString addLineDashUniqueNameToTable(
+ const Any & rValue,
+ const Reference< lang::XMultiServiceFactory > & xFact,
+ const OUString & rPreferredName )
+{
+ if( xFact.is())
+ {
+ Reference< container::XNameContainer > xNameCnt(
+ xFact->createInstance( "com.sun.star.drawing.DashTable"),
+ uno::UNO_QUERY );
+ if( xNameCnt.is())
+ return lcl_addNamedPropertyUniqueNameToTable(
+ rValue, xNameCnt, "ChartDash ", rPreferredName );
+ }
+ return OUString();
+}
+
+OUString addGradientUniqueNameToTable(
+ const Any & rValue,
+ const Reference< lang::XMultiServiceFactory > & xFact,
+ const OUString & rPreferredName )
+{
+ if( xFact.is())
+ {
+ Reference< container::XNameContainer > xNameCnt(
+ xFact->createInstance( "com.sun.star.drawing.GradientTable"),
+ uno::UNO_QUERY );
+ if( xNameCnt.is())
+ return lcl_addNamedPropertyUniqueNameToTable(
+ rValue, xNameCnt, "ChartGradient ", rPreferredName );
+ }
+ return OUString();
+}
+
+OUString addTransparencyGradientUniqueNameToTable(
+ const Any & rValue,
+ const Reference< lang::XMultiServiceFactory > & xFact,
+ const OUString & rPreferredName )
+{
+ if( xFact.is())
+ {
+ Reference< container::XNameContainer > xNameCnt(
+ xFact->createInstance( "com.sun.star.drawing.TransparencyGradientTable"),
+ uno::UNO_QUERY );
+ if( xNameCnt.is())
+ return lcl_addNamedPropertyUniqueNameToTable(
+ rValue, xNameCnt, "ChartTransparencyGradient ", rPreferredName );
+ }
+ return OUString();
+}
+
+OUString addHatchUniqueNameToTable(
+ const Any & rValue,
+ const Reference< lang::XMultiServiceFactory > & xFact,
+ const OUString & rPreferredName )
+{
+ if( xFact.is())
+ {
+ Reference< container::XNameContainer > xNameCnt(
+ xFact->createInstance( "com.sun.star.drawing.HatchTable"),
+ uno::UNO_QUERY );
+ if( xNameCnt.is())
+ return lcl_addNamedPropertyUniqueNameToTable(
+ rValue, xNameCnt, "ChartHatch ", rPreferredName );
+ }
+ return OUString();
+}
+
+OUString addBitmapUniqueNameToTable(
+ const Any & rValue,
+ const Reference< lang::XMultiServiceFactory > & xFact,
+ const OUString & rPreferredName )
+{
+ if( xFact.is())
+ {
+ Reference< container::XNameContainer > xNameCnt(
+ xFact->createInstance( "com.sun.star.drawing.BitmapTable"),
+ uno::UNO_QUERY );
+ if( xNameCnt.is())
+ return lcl_addNamedPropertyUniqueNameToTable(
+ rValue, xNameCnt, "ChartBitmap ", rPreferredName );
+ }
+ return OUString();
+}
+
+void setPropertyValueAny( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const uno::Any & rAny )
+{
+ tPropertyValueMap::iterator aIt( rOutMap.find( key ));
+ if( aIt == rOutMap.end())
+ rOutMap.emplace( key, rAny );
+ else
+ (*aIt).second = rAny;
+}
+
+template<>
+ void setPropertyValue< css::uno::Any >( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const css::uno::Any & rAny )
+{
+ setPropertyValueAny( rOutMap, key, rAny );
+}
+
+void setPropertyValueDefaultAny( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const uno::Any & rAny )
+{
+ OSL_ENSURE( rOutMap.end() == rOutMap.find( key ), "Default already exists for property" );
+ setPropertyValue( rOutMap, key, rAny );
+}
+
+template<>
+ void setPropertyValueDefault< css::uno::Any >( tPropertyValueMap & rOutMap, tPropertyValueMapKey key, const css::uno::Any & rAny )
+{
+ setPropertyValueDefaultAny( rOutMap, key, rAny );
+}
+
+void setEmptyPropertyValueDefault( tPropertyValueMap & rOutMap, tPropertyValueMapKey key )
+{
+ setPropertyValueDefault( rOutMap, key, uno::Any());
+}
+
+} // namespace chart::PropertyHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/RangeHighlighter.cxx b/chart2/source/tools/RangeHighlighter.cxx
new file mode 100644
index 0000000000..1b2ae9153f
--- /dev/null
+++ b/chart2/source/tools/RangeHighlighter.cxx
@@ -0,0 +1,394 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RangeHighlighter.hxx>
+#include <WeakListenerAdapter.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <DataSourceHelper.hxx>
+#include <ObjectIdentifier.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <Diagram.hxx>
+
+#include <com/sun/star/chart2/ScaleData.hpp>
+#include <com/sun/star/chart2/XAxis.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <comphelper/sequence.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/color.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace
+{
+
+const Color defaultPreferredColor = COL_LIGHTBLUE;
+
+void lcl_fillRanges(
+ Sequence< chart2::data::HighlightedRange > & rOutRanges,
+ const Sequence< OUString >& aRangeStrings,
+ Color nPreferredColor,
+ sal_Int32 nIndex = -1 )
+{
+ rOutRanges.realloc( aRangeStrings.getLength());
+ auto pOutRanges = rOutRanges.getArray();
+ for( sal_Int32 i=0; i<aRangeStrings.getLength(); ++i )
+ {
+ pOutRanges[i].RangeRepresentation = aRangeStrings[i];
+ pOutRanges[i].PreferredColor = sal_Int32(nPreferredColor);
+ pOutRanges[i].AllowMerginigWithOtherRanges = false;
+ pOutRanges[i].Index = nIndex;
+ }
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+RangeHighlighter::RangeHighlighter(
+ const rtl::Reference< ChartModel > & xChartModel ) :
+ m_xSelectionSupplier(xChartModel->getCurrentController(), uno::UNO_QUERY),
+ m_xChartModel( xChartModel ),
+ m_nAddedListenerCount( 0 ),
+ m_bIncludeHiddenCells(true)
+{
+}
+
+RangeHighlighter::~RangeHighlighter()
+{}
+
+// ____ XRangeHighlighter ____
+Sequence< chart2::data::HighlightedRange > SAL_CALL RangeHighlighter::getSelectedRanges()
+{
+ return m_aSelectedRanges;
+}
+
+void RangeHighlighter::determineRanges()
+{
+ m_aSelectedRanges.realloc( 0 );
+ if( !m_xChartModel.is())
+ return;
+ if( !m_xSelectionSupplier.is())
+ return;
+
+ try
+ {
+ m_bIncludeHiddenCells = ChartModelHelper::isIncludeHiddenCells( m_xChartModel );
+
+ uno::Any aSelection( m_xSelectionSupplier->getSelection());
+ const uno::Type& rType = aSelection.getValueType();
+
+ if ( rType == cppu::UnoType<OUString>::get() )
+ {
+ // @todo??: maybe getSelection() should return a model object rather than a CID
+
+ OUString aCID;
+ aSelection >>= aCID;
+ if ( !aCID.isEmpty() )
+ {
+ ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID );
+ sal_Int32 nIndex = ObjectIdentifier::getIndexFromParticleOrCID( aCID );
+ rtl::Reference< DataSeries > xDataSeries( ObjectIdentifier::getDataSeriesForCID( aCID, m_xChartModel ) );
+ if( eObjectType == OBJECTTYPE_LEGEND_ENTRY )
+ {
+ OUString aParentParticel( ObjectIdentifier::getFullParentParticle( aCID ) );
+ ObjectType eParentObjectType = ObjectIdentifier::getObjectType( aParentParticel );
+ eObjectType = eParentObjectType;
+ if( eObjectType == OBJECTTYPE_DATA_POINT )
+ nIndex = ObjectIdentifier::getIndexFromParticleOrCID( aParentParticel );
+ }
+
+ if( eObjectType == OBJECTTYPE_DATA_POINT || eObjectType == OBJECTTYPE_DATA_LABEL )
+ {
+ // Data Point
+ fillRangesForDataPoint( xDataSeries, nIndex );
+ return;
+ }
+ else if( eObjectType == OBJECTTYPE_DATA_ERRORS_X ||
+ eObjectType == OBJECTTYPE_DATA_ERRORS_Y ||
+ eObjectType == OBJECTTYPE_DATA_ERRORS_Z )
+ {
+ // select error bar ranges, or data series, if the style is
+ // not set to FROM_DATA
+ fillRangesForErrorBars( ObjectIdentifier::getObjectPropertySet( aCID, m_xChartModel ), xDataSeries );
+ return;
+ }
+ else if( xDataSeries.is() )
+ {
+ // Data Series
+ fillRangesForDataSeries( xDataSeries );
+ return;
+ }
+ else if( eObjectType == OBJECTTYPE_AXIS )
+ {
+ // Axis (Categories)
+ Reference< chart2::XAxis > xAxis( ObjectIdentifier::getObjectPropertySet( aCID, m_xChartModel ), uno::UNO_QUERY );
+ if( xAxis.is())
+ {
+ fillRangesForCategories( xAxis );
+ return;
+ }
+ }
+ else if( eObjectType == OBJECTTYPE_PAGE
+ || eObjectType == OBJECTTYPE_DIAGRAM
+ || eObjectType == OBJECTTYPE_DIAGRAM_WALL
+ || eObjectType == OBJECTTYPE_DIAGRAM_FLOOR
+ )
+ {
+ // Diagram
+ rtl::Reference< ::chart::Diagram > xDia( ObjectIdentifier::getDiagramForCID( aCID, m_xChartModel ) );
+ if( xDia.is())
+ {
+ fillRangesForDiagram( xDia );
+ return;
+ }
+ }
+ }
+ }
+ else if ( rType == cppu::UnoType< drawing::XShape >::get() )
+ {
+ // #i12587# support for shapes in chart
+ Reference< drawing::XShape > xShape;
+ aSelection >>= xShape;
+ if ( xShape.is() )
+ {
+ return;
+ }
+ }
+ else
+ {
+ //if nothing is selected select all ranges
+ fillRangesForDiagram( m_xChartModel->getFirstChartDiagram() );
+ return;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void RangeHighlighter::fillRangesForDiagram( const rtl::Reference< Diagram > & xDiagram )
+{
+ Sequence< OUString > aSelectedRanges( DataSourceHelper::getUsedDataRanges( xDiagram ));
+ m_aSelectedRanges.realloc( aSelectedRanges.getLength());
+ auto pSelectedRanges = m_aSelectedRanges.getArray();
+ // @todo: merge ranges
+ for( sal_Int32 i=0; i<aSelectedRanges.getLength(); ++i )
+ {
+ pSelectedRanges[i].RangeRepresentation = aSelectedRanges[i];
+ pSelectedRanges[i].Index = -1;
+ pSelectedRanges[i].PreferredColor = sal_Int32(defaultPreferredColor);
+ pSelectedRanges[i].AllowMerginigWithOtherRanges = true;
+ }
+}
+
+void RangeHighlighter::fillRangesForDataSeries( const uno::Reference< chart2::XDataSeries > & xSeries )
+{
+ Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
+ if( xSource.is())
+ {
+ lcl_fillRanges( m_aSelectedRanges,
+ ::chart::DataSourceHelper::getRangesFromDataSource( xSource ),
+ defaultPreferredColor );
+ }
+}
+
+void RangeHighlighter::fillRangesForErrorBars(
+ const uno::Reference< beans::XPropertySet > & xErrorBar,
+ const uno::Reference< chart2::XDataSeries > & xSeries )
+{
+ // only show error bar ranges, if the style is set to FROM_DATA
+ bool bUsesRangesAsErrorBars = false;
+ try
+ {
+ sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
+ bUsesRangesAsErrorBars =
+ ( xErrorBar.is() &&
+ (xErrorBar->getPropertyValue( "ErrorBarStyle") >>= nStyle) &&
+ nStyle == css::chart::ErrorBarStyle::FROM_DATA );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ if( bUsesRangesAsErrorBars )
+ {
+ Reference< chart2::data::XDataSource > xSource( xErrorBar, uno::UNO_QUERY );
+ if( xSource.is())
+ {
+ lcl_fillRanges( m_aSelectedRanges,
+ ::chart::DataSourceHelper::getRangesFromDataSource( xSource ),
+ defaultPreferredColor );
+ }
+ }
+ else
+ {
+ fillRangesForDataSeries( xSeries );
+ }
+}
+
+void RangeHighlighter::fillRangesForCategories( const Reference< chart2::XAxis > & xAxis )
+{
+ if( ! xAxis.is())
+ return;
+ chart2::ScaleData aData( xAxis->getScaleData());
+ lcl_fillRanges( m_aSelectedRanges,
+ DataSourceHelper::getRangesFromLabeledDataSequence( aData.Categories ),
+ defaultPreferredColor );
+}
+
+void RangeHighlighter::fillRangesForDataPoint( const rtl::Reference< DataSeries > & xDataSeries, sal_Int32 nIndex )
+{
+ if( !xDataSeries.is())
+ return;
+
+ Color nPreferredColor = defaultPreferredColor;
+ std::vector< chart2::data::HighlightedRange > aHilightedRanges;
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aLSeqSeq( xDataSeries->getDataSequences2());
+ for( uno::Reference< chart2::data::XLabeledDataSequence > const & labelDataSeq : aLSeqSeq )
+ {
+ Reference< chart2::data::XDataSequence > xLabel( labelDataSeq->getLabel());
+ Reference< chart2::data::XDataSequence > xValues( labelDataSeq->getValues());
+
+ if( xLabel.is())
+ aHilightedRanges.emplace_back(
+ xLabel->getSourceRangeRepresentation(),
+ -1,
+ sal_Int32(nPreferredColor),
+ false );
+
+ sal_Int32 nUnhiddenIndex = DataSeriesHelper::translateIndexFromHiddenToFullSequence( nIndex, xValues, !m_bIncludeHiddenCells );
+ if( xValues.is())
+ aHilightedRanges.emplace_back(
+ xValues->getSourceRangeRepresentation(),
+ nUnhiddenIndex,
+ sal_Int32(nPreferredColor),
+ false );
+ }
+ m_aSelectedRanges = comphelper::containerToSequence( aHilightedRanges );
+}
+
+void SAL_CALL RangeHighlighter::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener )
+{
+ if(!xListener.is())
+ return;
+
+ if( m_nAddedListenerCount == 0 )
+ startListening();
+ std::unique_lock g(m_aMutex);
+ maSelectionChangeListeners.addInterface( g, xListener);
+ ++m_nAddedListenerCount;
+
+ //bring the new listener up to the current state
+ lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) );
+ xListener->selectionChanged( aEvent );
+}
+
+void SAL_CALL RangeHighlighter::removeSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ maSelectionChangeListeners.removeInterface( g, xListener );
+ --m_nAddedListenerCount;
+ if( m_nAddedListenerCount == 0 )
+ stopListening();
+}
+
+// ____ XSelectionChangeListener ____
+void SAL_CALL RangeHighlighter::selectionChanged( const lang::EventObject& /*aEvent*/ )
+{
+ determineRanges();
+
+ // determine ranges of selected view objects
+ // if changed, fire an event
+ fireSelectionEvent();
+}
+
+void RangeHighlighter::fireSelectionEvent()
+{
+ std::unique_lock g(m_aMutex);
+ if( maSelectionChangeListeners.getLength(g) )
+ {
+ lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) );
+ maSelectionChangeListeners.forEach(g,
+ [&aEvent](const css::uno::Reference<view::XSelectionChangeListener>& xListener)
+ {
+ xListener->selectionChanged(aEvent);
+ }
+ );
+ }
+}
+
+void SAL_CALL RangeHighlighter::disposing( const lang::EventObject& Source )
+{
+ if( Source.Source == m_xSelectionSupplier )
+ {
+ m_xSelectionSupplier.clear();
+ m_aSelectedRanges.realloc( 0 );
+ fireSelectionEvent();
+ }
+}
+
+void RangeHighlighter::startListening()
+{
+ if( m_xSelectionSupplier.is())
+ {
+ if( ! m_xListener.is())
+ {
+ m_xListener.set( new WeakSelectionChangeListenerAdapter( this ));
+ determineRanges();
+ }
+ m_xSelectionSupplier->addSelectionChangeListener( m_xListener );
+ }
+}
+
+void RangeHighlighter::stopListening()
+{
+ if( m_xSelectionSupplier.is() && m_xListener.is())
+ {
+ m_xSelectionSupplier->removeSelectionChangeListener( m_xListener );
+ m_xListener.clear();
+ }
+}
+
+// ____ WeakComponentImplHelperBase ____
+// is called when dispose() is called at this component
+void RangeHighlighter::disposing(std::unique_lock<std::mutex>&)
+{
+ // @todo: remove listener. Currently the controller shows an assertion
+ // because it is already disposed
+// stopListening();
+ m_xListener.clear();
+ m_xSelectionSupplier.clear();
+ m_nAddedListenerCount = 0;
+ m_aSelectedRanges.realloc( 0 );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ReferenceSizeProvider.cxx b/chart2/source/tools/ReferenceSizeProvider.cxx
new file mode 100644
index 0000000000..b1ca0b429a
--- /dev/null
+++ b/chart2/source/tools/ReferenceSizeProvider.cxx
@@ -0,0 +1,340 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ReferenceSizeProvider.hxx>
+#include <RelativeSizeHelper.hxx>
+#include <ChartModelHelper.hxx>
+#include <ChartModel.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesProperties.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <Legend.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart::DataSeriesProperties;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+ReferenceSizeProvider::ReferenceSizeProvider(
+ awt::Size aPageSize,
+ const rtl::Reference<::chart::ChartModel> & xChartDoc ) :
+ m_aPageSize( aPageSize ),
+ m_xChartDoc( xChartDoc ),
+ m_bUseAutoScale( getAutoResizeState( xChartDoc ) == AUTO_RESIZE_YES )
+{}
+
+void ReferenceSizeProvider::impl_setValuesAtTitled(
+ const Reference< XTitled > & xTitled )
+{
+ if( xTitled.is())
+ {
+ Reference< XTitle > xTitle( xTitled->getTitleObject());
+ if( xTitle.is())
+ setValuesAtTitle( xTitle );
+ }
+}
+
+void ReferenceSizeProvider::setValuesAtTitle(
+ const Reference< XTitle > & xTitle )
+{
+ try
+ {
+ Reference< beans::XPropertySet > xTitleProp( xTitle, uno::UNO_QUERY_THROW );
+ awt::Size aOldRefSize;
+ bool bHasOldRefSize(
+ xTitleProp->getPropertyValue( "ReferencePageSize") >>= aOldRefSize );
+
+ // set from auto-resize on to off -> adapt font sizes at XFormattedStrings
+ if( bHasOldRefSize && ! useAutoScale())
+ {
+ const uno::Sequence< uno::Reference< XFormattedString > > aStrSeq(
+ xTitle->getText());
+ for( uno::Reference< XFormattedString > const & formattedStr : aStrSeq )
+ {
+ RelativeSizeHelper::adaptFontSizes(
+ Reference< beans::XPropertySet >( formattedStr, uno::UNO_QUERY ),
+ aOldRefSize, getPageSize());
+ }
+ }
+
+ setValuesAtPropertySet( xTitleProp, /* bAdaptFontSizes = */ false );
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ReferenceSizeProvider::setValuesAtAllDataSeries()
+{
+ rtl::Reference< Diagram > xDiagram( m_xChartDoc->getFirstChartDiagram());
+ if (!xDiagram)
+ return;
+
+ // DataSeries/Points
+ std::vector< rtl::Reference< DataSeries > > aSeries =
+ xDiagram->getDataSeries();
+
+ for (auto const& elem : aSeries)
+ {
+ // data points
+ Sequence< sal_Int32 > aPointIndexes;
+ try
+ {
+ // "AttributedDataPoints"
+ if( elem->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS) >>= aPointIndexes )
+ {
+ for( sal_Int32 idx : std::as_const(aPointIndexes) )
+ setValuesAtPropertySet(
+ elem->getDataPointByIndex( idx ) );
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ //it is important to correct the datapoint properties first as they do reference the series properties
+ setValuesAtPropertySet( elem );
+ }
+}
+
+void ReferenceSizeProvider::setValuesAtPropertySet(
+ const Reference< beans::XPropertySet > & xProp,
+ bool bAdaptFontSizes /* = true */ )
+{
+ if( ! xProp.is())
+ return;
+
+ static constexpr OUString aRefSizeName = u"ReferencePageSize"_ustr;
+
+ try
+ {
+ awt::Size aRefSize( getPageSize() );
+ awt::Size aOldRefSize;
+ bool bHasOldRefSize( xProp->getPropertyValue( aRefSizeName ) >>= aOldRefSize );
+
+ if( useAutoScale())
+ {
+ if( ! bHasOldRefSize )
+ xProp->setPropertyValue( aRefSizeName, uno::Any( aRefSize ));
+ }
+ else
+ {
+ if( bHasOldRefSize )
+ {
+ xProp->setPropertyValue( aRefSizeName, uno::Any());
+
+ // adapt font sizes
+ if( bAdaptFontSizes )
+ RelativeSizeHelper::adaptFontSizes( xProp, aOldRefSize, aRefSize );
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void ReferenceSizeProvider::getAutoResizeFromPropSet(
+ const Reference< beans::XPropertySet > & xProp,
+ ReferenceSizeProvider::AutoResizeState & rInOutState )
+{
+ AutoResizeState eSingleState = AUTO_RESIZE_UNKNOWN;
+
+ if( xProp.is())
+ {
+ try
+ {
+ if( xProp->getPropertyValue( "ReferencePageSize" ).hasValue())
+ eSingleState = AUTO_RESIZE_YES;
+ else
+ eSingleState = AUTO_RESIZE_NO;
+ }
+ catch (const uno::Exception&)
+ {
+ // unknown property -> state stays unknown
+ }
+ }
+
+ // current state unknown => nothing changes. Otherwise if current state
+ // differs from state so far, we have an ambiguity
+ if( rInOutState == AUTO_RESIZE_UNKNOWN )
+ {
+ rInOutState = eSingleState;
+ }
+ else if( eSingleState != AUTO_RESIZE_UNKNOWN &&
+ eSingleState != rInOutState )
+ {
+ rInOutState = AUTO_RESIZE_AMBIGUOUS;
+ }
+}
+
+void ReferenceSizeProvider::impl_getAutoResizeFromTitled(
+ const Reference< XTitled > & xTitled,
+ ReferenceSizeProvider::AutoResizeState & rInOutState )
+{
+ if( xTitled.is())
+ {
+ Reference< beans::XPropertySet > xProp( xTitled->getTitleObject(), uno::UNO_QUERY );
+ if( xProp.is())
+ getAutoResizeFromPropSet( xProp, rInOutState );
+ }
+}
+
+/** Retrieves the state auto-resize from all objects that support this
+ feature. If all objects return the same state, AUTO_RESIZE_YES or
+ AUTO_RESIZE_NO is returned.
+
+ If no object supporting the feature is found, AUTO_RESIZE_UNKNOWN is
+ returned. If there are multiple objects, some with state YES and some
+ with state NO, AUTO_RESIZE_AMBIGUOUS is returned.
+*/
+ReferenceSizeProvider::AutoResizeState ReferenceSizeProvider::getAutoResizeState(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc )
+{
+ AutoResizeState eResult = AUTO_RESIZE_UNKNOWN;
+
+ // Main Title
+ if( xChartDoc.is())
+ impl_getAutoResizeFromTitled( xChartDoc, eResult );
+ if( eResult == AUTO_RESIZE_AMBIGUOUS )
+ return eResult;
+
+ // diagram is needed by the rest of the objects
+ rtl::Reference< Diagram > xDiagram = xChartDoc->getFirstChartDiagram();
+ if( ! xDiagram.is())
+ return eResult;
+
+ // Sub Title
+ if( xDiagram.is())
+ impl_getAutoResizeFromTitled( xDiagram, eResult );
+ if( eResult == AUTO_RESIZE_AMBIGUOUS )
+ return eResult;
+
+ // Legend
+ rtl::Reference< Legend > xLegend( xDiagram->getLegend2() );
+ if( xLegend.is())
+ getAutoResizeFromPropSet( xLegend, eResult );
+ if( eResult == AUTO_RESIZE_AMBIGUOUS )
+ return eResult;
+
+ // Axes (incl. Axis Titles)
+ const std::vector< rtl::Reference< Axis > > aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
+ for( rtl::Reference< Axis > const & axis : aAxes )
+ {
+ getAutoResizeFromPropSet( axis, eResult );
+ impl_getAutoResizeFromTitled( axis, eResult );
+ if( eResult == AUTO_RESIZE_AMBIGUOUS )
+ return eResult;
+ }
+
+ // DataSeries/Points
+ std::vector< rtl::Reference< DataSeries > > aSeries =
+ xDiagram->getDataSeries();
+
+ for (auto const& elem : aSeries)
+ {
+ getAutoResizeFromPropSet( elem, eResult );
+ if( eResult == AUTO_RESIZE_AMBIGUOUS )
+ return eResult;
+
+ // data points
+ Sequence< sal_Int32 > aPointIndexes;
+ try
+ {
+ // "AttributedDataPoints"
+ if( elem->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS) >>= aPointIndexes )
+ {
+ for( sal_Int32 idx : std::as_const(aPointIndexes) )
+ {
+ getAutoResizeFromPropSet(
+ elem->getDataPointByIndex( idx ), eResult );
+ if( eResult == AUTO_RESIZE_AMBIGUOUS )
+ return eResult;
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return eResult;
+}
+
+void ReferenceSizeProvider::toggleAutoResizeState()
+{
+ setAutoResizeState( m_bUseAutoScale ? AUTO_RESIZE_NO : AUTO_RESIZE_YES );
+}
+
+/** sets the auto-resize at all objects that support this feature for text.
+ eNewState must be either AUTO_RESIZE_YES or AUTO_RESIZE_NO
+*/
+void ReferenceSizeProvider::setAutoResizeState( ReferenceSizeProvider::AutoResizeState eNewState )
+{
+ m_bUseAutoScale = (eNewState == AUTO_RESIZE_YES);
+
+ // Main Title
+ impl_setValuesAtTitled( m_xChartDoc );
+
+ // diagram is needed by the rest of the objects
+ rtl::Reference< Diagram > xDiagram = m_xChartDoc->getFirstChartDiagram();
+ if( ! xDiagram.is())
+ return;
+
+ // Sub Title
+ impl_setValuesAtTitled( xDiagram );
+
+ // Legend
+ rtl::Reference< Legend > xLegend( xDiagram->getLegend2() );
+ if( xLegend.is())
+ setValuesAtPropertySet( xLegend );
+
+ // Axes (incl. Axis Titles)
+ const std::vector< rtl::Reference< Axis > > aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
+ for( rtl::Reference< Axis > const & axis : aAxes )
+ {
+ setValuesAtPropertySet( axis );
+ impl_setValuesAtTitled( axis );
+ }
+
+ // DataSeries/Points
+ setValuesAtAllDataSeries();
+
+ // recalculate new state (in case it stays unknown or is ambiguous
+ m_bUseAutoScale = (getAutoResizeState( m_xChartDoc ) == AUTO_RESIZE_YES);
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/RegressionCurveCalculator.cxx b/chart2/source/tools/RegressionCurveCalculator.cxx
new file mode 100644
index 0000000000..8f22f9834b
--- /dev/null
+++ b/chart2/source/tools/RegressionCurveCalculator.cxx
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RegressionCurveCalculator.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include <rtl/math.hxx>
+
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+
+#include <comphelper/numbers.hxx>
+#include <comphelper/extract.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+RegressionCurveCalculator::RegressionCurveCalculator()
+ : m_fCorrelationCoefficient(std::numeric_limits<double>::quiet_NaN())
+ , mDegree(2)
+ , mForceIntercept(false)
+ , mInterceptValue(std::numeric_limits<double>::quiet_NaN())
+ , mPeriod(2)
+ , mXName("x")
+ , mYName("f(x)")
+ , mnMovingType(0)
+{
+}
+
+RegressionCurveCalculator::~RegressionCurveCalculator()
+{}
+
+bool RegressionCurveCalculator::isLinearScaling(
+ const Reference< chart2::XScaling > & xScaling )
+{
+ // no scaling means linear
+ if( !xScaling.is())
+ return true;
+ uno::Reference< lang::XServiceName > xServiceName( xScaling, uno::UNO_QUERY );
+ return xServiceName.is() && xServiceName->getServiceName() == "com.sun.star.chart2.LinearScaling";
+}
+
+bool RegressionCurveCalculator::isLogarithmicScaling(
+ const Reference< chart2::XScaling > & xScaling )
+{
+ uno::Reference< lang::XServiceName > xServiceName( xScaling, uno::UNO_QUERY );
+ return xServiceName.is() && xServiceName->getServiceName() == "com.sun.star.chart2.LogarithmicScaling";
+}
+
+void RegressionCurveCalculator::setRegressionProperties(
+ sal_Int32 aDegree,
+ sal_Bool aForceIntercept,
+ double aInterceptValue,
+ sal_Int32 aPeriod,
+ sal_Int32 nMovingType )
+{
+ if( aPeriod < 0 )
+ throw lang::IllegalArgumentException("aPeriod may not be < 0", static_cast<cppu::OWeakObject*>(this), 3);
+ mDegree = aDegree;
+ mForceIntercept = aForceIntercept;
+ mInterceptValue = aInterceptValue;
+ mPeriod = aPeriod;
+ mnMovingType = nMovingType;
+}
+
+OUString RegressionCurveCalculator::getFormattedString(
+ const Reference< util::XNumberFormatter >& xNumFormatter,
+ sal_Int32 nNumberFormatKey,
+ double fNumber, const sal_Int32* pStringLength /* = nullptr */ )
+{
+ if ( pStringLength && *pStringLength <= 0 )
+ return "###";
+ OUString aResult;
+
+ if( xNumFormatter.is() )
+ {
+ bool bStandard = ::cppu::any2bool( ::comphelper::getNumberFormatProperty( xNumFormatter, nNumberFormatKey, "StandardFormat" ) );
+ if( pStringLength && bStandard )
+ { // round fNumber to *pStringLength characters
+ const sal_Int32 nMinDigit = 6; // minimum significant digits for General format
+ sal_Int32 nSignificantDigit = ( *pStringLength <= nMinDigit ? nMinDigit : *pStringLength );
+ aResult = ::rtl::math::doubleToUString( fNumber, rtl_math_StringFormat_G1, nSignificantDigit, '.', true );
+ // count characters different from significant digits (decimal separator, scientific notation)
+ sal_Int32 nExtraChar = aResult.getLength() - *pStringLength;
+ if ( nExtraChar > 0 && *pStringLength > nMinDigit )
+ {
+ nSignificantDigit = *pStringLength - nExtraChar;
+ if ( nSignificantDigit < nMinDigit )
+ nSignificantDigit = nMinDigit;
+ aResult = ::rtl::math::doubleToUString( fNumber, rtl_math_StringFormat_G1, nSignificantDigit, '.', true );
+ }
+ fNumber = ::rtl::math::stringToDouble( aResult, '.', ',' );
+ }
+ aResult = xNumFormatter->convertNumberToString( nNumberFormatKey, fNumber );
+ }
+ else
+ {
+ sal_Int32 nStringLength = 4; // default length
+ if ( pStringLength )
+ nStringLength = *pStringLength;
+ aResult = ::rtl::math::doubleToUString( fNumber, rtl_math_StringFormat_G1, nStringLength, '.', true );
+ }
+ return aResult;
+}
+
+Sequence< geometry::RealPoint2D > SAL_CALL RegressionCurveCalculator::getCurveValues(
+ double min, double max, ::sal_Int32 nPointCount,
+ const Reference< chart2::XScaling >& xScalingX,
+ const Reference< chart2::XScaling >& /* xScalingY */,
+ sal_Bool /* bMaySkipPointsInCalculation */ )
+{
+ if( nPointCount < 2 )
+ throw lang::IllegalArgumentException("too few points", static_cast<cppu::OWeakObject*>(this), 2);
+
+ // determine if scaling and inverse scaling for x-values work
+ bool bDoXScaling( xScalingX.is());
+ uno::Reference< chart2::XScaling > xInverseScaling;
+ if( bDoXScaling )
+ xInverseScaling.set( xScalingX->getInverseScaling());
+ bDoXScaling = bDoXScaling && xInverseScaling.is();
+
+ Sequence< geometry::RealPoint2D > aResult( nPointCount );
+ auto pResult = aResult.getArray();
+
+ double fMin( min );
+ double fFact = (max - min) / double(nPointCount-1);
+
+ if( bDoXScaling )
+ {
+ fMin = xScalingX->doScaling( min );
+ fFact = (xScalingX->doScaling( max ) - fMin) / double(nPointCount-1);
+ }
+
+ for(sal_Int32 nP=0; nP<nPointCount; nP++)
+ {
+ double x = fMin + nP * fFact;
+ if( bDoXScaling )
+ x = xInverseScaling->doScaling( x );
+ pResult[nP].X = x;
+ pResult[nP].Y = getCurveValue( x );
+ }
+
+ return aResult;
+}
+
+double SAL_CALL RegressionCurveCalculator::getCorrelationCoefficient()
+{
+ return m_fCorrelationCoefficient;
+}
+
+OUString SAL_CALL RegressionCurveCalculator::getRepresentation()
+{
+ return ImplGetRepresentation( Reference< util::XNumberFormatter >(), 0 );
+}
+
+OUString SAL_CALL RegressionCurveCalculator::getFormattedRepresentation(
+ const Reference< util::XNumberFormatsSupplier > & xNumFmtSupplier,
+ sal_Int32 nNumberFormatKey, sal_Int32 nFormulaLength )
+{
+ // create and prepare a number formatter
+ if( !xNumFmtSupplier.is())
+ return getRepresentation();
+ Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext(), uno::UNO_SET_THROW );
+ Reference< util::XNumberFormatter > xNumFormatter( util::NumberFormatter::create(xContext), uno::UNO_QUERY_THROW );
+ xNumFormatter->attachNumberFormatsSupplier( xNumFmtSupplier );
+
+ if ( nFormulaLength > 0 )
+ return ImplGetRepresentation( xNumFormatter, nNumberFormatKey, &nFormulaLength );
+ return ImplGetRepresentation( xNumFormatter, nNumberFormatKey );
+}
+
+void RegressionCurveCalculator::addStringToEquation(
+ OUStringBuffer& aStrEquation, sal_Int32& nLineLength, OUStringBuffer const & aAddString, const sal_Int32* pMaxWidth)
+{
+ if ( pMaxWidth && ( nLineLength + aAddString.getLength() > *pMaxWidth ) )
+ { // wrap line
+ aStrEquation.append( "\n " ); // start new line with a blank
+ nLineLength = 1;
+ }
+ aStrEquation.append( aAddString );
+ nLineLength += aAddString.getLength();
+}
+
+void SAL_CALL RegressionCurveCalculator::setXYNames( const OUString& aXName, const OUString& aYName )
+{
+ if ( aXName.isEmpty() )
+ mXName = OUString ("x");
+ else
+ mXName = aXName;
+ if ( aYName.isEmpty() )
+ mYName = OUString ("f(x)");
+ else
+ mYName = aYName;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/RegressionCurveHelper.cxx b/chart2/source/tools/RegressionCurveHelper.cxx
new file mode 100644
index 0000000000..0277e61a44
--- /dev/null
+++ b/chart2/source/tools/RegressionCurveHelper.cxx
@@ -0,0 +1,917 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cstddef>
+
+#include <RegressionCurveHelper.hxx>
+#include <MeanValueRegressionCurveCalculator.hxx>
+#include <LinearRegressionCurveCalculator.hxx>
+#include <PolynomialRegressionCurveCalculator.hxx>
+#include <MovingAverageRegressionCurveCalculator.hxx>
+#include <LogarithmicRegressionCurveCalculator.hxx>
+#include <ExponentialRegressionCurveCalculator.hxx>
+#include <PotentialRegressionCurveCalculator.hxx>
+#include <CommonConverters.hxx>
+#include <RegressionCurveModel.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <DataSeries.hxx>
+#include <Diagram.hxx>
+#include <ResId.hxx>
+#include <strings.hrc>
+#include <DiagramHelper.hxx>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/XRegressionCurveCalculator.hpp>
+#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/chart2/data/XDataSource.hpp>
+#include <o3tl/safeint.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/property.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::lang::XServiceName;
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Exception;
+
+namespace
+{
+OUString lcl_getServiceNameForType(SvxChartRegress eType)
+{
+ OUString aServiceName;
+ switch( eType )
+ {
+ case SvxChartRegress::Linear:
+ aServiceName = "com.sun.star.chart2.LinearRegressionCurve";
+ break;
+ case SvxChartRegress::Log:
+ aServiceName = "com.sun.star.chart2.LogarithmicRegressionCurve";
+ break;
+ case SvxChartRegress::Exp:
+ aServiceName = "com.sun.star.chart2.ExponentialRegressionCurve";
+ break;
+ case SvxChartRegress::Power:
+ aServiceName = "com.sun.star.chart2.PotentialRegressionCurve";
+ break;
+ case SvxChartRegress::Polynomial:
+ aServiceName = "com.sun.star.chart2.PolynomialRegressionCurve";
+ break;
+ case SvxChartRegress::MovingAverage:
+ aServiceName = "com.sun.star.chart2.MovingAverageRegressionCurve";
+ break;
+ default:
+ OSL_FAIL("unknown regression curve type - use linear instead");
+ aServiceName = "com.sun.star.chart2.LinearRegressionCurve";
+ break;
+ }
+ return aServiceName;
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+rtl::Reference< RegressionCurveModel > RegressionCurveHelper::createMeanValueLine()
+{
+ return new MeanValueRegressionCurve;
+}
+
+rtl::Reference< RegressionCurveModel > RegressionCurveHelper::createRegressionCurveByServiceName(
+ std::u16string_view aServiceName )
+{
+ rtl::Reference< RegressionCurveModel > xResult;
+
+ // todo: use factory methods with service name
+ if( aServiceName == u"com.sun.star.chart2.LinearRegressionCurve" )
+ {
+ xResult.set( new LinearRegressionCurve );
+ }
+ else if( aServiceName == u"com.sun.star.chart2.LogarithmicRegressionCurve" )
+ {
+ xResult.set( new LogarithmicRegressionCurve );
+ }
+ else if( aServiceName == u"com.sun.star.chart2.ExponentialRegressionCurve" )
+ {
+ xResult.set( new ExponentialRegressionCurve );
+ }
+ else if( aServiceName == u"com.sun.star.chart2.PotentialRegressionCurve" )
+ {
+ xResult.set( new PotentialRegressionCurve );
+ }
+ else if( aServiceName == u"com.sun.star.chart2.PolynomialRegressionCurve" )
+ {
+ xResult.set( new PolynomialRegressionCurve );
+ }
+ else if( aServiceName == u"com.sun.star.chart2.MovingAverageRegressionCurve" )
+ {
+ xResult.set( new MovingAverageRegressionCurve );
+ }
+
+ return xResult;
+}
+
+rtl::Reference< RegressionCurveCalculator > RegressionCurveHelper::createRegressionCurveCalculatorByServiceName(
+ std::u16string_view aServiceName )
+{
+ rtl::Reference< RegressionCurveCalculator > xResult;
+
+ // todo: use factory methods with service name
+ if( aServiceName == u"com.sun.star.chart2.MeanValueRegressionCurve" )
+ {
+ xResult.set( new MeanValueRegressionCurveCalculator() );
+ }
+ if( aServiceName == u"com.sun.star.chart2.LinearRegressionCurve" )
+ {
+ xResult.set( new LinearRegressionCurveCalculator() );
+ }
+ else if( aServiceName == u"com.sun.star.chart2.LogarithmicRegressionCurve" )
+ {
+ xResult.set( new LogarithmicRegressionCurveCalculator() );
+ }
+ else if( aServiceName == u"com.sun.star.chart2.ExponentialRegressionCurve" )
+ {
+ xResult.set( new ExponentialRegressionCurveCalculator() );
+ }
+ else if( aServiceName == u"com.sun.star.chart2.PotentialRegressionCurve" )
+ {
+ xResult.set( new PotentialRegressionCurveCalculator() );
+ }
+ else if( aServiceName == u"com.sun.star.chart2.PolynomialRegressionCurve" )
+ {
+ xResult.set( new PolynomialRegressionCurveCalculator() );
+ }
+ else if( aServiceName == u"com.sun.star.chart2.MovingAverageRegressionCurve" )
+ {
+ xResult.set( new MovingAverageRegressionCurveCalculator() );
+ }
+
+ return xResult;
+}
+
+void RegressionCurveHelper::initializeCurveCalculator(
+ const Reference< XRegressionCurveCalculator > & xOutCurveCalculator,
+ const Reference< data::XDataSource > & xSource,
+ bool bUseXValuesIfAvailable /* = true */ )
+{
+ if( ! (xOutCurveCalculator.is() &&
+ xSource.is() ))
+ return;
+
+ Sequence< double > aXValues, aYValues;
+ bool bXValuesFound = false, bYValuesFound = false;
+
+ Sequence< Reference< data::XLabeledDataSequence > > aDataSeqs( xSource->getDataSequences());
+ sal_Int32 i = 0;
+ for( i=0;
+ ! (bXValuesFound && bYValuesFound) && i<aDataSeqs.getLength();
+ ++i )
+ {
+ try
+ {
+ Reference< data::XDataSequence > xSeq( aDataSeqs[i]->getValues());
+ Reference< XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
+ OUString aRole;
+ if( xProp->getPropertyValue( "Role" ) >>= aRole )
+ {
+ if( bUseXValuesIfAvailable && !bXValuesFound && aRole == "values-x" )
+ {
+ aXValues = DataSequenceToDoubleSequence( xSeq );
+ bXValuesFound = true;
+ }
+ else if( !bYValuesFound && aRole == "values-y" )
+ {
+ aYValues = DataSequenceToDoubleSequence( xSeq );
+ bYValuesFound = true;
+ }
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ if( ! bXValuesFound &&
+ bYValuesFound )
+ {
+ // initialize with 1, 2, ...
+ //first category (index 0) matches with real number 1.0
+ aXValues.realloc( aYValues.getLength());
+ auto pXValues = aXValues.getArray();
+ for( i=0; i<aXValues.getLength(); ++i )
+ pXValues[i] = i+1;
+ bXValuesFound = true;
+ }
+
+ if( bXValuesFound && bYValuesFound &&
+ aXValues.hasElements() &&
+ aYValues.hasElements() )
+ xOutCurveCalculator->recalculateRegression( aXValues, aYValues );
+}
+
+void RegressionCurveHelper::initializeCurveCalculator(
+ const Reference< XRegressionCurveCalculator > & xOutCurveCalculator,
+ const rtl::Reference< ::chart::DataSeries > & xSeries,
+ const rtl::Reference<::chart::ChartModel> & xModel )
+{
+ sal_Int32 nAxisType = ChartTypeHelper::getAxisType(
+ ChartModelHelper::getChartTypeOfSeries( xModel, xSeries ), 0 ); // x-axis
+
+ initializeCurveCalculator( xOutCurveCalculator,
+ xSeries,
+ (nAxisType == AxisType::REALNUMBER) );
+}
+
+bool RegressionCurveHelper::hasMeanValueLine(
+ const uno::Reference< XRegressionCurveContainer > & xRegCnt )
+{
+ if( !xRegCnt.is())
+ return false;
+
+ try
+ {
+ const uno::Sequence< uno::Reference< XRegressionCurve > > aCurves(
+ xRegCnt->getRegressionCurves());
+ for( uno::Reference< XRegressionCurve > const & curve : aCurves )
+ {
+ if( isMeanValueLine( curve ))
+ return true;
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return false;
+}
+
+bool RegressionCurveHelper::hasMeanValueLine(
+ const rtl::Reference< DataSeries > & xRegCnt )
+{
+ if( !xRegCnt.is())
+ return false;
+
+ try
+ {
+ for( rtl::Reference< RegressionCurveModel > const & curve : xRegCnt->getRegressionCurves2() )
+ {
+ if( isMeanValueLine( curve ))
+ return true;
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return false;
+}
+
+bool RegressionCurveHelper::isMeanValueLine(
+ const uno::Reference< chart2::XRegressionCurve > & xRegCurve )
+{
+ uno::Reference< XServiceName > xServName( xRegCurve, uno::UNO_QUERY );
+ return xServName.is() &&
+ xServName->getServiceName() ==
+ "com.sun.star.chart2.MeanValueRegressionCurve";
+}
+
+bool RegressionCurveHelper::isMeanValueLine(
+ const rtl::Reference< RegressionCurveModel > & xRegCurve )
+{
+ return xRegCurve.is() &&
+ xRegCurve->getServiceName() ==
+ "com.sun.star.chart2.MeanValueRegressionCurve";
+}
+
+rtl::Reference< RegressionCurveModel >
+ RegressionCurveHelper::getMeanValueLine(
+ const uno::Reference< chart2::XRegressionCurveContainer > & xRegCnt )
+{
+ if( xRegCnt.is())
+ {
+ try
+ {
+ const uno::Sequence< uno::Reference< XRegressionCurve > > aCurves(
+ xRegCnt->getRegressionCurves());
+ for( uno::Reference< XRegressionCurve > const & curve : aCurves )
+ {
+ if( isMeanValueLine( curve ))
+ return dynamic_cast<RegressionCurveModel*>(curve.get());
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return nullptr;
+}
+
+rtl::Reference< RegressionCurveModel >
+ RegressionCurveHelper::getMeanValueLine(
+ const rtl::Reference< DataSeries > & xRegCnt )
+{
+ if( xRegCnt.is())
+ {
+ try
+ {
+ for( rtl::Reference< RegressionCurveModel > const & curve : xRegCnt->getRegressionCurves2() )
+ {
+ if( isMeanValueLine( curve ))
+ return curve;
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return nullptr;
+}
+
+void RegressionCurveHelper::addMeanValueLine(
+ uno::Reference< XRegressionCurveContainer > const & xRegCnt,
+ const uno::Reference< XPropertySet > & xSeriesProp )
+{
+ if( !xRegCnt.is() ||
+ ::chart::RegressionCurveHelper::hasMeanValueLine( xRegCnt ) )
+ return;
+
+ // todo: use a valid context
+ uno::Reference< XRegressionCurve > xCurve( createMeanValueLine() );
+ xRegCnt->addRegressionCurve( xCurve );
+
+ if( xSeriesProp.is())
+ {
+ uno::Reference< XPropertySet > xProp( xCurve, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ xProp->setPropertyValue( "LineColor",
+ xSeriesProp->getPropertyValue( "Color"));
+ }
+ }
+}
+
+void RegressionCurveHelper::addMeanValueLine(
+ rtl::Reference< DataSeries > const & xRegCnt,
+ const uno::Reference< XPropertySet > & xSeriesProp )
+{
+ if( !xRegCnt.is() ||
+ ::chart::RegressionCurveHelper::hasMeanValueLine( xRegCnt ) )
+ return;
+
+ // todo: use a valid context
+ rtl::Reference< RegressionCurveModel > xCurve( createMeanValueLine() );
+ xRegCnt->addRegressionCurve( xCurve );
+
+ if( xSeriesProp.is())
+ {
+ xCurve->setPropertyValue( "LineColor",
+ xSeriesProp->getPropertyValue( "Color"));
+ }
+}
+
+void RegressionCurveHelper::removeMeanValueLine(
+ Reference< XRegressionCurveContainer > const & xRegCnt )
+{
+ if( !xRegCnt.is())
+ return;
+
+ try
+ {
+ const Sequence< Reference< XRegressionCurve > > aCurves(
+ xRegCnt->getRegressionCurves());
+ for( Reference< XRegressionCurve > const & curve : aCurves )
+ {
+ if( isMeanValueLine( curve ))
+ {
+ xRegCnt->removeRegressionCurve( curve );
+ // attention: the iterator i has become invalid now
+
+ // note: assume that there is only one mean-value curve
+ // to remove multiple mean-value curves remove the break
+ break;
+ }
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+void RegressionCurveHelper::removeMeanValueLine(
+ rtl::Reference< DataSeries > const & xRegCnt )
+{
+ if( !xRegCnt.is())
+ return;
+
+ try
+ {
+ for( rtl::Reference< RegressionCurveModel > const & curve : xRegCnt->getRegressionCurves2() )
+ {
+ if( isMeanValueLine( curve ))
+ {
+ xRegCnt->removeRegressionCurve( curve );
+ // attention: the iterator i has become invalid now
+
+ // note: assume that there is only one mean-value curve
+ // to remove multiple mean-value curves remove the break
+ break;
+ }
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+rtl::Reference< RegressionCurveModel > RegressionCurveHelper::addRegressionCurve(
+ SvxChartRegress eType,
+ uno::Reference< XRegressionCurveContainer > const & xRegressionCurveContainer,
+ const uno::Reference< beans::XPropertySet >& xPropertySource,
+ const uno::Reference< beans::XPropertySet >& xEquationProperties )
+{
+ rtl::Reference< RegressionCurveModel > xCurve;
+
+ if( !xRegressionCurveContainer.is() )
+ return xCurve;
+
+ if( eType == SvxChartRegress::NONE )
+ {
+ OSL_FAIL("don't create a regression curve of type none");
+ return xCurve;
+ }
+
+ OUString aServiceName( lcl_getServiceNameForType( eType ));
+ if( !aServiceName.isEmpty())
+ {
+ // todo: use a valid context
+ xCurve = createRegressionCurveByServiceName( aServiceName );
+
+ if( xEquationProperties.is())
+ xCurve->setEquationProperties( xEquationProperties );
+
+ if( xPropertySource.is())
+ comphelper::copyProperties( xPropertySource, xCurve );
+ else
+ {
+ uno::Reference< XPropertySet > xSeriesProp( xRegressionCurveContainer, uno::UNO_QUERY );
+ if( xSeriesProp.is())
+ {
+ xCurve->setPropertyValue( "LineColor",
+ xSeriesProp->getPropertyValue( "Color"));
+ }
+ }
+ }
+ xRegressionCurveContainer->addRegressionCurve( xCurve );
+
+ return xCurve;
+}
+
+rtl::Reference< RegressionCurveModel > RegressionCurveHelper::addRegressionCurve(
+ SvxChartRegress eType,
+ rtl::Reference< DataSeries > const & xRegressionCurveContainer,
+ const uno::Reference< beans::XPropertySet >& xPropertySource,
+ const uno::Reference< beans::XPropertySet >& xEquationProperties )
+{
+ rtl::Reference< RegressionCurveModel > xCurve;
+
+ if( !xRegressionCurveContainer.is() )
+ return xCurve;
+
+ if( eType == SvxChartRegress::NONE )
+ {
+ OSL_FAIL("don't create a regression curve of type none");
+ return xCurve;
+ }
+
+ OUString aServiceName( lcl_getServiceNameForType( eType ));
+ if( !aServiceName.isEmpty())
+ {
+ // todo: use a valid context
+ xCurve = createRegressionCurveByServiceName( aServiceName );
+
+ if( xEquationProperties.is())
+ xCurve->setEquationProperties( xEquationProperties );
+
+ if( xPropertySource.is())
+ comphelper::copyProperties( xPropertySource, xCurve );
+ else
+ {
+ xCurve->setPropertyValue( "LineColor",
+ xRegressionCurveContainer->getPropertyValue( "Color"));
+ }
+ }
+ xRegressionCurveContainer->addRegressionCurve( xCurve );
+
+ return xCurve;
+}
+
+/** removes all regression curves that are not of type mean value
+ and returns true, if anything was removed
+ */
+bool RegressionCurveHelper::removeAllExceptMeanValueLine(
+ rtl::Reference< DataSeries > const & xRegCnt )
+{
+ if( !xRegCnt.is())
+ return false;
+
+ bool bRemovedSomething = false;
+ try
+ {
+ std::vector< rtl::Reference< RegressionCurveModel > > aCurvesToDelete;
+ for( rtl::Reference< RegressionCurveModel > const & curve : xRegCnt->getRegressionCurves2() )
+ {
+ if( ! isMeanValueLine( curve ))
+ {
+ aCurvesToDelete.push_back( curve );
+ }
+ }
+
+ for (auto const& curveToDelete : aCurvesToDelete)
+ {
+ xRegCnt->removeRegressionCurve(curveToDelete);
+ bRemovedSomething = true;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return bRemovedSomething;
+}
+
+void RegressionCurveHelper::removeEquations(
+ rtl::Reference< DataSeries > const & xRegCnt )
+{
+ if( !xRegCnt.is())
+ return;
+
+ try
+ {
+ for( rtl::Reference< RegressionCurveModel > const & curve : xRegCnt->getRegressionCurves2() )
+ {
+ if( !isMeanValueLine( curve ) )
+ {
+ uno::Reference< beans::XPropertySet > xEqProp( curve->getEquationProperties() ) ;
+ if( xEqProp.is())
+ {
+ xEqProp->setPropertyValue( "ShowEquation", uno::Any( false ));
+ xEqProp->setPropertyValue( "XName", uno::Any( OUString("x") ));
+ xEqProp->setPropertyValue( "YName", uno::Any( OUString("f(x) ") ));
+ xEqProp->setPropertyValue( "ShowCorrelationCoefficient", uno::Any( false ));
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+rtl::Reference< RegressionCurveModel > RegressionCurveHelper::changeRegressionCurveType(
+ SvxChartRegress eType,
+ uno::Reference< XRegressionCurveContainer > const & xRegressionCurveContainer,
+ uno::Reference< XRegressionCurve > const & xRegressionCurve )
+{
+ xRegressionCurveContainer->removeRegressionCurve( xRegressionCurve );
+ return RegressionCurveHelper::addRegressionCurve(
+ eType,
+ xRegressionCurveContainer,
+ uno::Reference< beans::XPropertySet >( xRegressionCurve, uno::UNO_QUERY ),
+ xRegressionCurve->getEquationProperties());
+}
+
+rtl::Reference< RegressionCurveModel > RegressionCurveHelper::getFirstCurveNotMeanValueLine(
+ const Reference< XRegressionCurveContainer > & xRegCnt )
+{
+ if( !xRegCnt.is())
+ return nullptr;
+
+ try
+ {
+ const uno::Sequence< uno::Reference< chart2::XRegressionCurve > > aCurves(
+ xRegCnt->getRegressionCurves());
+ for( uno::Reference< chart2::XRegressionCurve > const & curve : aCurves )
+ {
+ if( ! isMeanValueLine( curve ))
+ {
+ return dynamic_cast<RegressionCurveModel*>(curve.get());
+ }
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return nullptr;
+}
+
+rtl::Reference< RegressionCurveModel > RegressionCurveHelper::getFirstCurveNotMeanValueLine(
+ const rtl::Reference< DataSeries > & xRegCnt )
+{
+ if( !xRegCnt.is())
+ return nullptr;
+
+ try
+ {
+ for( rtl::Reference< RegressionCurveModel > const & curve : xRegCnt->getRegressionCurves2() )
+ {
+ if( ! isMeanValueLine( curve ))
+ {
+ return curve;
+ }
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return nullptr;
+}
+
+rtl::Reference< RegressionCurveModel > RegressionCurveHelper::getRegressionCurveAtIndex(
+ const rtl::Reference< DataSeries >& xCurveContainer,
+ sal_Int32 aIndex )
+{
+ if( !xCurveContainer.is())
+ return nullptr;
+
+ try
+ {
+ const std::vector< rtl::Reference< RegressionCurveModel > > aCurves(xCurveContainer->getRegressionCurves2());
+ if(0 <= aIndex && o3tl::make_unsigned(aIndex) < aCurves.size())
+ {
+ if(!isMeanValueLine(aCurves[aIndex]))
+ return aCurves[aIndex];
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return nullptr;
+}
+
+SvxChartRegress RegressionCurveHelper::getRegressionType(
+ const Reference< XRegressionCurve > & xCurve )
+{
+ SvxChartRegress eResult = SvxChartRegress::Unknown;
+
+ try
+ {
+ Reference< lang::XServiceName > xServName( xCurve, uno::UNO_QUERY );
+ if( xServName.is())
+ {
+ OUString aServiceName( xServName->getServiceName() );
+
+ if( aServiceName == "com.sun.star.chart2.LinearRegressionCurve" )
+ {
+ eResult = SvxChartRegress::Linear;
+ }
+ else if( aServiceName == "com.sun.star.chart2.LogarithmicRegressionCurve" )
+ {
+ eResult = SvxChartRegress::Log;
+ }
+ else if( aServiceName == "com.sun.star.chart2.ExponentialRegressionCurve" )
+ {
+ eResult = SvxChartRegress::Exp;
+ }
+ else if( aServiceName == "com.sun.star.chart2.PotentialRegressionCurve" )
+ {
+ eResult = SvxChartRegress::Power;
+ }
+ else if( aServiceName == "com.sun.star.chart2.MeanValueRegressionCurve" )
+ {
+ eResult = SvxChartRegress::MeanValue;
+ }
+ else if( aServiceName == "com.sun.star.chart2.PolynomialRegressionCurve" )
+ {
+ eResult = SvxChartRegress::Polynomial;
+ }
+ else if( aServiceName == "com.sun.star.chart2.MovingAverageRegressionCurve" )
+ {
+ eResult = SvxChartRegress::MovingAverage;
+ }
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+
+ return eResult;
+}
+
+SvxChartRegress RegressionCurveHelper::getFirstRegressTypeNotMeanValueLine(
+ const Reference< XRegressionCurveContainer > & xRegCnt )
+{
+ SvxChartRegress eResult = SvxChartRegress::NONE;
+
+ if( xRegCnt.is())
+ {
+ const Sequence< Reference< XRegressionCurve > > aCurves(
+ xRegCnt->getRegressionCurves());
+ for( Reference< XRegressionCurve > const & curve : aCurves )
+ {
+ SvxChartRegress eType = getRegressionType( curve );
+ if( eType != SvxChartRegress::MeanValue &&
+ eType != SvxChartRegress::Unknown )
+ {
+ eResult = eType;
+ break;
+ }
+ }
+ }
+
+ return eResult;
+}
+
+OUString RegressionCurveHelper::getUINameForRegressionCurve( const Reference< XRegressionCurve >& xRegressionCurve )
+{
+ OUString aResult = getRegressionCurveSpecificName(xRegressionCurve);
+ if (aResult.isEmpty())
+ {
+ aResult = getRegressionCurveGenericName(xRegressionCurve);
+ if (!aResult.isEmpty())
+ {
+ aResult += " (%SERIESNAME)";
+ }
+ }
+ return aResult;
+}
+
+OUString RegressionCurveHelper::getRegressionCurveGenericName(const Reference< XRegressionCurve >& xRegressionCurve)
+{
+ OUString aResult;
+ if(!xRegressionCurve.is())
+ return aResult;
+
+ Reference< lang::XServiceName > xServiceName( xRegressionCurve, uno::UNO_QUERY );
+ if(!xServiceName.is())
+ return aResult;
+
+ OUString aServiceName(xServiceName->getServiceName());
+
+ if( aServiceName == "com.sun.star.chart2.MeanValueRegressionCurve" )
+ {
+ aResult = SchResId(STR_REGRESSION_MEAN);
+ }
+ else if( aServiceName == "com.sun.star.chart2.LinearRegressionCurve" )
+ {
+ aResult = SchResId(STR_REGRESSION_LINEAR);
+ }
+ else if( aServiceName == "com.sun.star.chart2.LogarithmicRegressionCurve" )
+ {
+ aResult = SchResId(STR_REGRESSION_LOG);
+ }
+ else if( aServiceName == "com.sun.star.chart2.ExponentialRegressionCurve" )
+ {
+ aResult = SchResId(STR_REGRESSION_EXP);
+ }
+ else if( aServiceName == "com.sun.star.chart2.PotentialRegressionCurve" )
+ {
+ aResult = SchResId(STR_REGRESSION_POWER);
+ }
+ else if( aServiceName == "com.sun.star.chart2.PolynomialRegressionCurve" )
+ {
+ aResult = SchResId(STR_REGRESSION_POLYNOMIAL);
+ }
+ else if( aServiceName == "com.sun.star.chart2.MovingAverageRegressionCurve" )
+ {
+ aResult = SchResId(STR_REGRESSION_MOVING_AVERAGE);
+ }
+ return aResult;
+}
+
+OUString RegressionCurveHelper::getRegressionCurveSpecificName(const Reference< XRegressionCurve >& xRegressionCurve)
+{
+ OUString aResult;
+
+ if(!xRegressionCurve.is())
+ return aResult;
+
+ Reference<XPropertySet> xProperties( xRegressionCurve, uno::UNO_QUERY );
+ if(!xProperties.is())
+ return aResult;
+
+ xProperties->getPropertyValue("CurveName") >>= aResult;
+
+ return aResult;
+}
+
+OUString RegressionCurveHelper::getRegressionCurveName( const Reference< XRegressionCurve >& xRegressionCurve )
+{
+ OUString aResult = getRegressionCurveSpecificName(xRegressionCurve);
+ if (aResult.isEmpty())
+ return getRegressionCurveGenericName(xRegressionCurve);
+ return aResult;
+}
+
+void RegressionCurveHelper::resetEquationPosition(
+ const Reference< chart2::XRegressionCurve > & xCurve )
+{
+ if( !xCurve.is())
+ return;
+
+ try
+ {
+ static constexpr OUString aPosPropertyName( u"RelativePosition"_ustr );
+ Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties()); // since m233: , uno::UNO_SET_THROW );
+ if( xEqProp->getPropertyValue( aPosPropertyName ).hasValue())
+ xEqProp->setPropertyValue( aPosPropertyName, uno::Any());
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+}
+
+sal_Int32 RegressionCurveHelper::getRegressionCurveIndex(
+ const rtl::Reference< DataSeries >& xContainer,
+ const rtl::Reference< RegressionCurveModel >& xCurve )
+{
+ if( xContainer.is())
+ {
+ const std::vector< rtl::Reference< RegressionCurveModel > > & aCurves(
+ xContainer->getRegressionCurves2());
+
+ for( std::size_t i = 0; i < aCurves.size(); ++i )
+ {
+ if( xCurve == aCurves[i] )
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool RegressionCurveHelper::hasEquation( const Reference< chart2::XRegressionCurve > & xCurve )
+{
+ bool bHasEquation = false;
+ if( xCurve.is())
+ {
+ uno::Reference< beans::XPropertySet > xEquationProp( xCurve->getEquationProperties());
+ if( xEquationProp.is())
+ {
+ bool bShowEquation = false;
+ bool bShowCoefficient = false;
+ xEquationProp->getPropertyValue( "ShowEquation") >>= bShowEquation;
+ xEquationProp->getPropertyValue( "ShowCorrelationCoefficient") >>= bShowCoefficient;
+ bHasEquation = bShowEquation || bShowCoefficient;
+ }
+ }
+ return bHasEquation;
+}
+
+bool RegressionCurveHelper::MayHaveCorrelationCoefficient( const Reference< chart2::XRegressionCurve > & xCurve )
+{
+ bool bMayHaveCorrelationCoefficient = true;
+ if( xCurve.is())
+ {
+ uno::Reference< beans::XPropertySet > xEquationProp( xCurve->getEquationProperties() );
+ if( xEquationProp.is() )
+ {
+ xEquationProp->getPropertyValue( "MayHaveCorrelationCoefficient") >>= bMayHaveCorrelationCoefficient;
+ }
+ }
+ return bMayHaveCorrelationCoefficient;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/RegressionCurveModel.cxx b/chart2/source/tools/RegressionCurveModel.cxx
new file mode 100644
index 0000000000..06be003ef1
--- /dev/null
+++ b/chart2/source/tools/RegressionCurveModel.cxx
@@ -0,0 +1,551 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RegressionCurveModel.hxx>
+#include <LinePropertiesHelper.hxx>
+#include <RegressionCurveCalculator.hxx>
+#include <RegressionCurveHelper.hxx>
+#include "RegressionEquation.hxx"
+#include <CloneHelper.hxx>
+#include <PropertyHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+
+namespace
+{
+enum
+{
+ PROPERTY_DEGREE,
+ PROPERTY_PERIOD,
+ PROPERTY_EXTRAPOLATE_FORWARD,
+ PROPERTY_EXTRAPOLATE_BACKWARD,
+ PROPERTY_FORCE_INTERCEPT,
+ PROPERTY_INTERCEPT_VALUE,
+ PROPERTY_CURVE_NAME,
+ PROPERTY_MOVING_AVERAGE_TYPE
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "PolynomialDegree",
+ PROPERTY_DEGREE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND |
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "MovingAveragePeriod",
+ PROPERTY_PERIOD,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND |
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "MovingAverageType",
+ PROPERTY_MOVING_AVERAGE_TYPE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND |
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ExtrapolateForward",
+ PROPERTY_EXTRAPOLATE_FORWARD,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND |
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ExtrapolateBackward",
+ PROPERTY_EXTRAPOLATE_BACKWARD,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND |
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ForceIntercept",
+ PROPERTY_FORCE_INTERCEPT,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "InterceptValue",
+ PROPERTY_INTERCEPT_VALUE,
+ cppu::UnoType<double>::get(),
+ beans::PropertyAttribute::BOUND |
+ beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "CurveName",
+ PROPERTY_CURVE_NAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND );
+}
+
+const ::chart::tPropertyValueMap & GetStaticXXXDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults =
+ [](){
+ ::chart::tPropertyValueMap aTmp;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aTmp );
+ return aTmp;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& GetStaticRegressionCurveInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper =
+ [](){
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+uno::Reference< beans::XPropertySetInfo >& GetStaticRegressionCurveInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(GetStaticRegressionCurveInfoHelper() ) );
+ return xPropertySetInfo;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+RegressionCurveModel::RegressionCurveModel( tCurveType eCurveType ) :
+ m_eRegressionCurveType( eCurveType ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() ),
+ m_xEquationProperties( new RegressionEquation )
+{
+ // set 0 line width (default) hard, so that it is always written to XML,
+ // because the old implementation uses different defaults
+ setFastPropertyValue_NoBroadcast(
+ LinePropertiesHelper::PROP_LINE_WIDTH, uno::Any( sal_Int32( 0 )));
+ ModifyListenerHelper::addListener( m_xEquationProperties, m_xModifyEventForwarder );
+}
+
+RegressionCurveModel::RegressionCurveModel( const RegressionCurveModel & rOther ) :
+ impl::RegressionCurveModel_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_eRegressionCurveType( rOther.m_eRegressionCurveType ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ m_xEquationProperties.set( CloneHelper::CreateRefClone< beans::XPropertySet >()( rOther.m_xEquationProperties ));
+ ModifyListenerHelper::addListener( m_xEquationProperties, m_xModifyEventForwarder );
+}
+
+RegressionCurveModel::~RegressionCurveModel()
+{}
+
+// ____ XRegressionCurve ____
+uno::Reference< chart2::XRegressionCurveCalculator > SAL_CALL
+ RegressionCurveModel::getCalculator()
+{
+ return RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( getServiceName());
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL RegressionCurveModel::getEquationProperties()
+{
+ return m_xEquationProperties;
+}
+
+void SAL_CALL RegressionCurveModel::setEquationProperties( const uno::Reference< beans::XPropertySet >& xEquationProperties )
+{
+ if( xEquationProperties.is())
+ {
+ if( m_xEquationProperties.is())
+ ModifyListenerHelper::removeListener( m_xEquationProperties, m_xModifyEventForwarder );
+
+ m_xEquationProperties.set( xEquationProperties );
+ setPropertyMayHaveR2();
+ ModifyListenerHelper::addListener( m_xEquationProperties, m_xModifyEventForwarder );
+ fireModifyEvent();
+ }
+}
+
+void RegressionCurveModel::setPropertyMayHaveR2()
+{
+ if( m_xEquationProperties.is()) {
+ bool bMayHaveR2 = m_eRegressionCurveType != CURVE_TYPE_MOVING_AVERAGE;
+ m_xEquationProperties->setPropertyValue( "MayHaveCorrelationCoefficient", uno::Any( bMayHaveR2 ) );
+ }
+}
+
+// ____ XServiceName ____
+OUString SAL_CALL RegressionCurveModel::getServiceName()
+{
+ switch( m_eRegressionCurveType )
+ {
+ case CURVE_TYPE_MEAN_VALUE:
+ return "com.sun.star.chart2.MeanValueRegressionCurve";
+ case CURVE_TYPE_LINEAR:
+ return "com.sun.star.chart2.LinearRegressionCurve";
+ case CURVE_TYPE_LOGARITHM:
+ return "com.sun.star.chart2.LogarithmicRegressionCurve";
+ case CURVE_TYPE_EXPONENTIAL:
+ return "com.sun.star.chart2.ExponentialRegressionCurve";
+ case CURVE_TYPE_POWER:
+ return "com.sun.star.chart2.PotentialRegressionCurve";
+ case CURVE_TYPE_POLYNOMIAL:
+ return "com.sun.star.chart2.PolynomialRegressionCurve";
+ case CURVE_TYPE_MOVING_AVERAGE:
+ return "com.sun.star.chart2.MovingAverageRegressionCurve";
+ }
+
+ return OUString();
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL RegressionCurveModel::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL RegressionCurveModel::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL RegressionCurveModel::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL RegressionCurveModel::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void RegressionCurveModel::firePropertyChangeEvent()
+{
+ setPropertyMayHaveR2();
+ fireModifyEvent();
+}
+
+void RegressionCurveModel::fireModifyEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+// ____ OPropertySet ____
+void RegressionCurveModel::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = GetStaticXXXDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL RegressionCurveModel::getInfoHelper()
+{
+ return GetStaticRegressionCurveInfoHelper();
+}
+
+// ____ XPropertySet ____
+uno::Reference< beans::XPropertySetInfo > SAL_CALL RegressionCurveModel::getPropertySetInfo()
+{
+ return GetStaticRegressionCurveInfo();
+}
+
+// needed by MSC compiler
+using impl::RegressionCurveModel_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( RegressionCurveModel, RegressionCurveModel_Base, OPropertySet )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( RegressionCurveModel, RegressionCurveModel_Base, OPropertySet )
+
+// implementations
+
+MeanValueRegressionCurve::MeanValueRegressionCurve()
+ : RegressionCurveModel( RegressionCurveModel::CURVE_TYPE_MEAN_VALUE )
+{}
+MeanValueRegressionCurve::MeanValueRegressionCurve(
+ const MeanValueRegressionCurve & rOther ) :
+ RegressionCurveModel( rOther )
+{}
+MeanValueRegressionCurve::~MeanValueRegressionCurve()
+{}
+
+OUString SAL_CALL MeanValueRegressionCurve::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.MeanValueRegressionCurve";
+}
+
+sal_Bool SAL_CALL MeanValueRegressionCurve::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL MeanValueRegressionCurve::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.RegressionCurve", "com.sun.star.chart2.MeanValueRegressionCurve" };
+}
+
+uno::Reference< util::XCloneable > SAL_CALL MeanValueRegressionCurve::createClone()
+{
+ return uno::Reference< util::XCloneable >( new MeanValueRegressionCurve( *this ));
+}
+
+LinearRegressionCurve::LinearRegressionCurve()
+ : RegressionCurveModel( RegressionCurveModel::CURVE_TYPE_LINEAR )
+{}
+LinearRegressionCurve::LinearRegressionCurve(
+ const LinearRegressionCurve & rOther ) :
+ RegressionCurveModel( rOther )
+{}
+LinearRegressionCurve::~LinearRegressionCurve()
+{}
+
+OUString SAL_CALL LinearRegressionCurve::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.LinearRegressionCurve";
+}
+
+sal_Bool SAL_CALL LinearRegressionCurve::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL LinearRegressionCurve::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.RegressionCurve", "com.sun.star.chart2.LinearRegressionCurve" };
+}
+
+uno::Reference< util::XCloneable > SAL_CALL LinearRegressionCurve::createClone()
+{
+ return uno::Reference< util::XCloneable >( new LinearRegressionCurve( *this ));
+}
+
+LogarithmicRegressionCurve::LogarithmicRegressionCurve()
+ : RegressionCurveModel( RegressionCurveModel::CURVE_TYPE_LOGARITHM )
+{}
+LogarithmicRegressionCurve::LogarithmicRegressionCurve(
+ const LogarithmicRegressionCurve & rOther ) :
+ RegressionCurveModel( rOther )
+{}
+LogarithmicRegressionCurve::~LogarithmicRegressionCurve()
+{}
+
+OUString SAL_CALL LogarithmicRegressionCurve::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.LogarithmicRegressionCurve";
+}
+
+sal_Bool SAL_CALL LogarithmicRegressionCurve::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL LogarithmicRegressionCurve::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.RegressionCurve", "com.sun.star.chart2.LogarithmicRegressionCurve" };
+}
+
+uno::Reference< util::XCloneable > SAL_CALL LogarithmicRegressionCurve::createClone()
+{
+ return uno::Reference< util::XCloneable >( new LogarithmicRegressionCurve( *this ));
+}
+
+ExponentialRegressionCurve::ExponentialRegressionCurve()
+ : RegressionCurveModel( RegressionCurveModel::CURVE_TYPE_EXPONENTIAL )
+{}
+ExponentialRegressionCurve::ExponentialRegressionCurve(
+ const ExponentialRegressionCurve & rOther ) :
+ RegressionCurveModel( rOther )
+{}
+ExponentialRegressionCurve::~ExponentialRegressionCurve()
+{}
+
+OUString SAL_CALL ExponentialRegressionCurve::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.ExponentialRegressionCurve";
+}
+
+sal_Bool SAL_CALL ExponentialRegressionCurve::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ExponentialRegressionCurve::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.RegressionCurve", "com.sun.star.chart2.ExponentialRegressionCurve" };
+}
+
+uno::Reference< util::XCloneable > SAL_CALL ExponentialRegressionCurve::createClone()
+{
+ return uno::Reference< util::XCloneable >( new ExponentialRegressionCurve( *this ));
+}
+
+PotentialRegressionCurve::PotentialRegressionCurve()
+ : RegressionCurveModel( RegressionCurveModel::CURVE_TYPE_POWER )
+{}
+PotentialRegressionCurve::PotentialRegressionCurve(
+ const PotentialRegressionCurve & rOther ) :
+ RegressionCurveModel( rOther )
+{}
+PotentialRegressionCurve::~PotentialRegressionCurve()
+{}
+
+OUString SAL_CALL PotentialRegressionCurve::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.PotentialRegressionCurve";
+}
+
+sal_Bool SAL_CALL PotentialRegressionCurve::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL PotentialRegressionCurve::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.RegressionCurve", "com.sun.star.chart2.PotentialRegressionCurve" };
+}
+
+uno::Reference< util::XCloneable > SAL_CALL PotentialRegressionCurve::createClone()
+{
+ return uno::Reference< util::XCloneable >( new PotentialRegressionCurve( *this ));
+}
+
+PolynomialRegressionCurve::PolynomialRegressionCurve()
+ : RegressionCurveModel( RegressionCurveModel::CURVE_TYPE_POLYNOMIAL )
+{}
+PolynomialRegressionCurve::PolynomialRegressionCurve(
+ const PolynomialRegressionCurve & rOther ) :
+ RegressionCurveModel( rOther )
+{}
+PolynomialRegressionCurve::~PolynomialRegressionCurve()
+{}
+
+OUString SAL_CALL PolynomialRegressionCurve::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.PolynomialRegressionCurve";
+}
+
+sal_Bool SAL_CALL PolynomialRegressionCurve::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL PolynomialRegressionCurve::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.RegressionCurve", "com.sun.star.chart2.PolynomialRegressionCurve" };
+}
+
+uno::Reference< util::XCloneable > SAL_CALL PolynomialRegressionCurve::createClone()
+{
+ return uno::Reference< util::XCloneable >( new PolynomialRegressionCurve( *this ));
+}
+
+MovingAverageRegressionCurve::MovingAverageRegressionCurve()
+ : RegressionCurveModel( RegressionCurveModel::CURVE_TYPE_MOVING_AVERAGE )
+{}
+MovingAverageRegressionCurve::MovingAverageRegressionCurve(
+ const MovingAverageRegressionCurve & rOther ) :
+ RegressionCurveModel( rOther )
+{}
+MovingAverageRegressionCurve::~MovingAverageRegressionCurve()
+{}
+
+OUString SAL_CALL MovingAverageRegressionCurve::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.MovingAverageRegressionCurve";
+}
+
+sal_Bool SAL_CALL MovingAverageRegressionCurve::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL MovingAverageRegressionCurve::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.RegressionCurve", "com.sun.star.chart2.MovingAverageRegressionCurve" };
+}
+
+uno::Reference< util::XCloneable > SAL_CALL MovingAverageRegressionCurve::createClone()
+{
+ return uno::Reference< util::XCloneable >( new MovingAverageRegressionCurve( *this ));
+}
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_ExponentialRegressionCurve_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::ExponentialRegressionCurve );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_LinearRegressionCurve_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::LinearRegressionCurve );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_LogarithmicRegressionCurve_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::LogarithmicRegressionCurve );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_MeanValueRegressionCurve_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::MeanValueRegressionCurve );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_PotentialRegressionCurve_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::PotentialRegressionCurve );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_PolynomialRegressionCurve_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::PolynomialRegressionCurve );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_MovingAverageRegressionCurve_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::MovingAverageRegressionCurve );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/RegressionEquation.cxx b/chart2/source/tools/RegressionEquation.cxx
new file mode 100644
index 0000000000..34bbd6b491
--- /dev/null
+++ b/chart2/source/tools/RegressionEquation.cxx
@@ -0,0 +1,301 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "RegressionEquation.hxx"
+#include <LinePropertiesHelper.hxx>
+#include <FillProperties.hxx>
+#include <UserDefinedProperties.hxx>
+#include <CharacterProperties.hxx>
+#include <PropertyHelper.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <unonames.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/awt/Size.hpp>
+
+#include <algorithm>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::beans::Property;
+using ::osl::MutexGuard;
+
+namespace
+{
+
+enum
+{
+ PROP_EQUATION_SHOW,
+ PROP_EQUATION_XNAME,
+ PROP_EQUATION_YNAME,
+ PROP_EQUATION_SHOW_CORRELATION_COEFF,
+ PROP_EQUATION_MAY_HAVE_CORRELATION_COEFF,
+ PROP_EQUATION_REF_PAGE_SIZE,
+ PROP_EQUATION_REL_POS,
+ PROP_EQUATION_NUMBER_FORMAT
+};
+
+void lcl_AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "ShowEquation",
+ PROP_EQUATION_SHOW,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "XName",
+ PROP_EQUATION_XNAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "YName",
+ PROP_EQUATION_YNAME,
+ cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ShowCorrelationCoefficient",
+ PROP_EQUATION_SHOW_CORRELATION_COEFF,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "MayHaveCorrelationCoefficient",
+ PROP_EQUATION_MAY_HAVE_CORRELATION_COEFF,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ rOutProperties.emplace_back( "ReferencePageSize",
+ PROP_EQUATION_REF_PAGE_SIZE,
+ cppu::UnoType<awt::Size>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( "RelativePosition",
+ PROP_EQUATION_REL_POS,
+ cppu::UnoType<chart2::RelativePosition>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+
+ rOutProperties.emplace_back( CHART_UNONAME_NUMFMT,
+ PROP_EQUATION_NUMBER_FORMAT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+}
+
+::chart::tPropertyValueMap& GetStaticRegressionEquationDefaults()
+{
+ static ::chart::tPropertyValueMap aStaticDefaults =
+ [](){
+ ::chart::tPropertyValueMap aOutMap;
+ ::chart::LinePropertiesHelper::AddDefaultsToMap( aOutMap );
+ ::chart::FillProperties::AddDefaultsToMap( aOutMap );
+ ::chart::CharacterProperties::AddDefaultsToMap( aOutMap );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_EQUATION_SHOW, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_EQUATION_XNAME, OUString("x") );
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_EQUATION_YNAME, OUString("f(x)") );
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_EQUATION_SHOW_CORRELATION_COEFF, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_EQUATION_MAY_HAVE_CORRELATION_COEFF, true );
+ //::chart::PropertyHelper::setPropertyValueDefault( aOutMap, PROP_EQUATION_SEPARATOR, OUString( '\n' ));
+
+ // override other defaults
+ ::chart::PropertyHelper::setPropertyValue( aOutMap, ::chart::FillProperties::PROP_FILL_STYLE, drawing::FillStyle_NONE );
+ ::chart::PropertyHelper::setPropertyValue( aOutMap, ::chart::LinePropertiesHelper::PROP_LINE_STYLE, drawing::LineStyle_NONE );
+
+ float fDefaultCharHeight = 10.0;
+ ::chart::PropertyHelper::setPropertyValue( aOutMap, ::chart::CharacterProperties::PROP_CHAR_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aOutMap, ::chart::CharacterProperties::PROP_CHAR_ASIAN_CHAR_HEIGHT, fDefaultCharHeight );
+ ::chart::PropertyHelper::setPropertyValue( aOutMap, ::chart::CharacterProperties::PROP_CHAR_COMPLEX_CHAR_HEIGHT, fDefaultCharHeight );
+ return aOutMap;
+ }();
+ return aStaticDefaults;
+};
+
+::cppu::OPropertyArrayHelper& GetStaticRegressionEquationInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper aPropHelper =
+ [](){
+ std::vector< css::beans::Property > aProperties;
+ lcl_AddPropertiesToVector( aProperties );
+ ::chart::LinePropertiesHelper::AddPropertiesToVector( aProperties );
+ ::chart::FillProperties::AddPropertiesToVector( aProperties );
+ ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
+ ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
+
+ std::sort( aProperties.begin(), aProperties.end(),
+ ::chart::PropertyNameLess() );
+
+ return comphelper::containerToSequence( aProperties );
+ }();
+ return aPropHelper;
+};
+
+const uno::Reference< beans::XPropertySetInfo > & GetStaticRegressionEquationInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xPropertySetInfo(
+ ::cppu::OPropertySetHelper::createPropertySetInfo(GetStaticRegressionEquationInfoHelper()) );
+ return xPropertySetInfo;
+};
+
+} // anonymous namespace
+
+namespace chart
+{
+
+RegressionEquation::RegressionEquation() :
+ m_xModifyEventForwarder( new ModifyEventForwarder())
+{}
+
+RegressionEquation::RegressionEquation( const RegressionEquation & rOther ) :
+ impl::RegressionEquation_Base(rOther),
+ ::property::OPropertySet( rOther ),
+ m_xModifyEventForwarder( new ModifyEventForwarder())
+{}
+
+RegressionEquation::~RegressionEquation()
+{}
+
+// ____ XCloneable ____
+uno::Reference< util::XCloneable > SAL_CALL RegressionEquation::createClone()
+{
+ return uno::Reference< util::XCloneable >( new RegressionEquation( *this ));
+}
+
+// ____ OPropertySet ____
+void RegressionEquation::GetDefaultValue( sal_Int32 nHandle, uno::Any& rAny ) const
+{
+ const tPropertyValueMap& rStaticDefaults = GetStaticRegressionEquationDefaults();
+ tPropertyValueMap::const_iterator aFound( rStaticDefaults.find( nHandle ) );
+ if( aFound == rStaticDefaults.end() )
+ rAny.clear();
+ else
+ rAny = (*aFound).second;
+}
+
+::cppu::IPropertyArrayHelper & SAL_CALL RegressionEquation::getInfoHelper()
+{
+ return GetStaticRegressionEquationInfoHelper();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL RegressionEquation::getPropertySetInfo()
+{
+ return GetStaticRegressionEquationInfo();
+}
+
+// ____ XModifyBroadcaster ____
+void SAL_CALL RegressionEquation::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL RegressionEquation::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+// ____ XModifyListener ____
+void SAL_CALL RegressionEquation::modified( const lang::EventObject& aEvent )
+{
+ m_xModifyEventForwarder->modified( aEvent );
+}
+
+// ____ XEventListener (base of XModifyListener) ____
+void SAL_CALL RegressionEquation::disposing( const lang::EventObject& /* Source */ )
+{
+ // nothing
+}
+
+// ____ OPropertySet ____
+void RegressionEquation::firePropertyChangeEvent()
+{
+ fireModifyEvent();
+}
+
+void RegressionEquation::fireModifyEvent()
+{
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+// ____ XTitle ____
+uno::Sequence< uno::Reference< chart2::XFormattedString > > SAL_CALL RegressionEquation::getText()
+{
+ MutexGuard aGuard( m_aMutex );
+ return m_aStrings;
+}
+
+void SAL_CALL RegressionEquation::setText( const uno::Sequence< uno::Reference< chart2::XFormattedString > >& Strings )
+{
+ MutexGuard aGuard( m_aMutex );
+ ModifyListenerHelper::removeListenerFromAllElements(
+ comphelper::sequenceToContainer<std::vector<uno::Reference< chart2::XFormattedString > > >( m_aStrings ),
+ m_xModifyEventForwarder );
+ m_aStrings = Strings;
+ ModifyListenerHelper::addListenerToAllElements(
+ comphelper::sequenceToContainer<std::vector<uno::Reference< chart2::XFormattedString > > >( m_aStrings ),
+ m_xModifyEventForwarder );
+ fireModifyEvent();
+}
+
+OUString SAL_CALL RegressionEquation::getImplementationName()
+{
+ return "com.sun.star.comp.chart2.RegressionEquation";
+}
+
+sal_Bool SAL_CALL RegressionEquation::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL RegressionEquation::getSupportedServiceNames()
+{
+ return { "com.sun.star.chart2.RegressionEquation",
+ "com.sun.star.beans.PropertySet",
+ "com.sun.star.drawing.FillProperties",
+ "com.sun.star.drawing.LineProperties",
+ "com.sun.star.style.CharacterProperties" };
+}
+
+using impl::RegressionEquation_Base;
+
+IMPLEMENT_FORWARD_XINTERFACE2( RegressionEquation, RegressionEquation_Base, ::property::OPropertySet )
+
+} // namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_RegressionEquation_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new ::chart::RegressionEquation);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/RegressionEquation.hxx b/chart2/source/tools/RegressionEquation.hxx
new file mode 100644
index 0000000000..8a500cd1d7
--- /dev/null
+++ b/chart2/source/tools/RegressionEquation.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/chart2/XTitle.hpp>
+
+#include <OPropertySet.hxx>
+
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <ModifyListenerHelper.hxx>
+
+namespace chart
+{
+
+namespace impl
+{
+typedef ::cppu::WeakImplHelper<
+ css::lang::XServiceInfo,
+ css::util::XCloneable,
+ css::util::XModifyBroadcaster,
+ css::util::XModifyListener,
+ css::chart2::XTitle >
+ RegressionEquation_Base;
+}
+
+class RegressionEquation final :
+ public impl::RegressionEquation_Base,
+ public ::property::OPropertySet
+{
+public:
+ explicit RegressionEquation();
+ virtual ~RegressionEquation() override;
+
+ virtual OUString SAL_CALL
+ getImplementationName()
+ override;
+ virtual sal_Bool SAL_CALL
+ supportsService( const OUString& ServiceName )
+ override;
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames()
+ override;
+
+ /// merge XInterface implementations
+ DECLARE_XINTERFACE()
+
+private:
+ explicit RegressionEquation( const RegressionEquation & rOther );
+
+ // ____ OPropertySet ____
+ virtual void GetDefaultValue( sal_Int32 nHandle, css::uno::Any& rAny ) const override;
+
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ // ____ XPropertySet ____
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() override;
+
+ // ____ XCloneable ____
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override;
+
+ // ____ XModifyBroadcaster ____
+ virtual void SAL_CALL addModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+ virtual void SAL_CALL removeModifyListener(
+ const css::uno::Reference< css::util::XModifyListener >& aListener ) override;
+
+ // ____ XModifyListener ____
+ virtual void SAL_CALL modified(
+ const css::lang::EventObject& aEvent ) override;
+
+ // ____ XEventListener (base of XModifyListener) ____
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& Source ) override;
+
+ // ____ XTitle ____
+ virtual css::uno::Sequence<
+ css::uno::Reference< css::chart2::XFormattedString > > SAL_CALL getText() override;
+ virtual void SAL_CALL setText( const css::uno::Sequence<
+ css::uno::Reference<
+ css::chart2::XFormattedString > >& Strings ) override;
+
+ using ::cppu::OPropertySetHelper::disposing;
+
+ // ____ OPropertySet ____
+ virtual void firePropertyChangeEvent() override;
+
+ void fireModifyEvent();
+
+ css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > > m_aStrings;
+
+ rtl::Reference<ModifyEventForwarder> m_xModifyEventForwarder;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/RelativePositionHelper.cxx b/chart2/source/tools/RelativePositionHelper.cxx
new file mode 100644
index 0000000000..260888e907
--- /dev/null
+++ b/chart2/source/tools/RelativePositionHelper.cxx
@@ -0,0 +1,381 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RelativePositionHelper.hxx>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <rtl/math.hxx>
+#include <osl/diagnose.h>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+chart2::RelativePosition RelativePositionHelper::getReanchoredPosition(
+ const chart2::RelativePosition & rPosition,
+ const chart2::RelativeSize & rObjectSize,
+ drawing::Alignment aNewAnchor )
+{
+ chart2::RelativePosition aResult( rPosition );
+ if( rPosition.Anchor != aNewAnchor )
+ {
+ sal_Int32 nShiftHalfWidths = 0;
+ sal_Int32 nShiftHalfHeights = 0;
+
+ // normalize to top-left
+ switch( rPosition.Anchor )
+ {
+ case drawing::Alignment_TOP_LEFT:
+ break;
+ case drawing::Alignment_LEFT:
+ nShiftHalfHeights -= 1;
+ break;
+ case drawing::Alignment_BOTTOM_LEFT:
+ nShiftHalfHeights -= 2;
+ break;
+ case drawing::Alignment_TOP:
+ nShiftHalfWidths -= 1;
+ break;
+ case drawing::Alignment_CENTER:
+ nShiftHalfWidths -= 1;
+ nShiftHalfHeights -= 1;
+ break;
+ case drawing::Alignment_BOTTOM:
+ nShiftHalfWidths -= 1;
+ nShiftHalfHeights -= 2;
+ break;
+ case drawing::Alignment_TOP_RIGHT:
+ nShiftHalfWidths -= 2;
+ break;
+ case drawing::Alignment_RIGHT:
+ nShiftHalfWidths -= 2;
+ nShiftHalfHeights -= 1;
+ break;
+ case drawing::Alignment_BOTTOM_RIGHT:
+ nShiftHalfWidths -= 2;
+ nShiftHalfHeights -= 2;
+ break;
+ case drawing::Alignment::Alignment_MAKE_FIXED_SIZE:
+ break;
+ }
+
+ // transform
+ switch( aNewAnchor )
+ {
+ case drawing::Alignment_TOP_LEFT:
+ break;
+ case drawing::Alignment_LEFT:
+ nShiftHalfHeights += 1;
+ break;
+ case drawing::Alignment_BOTTOM_LEFT:
+ nShiftHalfHeights += 2;
+ break;
+ case drawing::Alignment_TOP:
+ nShiftHalfWidths += 1;
+ break;
+ case drawing::Alignment_CENTER:
+ nShiftHalfWidths += 1;
+ nShiftHalfHeights += 1;
+ break;
+ case drawing::Alignment_BOTTOM:
+ nShiftHalfWidths += 1;
+ nShiftHalfHeights += 2;
+ break;
+ case drawing::Alignment_TOP_RIGHT:
+ nShiftHalfWidths += 2;
+ break;
+ case drawing::Alignment_RIGHT:
+ nShiftHalfWidths += 2;
+ nShiftHalfHeights += 1;
+ break;
+ case drawing::Alignment_BOTTOM_RIGHT:
+ nShiftHalfWidths += 2;
+ nShiftHalfHeights += 2;
+ break;
+ case drawing::Alignment::Alignment_MAKE_FIXED_SIZE:
+ break;
+ }
+
+ if( nShiftHalfWidths != 0 )
+ aResult.Primary += (rObjectSize.Primary / 2.0) * nShiftHalfWidths;
+ if( nShiftHalfHeights != 0 )
+ aResult.Secondary += (rObjectSize.Secondary / 2.0) * nShiftHalfHeights;
+ }
+
+ return aResult;
+}
+
+awt::Point RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
+ awt::Point aPoint
+ , awt::Size aObjectSize
+ , drawing::Alignment aAnchor )
+{
+ awt::Point aResult( aPoint );
+
+ double fXDelta = 0.0;
+ double fYDelta = 0.0;
+
+ // adapt x-value
+ switch( aAnchor )
+ {
+ case drawing::Alignment_TOP:
+ case drawing::Alignment_CENTER:
+ case drawing::Alignment_BOTTOM:
+ fXDelta -= static_cast< double >( aObjectSize.Width ) / 2.0;
+ break;
+ case drawing::Alignment_TOP_RIGHT:
+ case drawing::Alignment_RIGHT:
+ case drawing::Alignment_BOTTOM_RIGHT:
+ fXDelta -= aObjectSize.Width;
+ break;
+ case drawing::Alignment_TOP_LEFT:
+ case drawing::Alignment_LEFT:
+ case drawing::Alignment_BOTTOM_LEFT:
+ default:
+ // nothing to do
+ break;
+ }
+
+ // adapt y-value
+ switch( aAnchor )
+ {
+ case drawing::Alignment_LEFT:
+ case drawing::Alignment_CENTER:
+ case drawing::Alignment_RIGHT:
+ fYDelta -= static_cast< double >( aObjectSize.Height ) / 2.0;
+ break;
+ case drawing::Alignment_BOTTOM_LEFT:
+ case drawing::Alignment_BOTTOM:
+ case drawing::Alignment_BOTTOM_RIGHT:
+ fYDelta -= aObjectSize.Height;
+ break;
+ case drawing::Alignment_TOP_LEFT:
+ case drawing::Alignment_TOP:
+ case drawing::Alignment_TOP_RIGHT:
+ default:
+ // nothing to do
+ break;
+ }
+
+ aResult.X += static_cast< sal_Int32 >( ::rtl::math::round( fXDelta ));
+ aResult.Y += static_cast< sal_Int32 >( ::rtl::math::round( fYDelta ));
+
+ return aResult;
+}
+
+awt::Point RelativePositionHelper::getCenterOfAnchoredObject(
+ awt::Point aPoint
+ , awt::Size aUnrotatedObjectSize
+ , drawing::Alignment aAnchor
+ , double fAnglePi )
+{
+ awt::Point aResult( aPoint );
+
+ double fXDelta = 0.0;
+ double fYDelta = 0.0;
+
+ // adapt x-value
+ switch( aAnchor )
+ {
+ case drawing::Alignment_TOP:
+ case drawing::Alignment_CENTER:
+ case drawing::Alignment_BOTTOM:
+ // nothing to do
+ break;
+ case drawing::Alignment_TOP_RIGHT:
+ case drawing::Alignment_RIGHT:
+ case drawing::Alignment_BOTTOM_RIGHT:
+ fXDelta -= aUnrotatedObjectSize.Width/2;
+ break;
+ case drawing::Alignment_TOP_LEFT:
+ case drawing::Alignment_LEFT:
+ case drawing::Alignment_BOTTOM_LEFT:
+ default:
+ fXDelta += aUnrotatedObjectSize.Width/2;
+ break;
+ }
+
+ // adapt y-value
+ switch( aAnchor )
+ {
+ case drawing::Alignment_LEFT:
+ case drawing::Alignment_CENTER:
+ case drawing::Alignment_RIGHT:
+ // nothing to do
+ break;
+ case drawing::Alignment_BOTTOM_LEFT:
+ case drawing::Alignment_BOTTOM:
+ case drawing::Alignment_BOTTOM_RIGHT:
+ fYDelta -= aUnrotatedObjectSize.Height/2;
+ break;
+ case drawing::Alignment_TOP_LEFT:
+ case drawing::Alignment_TOP:
+ case drawing::Alignment_TOP_RIGHT:
+ fYDelta += aUnrotatedObjectSize.Height/2;
+ break;
+ default:
+ // nothing to do
+ break;
+ }
+
+ //take rotation into account:
+ aResult.X += static_cast< sal_Int32 >(
+ ::rtl::math::round( fXDelta * std::cos( fAnglePi ) + fYDelta * std::sin( fAnglePi ) ) );
+ aResult.Y += static_cast< sal_Int32 >(
+ ::rtl::math::round( - fXDelta * std::sin( fAnglePi ) + fYDelta * std::cos( fAnglePi ) ) );
+
+ return aResult;
+}
+
+bool RelativePositionHelper::centerGrow(
+ chart2::RelativePosition & rInOutPosition,
+ chart2::RelativeSize & rInOutSize,
+ double fAmountX, double fAmountY )
+{
+ chart2::RelativePosition aPos( rInOutPosition );
+ chart2::RelativeSize aSize( rInOutSize );
+ const double fPosCheckThreshold = 0.02;
+ const double fSizeCheckThreshold = 0.1;
+
+ // grow/shrink, back to relative
+ aSize.Primary += fAmountX;
+ aSize.Secondary += fAmountY;
+
+ double fShiftAmountX = fAmountX / 2.0;
+ double fShiftAmountY = fAmountY / 2.0;
+
+ // shift X
+ switch( rInOutPosition.Anchor )
+ {
+ case drawing::Alignment_TOP_LEFT:
+ case drawing::Alignment_LEFT:
+ case drawing::Alignment_BOTTOM_LEFT:
+ aPos.Primary -= fShiftAmountX;
+ break;
+ case drawing::Alignment_TOP:
+ case drawing::Alignment_CENTER:
+ case drawing::Alignment_BOTTOM:
+ // nothing
+ break;
+ case drawing::Alignment_TOP_RIGHT:
+ case drawing::Alignment_RIGHT:
+ case drawing::Alignment_BOTTOM_RIGHT:
+ aPos.Primary += fShiftAmountX;
+ break;
+ case drawing::Alignment::Alignment_MAKE_FIXED_SIZE:
+ break;
+ }
+
+ // shift Y
+ switch( rInOutPosition.Anchor )
+ {
+ case drawing::Alignment_TOP:
+ case drawing::Alignment_TOP_LEFT:
+ case drawing::Alignment_TOP_RIGHT:
+ aPos.Secondary -= fShiftAmountY;
+ break;
+ case drawing::Alignment_CENTER:
+ case drawing::Alignment_LEFT:
+ case drawing::Alignment_RIGHT:
+ // nothing
+ break;
+ case drawing::Alignment_BOTTOM:
+ case drawing::Alignment_BOTTOM_LEFT:
+ case drawing::Alignment_BOTTOM_RIGHT:
+ aPos.Secondary += fShiftAmountY;
+ break;
+ case drawing::Alignment::Alignment_MAKE_FIXED_SIZE:
+ break;
+ }
+
+ // anchor must not be changed
+ OSL_ASSERT( rInOutPosition.Anchor == aPos.Anchor );
+
+ if( rInOutPosition.Primary == aPos.Primary &&
+ rInOutPosition.Secondary == aPos.Secondary &&
+ rInOutSize.Primary == aSize.Primary &&
+ rInOutSize.Secondary == aSize.Secondary )
+ return false;
+
+ // Note: this somewhat complicated check allows the output being
+ // out-of-bounds if the input was also out-of-bounds, and the change is
+ // for "advantage". E.g., you have a chart that laps out on the left
+ // side. If you shrink it, this should be possible, also if it still
+ // laps out on the left side afterwards. But you shouldn't be able to
+ // grow it then.
+
+ chart2::RelativePosition aUpperLeft(
+ RelativePositionHelper::getReanchoredPosition( aPos, aSize, drawing::Alignment_TOP_LEFT ));
+ chart2::RelativePosition aLowerRight(
+ RelativePositionHelper::getReanchoredPosition( aPos, aSize, drawing::Alignment_BOTTOM_RIGHT ));
+
+ // Do not grow, if this leads to corners being off-screen
+ if( fAmountX > 0.0 &&
+ ( (aUpperLeft.Primary < fPosCheckThreshold) ||
+ (aLowerRight.Primary > (1.0 - fPosCheckThreshold)) ))
+ return false;
+ if( fAmountY > 0.0 &&
+ ( (aUpperLeft.Secondary < fPosCheckThreshold) ||
+ (aLowerRight.Secondary > (1.0 - fPosCheckThreshold)) ))
+ return false;
+
+ // Do not shrink, if this leads to a size too small
+ if( fAmountX < 0.0 &&
+ ( aSize.Primary < fSizeCheckThreshold ))
+ return false;
+ if( fAmountY < 0.0 &&
+ ( aSize.Secondary < fSizeCheckThreshold ))
+ return false;
+
+ rInOutPosition = aPos;
+ rInOutSize = aSize;
+ return true;
+}
+
+bool RelativePositionHelper::moveObject(
+ chart2::RelativePosition & rInOutPosition,
+ const chart2::RelativeSize & rObjectSize,
+ double fAmountX, double fAmountY )
+{
+ chart2::RelativePosition aPos( rInOutPosition );
+ aPos.Primary += fAmountX;
+ aPos.Secondary += fAmountY;
+ const double fPosCheckThreshold = 0.02;
+
+ chart2::RelativePosition aUpperLeft(
+ RelativePositionHelper::getReanchoredPosition( aPos, rObjectSize, drawing::Alignment_TOP_LEFT ));
+ chart2::RelativePosition aLowerRight( aUpperLeft );
+ aLowerRight.Primary += rObjectSize.Primary;
+ aLowerRight.Secondary += rObjectSize.Secondary;
+
+ const double fFarEdgeThreshold = 1.0 - fPosCheckThreshold;
+ if( ( fAmountX > 0.0 && (aLowerRight.Primary > fFarEdgeThreshold)) ||
+ ( fAmountX < 0.0 && (aUpperLeft.Primary < fPosCheckThreshold)) ||
+ ( fAmountY > 0.0 && (aLowerRight.Secondary > fFarEdgeThreshold)) ||
+ ( fAmountY < 0.0 && (aUpperLeft.Secondary < fPosCheckThreshold)) )
+ return false;
+
+ rInOutPosition = aPos;
+ return true;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/RelativeSizeHelper.cxx b/chart2/source/tools/RelativeSizeHelper.cxx
new file mode 100644
index 0000000000..4a3cd84cfb
--- /dev/null
+++ b/chart2/source/tools/RelativeSizeHelper.cxx
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <RelativeSizeHelper.hxx>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <svx/unoshape.hxx>
+#include <vector>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Exception;
+
+namespace chart
+{
+
+double RelativeSizeHelper::calculate(
+ double fValue,
+ const awt::Size & rOldReferenceSize,
+ const awt::Size & rNewReferenceSize )
+{
+ if( rOldReferenceSize.Width <= 0 ||
+ rOldReferenceSize.Height <= 0 )
+ return fValue;
+
+ return std::min(
+ static_cast< double >( rNewReferenceSize.Width ) / static_cast< double >( rOldReferenceSize.Width ),
+ static_cast< double >( rNewReferenceSize.Height ) / static_cast< double >( rOldReferenceSize.Height ))
+ * fValue;
+}
+
+void RelativeSizeHelper::adaptFontSizes(
+ SvxShapeText& xTargetProperties,
+ const awt::Size & rOldReferenceSize,
+ const awt::Size & rNewReferenceSize )
+{
+ float fFontHeight = 0;
+
+ std::vector< OUString > aProperties;
+ aProperties.emplace_back("CharHeight" );
+ aProperties.emplace_back("CharHeightAsian" );
+ aProperties.emplace_back("CharHeightComplex" );
+
+ for (auto const& property : aProperties)
+ {
+ try
+ {
+ if( xTargetProperties.SvxShape::getPropertyValue(property) >>= fFontHeight )
+ {
+ xTargetProperties.SvxShape::setPropertyValue(
+ property,
+ Any( static_cast< float >(
+ calculate( fFontHeight, rOldReferenceSize, rNewReferenceSize ))));
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+}
+
+void RelativeSizeHelper::adaptFontSizes(
+ const Reference< XPropertySet > & xTargetProperties,
+ const awt::Size & rOldReferenceSize,
+ const awt::Size & rNewReferenceSize )
+{
+ if( ! xTargetProperties.is())
+ return;
+
+ float fFontHeight = 0;
+
+ std::vector< OUString > aProperties;
+ aProperties.emplace_back("CharHeight" );
+ aProperties.emplace_back("CharHeightAsian" );
+ aProperties.emplace_back("CharHeightComplex" );
+
+ for (auto const& property : aProperties)
+ {
+ try
+ {
+ if( xTargetProperties->getPropertyValue(property) >>= fFontHeight )
+ {
+ xTargetProperties->setPropertyValue(
+ property,
+ Any( static_cast< float >(
+ calculate( fFontHeight, rOldReferenceSize, rNewReferenceSize ))));
+ }
+ }
+ catch( const Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ResId.cxx b/chart2/source/tools/ResId.cxx
new file mode 100644
index 0000000000..aaa1d840c9
--- /dev/null
+++ b/chart2/source/tools/ResId.cxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ResId.hxx>
+
+namespace chart
+{
+ OUString SchResId(TranslateId aId)
+ {
+ return Translate::get(aId, Translate::Create("chart"));
+ }
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/Scaling.cxx b/chart2/source/tools/Scaling.cxx
new file mode 100644
index 0000000000..b7179537c4
--- /dev/null
+++ b/chart2/source/tools/Scaling.cxx
@@ -0,0 +1,267 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <Scaling.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <cmath>
+#include <limits>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace
+{
+
+constexpr OUString lcl_aServiceName_Logarithmic = u"com.sun.star.chart2.LogarithmicScaling"_ustr;
+constexpr OUString lcl_aServiceName_Exponential = u"com.sun.star.chart2.ExponentialScaling"_ustr;
+constexpr OUString lcl_aServiceName_Linear = u"com.sun.star.chart2.LinearScaling"_ustr;
+constexpr OUString lcl_aServiceName_Power = u"com.sun.star.chart2.PowerScaling"_ustr;
+
+}
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+LogarithmicScaling::LogarithmicScaling() :
+ m_fBase( 10.0 ),
+ m_fLogOfBase( log( 10.0 ) )
+{
+}
+
+LogarithmicScaling::LogarithmicScaling( double fBase ) :
+ m_fBase( fBase ),
+ m_fLogOfBase( log( fBase ) )
+{
+}
+
+LogarithmicScaling::~LogarithmicScaling()
+{
+}
+
+double SAL_CALL LogarithmicScaling::doScaling( double value )
+{
+ if( std::isnan( value ) || std::isinf( value ) )
+ return std::numeric_limits<double>::quiet_NaN();
+ return std::log( value ) / m_fLogOfBase;
+}
+
+uno::Reference< XScaling > SAL_CALL LogarithmicScaling::getInverseScaling()
+{
+ return new ExponentialScaling( m_fBase );
+}
+
+OUString SAL_CALL LogarithmicScaling::getServiceName()
+{
+ return lcl_aServiceName_Logarithmic;
+}
+
+OUString SAL_CALL LogarithmicScaling::getImplementationName()
+{
+ return lcl_aServiceName_Logarithmic;
+}
+
+sal_Bool SAL_CALL LogarithmicScaling::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL LogarithmicScaling::getSupportedServiceNames()
+{
+ return { lcl_aServiceName_Logarithmic };
+}
+
+ExponentialScaling::ExponentialScaling() :
+ m_fBase( 10.0 )
+{
+}
+
+ExponentialScaling::ExponentialScaling( double fBase ) :
+ m_fBase( fBase )
+{
+}
+
+ExponentialScaling::~ExponentialScaling()
+{
+}
+
+double SAL_CALL ExponentialScaling::doScaling( double value )
+{
+ if( std::isnan( value ) || std::isinf( value ) )
+ return std::numeric_limits<double>::quiet_NaN();
+ return std::pow( m_fBase, value );
+}
+
+uno::Reference< XScaling > SAL_CALL ExponentialScaling::getInverseScaling()
+{
+ return new LogarithmicScaling( m_fBase );
+}
+
+OUString SAL_CALL ExponentialScaling::getServiceName()
+{
+ return lcl_aServiceName_Exponential;
+}
+
+OUString SAL_CALL ExponentialScaling::getImplementationName()
+{
+ return lcl_aServiceName_Exponential;
+}
+
+sal_Bool SAL_CALL ExponentialScaling::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ExponentialScaling::getSupportedServiceNames()
+{
+ return { lcl_aServiceName_Exponential };
+}
+
+LinearScaling::LinearScaling() :
+ m_fSlope( 1.0 ),
+ m_fOffset( 0.0 )
+{}
+
+LinearScaling::LinearScaling( double fSlope, double fOffset ) :
+ m_fSlope( fSlope ),
+ m_fOffset( fOffset )
+{}
+
+LinearScaling::~LinearScaling()
+{}
+
+double SAL_CALL LinearScaling::doScaling( double value )
+{
+ if( std::isnan( value ) || std::isinf( value ) )
+ return std::numeric_limits<double>::quiet_NaN();
+ return m_fOffset + m_fSlope * value;
+}
+
+uno::Reference< XScaling > SAL_CALL
+ LinearScaling::getInverseScaling()
+{
+ // ToDo: ApproxEqual ?
+ if( m_fSlope == 0 )
+ throw uno::RuntimeException("Divide by zero exception");
+
+ return new LinearScaling( 1.0 / m_fSlope, m_fOffset / m_fSlope );
+}
+
+OUString SAL_CALL LinearScaling::getServiceName()
+{
+ return lcl_aServiceName_Linear;
+}
+
+OUString SAL_CALL LinearScaling::getImplementationName()
+{
+ return lcl_aServiceName_Linear ;
+}
+
+sal_Bool SAL_CALL LinearScaling::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL LinearScaling::getSupportedServiceNames()
+{
+ return { lcl_aServiceName_Linear };
+}
+
+PowerScaling::PowerScaling() :
+ m_fExponent( 10.0 )
+{}
+
+PowerScaling::PowerScaling( double fExponent ) :
+ m_fExponent( fExponent )
+{}
+
+PowerScaling::~PowerScaling()
+{}
+
+double SAL_CALL PowerScaling::doScaling( double value )
+{
+ if( std::isnan( value ) || std::isinf( value ) )
+ return std::numeric_limits<double>::quiet_NaN();
+ return std::pow( value, m_fExponent );
+}
+
+uno::Reference< XScaling > SAL_CALL
+ PowerScaling::getInverseScaling()
+{
+ // ToDo: ApproxEqual ?
+ if( m_fExponent == 0 )
+ throw uno::RuntimeException("Divide by zero exception");
+
+ return new PowerScaling( 1.0 / m_fExponent );
+}
+
+ OUString SAL_CALL
+PowerScaling::getServiceName()
+{
+ return lcl_aServiceName_Power;
+}
+
+OUString SAL_CALL PowerScaling::getImplementationName()
+{
+ return lcl_aServiceName_Power;
+}
+
+sal_Bool SAL_CALL PowerScaling::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL PowerScaling::getSupportedServiceNames()
+{
+ return { lcl_aServiceName_Power };
+}
+
+} //namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_chart2_LinearScaling_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new chart::LinearScaling );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_chart2_ExponentialScaling_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new chart::ExponentialScaling );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_chart2_LogarithmicScaling_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new chart::LogarithmicScaling );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_chart2_PowerScaling_get_implementation(css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new chart::PowerScaling );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/SceneProperties.cxx b/chart2/source/tools/SceneProperties.cxx
new file mode 100644
index 0000000000..eb65d81c94
--- /dev/null
+++ b/chart2/source/tools/SceneProperties.cxx
@@ -0,0 +1,333 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <SceneProperties.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <com/sun/star/drawing/ProjectionMode.hpp>
+#include <com/sun/star/drawing/CameraGeometry.hpp>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+
+namespace chart
+{
+
+void SceneProperties::AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ // transformation matrix
+ rOutProperties.emplace_back( "D3DTransformMatrix",
+ PROP_SCENE_TRANSF_MATRIX,
+ cppu::UnoType<drawing::HomogenMatrix>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // distance: deprecated ( this is not used by the chart view; it's only here for compatibility with old chart )
+ rOutProperties.emplace_back( "D3DSceneDistance",
+ PROP_SCENE_DISTANCE,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // focalLength: deprecated ( this is not used by the chart view; it's only here for compatibility with old chart )
+ rOutProperties.emplace_back( "D3DSceneFocalLength",
+ PROP_SCENE_FOCAL_LENGTH,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // shadowSlant
+ rOutProperties.emplace_back( "D3DSceneShadowSlant",
+ PROP_SCENE_SHADOW_SLANT,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // shadeMode
+ rOutProperties.emplace_back( "D3DSceneShadeMode",
+ PROP_SCENE_SHADE_MODE,
+ cppu::UnoType<drawing::ShadeMode>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // ambientColor
+ rOutProperties.emplace_back( "D3DSceneAmbientColor",
+ PROP_SCENE_AMBIENT_COLOR,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // lightingMode
+ rOutProperties.emplace_back( "D3DSceneTwoSidedLighting",
+ PROP_SCENE_TWO_SIDED_LIGHTING,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // camera geometry
+ rOutProperties.emplace_back( "D3DCameraGeometry",
+ PROP_SCENE_CAMERA_GEOMETRY,
+ cppu::UnoType<drawing::CameraGeometry>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // perspective
+ rOutProperties.emplace_back( "D3DScenePerspective",
+ PROP_SCENE_PERSPECTIVE,
+ cppu::UnoType<drawing::ProjectionMode>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+
+ // Light Sources
+ // light source 1
+ rOutProperties.emplace_back( "D3DSceneLightColor1",
+ PROP_SCENE_LIGHT_COLOR_1,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightDirection1",
+ PROP_SCENE_LIGHT_DIRECTION_1,
+ cppu::UnoType<drawing::Direction3D>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightOn1",
+ PROP_SCENE_LIGHT_ON_1,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // light source 2
+ rOutProperties.emplace_back( "D3DSceneLightColor2",
+ PROP_SCENE_LIGHT_COLOR_2,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightDirection2",
+ PROP_SCENE_LIGHT_DIRECTION_2,
+ cppu::UnoType<drawing::Direction3D>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightOn2",
+ PROP_SCENE_LIGHT_ON_2,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // light source 3
+ rOutProperties.emplace_back( "D3DSceneLightColor3",
+ PROP_SCENE_LIGHT_COLOR_3,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightDirection3",
+ PROP_SCENE_LIGHT_DIRECTION_3,
+ cppu::UnoType<drawing::Direction3D>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightOn3",
+ PROP_SCENE_LIGHT_ON_3,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // light source 4
+ rOutProperties.emplace_back( "D3DSceneLightColor4",
+ PROP_SCENE_LIGHT_COLOR_4,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightDirection4",
+ PROP_SCENE_LIGHT_DIRECTION_4,
+ cppu::UnoType<drawing::Direction3D>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightOn4",
+ PROP_SCENE_LIGHT_ON_4,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // light source 5
+ rOutProperties.emplace_back( "D3DSceneLightColor5",
+ PROP_SCENE_LIGHT_COLOR_5,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightDirection5",
+ PROP_SCENE_LIGHT_DIRECTION_5,
+ cppu::UnoType<drawing::Direction3D>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightOn5",
+ PROP_SCENE_LIGHT_ON_5,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // light source 6
+ rOutProperties.emplace_back( "D3DSceneLightColor6",
+ PROP_SCENE_LIGHT_COLOR_6,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightDirection6",
+ PROP_SCENE_LIGHT_DIRECTION_6,
+ cppu::UnoType<drawing::Direction3D>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightOn6",
+ PROP_SCENE_LIGHT_ON_6,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // light source 7
+ rOutProperties.emplace_back( "D3DSceneLightColor7",
+ PROP_SCENE_LIGHT_COLOR_7,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightDirection7",
+ PROP_SCENE_LIGHT_DIRECTION_7,
+ cppu::UnoType<drawing::Direction3D>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightOn7",
+ PROP_SCENE_LIGHT_ON_7,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ // light source 8
+ rOutProperties.emplace_back( "D3DSceneLightColor8",
+ PROP_SCENE_LIGHT_COLOR_8,
+ cppu::UnoType<sal_Int32>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightDirection8",
+ PROP_SCENE_LIGHT_DIRECTION_8,
+ cppu::UnoType<drawing::Direction3D>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+ rOutProperties.emplace_back( "D3DSceneLightOn8",
+ PROP_SCENE_LIGHT_ON_8,
+ cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID
+ | beans::PropertyAttribute::MAYBEDEFAULT );
+}
+
+void SceneProperties::AddDefaultsToMap(
+ ::chart::tPropertyValueMap & rOutMap )
+{
+ // Identity Matrix
+ drawing::HomogenMatrix aMtx;
+ aMtx.Line1.Column1 = aMtx.Line2.Column2 =
+ aMtx.Line3.Column3 = aMtx.Line4.Column4 = 1.0;
+ aMtx.Line1.Column2 = aMtx.Line1.Column3 = aMtx.Line1.Column4 =
+ aMtx.Line2.Column1 = aMtx.Line2.Column3 = aMtx.Line2.Column4 =
+ aMtx.Line3.Column1 = aMtx.Line3.Column2 = aMtx.Line3.Column4 =
+ aMtx.Line4.Column1 = aMtx.Line4.Column2 = aMtx.Line4.Column3 = 0.0;
+
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_TRANSF_MATRIX, aMtx );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_DISTANCE, sal_Int32(4200) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_FOCAL_LENGTH, sal_Int32(8000) );
+
+// PROP_SCENE_SHADOW_SLANT;
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_SHADE_MODE, drawing::ShadeMode_SMOOTH );
+
+ ::chart::PropertyHelper::setPropertyValueDefault(
+ rOutMap, PROP_SCENE_AMBIENT_COLOR, ChartTypeHelper::getDefaultAmbientLightColor(false,nullptr));
+
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_TWO_SIDED_LIGHTING, true );
+
+ drawing::Position3D vrp( 0.0, 0.0, 1.0 );
+ drawing::Direction3D vpn( 0.0, 0.0, 1.0 );
+ drawing::Direction3D vup( 0.0, 1.0, 0.0 );
+ drawing::CameraGeometry aDefaultCameraGeometry( vrp, vpn, vup );
+
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_CAMERA_GEOMETRY, aDefaultCameraGeometry );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_PERSPECTIVE, drawing::ProjectionMode_PERSPECTIVE );
+
+ // Light Sources
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_1, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_2, true );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_3, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_4, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_5, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_6, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_7, false );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_ON_8, false );
+
+ uno::Any aDefaultLightDirection( drawing::Direction3D( 0.0, 0.0, 1.0 ) );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_1, aDefaultLightDirection );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_2, ChartTypeHelper::getDefaultSimpleLightDirection(nullptr));
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_3, aDefaultLightDirection );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_4, aDefaultLightDirection );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_5, aDefaultLightDirection );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_6, aDefaultLightDirection );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_7, aDefaultLightDirection );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_DIRECTION_8, aDefaultLightDirection );
+
+ uno::Any aDefaultLightColor;
+ aDefaultLightColor <<= ChartTypeHelper::getDefaultDirectLightColor(false,nullptr);
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_1, aDefaultLightColor );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_2, aDefaultLightColor );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_3, aDefaultLightColor );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_4, aDefaultLightColor );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_5, aDefaultLightColor );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_6, aDefaultLightColor );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_7, aDefaultLightColor );
+ ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_SCENE_LIGHT_COLOR_8, aDefaultLightColor );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/StatisticsHelper.cxx b/chart2/source/tools/StatisticsHelper.cxx
new file mode 100644
index 0000000000..06eba5da4c
--- /dev/null
+++ b/chart2/source/tools/StatisticsHelper.cxx
@@ -0,0 +1,361 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <StatisticsHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <ErrorBar.hxx>
+#include <unonames.hxx>
+
+#include <rtl/ustrbuf.hxx>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
+#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
+#include <com/sun/star/chart2/data/XDataProvider.hpp>
+#include <com/sun/star/chart2/data/XDataSink.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <cmath>
+#include <limits>
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using namespace ::com::sun::star;
+
+namespace
+{
+
+double lcl_getVariance( const Sequence< double > & rData, sal_Int32 & rOutValidCount )
+{
+ const sal_Int32 nCount = rData.getLength();
+ rOutValidCount = nCount;
+
+ double fSum = 0.0;
+ double fQuadSum = 0.0;
+
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ const double fData = rData[i];
+ if( std::isnan( fData ))
+ --rOutValidCount;
+ else
+ {
+ fSum += fData;
+ fQuadSum += fData * fData;
+ }
+ }
+
+ if( rOutValidCount == 0 )
+ return std::numeric_limits<double>::quiet_NaN();
+
+ const double fN = static_cast< double >( rOutValidCount );
+ return (fQuadSum - fSum*fSum/fN) / fN;
+}
+
+uno::Reference< chart2::data::XLabeledDataSequence > lcl_getErrorBarLabeledSequence(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ bool bPositiveValue, bool bYError,
+ OUString & rOutRoleNameUsed )
+{
+ OUStringBuffer aRole( "error-bars-");
+ if( bYError )
+ aRole.append( 'y');
+ else
+ aRole.append( 'x');
+
+ OUString aPlainRole = aRole.makeStringAndClear();
+ aRole.append( aPlainRole + "-" );
+
+ if( bPositiveValue )
+ aRole.append( "positive" );
+ else
+ aRole.append( "negative" );
+
+ OUString aLongRole = aRole.makeStringAndClear();
+ uno::Reference< chart2::data::XLabeledDataSequence > xLSeq =
+ ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aLongRole );
+ // try role without "-negative" or "-positive" postfix
+ if( xLSeq.is())
+ rOutRoleNameUsed = aLongRole;
+ else
+ {
+ xLSeq = ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aPlainRole );
+ if( xLSeq.is())
+ rOutRoleNameUsed = aPlainRole;
+ else
+ rOutRoleNameUsed = aLongRole;
+ }
+
+ return xLSeq;
+}
+
+void lcl_setRole(
+ const Reference< chart2::data::XDataSequence > & xNewSequence,
+ const OUString & rRole )
+{
+ Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
+ if( xSeqProp.is())
+ xSeqProp->setPropertyValue( "Role", uno::Any( rRole ));
+}
+
+void lcl_addSequenceToDataSource(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ const Reference< chart2::data::XDataSequence > & xNewSequence,
+ const OUString & rRole )
+{
+ Reference< chart2::data::XDataSink > xSink( xDataSource, uno::UNO_QUERY );
+ Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
+ if( ! xSink.is() )
+ return;
+
+ Reference< chart2::data::XLabeledDataSequence > xLSeq( chart2::data::LabeledDataSequence::create(xContext), uno::UNO_QUERY_THROW );
+
+ lcl_setRole( xNewSequence, rRole );
+ xLSeq->setValues( xNewSequence );
+ Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
+ xDataSource->getDataSequences());
+ aSequences.realloc( aSequences.getLength() + 1 );
+ auto pSequences = aSequences.getArray();
+ pSequences[ aSequences.getLength() - 1 ] = xLSeq;
+ xSink->setData( aSequences );
+}
+
+void lcl_setXMLRangePropertyAtDataSequence(
+ const Reference< chart2::data::XDataSequence > & xDataSequence,
+ const OUString & rXMLRange )
+{
+ try
+ {
+ static constexpr OUString aXMLRangePropName( u"CachedXMLRange"_ustr);
+ Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
+ Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
+ if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
+ xProp->setPropertyValue( aXMLRangePropName, uno::Any( rXMLRange ));
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+double StatisticsHelper::getVariance(
+ const Sequence< double > & rData )
+{
+ sal_Int32 nValCount;
+ return lcl_getVariance( rData, nValCount );
+}
+
+double StatisticsHelper::getStandardDeviation( const Sequence< double > & rData )
+{
+ double fResult = getVariance( rData );
+ if( ! std::isnan( fResult ))
+ fResult = sqrt( fResult );
+
+ return fResult;
+}
+
+double StatisticsHelper::getStandardError( const Sequence< double > & rData )
+{
+ sal_Int32 nValCount;
+ double fVar = lcl_getVariance( rData, nValCount );
+
+ if( nValCount == 0 || std::isnan( fVar ))
+ return std::numeric_limits<double>::quiet_NaN();
+ // standard-deviation / sqrt(n)
+ return sqrt( fVar ) / sqrt( double(nValCount) );
+}
+
+uno::Reference< chart2::data::XLabeledDataSequence > StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ bool bPositiveValue,
+ bool bYError /* = true */ )
+{
+ uno::Reference< chart2::data::XLabeledDataSequence > xResult;
+ if( !xDataSource.is())
+ return xResult;
+
+ OUString aRole;
+ uno::Reference< chart2::data::XLabeledDataSequence > xLSeq =
+ lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole );
+ if( xLSeq.is())
+ xResult = xLSeq;
+
+ return xResult;
+}
+
+Reference< chart2::data::XDataSequence > StatisticsHelper::getErrorDataSequenceFromDataSource(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ bool bPositiveValue,
+ bool bYError /* = true */ )
+{
+ uno::Reference< chart2::data::XLabeledDataSequence > xLSeq =
+ StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
+ xDataSource, bPositiveValue,
+ bYError );
+ if( !xLSeq.is())
+ return Reference< chart2::data::XDataSequence >();
+
+ return xLSeq->getValues();
+}
+
+double StatisticsHelper::getErrorFromDataSource(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ sal_Int32 nIndex,
+ bool bPositiveValue,
+ bool bYError /* = true */ )
+{
+ double fResult = std::numeric_limits<double>::quiet_NaN();
+
+ Reference< chart2::data::XDataSequence > xValues(
+ StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource, bPositiveValue, bYError ));
+
+ Reference< chart2::data::XNumericalDataSequence > xNumValues( xValues, uno::UNO_QUERY );
+ if( xNumValues.is())
+ {
+ Sequence< double > aData( xNumValues->getNumericalData());
+ if( nIndex < aData.getLength())
+ fResult = aData[nIndex];
+ }
+ else if( xValues.is())
+ {
+ Sequence< uno::Any > aData( xValues->getData());
+ if( nIndex < aData.getLength())
+ aData[nIndex] >>= fResult;
+ }
+
+ return fResult;
+}
+
+void StatisticsHelper::setErrorDataSequence(
+ const Reference< chart2::data::XDataSource > & xDataSource,
+ const Reference< chart2::data::XDataProvider > & xDataProvider,
+ const OUString & rNewRange,
+ bool bPositiveValue,
+ bool bYError /* = true */,
+ OUString const * pXMLRange /* = 0 */ )
+{
+ Reference< chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
+ if( ! ( xDataSink.is() && xDataProvider.is()))
+ return;
+
+ OUString aRole;
+ Reference< chart2::data::XLabeledDataSequence > xLSeq(
+ lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
+ Reference< chart2::data::XDataSequence > xNewSequence(
+ xDataProvider->createDataSequenceByRangeRepresentation( rNewRange ));
+ if( xNewSequence.is())
+ {
+ if( pXMLRange )
+ lcl_setXMLRangePropertyAtDataSequence( xNewSequence, *pXMLRange );
+ if( xLSeq.is())
+ {
+ lcl_setRole( xNewSequence, aRole );
+ xLSeq->setValues( xNewSequence );
+ }
+ else
+ lcl_addSequenceToDataSource( xDataSource, xNewSequence, aRole );
+ }
+}
+
+Reference< beans::XPropertySet > StatisticsHelper::addErrorBars(
+ const rtl::Reference< DataSeries > & xDataSeries,
+ sal_Int32 nStyle,
+ bool bYError /* = true */ )
+{
+ Reference< beans::XPropertySet > xErrorBar;
+ if( !xDataSeries.is())
+ return xErrorBar;
+
+ const OUString aPropName(
+ bYError ? CHART_UNONAME_ERRORBAR_Y : CHART_UNONAME_ERRORBAR_X);
+ if( !( xDataSeries->getPropertyValue( aPropName ) >>= xErrorBar ) ||
+ !xErrorBar.is())
+ {
+ xErrorBar.set( new ErrorBar );
+ }
+
+ OSL_ASSERT( xErrorBar.is());
+ if( xErrorBar.is())
+ {
+ xErrorBar->setPropertyValue( "ErrorBarStyle", uno::Any( nStyle ));
+ }
+
+ xDataSeries->setPropertyValue( aPropName, uno::Any( xErrorBar ));
+
+ return xErrorBar;
+}
+
+Reference< beans::XPropertySet > StatisticsHelper::getErrorBars(
+ const rtl::Reference< DataSeries > & xDataSeries,
+ bool bYError /* = true */ )
+{
+ Reference< beans::XPropertySet > xErrorBar;
+ const OUString aPropName(
+ bYError ? CHART_UNONAME_ERRORBAR_Y : CHART_UNONAME_ERRORBAR_X);
+
+ if ( xDataSeries.is())
+ xDataSeries->getPropertyValue( aPropName ) >>= xErrorBar;
+
+ return xErrorBar;
+}
+
+bool StatisticsHelper::hasErrorBars(
+ const rtl::Reference< DataSeries > & xDataSeries,
+ bool bYError /* = true */ )
+{
+ Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
+ sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
+
+ return ( xErrorBar.is() &&
+ ( xErrorBar->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
+ nStyle != css::chart::ErrorBarStyle::NONE );
+}
+
+void StatisticsHelper::removeErrorBars(
+ const rtl::Reference< DataSeries > & xDataSeries,
+ bool bYError /* = true */ )
+{
+ Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
+ if ( xErrorBar.is())
+ xErrorBar->setPropertyValue( "ErrorBarStyle", uno::Any(
+ css::chart::ErrorBarStyle::NONE ));
+}
+
+bool StatisticsHelper::usesErrorBarRanges(
+ const rtl::Reference< DataSeries > & xDataSeries,
+ bool bYError /* = true */ )
+{
+ Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
+ sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
+
+ return ( xErrorBar.is() &&
+ ( xErrorBar->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
+ nStyle == css::chart::ErrorBarStyle::FROM_DATA );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/ThreeDHelper.cxx b/chart2/source/tools/ThreeDHelper.cxx
new file mode 100644
index 0000000000..5733c6f44b
--- /dev/null
+++ b/chart2/source/tools/ThreeDHelper.cxx
@@ -0,0 +1,826 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ThreeDHelper.hxx>
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ChartType.hxx>
+#include <BaseGFXHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <defines.hxx>
+
+#include <editeng/unoprnms.hxx>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/helpers.hxx>
+#include <rtl/math.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::rtl::math::cos;
+using ::rtl::math::sin;
+using ::rtl::math::tan;
+
+namespace
+{
+
+bool lcl_isRightAngledAxesSetAndSupported( const rtl::Reference< Diagram >& xDiagram )
+{
+ if( xDiagram.is() )
+ {
+ bool bRightAngledAxes = false;
+ xDiagram->getPropertyValue( "RightAngledAxes") >>= bRightAngledAxes;
+ if(bRightAngledAxes)
+ {
+ if( ChartTypeHelper::isSupportingRightAngledAxes(
+ xDiagram->getChartTypeByIndex( 0 ) ) )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} //end anonymous namespace
+
+drawing::CameraGeometry ThreeDHelper::getDefaultCameraGeometry( bool bPie )
+{
+ // ViewReferencePoint (Point on the View plane)
+ drawing::Position3D vrp(17634.6218373783, 10271.4823817647, 24594.8639082739);
+ // ViewPlaneNormal (Normal to the View Plane)
+ drawing::Direction3D vpn(0.416199821709347, 0.173649045905254, 0.892537795986984);
+ // ViewUpVector (determines the v-axis direction on the view plane as
+ // projection of VUP parallel to VPN onto th view pane)
+ drawing::Direction3D vup(-0.0733876362771618, 0.984807599917971, -0.157379306090273);
+
+ if( bPie )
+ {
+ vrp = drawing::Position3D( 0.0, 0.0, 87591.2408759124 );//--> 5 percent perspective
+ vpn = drawing::Direction3D( 0.0, 0.0, 1.0 );
+ vup = drawing::Direction3D( 0.0, 1.0, 0.0 );
+ }
+
+ return drawing::CameraGeometry( vrp, vpn, vup );
+}
+
+namespace
+{
+void lcl_ensureIntervalMinus1To1( double& rSinOrCos )
+{
+ if (rSinOrCos < -1.0)
+ rSinOrCos = -1.0;
+ else if (rSinOrCos > 1.0)
+ rSinOrCos = 1.0;
+}
+
+bool lcl_isSinZero( double fAngleRad )
+{
+ return ::basegfx::fTools::equalZero( sin(fAngleRad), 0.0000001 );
+}
+bool lcl_isCosZero( double fAngleRad )
+{
+ return ::basegfx::fTools::equalZero( cos(fAngleRad), 0.0000001 );
+}
+
+}
+
+void ThreeDHelper::convertElevationRotationDegToXYZAngleRad(
+ sal_Int32 nElevationDeg, sal_Int32 nRotationDeg,
+ double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad)
+{
+ // for a description of the algorithm see issue 72994
+ //https://bz.apache.org/ooo/show_bug.cgi?id=72994
+ //https://bz.apache.org/ooo/attachment.cgi?id=50608
+
+ nElevationDeg = NormAngle360(nElevationDeg);
+ nRotationDeg = NormAngle360(nRotationDeg);
+
+ double& x = rfXAngleRad;
+ double& y = rfYAngleRad;
+ double& z = rfZAngleRad;
+
+ double E = basegfx::deg2rad(nElevationDeg); //elevation in Rad
+ double R = basegfx::deg2rad(nRotationDeg); //rotation in Rad
+
+ if( (nRotationDeg == 0 || nRotationDeg == 180 )
+ && ( nElevationDeg == 90 || nElevationDeg == 270 ) )
+ {
+ //sR==0 && cE==0
+ z = 0.0;
+ //element 23
+ double f23 = cos(R)*sin(E);
+ if(f23>0)
+ x = M_PI_2;
+ else
+ x = -M_PI_2;
+ y = R;
+ }
+ else if( ( nRotationDeg == 90 || nRotationDeg == 270 )
+ && ( nElevationDeg == 90 || nElevationDeg == 270 ) )
+ {
+ //cR==0 && cE==0
+ z = M_PI_2;
+ if( sin(R)>0 )
+ x = M_PI_2;
+ else
+ x = -M_PI_2;
+
+ if( (sin(R)*sin(E))>0 )
+ y = 0.0;
+ else
+ y = M_PI;
+ }
+ else if( (nRotationDeg == 0 || nRotationDeg == 180 )
+ && ( nElevationDeg == 0 || nElevationDeg == 180 ) )
+ {
+ //sR==0 && sE==0
+ z = 0.0;
+ y = R;
+ x = E;
+ }
+ else if( ( nRotationDeg == 90 || nRotationDeg == 270 )
+ && ( nElevationDeg == 0 || nElevationDeg == 180 ) )
+ {
+ //cR==0 && sE==0
+ z = 0.0;
+
+ if( (sin(R)/cos(E))>0 )
+ y = M_PI_2;
+ else
+ y = -M_PI_2;
+
+ if( (cos(E))>0 )
+ x = 0;
+ else
+ x = M_PI;
+ }
+ else if ( nElevationDeg == 0 || nElevationDeg == 180 )
+ {
+ //sR!=0 cR!=0 sE==0
+ z = 0.0;
+ x = E;
+ y = R;
+ //use element 13 for sign
+ if((cos(x)*sin(y)*sin(R))<0.0)
+ y *= -1.0;
+ }
+ else if ( nElevationDeg == 90 || nElevationDeg == 270 )
+ {
+ //sR!=0 cR!=0 cE==0
+ //element 12 + 22 --> y=0 or M_PI and x=+-M_PI/2
+ //-->element 13/23:
+ z = atan(sin(R)/(cos(R)*sin(E)));
+ //use element 13 for sign for x
+ if( (sin(R)*sin(z))>0.0 )
+ x = M_PI_2;
+ else
+ x = -M_PI_2;
+ //use element 21 for y
+ if( (sin(R)*sin(E)*sin(z))>0.0)
+ y = 0.0;
+ else
+ y = M_PI;
+ }
+ else if ( nRotationDeg == 0 || nRotationDeg == 180 )
+ {
+ //sE!=0 cE!=0 sR==0
+ z = 0.0;
+ x = E;
+ y = R;
+ double f23 = cos(R)*sin(E);
+ if( (f23 * sin(x)) < 0.0 )
+ x *= -1.0; //todo ??
+ }
+ else if (nRotationDeg == 90 || nRotationDeg == 270)
+ {
+ //sE!=0 cE!=0 cR==0
+ //z = +- M_PI/2;
+ //x = +- M_PI/2;
+ z = M_PI_2;
+ x = M_PI_2;
+ double sR = sin(R);
+ if( sR<0.0 )
+ x *= -1.0; //different signs for x and z
+
+ //use element 21:
+ double cy = sR*sin(E)/sin(z);
+ lcl_ensureIntervalMinus1To1(cy);
+ y = acos(cy);
+
+ //use element 22 for sign:
+ if( (sin(x)*sin(y)*sin(z)*cos(E))<0.0)
+ y *= -1.0;
+ }
+ else
+ {
+ z = atan(tan(R) * sin(E));
+ if(cos(z)==0.0)
+ {
+ OSL_FAIL("calculation error in ThreeDHelper::convertElevationRotationDegToXYZAngleRad");
+ return;
+ }
+ double cy = cos(R)/cos(z);
+ lcl_ensureIntervalMinus1To1(cy);
+ y = acos(cy);
+
+ //element 12 in 23
+ double fDenominator = cos(z)*(1.0-pow(sin(y),2));
+ if(fDenominator==0.0)
+ {
+ OSL_FAIL("calculation error in ThreeDHelper::convertElevationRotationDegToXYZAngleRad");
+ return;
+ }
+ double sx = cos(R)*sin(E)/fDenominator;
+ lcl_ensureIntervalMinus1To1(sx);
+ x = asin( sx );
+
+ //use element 13 for sign:
+ double f13a = cos(x)*cos(z)*sin(y);
+ double f13b = sin(R)-sx*sin(z);
+ if( (f13b*f13a)<0.0 )
+ {
+ //change x or y
+ //use element 22 for further investigations:
+ //try
+ y *= -1;
+ double f22a = cos(x)*cos(z);
+ double f22b = cos(E)-(sx*sin(y)*sin(z));
+ if( (f22a*f22b)<0.0 )
+ {
+ y *= -1;
+ x=(M_PI-x);
+ }
+ }
+ else
+ {
+ //change nothing or both
+ //use element 22 for further investigations:
+ double f22a = cos(x)*cos(z);
+ double f22b = cos(E)-(sx*sin(y)*sin(z));
+ if( (f22a*f22b)<0.0 )
+ {
+ y *= -1;
+ x=(M_PI-x);
+ }
+ }
+ }
+}
+
+void ThreeDHelper::convertXYZAngleRadToElevationRotationDeg(
+ sal_Int32& rnElevationDeg, sal_Int32& rnRotationDeg,
+ double fXRad, double fYRad, double fZRad)
+{
+ // for a description of the algorithm see issue 72994
+ //https://bz.apache.org/ooo/show_bug.cgi?id=72994
+ //https://bz.apache.org/ooo/attachment.cgi?id=50608
+
+ double R = 0.0; //Rotation in Rad
+ double E = 0.0; //Elevation in Rad
+
+ double& x = fXRad;
+ double& y = fYRad;
+ double& z = fZRad;
+
+ double f11 = cos(y)*cos(z);
+
+ if( lcl_isSinZero(y) )
+ {
+ //siny == 0
+
+ if( lcl_isCosZero(x) )
+ {
+ //siny == 0 && cosx == 0
+
+ if( lcl_isSinZero(z) )
+ {
+ //siny == 0 && cosx == 0 && sinz == 0
+ //example: x=+-90 y=0oder180 z=0(oder180)
+
+ //element 13+11
+ if( f11 > 0 )
+ R = 0.0;
+ else
+ R = M_PI;
+
+ //element 23
+ double f23 = cos(z)*sin(x) / cos(R);
+ if( f23 > 0 )
+ E = M_PI_2;
+ else
+ E = -M_PI_2;
+ }
+ else if( lcl_isCosZero(z) )
+ {
+ //siny == 0 && cosx == 0 && cosz == 0
+ //example: x=+-90 y=0oder180 z=+-90
+
+ double f13 = sin(x)*sin(z);
+ //element 13+11
+ if( f13 > 0 )
+ R = M_PI_2;
+ else
+ R = -M_PI_2;
+
+ //element 21
+ double f21 = cos(y)*sin(z) / sin(R);
+ if( f21 > 0 )
+ E = M_PI_2;
+ else
+ E = -M_PI_2;
+ }
+ else
+ {
+ //siny == 0 && cosx == 0 && cosz != 0 && sinz != 0
+ //element 11 && 13
+ double f13 = sin(x)*sin(z);
+ R = atan( f13/f11 );
+
+ if(f11<0)
+ R+=M_PI;
+
+ //element 23
+ double f23 = cos(z)*sin(x);
+ if( f23/cos(R) > 0 )
+ E = M_PI_2;
+ else
+ E = -M_PI_2;
+ }
+ }
+ else if( lcl_isSinZero(x) )
+ {
+ //sinY==0 sinX==0
+ //element 13+11
+ if( f11 > 0 )
+ R = 0.0;
+ else
+ R = M_PI;
+
+ double f22 = cos(x)*cos(z);
+ if( f22 > 0 )
+ E = 0.0;
+ else
+ E = M_PI;
+ }
+ else if( lcl_isSinZero(z) )
+ {
+ //sinY==0 sinZ==0 sinx!=0 cosx!=0
+ //element 13+11
+ if( f11 > 0 )
+ R = 0.0;
+ else
+ R = M_PI;
+
+ //element 22 && 23
+ double f22 = cos(x)*cos(z);
+ double f23 = cos(z)*sin(x);
+ E = atan( f23/(f22*cos(R)) );
+ if( (f22*cos(E))<0 )
+ E+=M_PI;
+ }
+ else if( lcl_isCosZero(z) )
+ {
+ //sinY == 0 && cosZ == 0 && cosx != 0 && sinx != 0
+ double f13 = sin(x)*sin(z);
+ //element 13+11
+ if( f13 > 0 )
+ R = M_PI_2;
+ else
+ R = -M_PI_2;
+
+ //element 21+22
+ double f21 = cos(y)*sin(z);
+ if( f21/sin(R) > 0 )
+ E = M_PI_2;
+ else
+ E = -M_PI_2;
+ }
+ else
+ {
+ //sinY == 0 && all other !=0
+ double f13 = sin(x)*sin(z);
+ R = atan( f13/f11 );
+ if( (f11*cos(R))<0.0 )
+ R+=M_PI;
+
+ double f22 = cos(x)*cos(z);
+ if( !lcl_isCosZero(R) )
+ E = atan( cos(z)*sin(x) /( f22*cos(R) ) );
+ else
+ E = atan( cos(y)*sin(z) /( f22*sin(R) ) );
+ if( (f22*cos(E))<0 )
+ E+=M_PI;
+ }
+ }
+ else if( lcl_isCosZero(y) )
+ {
+ //cosY==0
+
+ double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y);
+ if( f13 >= 0 )
+ R = M_PI_2;
+ else
+ R = -M_PI_2;
+
+ double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z);
+ if( f22 >= 0 )
+ E = 0.0;
+ else
+ E = M_PI;
+ }
+ else if( lcl_isSinZero(x) )
+ {
+ //cosY!=0 sinY!=0 sinX=0
+ if( lcl_isSinZero(z) )
+ {
+ //cosY!=0 sinY!=0 sinX=0 sinZ=0
+ double f13 = cos(x)*cos(z)*sin(y);
+ R = atan( f13/f11 );
+ //R = asin(f13);
+ if( f11<0 )
+ R+=M_PI;
+
+ double f22 = cos(x)*cos(z);
+ if( f22>0 )
+ E = 0.0;
+ else
+ E = M_PI;
+ }
+ else if( lcl_isCosZero(z) )
+ {
+ //cosY!=0 sinY!=0 sinX=0 cosZ=0
+ R = x;
+ E = y;//or -y
+ //use 23 for 'signs'
+ double f23 = -1.0*cos(x)*sin(y)*sin(z);
+ if( (f23*cos(R)*sin(E))<0.0 )
+ {
+ //change R or E
+ E = -y;
+ }
+ }
+ else
+ {
+ //cosY!=0 sinY!=0 sinX=0 sinZ!=0 cosZ!=0
+ double f13 = cos(x)*cos(z)*sin(y);
+ R = atan( f13/f11 );
+
+ if( f11<0 )
+ R+=M_PI;
+
+ double f21 = cos(y)*sin(z);
+ double f22 = cos(x)*cos(z);
+ E = atan(f21/(f22*sin(R)) );
+
+ if( (f22*cos(E))<0.0 )
+ E+=M_PI;
+ }
+ }
+ else if( lcl_isCosZero(x) )
+ {
+ //cosY!=0 sinY!=0 cosX=0
+
+ if( lcl_isSinZero(z) )
+ {
+ //cosY!=0 sinY!=0 cosX=0 sinZ=0
+ R=0;//13 -> R=0 or M_PI
+ if( f11<0.0 )
+ R=M_PI;
+ E=M_PI_2;//22 -> E=+-M_PI/2
+ //use element 11 and 23 for sign
+ double f23 = cos(z)*sin(x);
+ if( (f11*f23*sin(E))<0.0 )
+ E=-M_PI_2;
+ }
+ else if( lcl_isCosZero(z) )
+ {
+ //cosY!=0 sinY!=0 cosX=0 cosZ=0
+ //element 11 & 13:
+ if( (sin(x)*sin(z))>0.0 )
+ R=M_PI_2;
+ else
+ R=-M_PI_2;
+ //element 22:
+ E=acos( sin(x)*sin(y)*sin(z));
+ //use element 21 for sign:
+ if( (cos(y)*sin(z)*sin(R)*sin(E))<0.0 )
+ E*=-1.0;
+ }
+ else
+ {
+ //cosY!=0 sinY!=0 cosX=0 sinZ!=0 cosZ!=0
+ //element 13/11
+ R = atan( sin(x)*sin(z)/(cos(y)*cos(z)) );
+ //use 13 for 'sign'
+ if( (sin(x)*sin(z))<0.0 )
+ R += M_PI;
+ //element 22
+ E = acos(sin(x)*sin(y)*sin(z) );
+ //use 21 for sign
+ if( (cos(y)*sin(z)*sin(R)*sin(E))<0.0 )
+ E*=-1.0;
+ }
+ }
+ else if( lcl_isSinZero(z) )
+ {
+ //cosY!=0 sinY!=0 sinX!=0 cosX!=0 sinZ=0
+ //element 11
+ R=y;
+ //use element 13 for sign
+ if( (cos(x)*cos(z)*sin(y)*sin(R))<0.0 )
+ R*=-1.0;
+ //element 22
+ E = acos( cos(x)*cos(z) );
+ //use element 23 for sign
+ if( (cos(z)*sin(x)*cos(R)*sin(E))<0.0 )
+ E*=-1.0;
+ }
+ else if( lcl_isCosZero(z) )
+ {
+ //cosY!=0 sinY!=0 sinX!=0 cosX!=0 cosZ=0
+ //element 21/23
+ R=atan(-cos(y)/(cos(x)*sin(y)));
+ //use element 13 for 'sign'
+ if( (sin(x)*sin(z)*sin(R))<0.0 )
+ R+=M_PI;
+ //element 21/22
+ E=atan( cos(y)*sin(z)/(sin(R)*sin(x)*sin(y)*sin(z)) );
+ //use element 23 for 'sign'
+ if( (-cos(x)*sin(y)*sin(z)*cos(R)*sin(E))<0.0 )
+ E+=M_PI;
+ }
+ else
+ {
+ //cosY!=0 sinY!=0 sinX!=0 cosX!=0 sinZ!=0 cosZ!=0
+ //13/11:
+ double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y);
+ R = atan( f13/ f11 );
+ if(f11<0.0)
+ R+=M_PI;
+ double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z);
+ double f23 = cos(x)*sin(y)*sin(z)-cos(z)*sin(x);
+ //23/22:
+ E = atan( -1.0*f23/(f22*cos(R)) );
+ if(f22<0.0)
+ E+=M_PI;
+ }
+
+ rnElevationDeg = basegfx::fround(basegfx::rad2deg(E));
+ rnRotationDeg = basegfx::fround(basegfx::rad2deg(R));
+}
+
+double ThreeDHelper::getValueClippedToRange( double fAngle, const double& fPositivLimit )
+{
+ if( fAngle<-1*fPositivLimit )
+ fAngle=-1*fPositivLimit;
+ else if( fAngle>fPositivLimit )
+ fAngle=fPositivLimit;
+ return fAngle;
+}
+
+void ThreeDHelper::adaptRadAnglesForRightAngledAxes( double& rfXAngleRad, double& rfYAngleRad )
+{
+ rfXAngleRad = ThreeDHelper::getValueClippedToRange(rfXAngleRad, basegfx::deg2rad(ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes()) );
+ rfYAngleRad = ThreeDHelper::getValueClippedToRange(rfYAngleRad, basegfx::deg2rad(ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes()) );
+}
+
+
+void ThreeDHelper::getCameraDistanceRange( double& rfMinimumDistance, double& rfMaximumDistance )
+{
+ rfMinimumDistance = 3.0/4.0*FIXED_SIZE_FOR_3D_CHART_VOLUME;//empiric value
+ rfMaximumDistance = 20.0*FIXED_SIZE_FOR_3D_CHART_VOLUME;//empiric value
+}
+
+void ThreeDHelper::ensureCameraDistanceRange( double& rfCameraDistance )
+{
+ double fMin, fMax;
+ getCameraDistanceRange( fMin, fMax );
+ if( rfCameraDistance < fMin )
+ rfCameraDistance = fMin;
+ if( rfCameraDistance > fMax )
+ rfCameraDistance = fMax;
+}
+
+double ThreeDHelper::CameraDistanceToPerspective( double fCameraDistance )
+{
+ double fMin, fMax;
+ ThreeDHelper::getCameraDistanceRange( fMin, fMax );
+ //fMax <-> 0; fMin <->100
+ //a/x + b = y
+ double a = 100.0*fMax*fMin/(fMax-fMin);
+ double b = -a/fMax;
+
+ double fRet = a/fCameraDistance + b;
+
+ return fRet;
+}
+
+double ThreeDHelper::PerspectiveToCameraDistance( double fPerspective )
+{
+ double fMin, fMax;
+ ThreeDHelper::getCameraDistanceRange( fMin, fMax );
+ //fMax <-> 0; fMin <->100
+ //a/x + b = y
+ double a = 100.0*fMax*fMin/(fMax-fMin);
+ double b = -a/fMax;
+
+ double fRet = a/(fPerspective - b);
+
+ return fRet;
+}
+
+void ThreeDHelper::getRoundedEdgesAndObjectLines(
+ const rtl::Reference< Diagram > & xDiagram
+ , sal_Int32& rnRoundedEdges, sal_Int32& rnObjectLines )
+{
+ rnRoundedEdges = -1;
+ rnObjectLines = -1;
+ try
+ {
+ bool bDifferentRoundedEdges = false;
+ bool bDifferentObjectLines = false;
+
+ drawing::LineStyle aLineStyle( drawing::LineStyle_SOLID );
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesList =
+ xDiagram->getDataSeries();
+ sal_Int32 nSeriesCount = static_cast<sal_Int32>( aSeriesList.size() );
+
+ OUString aPercentDiagonalPropertyName( "PercentDiagonal" );
+ OUString aBorderStylePropertyName( "BorderStyle" );
+
+ for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS )
+ {
+ rtl::Reference< DataSeries > xSeries( aSeriesList[nS] );
+ if(!nS)
+ {
+ rnRoundedEdges = 0;
+ try
+ {
+ sal_Int16 nPercentDiagonal = 0;
+
+ xSeries->getPropertyValue( aPercentDiagonalPropertyName ) >>= nPercentDiagonal;
+ rnRoundedEdges = static_cast< sal_Int32 >( nPercentDiagonal );
+
+ if( DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
+ , aPercentDiagonalPropertyName, uno::Any(nPercentDiagonal) ) )
+ bDifferentRoundedEdges = true;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ bDifferentRoundedEdges = true;
+ }
+ try
+ {
+ xSeries->getPropertyValue( aBorderStylePropertyName ) >>= aLineStyle;
+
+ if( DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
+ , aBorderStylePropertyName, uno::Any(aLineStyle) ) )
+ bDifferentObjectLines = true;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ bDifferentObjectLines = true;
+ }
+ }
+ else
+ {
+ if( !bDifferentRoundedEdges )
+ {
+ sal_Int16 nPercentDiagonal = 0;
+ xSeries->getPropertyValue( aPercentDiagonalPropertyName ) >>= nPercentDiagonal;
+ sal_Int32 nCurrentRoundedEdges = static_cast< sal_Int32 >( nPercentDiagonal );
+ if(nCurrentRoundedEdges!=rnRoundedEdges
+ || DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
+ , aPercentDiagonalPropertyName, uno::Any( static_cast< sal_Int16 >(rnRoundedEdges) ) ) )
+ {
+ bDifferentRoundedEdges = true;
+ }
+ }
+
+ if( !bDifferentObjectLines )
+ {
+ drawing::LineStyle aCurrentLineStyle;
+ xSeries->getPropertyValue( aBorderStylePropertyName ) >>= aCurrentLineStyle;
+ if(aCurrentLineStyle!=aLineStyle
+ || DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
+ , aBorderStylePropertyName, uno::Any(aLineStyle) ) )
+ bDifferentObjectLines = true;
+ }
+ }
+ if( bDifferentRoundedEdges && bDifferentObjectLines )
+ break;
+ }
+
+ //set rnObjectLines
+ rnObjectLines = 0;
+ if( bDifferentObjectLines )
+ rnObjectLines = -1;
+ else if( aLineStyle == drawing::LineStyle_SOLID )
+ rnObjectLines = 1;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ThreeDHelper::setRoundedEdgesAndObjectLines(
+ const rtl::Reference< Diagram > & xDiagram
+ , sal_Int32 nRoundedEdges, sal_Int32 nObjectLines )
+{
+ if( (nRoundedEdges<0||nRoundedEdges>100) && nObjectLines!=0 && nObjectLines!=1 )
+ return;
+
+ drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
+ if(nObjectLines==1)
+ aLineStyle = drawing::LineStyle_SOLID;
+
+ uno::Any aALineStyle( aLineStyle);
+ uno::Any aARoundedEdges( static_cast< sal_Int16 >( nRoundedEdges ));
+
+ std::vector< rtl::Reference< DataSeries > > aSeriesList =
+ xDiagram->getDataSeries();
+ for( auto const& xSeries : aSeriesList)
+ {
+ if( nRoundedEdges>=0 && nRoundedEdges<=100 )
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "PercentDiagonal", aARoundedEdges );
+
+ if( nObjectLines==0 || nObjectLines==1 )
+ DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", aALineStyle );
+ }
+}
+
+CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( const rtl::Reference< ::chart::Diagram >& xDiagram )
+{
+ CuboidPlanePosition eRet(CuboidPlanePosition_Left);
+
+ double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0;
+ xDiagram->getRotationAngle( fXAngleRad, fYAngleRad, fZAngleRad );
+ if( lcl_isRightAngledAxesSetAndSupported( xDiagram ) )
+ {
+ ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad );
+ }
+ if( sin(fYAngleRad)>0.0 )
+ eRet = CuboidPlanePosition_Right;
+ return eRet;
+}
+
+CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( const rtl::Reference< Diagram >& xDiagram )
+{
+ CuboidPlanePosition eRet(CuboidPlanePosition_Back);
+
+ double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0;
+ xDiagram->getRotationAngle( fXAngleRad, fYAngleRad, fZAngleRad );
+ if( lcl_isRightAngledAxesSetAndSupported( xDiagram ) )
+ {
+ ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad );
+ }
+ if( cos(fXAngleRad)*cos(fYAngleRad)<0.0 )
+ eRet = CuboidPlanePosition_Front;
+ return eRet;
+}
+
+CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( const rtl::Reference< Diagram >& xDiagram )
+{
+ CuboidPlanePosition eRet(CuboidPlanePosition_Bottom);
+
+ double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0;
+ xDiagram->getRotationAngle( fXAngleRad, fYAngleRad, fZAngleRad );
+ if( lcl_isRightAngledAxesSetAndSupported( xDiagram ) )
+ {
+ ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad );
+ }
+ if( sin(fXAngleRad)*cos(fYAngleRad)<0.0 )
+ eRet = CuboidPlanePosition_Top;
+ return eRet;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/TitleHelper.cxx b/chart2/source/tools/TitleHelper.cxx
new file mode 100644
index 0000000000..992f5cdf61
--- /dev/null
+++ b/chart2/source/tools/TitleHelper.cxx
@@ -0,0 +1,424 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <TitleHelper.hxx>
+#include <Title.hxx>
+#include <ChartModel.hxx>
+#include <ChartModelHelper.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <Diagram.hxx>
+#include <ReferenceSizeProvider.hxx>
+#include <com/sun/star/chart2/FormattedString.hpp>
+#include <rtl/ustrbuf.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+namespace {
+
+uno::Reference< XTitled > lcl_getTitleParentFromDiagram(
+ TitleHelper::eTitleType nTitleIndex
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ uno::Reference< XTitled > xResult;
+
+ if( nTitleIndex == TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION ||
+ nTitleIndex == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION )
+ {
+ bool bDummy = false;
+ bool bIsVertical = xDiagram && xDiagram->getVertical( bDummy, bDummy );
+
+ if( nTitleIndex == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION )
+ nTitleIndex = bIsVertical ? TitleHelper::X_AXIS_TITLE : TitleHelper::Y_AXIS_TITLE;
+ else
+ nTitleIndex = bIsVertical ? TitleHelper::Y_AXIS_TITLE : TitleHelper::X_AXIS_TITLE;
+ }
+
+ switch( nTitleIndex )
+ {
+ case TitleHelper::SUB_TITLE:
+ if( xDiagram.is())
+ xResult = xDiagram;
+ break;
+ case TitleHelper::X_AXIS_TITLE:
+ if( xDiagram.is())
+ xResult = AxisHelper::getAxis( 0, true, xDiagram );
+ break;
+ case TitleHelper::Y_AXIS_TITLE:
+ if( xDiagram.is())
+ xResult = AxisHelper::getAxis( 1, true, xDiagram );
+ break;
+ case TitleHelper::Z_AXIS_TITLE:
+ if( xDiagram.is())
+ xResult = AxisHelper::getAxis( 2, true, xDiagram );
+ break;
+ case TitleHelper::SECONDARY_X_AXIS_TITLE:
+ if( xDiagram.is())
+ xResult = AxisHelper::getAxis( 0, false, xDiagram );
+ break;
+ case TitleHelper::SECONDARY_Y_AXIS_TITLE:
+ if( xDiagram.is())
+ xResult = AxisHelper::getAxis( 1, false, xDiagram );
+ break;
+
+ case TitleHelper::MAIN_TITLE:
+ default:
+ OSL_FAIL( "Unsupported Title-Type requested" );
+ break;
+ }
+
+ return xResult;
+}
+
+uno::Reference< XTitled > lcl_getTitleParent( TitleHelper::eTitleType nTitleIndex
+ , const rtl::Reference< Diagram >& xDiagram )
+{
+ uno::Reference< XTitled > xResult;
+ switch( nTitleIndex )
+ {
+ case TitleHelper::MAIN_TITLE:
+ SAL_WARN("chart2", "should not be reached");
+ break;
+ case TitleHelper::SUB_TITLE:
+ case TitleHelper::X_AXIS_TITLE:
+ case TitleHelper::Y_AXIS_TITLE:
+ case TitleHelper::Z_AXIS_TITLE:
+ case TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION:
+ case TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION:
+ case TitleHelper::SECONDARY_X_AXIS_TITLE:
+ case TitleHelper::SECONDARY_Y_AXIS_TITLE:
+ xResult.set( lcl_getTitleParentFromDiagram( nTitleIndex, xDiagram ));
+ break;
+ default:
+ OSL_FAIL( "Unsupported Title-Type requested" );
+ break;
+ }
+
+ return xResult;
+}
+
+uno::Reference< XTitled > lcl_getTitleParent( TitleHelper::eTitleType nTitleIndex
+ , const rtl::Reference<::chart::ChartModel>& xModel )
+{
+ if(nTitleIndex == TitleHelper::MAIN_TITLE)
+ {
+ return xModel;
+ }
+
+ rtl::Reference< Diagram > xDiagram;
+
+ if( xModel.is())
+ xDiagram = xModel->getFirstChartDiagram();
+
+ return lcl_getTitleParent( nTitleIndex, xDiagram );
+}
+
+}
+
+rtl::Reference< Title > TitleHelper::getTitle( TitleHelper::eTitleType nTitleIndex
+ , ChartModel& rModel )
+{
+ if(nTitleIndex == TitleHelper::MAIN_TITLE)
+ return rModel.getTitleObject2();
+
+ rtl::Reference< Diagram > xDiagram = rModel.getFirstChartDiagram();
+ uno::Reference< XTitled > xTitled( lcl_getTitleParent( nTitleIndex, xDiagram ) );
+ if( !xTitled )
+ return nullptr;
+ uno::Reference<XTitle> xTitle = xTitled->getTitleObject();
+ auto pTitle = dynamic_cast<Title*>(xTitle.get());
+ assert(!xTitle || pTitle);
+ return pTitle;
+}
+
+rtl::Reference< Title > TitleHelper::getTitle( TitleHelper::eTitleType nTitleIndex
+ , const rtl::Reference<ChartModel>& xModel )
+{
+ uno::Reference< XTitled > xTitled;
+ if(nTitleIndex == TitleHelper::MAIN_TITLE)
+ {
+ xTitled = xModel;
+ }
+ else
+ {
+ rtl::Reference< Diagram > xDiagram;
+ if( xModel.is())
+ xDiagram = xModel->getFirstChartDiagram();
+ xTitled = lcl_getTitleParent( nTitleIndex, xDiagram );
+ }
+ if( !xTitled )
+ return nullptr;
+ uno::Reference<XTitle> xTitle = xTitled->getTitleObject();
+ Title* pTitle = dynamic_cast<Title*>(xTitle.get());
+ assert(!xTitle || pTitle);
+ return pTitle;
+}
+
+rtl::Reference< Title > TitleHelper::createOrShowTitle(
+ TitleHelper::eTitleType eTitleType
+ , const OUString& rTitleText
+ , const rtl::Reference<ChartModel>& xModel
+ , const uno::Reference< uno::XComponentContext > & xContext )
+{
+ rtl::Reference< Title > xTitled( TitleHelper::getTitle( eTitleType, xModel ) );
+ if( xTitled.is())
+ {
+ xTitled->setPropertyValue("Visible",css::uno::Any(true));
+ return xTitled;
+ }
+ else
+ {
+ return createTitle(eTitleType, rTitleText, xModel, xContext, nullptr/*pRefSizeProvider*/);
+ }
+}
+
+rtl::Reference< Title > TitleHelper::createTitle(
+ TitleHelper::eTitleType eTitleType
+ , const OUString& rTitleText
+ , const rtl::Reference<ChartModel>& xModel
+ , const uno::Reference< uno::XComponentContext > & xContext
+ , ReferenceSizeProvider * pRefSizeProvider )
+{
+ rtl::Reference< ::chart::Title > xTitle;
+ uno::Reference< XTitled > xTitled( lcl_getTitleParent( eTitleType, xModel ) );
+
+ if( !xTitled.is() )
+ {
+ rtl::Reference< Diagram > xDiagram( xModel->getFirstChartDiagram() );
+ rtl::Reference< Axis > xAxis;
+ switch( eTitleType )
+ {
+ case TitleHelper::SECONDARY_X_AXIS_TITLE:
+ xAxis = AxisHelper::createAxis( 0, false, xDiagram, xContext );
+ break;
+ case TitleHelper::SECONDARY_Y_AXIS_TITLE:
+ xAxis = AxisHelper::createAxis( 1, false, xDiagram, xContext );
+ break;
+ default:
+ break;
+ }
+ if( xAxis.is() )
+ {
+ xAxis->setPropertyValue( "Show", uno::Any( false ) );
+ xTitled = lcl_getTitleParent( eTitleType, xModel );
+ }
+ }
+
+ if(xTitled.is())
+ {
+ rtl::Reference< Diagram > xDiagram( xModel->getFirstChartDiagram() );
+
+ xTitle = new ::chart::Title();
+
+ // default char height (main: 13.0 == default)
+ float fDefaultCharHeightSub = 11.0;
+ float fDefaultCharHeightAxis = 9.0;
+ switch( eTitleType )
+ {
+ case TitleHelper::SUB_TITLE:
+ TitleHelper::setCompleteString(
+ rTitleText, xTitle, xContext, & fDefaultCharHeightSub );
+ break;
+ case TitleHelper::X_AXIS_TITLE:
+ case TitleHelper::Y_AXIS_TITLE:
+ case TitleHelper::Z_AXIS_TITLE:
+ case TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION:
+ case TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION:
+ case TitleHelper::SECONDARY_X_AXIS_TITLE:
+ case TitleHelper::SECONDARY_Y_AXIS_TITLE:
+ TitleHelper::setCompleteString(
+ rTitleText, xTitle, xContext, & fDefaultCharHeightAxis );
+ break;
+ default:
+ TitleHelper::setCompleteString( rTitleText, xTitle, xContext );
+ break;
+ }
+
+ // set/clear autoscale
+ if( pRefSizeProvider )
+ pRefSizeProvider->setValuesAtTitle( xTitle );
+
+ xTitled->setTitleObject( xTitle );
+
+ //default rotation 90 degree for y axis title in normal coordinatesystems or for x axis title for swapped coordinatesystems
+ if( eTitleType == TitleHelper::X_AXIS_TITLE ||
+ eTitleType == TitleHelper::Y_AXIS_TITLE ||
+ eTitleType == TitleHelper::SECONDARY_X_AXIS_TITLE ||
+ eTitleType == TitleHelper::SECONDARY_Y_AXIS_TITLE )
+
+ {
+ try
+ {
+ bool bDummy = false;
+ bool bIsVertical = xDiagram->getVertical( bDummy, bDummy );
+
+ if( (!bIsVertical && eTitleType == TitleHelper::Y_AXIS_TITLE)
+ || (bIsVertical && eTitleType == TitleHelper::X_AXIS_TITLE)
+ || (!bIsVertical && eTitleType == TitleHelper::SECONDARY_Y_AXIS_TITLE)
+ || (bIsVertical && eTitleType == TitleHelper::SECONDARY_X_AXIS_TITLE) )
+ {
+ xTitle->setPropertyValue( "TextRotation", uno::Any( 90.0 ));
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ return xTitle;
+
+}
+
+OUString TitleHelper::getCompleteString( const rtl::Reference< Title >& xTitle )
+{
+ if(!xTitle.is())
+ return OUString();
+ OUStringBuffer aRet;
+ const uno::Sequence< uno::Reference< XFormattedString > > aStringList = xTitle->getText();
+ for( uno::Reference< XFormattedString > const & formattedStr : aStringList )
+ aRet.append( formattedStr->getString() );
+ return aRet.makeStringAndClear();
+}
+
+void TitleHelper::setCompleteString( const OUString& rNewText
+ , const rtl::Reference< Title >& xTitle
+ , const uno::Reference< uno::XComponentContext > & xContext
+ , const float * pDefaultCharHeight /* = 0 */ )
+{
+ //the format of the first old text portion will be maintained if there is any
+ if(!xTitle.is())
+ return;
+
+ OUString aNewText = rNewText;
+
+ bool bStacked = false;
+ if( xTitle.is() )
+ xTitle->getPropertyValue( "StackCharacters" ) >>= bStacked;
+
+ if( bStacked )
+ {
+ //#i99841# remove linebreaks that were added for vertical stacking
+ OUStringBuffer aUnstackedStr;
+ OUStringBuffer aSource(rNewText);
+
+ bool bBreakIgnored = false;
+ sal_Int32 nLen = rNewText.getLength();
+ for( sal_Int32 nPos = 0; nPos < nLen; ++nPos )
+ {
+ sal_Unicode aChar = aSource[nPos];
+ if( aChar != '\n' )
+ {
+ aUnstackedStr.append( aChar );
+ bBreakIgnored = false;
+ }
+ else if( aChar == '\n' && bBreakIgnored )
+ aUnstackedStr.append( aChar );
+ else
+ bBreakIgnored = true;
+ }
+ aNewText = aUnstackedStr.makeStringAndClear();
+ }
+
+ uno::Sequence< uno::Reference< XFormattedString > > aNewStringList;
+
+ uno::Sequence< uno::Reference< XFormattedString > > aOldStringList = xTitle->getText();
+ if( aOldStringList.hasElements() )
+ {
+ aNewStringList = { aOldStringList[0] };
+ aNewStringList[0]->setString( aNewText );
+ }
+ else
+ {
+ uno::Reference< chart2::XFormattedString2 > xFormattedString =
+ chart2::FormattedString::create( xContext );
+
+ xFormattedString->setString( aNewText );
+ aNewStringList = { xFormattedString };
+ if( pDefaultCharHeight != nullptr )
+ {
+ try
+ {
+ uno::Any aFontSize( *pDefaultCharHeight );
+ xFormattedString->setPropertyValue( "CharHeight", aFontSize );
+ xFormattedString->setPropertyValue( "CharHeightAsian", aFontSize );
+ xFormattedString->setPropertyValue( "CharHeightComplex", aFontSize );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ xTitle->setText( aNewStringList );
+}
+
+void TitleHelper::removeTitle( TitleHelper::eTitleType nTitleIndex
+ , const rtl::Reference<ChartModel>& xModel )
+{
+ uno::Reference< XTitled > xTitled( lcl_getTitleParent( nTitleIndex, xModel ) );
+ if( xTitled.is())
+ {
+ xTitled->setTitleObject(nullptr);
+ }
+}
+
+bool TitleHelper::getTitleType( eTitleType& rType
+ , const rtl::Reference< Title >& xTitle
+ , const rtl::Reference<ChartModel>& xModel )
+{
+ if( !xTitle.is() || !xModel.is() )
+ return false;
+
+ rtl::Reference< Title > xCurrentTitle;
+ for( sal_Int32 nTitleType = TITLE_BEGIN; nTitleType < NORMAL_TITLE_END; nTitleType++ )
+ {
+ xCurrentTitle = TitleHelper::getTitle( static_cast<eTitleType>(nTitleType), xModel );
+ if( xCurrentTitle == xTitle )
+ {
+ rType = static_cast<eTitleType>(nTitleType);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void TitleHelper::hideTitle( TitleHelper::eTitleType nTitleIndex
+ , const rtl::Reference<ChartModel>& xModel)
+{
+ uno::Reference< chart2::XTitle > xTitled( TitleHelper::getTitle( nTitleIndex, xModel ) );
+ if( xTitled.is())
+ {
+ css::uno::Reference<css::beans::XPropertySet> xProps(xTitled, css::uno::UNO_QUERY_THROW);
+ xProps->setPropertyValue("Visible",css::uno::Any(false));
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/UncachedDataSequence.cxx b/chart2/source/tools/UncachedDataSequence.cxx
new file mode 100644
index 0000000000..7211daedba
--- /dev/null
+++ b/chart2/source/tools/UncachedDataSequence.cxx
@@ -0,0 +1,317 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <UncachedDataSequence.hxx>
+#include <CommonFunctors.hxx>
+#include <ModifyListenerHelper.hxx>
+#include <InternalDataProvider.hxx>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <algorithm>
+#include <strings.hrc>
+#include <ResId.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::osl::MutexGuard;
+
+// necessary for MS compiler
+using ::comphelper::OPropertyContainer;
+using ::chart::impl::UncachedDataSequence_Base;
+
+namespace
+{
+constexpr OUString lcl_aServiceName = u"com.sun.star.comp.chart.UncachedDataSequence"_ustr;
+
+enum
+{
+ PROP_NUMBERFORMAT_KEY,
+ PROP_PROPOSED_ROLE,
+ PROP_XML_RANGE
+};
+} // anonymous namespace
+
+namespace chart
+{
+
+UncachedDataSequence::UncachedDataSequence(
+ rtl::Reference< InternalDataProvider > xIntDataProv,
+ OUString aRangeRepresentation )
+ : OPropertyContainer( GetBroadcastHelper()),
+ UncachedDataSequence_Base( GetMutex()),
+ m_nNumberFormatKey(0),
+ m_xDataProvider(std::move( xIntDataProv )),
+ m_aSourceRepresentation(std::move( aRangeRepresentation )),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ registerProperties();
+}
+
+UncachedDataSequence::UncachedDataSequence(
+ rtl::Reference< InternalDataProvider > xIntDataProv,
+ OUString aRangeRepresentation,
+ const OUString & rRole )
+ : OPropertyContainer( GetBroadcastHelper()),
+ UncachedDataSequence_Base( GetMutex()),
+ m_nNumberFormatKey(0),
+ m_xDataProvider(std::move( xIntDataProv )),
+ m_aSourceRepresentation(std::move( aRangeRepresentation )),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ registerProperties();
+ setFastPropertyValue_NoBroadcast( PROP_PROPOSED_ROLE, uno::Any( rRole ));
+}
+
+UncachedDataSequence::UncachedDataSequence( const UncachedDataSequence & rSource )
+ : OPropertyContainer( GetBroadcastHelper()),
+ UncachedDataSequence_Base( GetMutex()),
+ m_nNumberFormatKey( rSource.m_nNumberFormatKey ),
+ m_sRole( rSource.m_sRole ),
+ m_xDataProvider( rSource.m_xDataProvider ),
+ m_aSourceRepresentation( rSource.m_aSourceRepresentation ),
+ m_xModifyEventForwarder( new ModifyEventForwarder() )
+{
+ registerProperties();
+}
+
+UncachedDataSequence::~UncachedDataSequence()
+{}
+
+void UncachedDataSequence::registerProperties()
+{
+ registerProperty( "NumberFormatKey",
+ PROP_NUMBERFORMAT_KEY,
+ 0, // PropertyAttributes
+ & m_nNumberFormatKey,
+ cppu::UnoType<decltype(m_nNumberFormatKey)>::get() );
+
+ registerProperty( "Role",
+ PROP_PROPOSED_ROLE,
+ 0, // PropertyAttributes
+ & m_sRole,
+ cppu::UnoType<decltype(m_sRole)>::get() );
+
+ registerProperty( "CachedXMLRange",
+ PROP_XML_RANGE,
+ 0, // PropertyAttributes
+ & m_aXMLRange,
+ cppu::UnoType<decltype(m_aXMLRange)>::get() );
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2( UncachedDataSequence, UncachedDataSequence_Base, OPropertyContainer )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( UncachedDataSequence, UncachedDataSequence_Base, OPropertyContainer )
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL UncachedDataSequence::getPropertySetInfo()
+{
+ return createPropertySetInfo( getInfoHelper() );
+}
+
+// ____ ::comphelper::OPropertySetHelper ____
+::cppu::IPropertyArrayHelper& UncachedDataSequence::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+// ____ ::comphelper::OPropertyArrayHelper ____
+::cppu::IPropertyArrayHelper* UncachedDataSequence::createArrayHelper() const
+{
+ Sequence< beans::Property > aProps;
+ // describes all properties which have been registered in the ctor
+ describeProperties( aProps );
+
+ return new ::cppu::OPropertyArrayHelper( aProps );
+}
+
+OUString SAL_CALL UncachedDataSequence::getImplementationName()
+{
+ return lcl_aServiceName;
+}
+
+sal_Bool SAL_CALL UncachedDataSequence::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL UncachedDataSequence::getSupportedServiceNames()
+{
+ return {
+ lcl_aServiceName,
+ "com.sun.star.chart2.data.DataSequence",
+ "com.sun.star.chart2.data.NumericalDataSequence",
+ "com.sun.star.chart2.data.TextualDataSequence"
+ };
+}
+
+// ________ XNumericalDataSequence ________
+Sequence< double > SAL_CALL UncachedDataSequence::getNumericalData()
+{
+ Sequence< double > aResult;
+ MutexGuard aGuard( GetMutex() );
+ if( m_xDataProvider.is())
+ {
+ const Sequence< uno::Any > aValues( m_xDataProvider->getDataByRangeRepresentation( m_aSourceRepresentation ));
+ aResult.realloc( aValues.getLength());
+ std::transform( aValues.begin(), aValues.end(),
+ aResult.getArray(), CommonFunctors::AnyToDouble());
+ }
+ return aResult;
+}
+
+// ________ XTextualDataSequence ________
+Sequence< OUString > SAL_CALL UncachedDataSequence::getTextualData()
+{
+ Sequence< OUString > aResult;
+ MutexGuard aGuard( GetMutex() );
+ if( m_xDataProvider.is())
+ {
+ const Sequence< uno::Any > aValues( m_xDataProvider->getDataByRangeRepresentation( m_aSourceRepresentation ));
+ aResult.realloc( aValues.getLength());
+ std::transform( aValues.begin(), aValues.end(),
+ aResult.getArray(), CommonFunctors::AnyToString());
+ }
+ return aResult;
+}
+
+// ________ XDataSequence ________
+Sequence< Any > SAL_CALL UncachedDataSequence::getData()
+{
+ MutexGuard aGuard( GetMutex() );
+ if( m_xDataProvider.is())
+ return m_xDataProvider->getDataByRangeRepresentation( m_aSourceRepresentation );
+ return Sequence< Any >();
+}
+
+OUString SAL_CALL UncachedDataSequence::getSourceRangeRepresentation()
+{
+ return getName();
+}
+
+Sequence< OUString > SAL_CALL UncachedDataSequence::generateLabel( chart2::data::LabelOrigin )
+{
+ // auto-generated label
+ sal_Int32 nSeries = m_aSourceRepresentation.toInt32() + 1;
+ OUString aResString(::chart::SchResId(STR_DATA_UNNAMED_SERIES_WITH_INDEX));
+ static constexpr OUString aReplacementStr(u"%NUMBER"_ustr);
+ sal_Int32 nIndex = aResString.indexOf(aReplacementStr);
+ OUString aName;
+ if( nIndex != -1 )
+ aName = aResString.replaceAt(nIndex, aReplacementStr.getLength(), OUString::number(nSeries));
+ return Sequence< OUString >( &aName, 1 );
+}
+
+::sal_Int32 SAL_CALL UncachedDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 )
+{
+ return m_nNumberFormatKey;
+}
+
+// ____ XIndexReplace ____
+void SAL_CALL UncachedDataSequence::replaceByIndex( ::sal_Int32 Index, const uno::Any& Element )
+{
+ MutexGuard aGuard( GetMutex() );
+ Sequence< Any > aData( getData());
+ if( Index < aData.getLength() &&
+ m_xDataProvider.is() )
+ {
+ aData.getArray()[Index] = Element;
+ m_xDataProvider->setDataByRangeRepresentation( m_aSourceRepresentation, aData );
+ fireModifyEvent();
+ }
+}
+
+// ____ XIndexAccess (base of XIndexReplace) ____
+::sal_Int32 SAL_CALL UncachedDataSequence::getCount()
+{
+ OSL_FAIL( "Implement!" );
+ return 0;
+}
+
+uno::Any SAL_CALL UncachedDataSequence::getByIndex( ::sal_Int32 )
+{
+ OSL_FAIL( "Implement!" );
+ return uno::Any();
+}
+
+// ____ XElementAccess (base of XIndexAccess) ____
+uno::Type SAL_CALL UncachedDataSequence::getElementType()
+{
+ return cppu::UnoType<uno::Any>::get();
+}
+
+sal_Bool SAL_CALL UncachedDataSequence::hasElements()
+{
+ if( ! m_xDataProvider.is())
+ return false;
+ return m_xDataProvider->hasDataByRangeRepresentation( m_aSourceRepresentation );
+}
+
+// ____ XNamed ____
+OUString SAL_CALL UncachedDataSequence::getName()
+{
+ return m_aSourceRepresentation;
+}
+
+void SAL_CALL UncachedDataSequence::setName( const OUString& aName )
+{
+ m_aSourceRepresentation = aName;
+ fireModifyEvent();
+}
+
+Reference< util::XCloneable > SAL_CALL UncachedDataSequence::createClone()
+{
+ return new UncachedDataSequence( *this );
+}
+
+// ____ XModifiable ____
+sal_Bool SAL_CALL UncachedDataSequence::isModified()
+{
+ return false;
+}
+
+void SAL_CALL UncachedDataSequence::setModified( sal_Bool bModified )
+{
+ if( bModified )
+ fireModifyEvent();
+}
+
+// ____ XModifyBroadcaster (base of XModifiable) ____
+void SAL_CALL UncachedDataSequence::addModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->addModifyListener( aListener );
+}
+
+void SAL_CALL UncachedDataSequence::removeModifyListener( const Reference< util::XModifyListener >& aListener )
+{
+ m_xModifyEventForwarder->removeModifyListener( aListener );
+}
+
+void UncachedDataSequence::fireModifyEvent()
+{
+ // @todo: currently never called, as data changes are not yet reported by
+ // the data provider
+ m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/UserDefinedProperties.cxx b/chart2/source/tools/UserDefinedProperties.cxx
new file mode 100644
index 0000000000..f610ae0f74
--- /dev/null
+++ b/chart2/source/tools/UserDefinedProperties.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <UserDefinedProperties.hxx>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <cppu/unotype.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::beans::Property;
+
+namespace chart
+{
+
+void UserDefinedProperties::AddPropertiesToVector(
+ std::vector< Property > & rOutProperties )
+{
+ rOutProperties.emplace_back( "ChartUserDefinedAttributes",
+ PROP_XML_USERDEF_CHART,
+ cppu::UnoType<container::XNameContainer>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "TextUserDefinedAttributes",
+ PROP_XML_USERDEF_TEXT,
+ cppu::UnoType<container::XNameContainer>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ rOutProperties.emplace_back( "ParaUserDefinedAttributes",
+ PROP_XML_USERDEF_PARA,
+ cppu::UnoType<container::XNameContainer>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+ // UserDefinedAttributesSupplier
+ rOutProperties.emplace_back( "UserDefinedAttributes",
+ PROP_XML_USERDEF,
+ cppu::UnoType<container::XNameContainer>::get(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::MAYBEVOID );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/WeakListenerAdapter.cxx b/chart2/source/tools/WeakListenerAdapter.cxx
new file mode 100644
index 0000000000..16b3d81503
--- /dev/null
+++ b/chart2/source/tools/WeakListenerAdapter.cxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WeakListenerAdapter.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+WeakSelectionChangeListenerAdapter::WeakSelectionChangeListenerAdapter(
+ const Reference< view::XSelectionChangeListener > & xListener ) :
+ WeakListenerAdapter< css::view::XSelectionChangeListener >( xListener )
+{}
+
+WeakSelectionChangeListenerAdapter::~WeakSelectionChangeListenerAdapter()
+{}
+
+void SAL_CALL WeakSelectionChangeListenerAdapter::selectionChanged( const lang::EventObject& aEvent )
+{
+ Reference< view::XSelectionChangeListener > xSelChgListener( getListener() );
+ if( xSelChgListener.is())
+ xSelChgListener->selectionChanged( aEvent );
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/WrappedDefaultProperty.cxx b/chart2/source/tools/WrappedDefaultProperty.cxx
new file mode 100644
index 0000000000..00a94493ea
--- /dev/null
+++ b/chart2/source/tools/WrappedDefaultProperty.cxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WrappedDefaultProperty.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+WrappedDefaultProperty::WrappedDefaultProperty(
+ const OUString& rOuterName, const OUString& rInnerName,
+ uno::Any aNewOuterDefault ) :
+ WrappedProperty( rOuterName, rInnerName ),
+ m_aOuterDefaultValue(std::move( aNewOuterDefault ))
+{}
+
+WrappedDefaultProperty::~WrappedDefaultProperty()
+{}
+
+void WrappedDefaultProperty::setPropertyToDefault(
+ const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ Reference< beans::XPropertySet > xInnerPropSet( xInnerPropertyState, uno::UNO_QUERY );
+ if( xInnerPropSet.is())
+ setPropertyValue( m_aOuterDefaultValue, xInnerPropSet );
+}
+
+uno::Any WrappedDefaultProperty::getPropertyDefault(
+ const Reference< beans::XPropertyState >& /* xInnerPropertyState */ ) const
+{
+ return m_aOuterDefaultValue;
+}
+
+beans::PropertyState WrappedDefaultProperty::getPropertyState(
+ const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ beans::PropertyState aState = beans::PropertyState_DIRECT_VALUE;
+ try
+ {
+ Reference< beans::XPropertySet > xInnerProp( xInnerPropertyState, uno::UNO_QUERY_THROW );
+ uno::Any aValue = getPropertyValue( xInnerProp );
+ if( m_aOuterDefaultValue == convertInnerToOuterValue( aValue ))
+ aState = beans::PropertyState_DEFAULT_VALUE;
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return aState;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/WrappedDirectStateProperty.cxx b/chart2/source/tools/WrappedDirectStateProperty.cxx
new file mode 100644
index 0000000000..ff74fac8c1
--- /dev/null
+++ b/chart2/source/tools/WrappedDirectStateProperty.cxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WrappedDirectStateProperty.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+WrappedDirectStateProperty::WrappedDirectStateProperty(
+ const OUString& rOuterName, const OUString& rInnerName ) :
+ WrappedProperty( rOuterName, rInnerName )
+{}
+
+WrappedDirectStateProperty::~WrappedDirectStateProperty()
+{}
+
+beans::PropertyState WrappedDirectStateProperty::getPropertyState(
+ const Reference< beans::XPropertyState >& /* xInnerPropertyState */ ) const
+{
+ return beans::PropertyState_DIRECT_VALUE;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/WrappedIgnoreProperty.cxx b/chart2/source/tools/WrappedIgnoreProperty.cxx
new file mode 100644
index 0000000000..4e62dca5bd
--- /dev/null
+++ b/chart2/source/tools/WrappedIgnoreProperty.cxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WrappedIgnoreProperty.hxx>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/RectanglePoint.hpp>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+WrappedIgnoreProperty::WrappedIgnoreProperty( const OUString& rOuterName, const Any& rDefaultValue )
+ : WrappedProperty( rOuterName, OUString() )
+ , m_aDefaultValue( rDefaultValue )
+ , m_aCurrentValue( rDefaultValue )
+{
+}
+WrappedIgnoreProperty::~WrappedIgnoreProperty()
+{
+}
+
+void WrappedIgnoreProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& /* xInnerPropertySet */ ) const
+{
+ m_aCurrentValue = rOuterValue;
+}
+
+Any WrappedIgnoreProperty::getPropertyValue( const Reference< beans::XPropertySet >& /* xInnerPropertySet */ ) const
+{
+ return m_aCurrentValue;
+}
+
+void WrappedIgnoreProperty::setPropertyToDefault( const Reference< beans::XPropertyState >& /* xInnerPropertyState */ ) const
+{
+ m_aCurrentValue = m_aDefaultValue;
+}
+
+Any WrappedIgnoreProperty::getPropertyDefault( const Reference< beans::XPropertyState >& /* xInnerPropertyState */ ) const
+{
+ return m_aDefaultValue;
+}
+
+beans::PropertyState WrappedIgnoreProperty::getPropertyState( const Reference< beans::XPropertyState >& /* xInnerPropertyState */ ) const
+{
+ return ( m_aCurrentValue == m_aDefaultValue
+ ? beans::PropertyState_DEFAULT_VALUE
+ : beans::PropertyState_DIRECT_VALUE );
+}
+
+void WrappedIgnoreProperties::addIgnoreLineProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList )
+{
+ rList.emplace_back( new WrappedIgnoreProperty( "LineStyle", uno::Any( drawing::LineStyle_SOLID ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "LineDashName", uno::Any( OUString() ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "LineColor", uno::Any( sal_Int32(0) ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "LineTransparence", uno::Any( sal_Int16(0) ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "LineWidth", uno::Any( sal_Int32(0) ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "LineJoint", uno::Any( drawing::LineJoint_ROUND ) ) );
+}
+
+void WrappedIgnoreProperties::addIgnoreFillProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList )
+{
+ addIgnoreFillProperties_without_BitmapProperties( rList );
+ addIgnoreFillProperties_only_BitmapProperties( rList );
+}
+
+void WrappedIgnoreProperties::addIgnoreFillProperties_without_BitmapProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList )
+{
+ rList.emplace_back( new WrappedIgnoreProperty( "FillStyle", uno::Any( drawing::FillStyle_SOLID ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillColor", uno::Any( sal_Int32(-1) ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillTransparence", uno::Any( sal_Int16(0) ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillTransparenceGradientName", uno::Any( OUString() ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillGradientName", uno::Any( OUString() ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillHatchName", uno::Any( OUString() ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillBackground", uno::Any( false ) ) );
+}
+
+void WrappedIgnoreProperties::addIgnoreFillProperties_only_BitmapProperties( std::vector< std::unique_ptr<WrappedProperty> >& rList )
+{
+ rList.emplace_back( new WrappedIgnoreProperty( "FillBitmapOffsetX", uno::Any( sal_Int16(0) ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillBitmapOffsetY", uno::Any( sal_Int16(0) ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillBitmapPositionOffsetX", uno::Any( sal_Int16(0) ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillBitmapPositionOffsetY", uno::Any( sal_Int16(0) ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillBitmapRectanglePoint", uno::Any( drawing::RectanglePoint_LEFT_TOP ) ) );
+ rList.emplace_back( new WrappedIgnoreProperty( "FillBitmapLogicalSize", uno::Any( false ) ) );//todo correct default?
+ rList.emplace_back( new WrappedIgnoreProperty( "FillBitmapSizeX", uno::Any( sal_Int32(10) ) ) );//todo which default?
+ rList.emplace_back( new WrappedIgnoreProperty( "FillBitmapSizeY", uno::Any( sal_Int32(10) ) ) );//todo which default?
+ rList.emplace_back( new WrappedIgnoreProperty( "FillBitmapMode", uno::Any( drawing::BitmapMode_REPEAT ) ) );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/WrappedProperty.cxx b/chart2/source/tools/WrappedProperty.cxx
new file mode 100644
index 0000000000..8b0891c770
--- /dev/null
+++ b/chart2/source/tools/WrappedProperty.cxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WrappedProperty.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+WrappedProperty::WrappedProperty( OUString aOuterName, OUString aInnerName)
+ : m_aOuterName(std::move( aOuterName ))
+ , m_aInnerName(std::move( aInnerName ))
+{
+}
+WrappedProperty::~WrappedProperty()
+{
+}
+
+OUString WrappedProperty::getInnerName() const
+{
+ return m_aInnerName;
+}
+
+Any WrappedProperty::convertInnerToOuterValue( const Any& rInnerValue ) const
+{
+ return rInnerValue;
+}
+Any WrappedProperty::convertOuterToInnerValue( const Any& rOuterValue ) const
+{
+ return rOuterValue;
+}
+
+void WrappedProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ if(xInnerPropertySet.is())
+ xInnerPropertySet->setPropertyValue( getInnerName(), convertOuterToInnerValue( rOuterValue ) );
+}
+
+Any WrappedProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
+{
+ Any aRet;
+ if( xInnerPropertySet.is() )
+ {
+ aRet = xInnerPropertySet->getPropertyValue( getInnerName() );
+ aRet = convertInnerToOuterValue( aRet );
+ }
+ return aRet;
+}
+
+void WrappedProperty::setPropertyToDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ if( xInnerPropertyState.is() && !getInnerName().isEmpty() )
+ xInnerPropertyState->setPropertyToDefault(getInnerName());
+ else
+ {
+ Reference< beans::XPropertySet > xInnerProp( xInnerPropertyState, uno::UNO_QUERY );
+ setPropertyValue( getPropertyDefault( xInnerPropertyState ), xInnerProp );
+ }
+}
+
+Any WrappedProperty::getPropertyDefault( const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ Any aRet;
+ if( xInnerPropertyState.is() )
+ {
+ aRet = xInnerPropertyState->getPropertyDefault( getInnerName() );
+ aRet = convertInnerToOuterValue( aRet );
+ }
+ return aRet;
+}
+
+beans::PropertyState WrappedProperty::getPropertyState( const Reference< beans::XPropertyState >& xInnerPropertyState ) const
+{
+ beans::PropertyState aState = beans::PropertyState_DIRECT_VALUE;
+ OUString aInnerName( getInnerName() );
+ if( xInnerPropertyState.is() && !aInnerName.isEmpty() )
+ aState = xInnerPropertyState->getPropertyState( aInnerName );
+ else
+ {
+ try
+ {
+ Reference< beans::XPropertySet > xInnerProp( xInnerPropertyState, uno::UNO_QUERY );
+ uno::Any aValue = getPropertyValue( xInnerProp );
+ if( !aValue.hasValue() )
+ aState = beans::PropertyState_DEFAULT_VALUE;
+ else
+ {
+ uno::Any aDefault = getPropertyDefault( xInnerPropertyState );
+ if( aValue == aDefault )
+ aState = beans::PropertyState_DEFAULT_VALUE;
+ }
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ return aState;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/WrappedPropertySet.cxx b/chart2/source/tools/WrappedPropertySet.cxx
new file mode 100644
index 0000000000..9eee3f8632
--- /dev/null
+++ b/chart2/source/tools/WrappedPropertySet.cxx
@@ -0,0 +1,445 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <WrappedPropertySet.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+
+namespace chart
+{
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+WrappedPropertySet::WrappedPropertySet()
+{
+}
+WrappedPropertySet::~WrappedPropertySet()
+{
+ clearWrappedPropertySet();
+}
+
+Reference< beans::XPropertyState > WrappedPropertySet::getInnerPropertyState()
+{
+ return Reference< beans::XPropertyState >( getInnerPropertySet(), uno::UNO_QUERY );
+}
+
+void WrappedPropertySet::clearWrappedPropertySet()
+{
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );//do not use different mutex than is already used for static property sequence
+
+ m_pPropertyArrayHelper.reset();
+ m_pWrappedPropertyMap.reset();
+
+ m_xInfo = nullptr;
+}
+
+//XPropertySet
+Reference< beans::XPropertySetInfo > SAL_CALL WrappedPropertySet::getPropertySetInfo( )
+{
+ Reference< beans::XPropertySetInfo > xInfo = m_xInfo;
+ if( !xInfo.is() )
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );//do not use different mutex than is already used for static property sequence
+ xInfo = m_xInfo;
+ if( !xInfo.is() )
+ {
+ xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() );
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ m_xInfo = xInfo;
+ }
+ }
+ else
+ {
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ }
+ return m_xInfo;
+}
+
+void SAL_CALL WrappedPropertySet::setPropertyValue( const OUString& rPropertyName, const Any& rValue )
+{
+ try
+ {
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( nHandle );
+ Reference< beans::XPropertySet > xInnerPropertySet( getInnerPropertySet() );
+ if( pWrappedProperty )
+ pWrappedProperty->setPropertyValue( rValue, xInnerPropertySet );
+ else if( xInnerPropertySet.is() )
+ xInnerPropertySet->setPropertyValue( rPropertyName, rValue );
+ else
+ {
+ SAL_WARN("chart2.tools", "found no inner property set to map to");
+ }
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ throw;
+ }
+ catch( const beans::PropertyVetoException& )
+ {
+ throw;
+ }
+ catch( const lang::IllegalArgumentException& )
+ {
+ throw;
+ }
+ catch( const lang::WrappedTargetException& )
+ {
+ throw;
+ }
+ catch( const uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( const uno::Exception& ex )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ TOOLS_WARN_EXCEPTION( "chart2", "invalid exception caught in WrappedPropertySet::setPropertyValue");
+ throw lang::WrappedTargetException( ex.Message, nullptr, anyEx );
+ }
+}
+Any SAL_CALL WrappedPropertySet::getPropertyValue( const OUString& rPropertyName )
+{
+ Any aRet;
+
+ try
+ {
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( nHandle );
+ Reference< beans::XPropertySet > xInnerPropertySet( getInnerPropertySet() );
+ if( pWrappedProperty )
+ aRet = pWrappedProperty->getPropertyValue( xInnerPropertySet );
+ else if( xInnerPropertySet.is() )
+ aRet = xInnerPropertySet->getPropertyValue( rPropertyName );
+ else
+ {
+ SAL_WARN("chart2.tools", "found no inner property set to map to");
+ }
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ throw;
+ }
+ catch( const lang::WrappedTargetException& )
+ {
+ throw;
+ }
+ catch( const uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( const uno::Exception& ex )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ TOOLS_WARN_EXCEPTION( "chart2", "invalid exception caught in WrappedPropertySet::setPropertyValue");
+ throw lang::WrappedTargetException( ex.Message, nullptr, anyEx );
+ }
+
+ return aRet;
+}
+
+void SAL_CALL WrappedPropertySet::addPropertyChangeListener( const OUString& rPropertyName, const Reference< beans::XPropertyChangeListener >& xListener )
+{
+ Reference< beans::XPropertySet > xInnerPropertySet( getInnerPropertySet() );
+ if( xInnerPropertySet.is() )
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName );
+ if( pWrappedProperty )
+ xInnerPropertySet->addPropertyChangeListener( pWrappedProperty->getInnerName(), xListener );
+ else
+ xInnerPropertySet->addPropertyChangeListener( rPropertyName, xListener );
+ }
+}
+void SAL_CALL WrappedPropertySet::removePropertyChangeListener( const OUString& rPropertyName, const Reference< beans::XPropertyChangeListener >& aListener )
+{
+ Reference< beans::XPropertySet > xInnerPropertySet( getInnerPropertySet() );
+ if( xInnerPropertySet.is() )
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName );
+ if( pWrappedProperty )
+ xInnerPropertySet->removePropertyChangeListener( pWrappedProperty->getInnerName(), aListener );
+ else
+ xInnerPropertySet->removePropertyChangeListener( rPropertyName, aListener );
+ }
+}
+void SAL_CALL WrappedPropertySet::addVetoableChangeListener( const OUString& rPropertyName, const Reference< beans::XVetoableChangeListener >& aListener )
+{
+ Reference< beans::XPropertySet > xInnerPropertySet( getInnerPropertySet() );
+ if( xInnerPropertySet.is() )
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName );
+ if( pWrappedProperty )
+ xInnerPropertySet->addVetoableChangeListener( pWrappedProperty->getInnerName(), aListener );
+ else
+ xInnerPropertySet->addVetoableChangeListener( rPropertyName, aListener );
+ }
+}
+void SAL_CALL WrappedPropertySet::removeVetoableChangeListener( const OUString& rPropertyName, const Reference< beans::XVetoableChangeListener >& aListener )
+{
+ Reference< beans::XPropertySet > xInnerPropertySet( getInnerPropertySet() );
+ if( xInnerPropertySet.is() )
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName );
+ if( pWrappedProperty )
+ xInnerPropertySet->removeVetoableChangeListener( pWrappedProperty->getInnerName(), aListener );
+ else
+ xInnerPropertySet->removeVetoableChangeListener( rPropertyName, aListener );
+ }
+}
+
+//XMultiPropertySet
+void SAL_CALL WrappedPropertySet::setPropertyValues( const Sequence< OUString >& rNameSeq, const Sequence< Any >& rValueSeq )
+{
+ bool bUnknownProperty = false;
+ sal_Int32 nMinCount = std::min( rValueSeq.getLength(), rNameSeq.getLength() );
+ for(sal_Int32 nN=0; nN<nMinCount; nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ try
+ {
+ setPropertyValue( aPropertyName, rValueSeq[nN] );
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ bUnknownProperty = true;
+ }
+ }
+ //todo: store unknown properties elsewhere
+ OSL_ENSURE(!bUnknownProperty,"unknown property");
+// if( bUnknownProperty )
+// throw beans::UnknownPropertyException();
+}
+Sequence< Any > SAL_CALL WrappedPropertySet::getPropertyValues( const Sequence< OUString >& rNameSeq )
+{
+ Sequence< Any > aRetSeq;
+ if( rNameSeq.hasElements() )
+ {
+ aRetSeq.realloc( rNameSeq.getLength() );
+ auto pRetSeq = aRetSeq.getArray();
+ for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++)
+ {
+ try
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ pRetSeq[nN] = getPropertyValue( aPropertyName );
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ catch( const lang::WrappedTargetException& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ }
+ return aRetSeq;
+}
+void SAL_CALL WrappedPropertySet::addPropertiesChangeListener( const Sequence< OUString >& /* rNameSeq */, const Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented yet");
+ //todo
+}
+void SAL_CALL WrappedPropertySet::removePropertiesChangeListener( const Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented yet");
+ //todo
+}
+void SAL_CALL WrappedPropertySet::firePropertiesChangeEvent( const Sequence< OUString >& /* rNameSeq */, const Reference< beans::XPropertiesChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented yet");
+ //todo
+}
+
+//XPropertyState
+beans::PropertyState SAL_CALL WrappedPropertySet::getPropertyState( const OUString& rPropertyName )
+{
+ beans::PropertyState aState( beans::PropertyState_DIRECT_VALUE );
+
+ Reference< beans::XPropertyState > xInnerPropertyState( getInnerPropertyState() );
+ if( xInnerPropertyState.is() )
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName );
+ if( pWrappedProperty )
+ aState = pWrappedProperty->getPropertyState( xInnerPropertyState );
+ else
+ aState = xInnerPropertyState->getPropertyState( rPropertyName );
+ }
+ return aState;
+}
+
+const WrappedProperty* WrappedPropertySet::getWrappedProperty( const OUString& rOuterName )
+{
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( rOuterName );
+ return getWrappedProperty( nHandle );
+}
+
+const WrappedProperty* WrappedPropertySet::getWrappedProperty( sal_Int32 nHandle )
+{
+ tWrappedPropertyMap::const_iterator aFound( getWrappedPropertyMap().find( nHandle ) );
+ if( aFound != getWrappedPropertyMap().end() )
+ return (*aFound).second.get();
+ return nullptr;
+}
+
+Sequence< beans::PropertyState > SAL_CALL WrappedPropertySet::getPropertyStates( const Sequence< OUString >& rNameSeq )
+{
+ Sequence< beans::PropertyState > aRetSeq;
+ if( rNameSeq.hasElements() )
+ {
+ aRetSeq.realloc( rNameSeq.getLength() );
+ auto pRetSeq = aRetSeq.getArray();
+ for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ pRetSeq[nN] = getPropertyState( aPropertyName );
+ }
+ }
+ return aRetSeq;
+}
+
+void SAL_CALL WrappedPropertySet::setPropertyToDefault( const OUString& rPropertyName )
+{
+ Reference< beans::XPropertyState > xInnerPropertyState( getInnerPropertyState() );
+ if( xInnerPropertyState.is() )
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName );
+ if( pWrappedProperty )
+ pWrappedProperty->setPropertyToDefault( xInnerPropertyState );
+ else
+ xInnerPropertyState->setPropertyToDefault( rPropertyName );
+ }
+}
+Any SAL_CALL WrappedPropertySet::getPropertyDefault( const OUString& rPropertyName )
+{
+ Any aRet;
+ Reference< beans::XPropertyState > xInnerPropertyState( getInnerPropertyState() );
+ if( xInnerPropertyState.is() )
+ {
+ const WrappedProperty* pWrappedProperty = getWrappedProperty( rPropertyName );
+ if( pWrappedProperty )
+ aRet = pWrappedProperty->getPropertyDefault(xInnerPropertyState);
+ else
+ aRet = xInnerPropertyState->getPropertyDefault( rPropertyName );
+ }
+ return aRet;
+}
+
+//XMultiPropertyStates
+void SAL_CALL WrappedPropertySet::setAllPropertiesToDefault( )
+{
+ const Sequence< beans::Property >& rPropSeq = getPropertySequence();
+ for(beans::Property const & prop : rPropSeq)
+ {
+ setPropertyToDefault( prop.Name );
+ }
+}
+void SAL_CALL WrappedPropertySet::setPropertiesToDefault( const Sequence< OUString >& rNameSeq )
+{
+ for(OUString const & s : rNameSeq)
+ {
+ setPropertyToDefault( s );
+ }
+}
+Sequence< Any > SAL_CALL WrappedPropertySet::getPropertyDefaults( const Sequence< OUString >& rNameSeq )
+{
+ Sequence< Any > aRetSeq;
+ if( rNameSeq.hasElements() )
+ {
+ aRetSeq.realloc( rNameSeq.getLength() );
+ auto pRetSeq = aRetSeq.getArray();
+ for(sal_Int32 nN=0; nN<rNameSeq.getLength(); nN++)
+ {
+ OUString aPropertyName( rNameSeq[nN] );
+ pRetSeq[nN] = getPropertyDefault( aPropertyName );
+ }
+ }
+ return aRetSeq;
+}
+
+::cppu::IPropertyArrayHelper& WrappedPropertySet::getInfoHelper()
+{
+ ::cppu::OPropertyArrayHelper* p = m_pPropertyArrayHelper.get();
+ if(!p)
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );//do not use different mutex than is already used for static property sequence
+ p = m_pPropertyArrayHelper.get();
+ if(!p)
+ {
+ p = new ::cppu::OPropertyArrayHelper( getPropertySequence(), true );
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ m_pPropertyArrayHelper.reset(p);
+ }
+ }
+ else
+ {
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ }
+ return *m_pPropertyArrayHelper;
+}
+
+tWrappedPropertyMap& WrappedPropertySet::getWrappedPropertyMap()
+{
+ tWrappedPropertyMap* p = m_pWrappedPropertyMap.get();
+ if(!p)
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );//do not use different mutex than is already used for static property sequence
+ p = m_pWrappedPropertyMap.get();
+ if(!p)
+ {
+ std::vector< std::unique_ptr<WrappedProperty> > aPropList( createWrappedProperties() );
+ p = new tWrappedPropertyMap;
+
+ for (auto & elem : aPropList)
+ {
+ sal_Int32 nHandle = getInfoHelper().getHandleByName( elem->getOuterName() );
+
+ if( nHandle == -1 )
+ {
+ OSL_FAIL( "missing property in property list" );
+ }
+ else if( p->find( nHandle ) != p->end() )
+ {
+ //duplicate Wrapped property
+ OSL_FAIL( "duplicate Wrapped property" );
+ }
+ else
+ (*p)[ nHandle ] = std::move(elem);
+ }
+
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ m_pWrappedPropertyMap.reset(p);
+ }
+ }
+ else
+ {
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ }
+ return *m_pWrappedPropertyMap;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/tools/XMLRangeHelper.cxx b/chart2/source/tools/XMLRangeHelper.cxx
new file mode 100644
index 0000000000..196a039654
--- /dev/null
+++ b/chart2/source/tools/XMLRangeHelper.cxx
@@ -0,0 +1,393 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <XMLRangeHelper.hxx>
+#include <rtl/character.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/string_view.hxx>
+
+#include <algorithm>
+
+namespace
+{
+/** unary function that escapes backslashes and single quotes in a sal_Unicode
+ array (which you can get from an OUString with getStr()) and puts the result
+ into the OUStringBuffer given in the CTOR
+ */
+class lcl_Escape
+{
+public:
+ explicit lcl_Escape( OUStringBuffer & aResultBuffer ) : m_aResultBuffer( aResultBuffer ) {}
+ void operator() ( sal_Unicode aChar )
+ {
+ static const sal_Unicode s_aQuote( '\'' );
+ static const sal_Unicode s_aBackslash( '\\' );
+
+ if( aChar == s_aQuote ||
+ aChar == s_aBackslash )
+ m_aResultBuffer.append( s_aBackslash );
+ m_aResultBuffer.append( aChar );
+ }
+
+private:
+ OUStringBuffer & m_aResultBuffer;
+};
+
+/** unary function that removes backslash escapes in a sal_Unicode array (which
+ you can get from an OUString with getStr()) and puts the result into the
+ OUStringBuffer given in the CTOR
+ */
+class lcl_UnEscape
+{
+public:
+ explicit lcl_UnEscape( OUStringBuffer & aResultBuffer ) : m_aResultBuffer( aResultBuffer ) {}
+ void operator() ( sal_Unicode aChar )
+ {
+ static const sal_Unicode s_aBackslash( '\\' );
+
+ if( aChar != s_aBackslash )
+ m_aResultBuffer.append( aChar );
+ }
+
+private:
+ OUStringBuffer & m_aResultBuffer;
+};
+
+void lcl_getXMLStringForCell( const ::chart::XMLRangeHelper::Cell & rCell, OUStringBuffer * output )
+{
+ OSL_ASSERT(output != nullptr);
+
+ if( rCell.empty())
+ return;
+
+ sal_Int32 nCol = rCell.nColumn;
+ output->append( '.' );
+ if( ! rCell.bRelativeColumn )
+ output->append( '$' );
+
+ // get A, B, C, ..., AA, AB, ... representation of column number
+ if( nCol < 26 )
+ output->append( static_cast<sal_Unicode>('A' + nCol) );
+ else if( nCol < 702 )
+ {
+ output->append( static_cast<sal_Unicode>('A' + nCol / 26 - 1 ));
+ output->append( static_cast<sal_Unicode>('A' + nCol % 26) );
+ }
+ else // works for nCol <= 18,278
+ {
+ output->append( static_cast<sal_Unicode>('A' + nCol / 702 - 1 ));
+ output->append( static_cast<sal_Unicode>('A' + (nCol % 702) / 26 ));
+ output->append( static_cast<sal_Unicode>('A' + nCol % 26) );
+ }
+
+ // write row number as number
+ if( ! rCell.bRelativeRow )
+ output->append( '$' );
+ output->append( rCell.nRow + sal_Int32(1) );
+}
+
+void lcl_getSingleCellAddressFromXMLString(
+ std::u16string_view rXMLString,
+ sal_Int32 nStartPos, sal_Int32 nEndPos,
+ ::chart::XMLRangeHelper::Cell & rOutCell )
+{
+ // expect "\$?[a-zA-Z]+\$?[1-9][0-9]*"
+ static const sal_Unicode aDollar( '$' );
+ static const sal_Unicode aLetterA( 'A' );
+
+ OUString aCellStr = OUString(rXMLString.substr( nStartPos, nEndPos - nStartPos + 1 )).toAsciiUpperCase();
+ const sal_Unicode* pStrArray = aCellStr.getStr();
+ sal_Int32 nLength = aCellStr.getLength();
+ sal_Int32 i = nLength - 1, nColumn = 0;
+
+ // parse number for row
+ while( rtl::isAsciiDigit( pStrArray[ i ] ) && i >= 0 )
+ i--;
+ rOutCell.nRow = (o3tl::toInt32(aCellStr.subView( i + 1 ))) - 1;
+ // a dollar in XML means absolute (whereas in UI it means relative)
+ if( pStrArray[ i ] == aDollar )
+ {
+ i--;
+ rOutCell.bRelativeRow = false;
+ }
+ else
+ rOutCell.bRelativeRow = true;
+
+ // parse rest for column
+ sal_Int32 nPower = 1;
+ while( rtl::isAsciiAlpha( pStrArray[ i ] ))
+ {
+ nColumn += (pStrArray[ i ] - aLetterA + 1) * nPower;
+ i--;
+ nPower *= 26;
+ }
+ rOutCell.nColumn = nColumn - 1;
+
+ rOutCell.bRelativeColumn = true;
+ if( i >= 0 &&
+ pStrArray[ i ] == aDollar )
+ rOutCell.bRelativeColumn = false;
+ rOutCell.bIsEmpty = false;
+}
+
+bool lcl_getCellAddressFromXMLString(
+ const OUString& rXMLString,
+ sal_Int32 nStartPos, sal_Int32 nEndPos,
+ ::chart::XMLRangeHelper::Cell & rOutCell,
+ OUString& rOutTableName )
+{
+ static const sal_Unicode aDot( '.' );
+ static const sal_Unicode aQuote( '\'' );
+ static const sal_Unicode aBackslash( '\\' );
+
+ sal_Int32 nNextDelimiterPos = nStartPos;
+
+ sal_Int32 nDelimiterPos = nStartPos;
+ bool bInQuotation = false;
+ // parse table name
+ while( nDelimiterPos < nEndPos &&
+ ( bInQuotation || rXMLString[ nDelimiterPos ] != aDot ))
+ {
+ // skip escaped characters (with backslash)
+ if( rXMLString[ nDelimiterPos ] == aBackslash )
+ ++nDelimiterPos;
+ // toggle quotation mode when finding single quotes
+ else if( rXMLString[ nDelimiterPos ] == aQuote )
+ bInQuotation = ! bInQuotation;
+
+ ++nDelimiterPos;
+ }
+
+ if( nDelimiterPos == -1 )
+ return false;
+
+ if( nDelimiterPos > nStartPos && nDelimiterPos < nEndPos )
+ {
+ // there is a table name before the address
+
+ OUStringBuffer aTableNameBuffer;
+ const sal_Unicode * pTableName = rXMLString.getStr();
+
+ // remove escapes from table name
+ std::for_each( pTableName + nStartPos,
+ pTableName + nDelimiterPos,
+ lcl_UnEscape( aTableNameBuffer ));
+
+ // unquote quoted table name
+ const sal_Unicode * pBuf = aTableNameBuffer.getStr();
+ if( pBuf[ 0 ] == aQuote &&
+ pBuf[ aTableNameBuffer.getLength() - 1 ] == aQuote )
+ {
+ OUString aName = aTableNameBuffer.makeStringAndClear();
+ rOutTableName = aName.copy( 1, aName.getLength() - 2 );
+ }
+ else
+ rOutTableName = aTableNameBuffer.makeStringAndClear();
+ }
+ else
+ nDelimiterPos = nStartPos;
+
+ for( sal_Int32 i = 0;
+ nNextDelimiterPos < nEndPos;
+ nDelimiterPos = nNextDelimiterPos, i++ )
+ {
+ nNextDelimiterPos = rXMLString.indexOf( aDot, nDelimiterPos + 1 );
+ if( nNextDelimiterPos == -1 ||
+ nNextDelimiterPos > nEndPos )
+ nNextDelimiterPos = nEndPos + 1;
+
+ if( i==0 )
+ // only take first cell
+ lcl_getSingleCellAddressFromXMLString(
+ rXMLString, nDelimiterPos + 1, nNextDelimiterPos - 1, rOutCell );
+ }
+
+ return true;
+}
+
+bool lcl_getCellRangeAddressFromXMLString(
+ const OUString& rXMLString,
+ sal_Int32 nStartPos, sal_Int32 nEndPos,
+ ::chart::XMLRangeHelper::CellRange & rOutRange )
+{
+ bool bResult = true;
+ static const sal_Unicode aColon( ':' );
+ static const sal_Unicode aQuote( '\'' );
+ static const sal_Unicode aBackslash( '\\' );
+
+ sal_Int32 nDelimiterPos = nStartPos;
+ bool bInQuotation = false;
+ // parse table name
+ while( nDelimiterPos < nEndPos &&
+ ( bInQuotation || rXMLString[ nDelimiterPos ] != aColon ))
+ {
+ // skip escaped characters (with backslash)
+ if( rXMLString[ nDelimiterPos ] == aBackslash )
+ ++nDelimiterPos;
+ // toggle quotation mode when finding single quotes
+ else if( rXMLString[ nDelimiterPos ] == aQuote )
+ bInQuotation = ! bInQuotation;
+
+ ++nDelimiterPos;
+ }
+
+ if( nDelimiterPos == nEndPos )
+ {
+ // only one cell
+ bResult = lcl_getCellAddressFromXMLString( rXMLString, nStartPos, nEndPos,
+ rOutRange.aUpperLeft,
+ rOutRange.aTableName );
+ if( rOutRange.aTableName.isEmpty() )
+ bResult = false;
+ }
+ else
+ {
+ // range (separated by a colon)
+ bResult = lcl_getCellAddressFromXMLString( rXMLString, nStartPos, nDelimiterPos - 1,
+ rOutRange.aUpperLeft,
+ rOutRange.aTableName );
+ if( rOutRange.aTableName.isEmpty() )
+ bResult = false;
+
+ OUString sTableSecondName;
+ if( bResult )
+ {
+ bResult = lcl_getCellAddressFromXMLString( rXMLString, nDelimiterPos + 1, nEndPos,
+ rOutRange.aLowerRight,
+ sTableSecondName );
+ }
+ if( bResult &&
+ !sTableSecondName.isEmpty() &&
+ sTableSecondName != rOutRange.aTableName )
+ bResult = false;
+ }
+
+ return bResult;
+}
+
+} // anonymous namespace
+
+namespace chart::XMLRangeHelper
+{
+
+CellRange getCellRangeFromXMLString( const OUString & rXMLString )
+{
+ static const sal_Unicode aSpace( ' ' );
+ static const sal_Unicode aQuote( '\'' );
+// static const sal_Unicode aDoubleQuote( '\"' );
+ static const sal_Unicode aDollar( '$' );
+ static const sal_Unicode aBackslash( '\\' );
+
+ const sal_Int32 nLength = rXMLString.getLength();
+
+ // reset
+ CellRange aResult;
+
+ // iterate over different ranges
+ for( sal_Int32 nStartPos = 0, nEndPos = nStartPos;
+ nEndPos < nLength;
+ nStartPos = ++nEndPos )
+ {
+ // find start point of next range
+
+ // ignore leading '$'
+ if( rXMLString[ nEndPos ] == aDollar)
+ nEndPos++;
+
+ bool bInQuotation = false;
+ // parse range
+ while( nEndPos < nLength &&
+ ( bInQuotation || rXMLString[ nEndPos ] != aSpace ))
+ {
+ // skip escaped characters (with backslash)
+ if( rXMLString[ nEndPos ] == aBackslash )
+ ++nEndPos;
+ // toggle quotation mode when finding single quotes
+ else if( rXMLString[ nEndPos ] == aQuote )
+ bInQuotation = ! bInQuotation;
+
+ ++nEndPos;
+ }
+
+ if( ! lcl_getCellRangeAddressFromXMLString(
+ rXMLString,
+ nStartPos, nEndPos - 1,
+ aResult ))
+ {
+ // if an error occurred, bail out
+ return CellRange();
+ }
+ }
+
+ return aResult;
+}
+
+OUString getXMLStringFromCellRange( const CellRange & rRange )
+{
+ static const sal_Unicode aSpace( ' ' );
+ static const sal_Unicode aQuote( '\'' );
+
+ OUStringBuffer aBuffer;
+
+ if( !rRange.aTableName.isEmpty())
+ {
+ bool bNeedsEscaping = ( rRange.aTableName.indexOf( aQuote ) > -1 );
+ bool bNeedsQuoting = bNeedsEscaping || ( rRange.aTableName.indexOf( aSpace ) > -1 );
+
+ // quote table name if it contains spaces or quotes
+ if( bNeedsQuoting )
+ {
+ // leading quote
+ aBuffer.append( aQuote );
+
+ // escape existing quotes
+ if( bNeedsEscaping )
+ {
+ const sal_Unicode * pTableNameBeg = rRange.aTableName.getStr();
+
+ // append the quoted string at the buffer
+ std::for_each( pTableNameBeg,
+ pTableNameBeg + rRange.aTableName.getLength(),
+ lcl_Escape( aBuffer ) );
+ }
+ else
+ aBuffer.append( rRange.aTableName );
+
+ // final quote
+ aBuffer.append( aQuote );
+ }
+ else
+ aBuffer.append( rRange.aTableName );
+ }
+ lcl_getXMLStringForCell( rRange.aUpperLeft, &aBuffer );
+
+ if( ! rRange.aLowerRight.empty())
+ {
+ // we have a range (not a single cell)
+ aBuffer.append( u':');
+ lcl_getXMLStringForCell( rRange.aLowerRight, &aBuffer );
+ }
+
+ return aBuffer.makeStringAndClear();
+}
+
+} // namespace chart::XMLRangeHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/DateHelper.cxx b/chart2/source/view/axes/DateHelper.cxx
new file mode 100644
index 0000000000..4c4a96dce2
--- /dev/null
+++ b/chart2/source/view/axes/DateHelper.cxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DateHelper.hxx>
+#include <rtl/math.hxx>
+#include <com/sun/star/chart/TimeUnit.hpp>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+bool DateHelper::IsInSameYear( const Date& rD1, const Date& rD2 )
+{
+ return rD1.GetYear() == rD2.GetYear();
+}
+
+bool DateHelper::IsInSameMonth( const Date& rD1, const Date& rD2 )
+{
+ return (rD1.GetYear() == rD2.GetYear())
+ && (rD1.GetMonth() == rD2.GetMonth());
+}
+
+Date DateHelper::GetDateSomeMonthsAway( const Date& rD, sal_Int32 nMonthDistance )
+{
+ Date aRet(rD);
+ aRet.AddMonths( nMonthDistance );
+ return aRet;
+}
+
+Date DateHelper::GetDateSomeYearsAway( const Date& rD, sal_Int32 nYearDistance )
+{
+ Date aRet(rD);
+ aRet.AddYears( static_cast<sal_Int16>(nYearDistance) );
+ return aRet;
+}
+
+bool DateHelper::IsLessThanOneMonthAway( const Date& rD1, const Date& rD2 )
+{
+ Date aDMin( DateHelper::GetDateSomeMonthsAway( rD1, -1 ) );
+ Date aDMax( DateHelper::GetDateSomeMonthsAway( rD1, 1 ) );
+
+ return rD2 > aDMin && rD2 < aDMax;
+}
+
+bool DateHelper::IsLessThanOneYearAway( const Date& rD1, const Date& rD2 )
+{
+ Date aDMin( DateHelper::GetDateSomeYearsAway( rD1, -1 ) );
+ Date aDMax( DateHelper::GetDateSomeYearsAway( rD1, 1 ) );
+
+ return rD2 > aDMin && rD2 < aDMax;
+}
+
+double DateHelper::RasterizeDateValue( double fValue, const Date& rNullDate, tools::Long TimeResolution )
+{
+ if (std::isnan(fValue))
+ return fValue;
+
+ Date aDate(rNullDate); aDate.AddDays(::rtl::math::approxFloor(fValue));
+ switch(TimeResolution)
+ {
+ case css::chart::TimeUnit::DAY:
+ break;
+ case css::chart::TimeUnit::YEAR:
+ aDate.SetMonth(1);
+ aDate.SetDay(1);
+ break;
+ case css::chart::TimeUnit::MONTH:
+ default:
+ aDate.SetDay(1);
+ break;
+ }
+ return aDate - rNullDate;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/DateScaling.cxx b/chart2/source/view/axes/DateScaling.cxx
new file mode 100644
index 0000000000..f24f46a8e4
--- /dev/null
+++ b/chart2/source/view/axes/DateScaling.cxx
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "DateScaling.hxx"
+#include <com/sun/star/chart/TimeUnit.hpp>
+#include <rtl/math.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <limits>
+
+namespace
+{
+
+constexpr OUString lcl_aServiceName_DateScaling = u"com.sun.star.chart2.DateScaling"_ustr;
+constexpr OUString lcl_aServiceName_InverseDateScaling
+ = u"com.sun.star.chart2.InverseDateScaling"_ustr;
+
+const double lcl_fNumberOfMonths = 12.0;//todo: this needs to be offered by basic tools Date class if it should be more generic
+}
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::chart::TimeUnit::DAY;
+using ::com::sun::star::chart::TimeUnit::MONTH;
+using ::com::sun::star::chart::TimeUnit::YEAR;
+
+DateScaling::DateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted )
+ : m_aNullDate( rNullDate )
+ , m_nTimeUnit( nTimeUnit )
+ , m_bShifted( bShifted )
+{
+}
+
+DateScaling::~DateScaling()
+{
+}
+
+double SAL_CALL DateScaling::doScaling( double value )
+{
+ double fResult(value);
+ if( std::isnan( value ) || std::isinf( value ) )
+ return std::numeric_limits<double>::quiet_NaN();
+ switch( m_nTimeUnit )
+ {
+ case DAY:
+ fResult = value;
+ if(m_bShifted)
+ fResult+=0.5;
+ break;
+ case YEAR:
+ case MONTH:
+ default:
+ {
+ Date aDate(m_aNullDate);
+ aDate.AddDays(::rtl::math::approxFloor(value));
+ fResult = aDate.GetYear();
+ fResult *= lcl_fNumberOfMonths;//assuming equal count of months in each year
+ fResult += aDate.GetMonth();
+
+ double fDayOfMonth = aDate.GetDay();
+ fDayOfMonth -= 1.0;
+ double fDaysInMonth = aDate.GetDaysInMonth();
+ fResult += fDayOfMonth/fDaysInMonth;
+ if(m_bShifted)
+ {
+ if( m_nTimeUnit==YEAR )
+ fResult += 0.5*lcl_fNumberOfMonths;
+ else
+ fResult += 0.5;
+ }
+ break;
+ }
+ }
+ return fResult;
+}
+
+uno::Reference< XScaling > SAL_CALL DateScaling::getInverseScaling()
+{
+ return new InverseDateScaling( m_aNullDate, m_nTimeUnit, m_bShifted );
+}
+
+OUString SAL_CALL DateScaling::getServiceName()
+{
+ return lcl_aServiceName_DateScaling;
+}
+
+OUString SAL_CALL DateScaling::getImplementationName()
+{
+ return lcl_aServiceName_DateScaling;
+}
+
+sal_Bool SAL_CALL DateScaling::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL DateScaling::getSupportedServiceNames()
+{
+ return { lcl_aServiceName_DateScaling };
+}
+
+InverseDateScaling::InverseDateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted )
+ : m_aNullDate( rNullDate )
+ , m_nTimeUnit( nTimeUnit )
+ , m_bShifted( bShifted )
+{
+}
+
+InverseDateScaling::~InverseDateScaling()
+{
+}
+
+double SAL_CALL InverseDateScaling::doScaling( double value )
+{
+ double fResult(value);
+ if( std::isnan( value ) || std::isinf( value ) )
+ return std::numeric_limits<double>::quiet_NaN();
+ else
+ {
+ switch( m_nTimeUnit )
+ {
+ case DAY:
+ if(m_bShifted)
+ value -= 0.5;
+ fResult = value;
+ break;
+ case YEAR:
+ case MONTH:
+ default:
+ //Date aDate(m_aNullDate);
+ if(m_bShifted)
+ {
+ if( m_nTimeUnit==YEAR )
+ value -= 0.5*lcl_fNumberOfMonths;
+ else
+ value -= 0.5;
+ }
+ Date aDate( Date::EMPTY );
+ double fYear = ::rtl::math::approxFloor(value/lcl_fNumberOfMonths);
+ double fMonth = ::rtl::math::approxFloor(value-(fYear*lcl_fNumberOfMonths));
+ if( fMonth==0.0 )
+ {
+ fYear--;
+ fMonth=12.0;
+ }
+ aDate.SetYear( static_cast<sal_uInt16>(fYear) );
+ aDate.SetMonth( static_cast<sal_uInt16>(fMonth) );
+ aDate.SetDay( 1 );
+ double fMonthCount = (fYear*lcl_fNumberOfMonths)+fMonth;
+ double fDay = (value-fMonthCount)*aDate.GetDaysInMonth();
+ fDay += 1.0;
+ aDate.SetDay( static_cast<sal_uInt16>(::rtl::math::round(fDay)) );
+ fResult = aDate - m_aNullDate;
+ break;
+ }
+ }
+ return fResult;
+}
+
+uno::Reference< XScaling > SAL_CALL InverseDateScaling::getInverseScaling()
+{
+ return new DateScaling( m_aNullDate, m_nTimeUnit, m_bShifted );
+}
+
+OUString SAL_CALL InverseDateScaling::getServiceName()
+{
+ return lcl_aServiceName_InverseDateScaling;
+}
+
+OUString SAL_CALL InverseDateScaling::getImplementationName()
+{
+ return lcl_aServiceName_InverseDateScaling;
+}
+
+sal_Bool SAL_CALL InverseDateScaling::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL InverseDateScaling::getSupportedServiceNames()
+{
+ return { lcl_aServiceName_InverseDateScaling };
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/DateScaling.hxx b/chart2/source/view/axes/DateScaling.hxx
new file mode 100644
index 0000000000..29b7a139ae
--- /dev/null
+++ b/chart2/source/view/axes/DateScaling.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/chart2/XScaling.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <tools/date.hxx>
+
+namespace chart
+{
+
+class DateScaling :
+ public ::cppu::WeakImplHelper<
+ css::chart2::XScaling,
+ css::lang::XServiceName,
+ css::lang::XServiceInfo
+ >
+{
+public:
+ DateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted );
+ virtual ~DateScaling() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XScaling ____
+ virtual double SAL_CALL doScaling( double value ) override;
+
+ virtual css::uno::Reference<
+ css::chart2::XScaling > SAL_CALL
+ getInverseScaling() override;
+
+ // ____ XServiceName ____
+ virtual OUString SAL_CALL getServiceName() override;
+
+private:
+ const Date m_aNullDate;
+ const sal_Int32 m_nTimeUnit;
+ const bool m_bShifted;
+};
+
+class InverseDateScaling :
+ public ::cppu::WeakImplHelper<
+ css::chart2::XScaling,
+ css::lang::XServiceName,
+ css::lang::XServiceInfo
+ >
+{
+public:
+ InverseDateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted );
+ virtual ~InverseDateScaling() override;
+
+ /// declare XServiceInfo methods
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // ____ XScaling ____
+ virtual double SAL_CALL doScaling( double value ) override;
+
+ virtual css::uno::Reference< css::chart2::XScaling > SAL_CALL
+ getInverseScaling() override;
+
+ // ____ XServiceName ____
+ virtual OUString SAL_CALL getServiceName() override;
+
+private:
+ const Date m_aNullDate;
+ const sal_Int32 m_nTimeUnit;
+ const bool m_bShifted;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx b/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx
new file mode 100644
index 0000000000..eaf5c43473
--- /dev/null
+++ b/chart2/source/view/axes/MinimumAndMaximumSupplier.cxx
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <MinimumAndMaximumSupplier.hxx>
+
+#include <com/sun/star/chart/TimeUnit.hpp>
+
+#include <cmath>
+#include <limits>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+MergedMinimumAndMaximumSupplier::MergedMinimumAndMaximumSupplier()
+{
+}
+
+MergedMinimumAndMaximumSupplier::~MergedMinimumAndMaximumSupplier()
+{
+}
+
+void MergedMinimumAndMaximumSupplier::addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
+{
+ m_aMinimumAndMaximumSupplierList.insert( pMinimumAndMaximumSupplier );
+}
+
+bool MergedMinimumAndMaximumSupplier::hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
+{
+ return m_aMinimumAndMaximumSupplierList.count( pMinimumAndMaximumSupplier ) != 0;
+}
+
+double MergedMinimumAndMaximumSupplier::getMinimumX()
+{
+ double fGlobalExtremum = std::numeric_limits<double>::infinity();
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ {
+ double fLocalExtremum = elem->getMinimumX();
+ if(fLocalExtremum<fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(std::isinf(fGlobalExtremum))
+ return std::numeric_limits<double>::quiet_NaN();
+ return fGlobalExtremum;
+}
+
+double MergedMinimumAndMaximumSupplier::getMaximumX()
+{
+ double fGlobalExtremum = -std::numeric_limits<double>::infinity();
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ {
+ double fLocalExtremum = elem->getMaximumX();
+ if(fLocalExtremum>fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(std::isinf(fGlobalExtremum))
+ return std::numeric_limits<double>::quiet_NaN();
+ return fGlobalExtremum;
+}
+
+double MergedMinimumAndMaximumSupplier::getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex )
+{
+ double fGlobalExtremum = std::numeric_limits<double>::infinity();
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ {
+ double fLocalExtremum = elem->getMinimumYInRange( fMinimumX, fMaximumX, nAxisIndex );
+ if(fLocalExtremum<fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(std::isinf(fGlobalExtremum))
+ return std::numeric_limits<double>::quiet_NaN();
+ return fGlobalExtremum;
+}
+
+double MergedMinimumAndMaximumSupplier::getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex )
+{
+ double fGlobalExtremum = -std::numeric_limits<double>::infinity();
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ {
+ double fLocalExtremum = elem->getMaximumYInRange( fMinimumX, fMaximumX, nAxisIndex );
+ if(fLocalExtremum>fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(std::isinf(fGlobalExtremum))
+ return std::numeric_limits<double>::quiet_NaN();
+ return fGlobalExtremum;
+}
+
+double MergedMinimumAndMaximumSupplier::getMinimumZ()
+{
+ double fGlobalExtremum = std::numeric_limits<double>::infinity();
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ {
+ double fLocalExtremum = elem->getMinimumZ();
+ if(fLocalExtremum<fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(std::isinf(fGlobalExtremum))
+ return std::numeric_limits<double>::quiet_NaN();
+ return fGlobalExtremum;
+}
+
+double MergedMinimumAndMaximumSupplier::getMaximumZ()
+{
+ double fGlobalExtremum = -std::numeric_limits<double>::infinity();
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ {
+ double fLocalExtremum = elem->getMaximumZ();
+ if(fLocalExtremum>fGlobalExtremum)
+ fGlobalExtremum=fLocalExtremum;
+ }
+ if(std::isinf(fGlobalExtremum))
+ return std::numeric_limits<double>::quiet_NaN();
+ return fGlobalExtremum;
+}
+
+bool MergedMinimumAndMaximumSupplier::isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex )
+{
+ // only return true, if *all* suppliers want to scale to the main tick marks
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ if( !elem->isExpandBorderToIncrementRhythm( nDimensionIndex ) )
+ return false;
+ return true;
+}
+
+bool MergedMinimumAndMaximumSupplier::isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex )
+{
+ // only return true, if *all* suppliers want to expand the range
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ if( !elem->isExpandIfValuesCloseToBorder( nDimensionIndex ) )
+ return false;
+ return true;
+}
+
+bool MergedMinimumAndMaximumSupplier::isExpandWideValuesToZero( sal_Int32 nDimensionIndex )
+{
+ // already return true, if at least one supplier wants to expand the range
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ if( elem->isExpandWideValuesToZero( nDimensionIndex ) )
+ return true;
+ return false;
+}
+
+bool MergedMinimumAndMaximumSupplier::isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex )
+{
+ // already return true, if at least one supplier wants to expand the range
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ if( elem->isExpandNarrowValuesTowardZero( nDimensionIndex ) )
+ return true;
+ return false;
+}
+
+bool MergedMinimumAndMaximumSupplier::isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex )
+{
+ // should not be called
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ if( elem->isSeparateStackingForDifferentSigns( nDimensionIndex ) )
+ return true;
+ return false;
+}
+
+void MergedMinimumAndMaximumSupplier::clearMinimumAndMaximumSupplierList()
+{
+ m_aMinimumAndMaximumSupplierList.clear();
+}
+
+tools::Long MergedMinimumAndMaximumSupplier::calculateTimeResolutionOnXAxis()
+{
+ tools::Long nRet = css::chart::TimeUnit::YEAR;
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ {
+ tools::Long nCurrent = elem->calculateTimeResolutionOnXAxis();
+ if(nRet>nCurrent)
+ nRet=nCurrent;
+ }
+ return nRet;
+}
+
+void MergedMinimumAndMaximumSupplier::setTimeResolutionOnXAxis( tools::Long nTimeResolution, const Date& rNullDate )
+{
+ for (auto const& elem : m_aMinimumAndMaximumSupplierList)
+ elem->setTimeResolutionOnXAxis( nTimeResolution, rNullDate );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/ScaleAutomatism.cxx b/chart2/source/view/axes/ScaleAutomatism.cxx
new file mode 100644
index 0000000000..24195c8fdc
--- /dev/null
+++ b/chart2/source/view/axes/ScaleAutomatism.cxx
@@ -0,0 +1,989 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ScaleAutomatism.hxx>
+#include "Tickmarks_Equidistant.hxx"
+#include <DateHelper.hxx>
+#include "DateScaling.hxx"
+#include <AxisHelper.hxx>
+#include <com/sun/star/chart/TimeUnit.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+
+#include <rtl/math.hxx>
+#include <tools/long.hxx>
+#include <limits>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::chart::TimeUnit::DAY;
+using ::com::sun::star::chart::TimeUnit::MONTH;
+using ::com::sun::star::chart::TimeUnit::YEAR;
+
+const sal_Int32 MAXIMUM_MANUAL_INCREMENT_COUNT = 500;
+const sal_Int32 MAXIMUM_SUB_INCREMENT_COUNT = 100;
+
+static sal_Int32 lcl_getMaximumAutoIncrementCount( sal_Int32 nAxisType )
+{
+ sal_Int32 nMaximumAutoIncrementCount = 10;
+ if( nAxisType==AxisType::DATE )
+ nMaximumAutoIncrementCount = MAXIMUM_MANUAL_INCREMENT_COUNT;
+ return nMaximumAutoIncrementCount;
+}
+
+namespace
+{
+
+void lcl_ensureMaximumSubIncrementCount( sal_Int32& rnSubIntervalCount )
+{
+ if( rnSubIntervalCount > MAXIMUM_SUB_INCREMENT_COUNT )
+ rnSubIntervalCount = MAXIMUM_SUB_INCREMENT_COUNT;
+}
+
+}//end anonymous namespace
+
+ExplicitScaleData::ExplicitScaleData()
+ : Minimum(0.0)
+ , Maximum(10.0)
+ , Origin(0.0)
+ , Orientation(css::chart2::AxisOrientation_MATHEMATICAL)
+ , AxisType(css::chart2::AxisType::REALNUMBER)
+ , m_bShiftedCategoryPosition(false)
+ , TimeResolution(css::chart::TimeUnit::DAY)
+ , NullDate(30,12,1899)
+{
+}
+
+ExplicitSubIncrement::ExplicitSubIncrement()
+ : IntervalCount(2)
+ , PostEquidistant(true)
+{
+}
+
+ExplicitIncrementData::ExplicitIncrementData()
+ : MajorTimeInterval(1,css::chart::TimeUnit::DAY)
+ , MinorTimeInterval(1,css::chart::TimeUnit::DAY)
+ , Distance(1.0)
+ , PostEquidistant(true)
+ , BaseValue(0.0)
+{
+}
+
+ScaleAutomatism::ScaleAutomatism( const ScaleData& rSourceScale, const Date& rNullDate )
+ : m_aSourceScale( rSourceScale )
+ , m_fValueMinimum( 0.0 )
+ , m_fValueMaximum( 0.0 )
+ , m_nMaximumAutoMainIncrementCount( lcl_getMaximumAutoIncrementCount( rSourceScale.AxisType ) )
+ , m_bExpandBorderToIncrementRhythm( false )
+ , m_bExpandIfValuesCloseToBorder( false )
+ , m_bExpandWideValuesToZero( false )
+ , m_bExpandNarrowValuesTowardZero( false )
+ , m_nTimeResolution(css::chart::TimeUnit::DAY)
+ , m_aNullDate(rNullDate)
+{
+ resetValueRange();
+
+ double fExplicitOrigin = 0.0;
+ if( m_aSourceScale.Origin >>= fExplicitOrigin )
+ expandValueRange( fExplicitOrigin, fExplicitOrigin);
+}
+
+void ScaleAutomatism::resetValueRange( )
+{
+ m_fValueMinimum = std::numeric_limits<double>::quiet_NaN();
+ m_fValueMaximum = std::numeric_limits<double>::quiet_NaN();
+}
+
+void ScaleAutomatism::expandValueRange( double fMinimum, double fMaximum )
+{
+ // if m_fValueMinimum and m_fValueMaximum == 0, it means that they were not determined.
+ // m_fValueMinimum == 0 makes impossible to determine real minimum,
+ // so they need to be reset tdf#96807
+ if( (m_fValueMinimum == 0.0) && (m_fValueMaximum == 0.0) )
+ resetValueRange();
+ if( (fMinimum < m_fValueMinimum) || std::isnan( m_fValueMinimum ) )
+ m_fValueMinimum = fMinimum;
+ if( (fMaximum > m_fValueMaximum) || std::isnan( m_fValueMaximum ) )
+ m_fValueMaximum = fMaximum;
+}
+
+void ScaleAutomatism::setAutoScalingOptions(
+ bool bExpandBorderToIncrementRhythm,
+ bool bExpandIfValuesCloseToBorder,
+ bool bExpandWideValuesToZero,
+ bool bExpandNarrowValuesTowardZero )
+{
+ // if called multiple times, enable an option, if it is set in at least one call
+ m_bExpandBorderToIncrementRhythm |= bExpandBorderToIncrementRhythm;
+ m_bExpandIfValuesCloseToBorder |= bExpandIfValuesCloseToBorder;
+ m_bExpandWideValuesToZero |= bExpandWideValuesToZero;
+ m_bExpandNarrowValuesTowardZero |= bExpandNarrowValuesTowardZero;
+
+ if( m_aSourceScale.AxisType==AxisType::PERCENT )
+ m_bExpandIfValuesCloseToBorder = false;
+}
+
+void ScaleAutomatism::setMaximumAutoMainIncrementCount( sal_Int32 nMaximumAutoMainIncrementCount )
+{
+ if( nMaximumAutoMainIncrementCount < 2 )
+ m_nMaximumAutoMainIncrementCount = 2; //#i82006
+ else if( nMaximumAutoMainIncrementCount > lcl_getMaximumAutoIncrementCount( m_aSourceScale.AxisType ) )
+ m_nMaximumAutoMainIncrementCount = lcl_getMaximumAutoIncrementCount( m_aSourceScale.AxisType );
+ else
+ m_nMaximumAutoMainIncrementCount = nMaximumAutoMainIncrementCount;
+}
+
+void ScaleAutomatism::setAutomaticTimeResolution( sal_Int32 nTimeResolution )
+{
+ m_nTimeResolution = nTimeResolution;
+}
+
+void ScaleAutomatism::calculateExplicitScaleAndIncrement(
+ ExplicitScaleData& rExplicitScale, ExplicitIncrementData& rExplicitIncrement ) const
+{
+ // fill explicit scale
+ rExplicitScale.Orientation = m_aSourceScale.Orientation;
+ rExplicitScale.Scaling = m_aSourceScale.Scaling;
+ rExplicitScale.AxisType = m_aSourceScale.AxisType;
+ rExplicitScale.NullDate = m_aNullDate;
+
+ bool bAutoMinimum = !(m_aSourceScale.Minimum >>= rExplicitScale.Minimum);
+ bool bAutoMaximum = !(m_aSourceScale.Maximum >>= rExplicitScale.Maximum);
+ bool bAutoOrigin = !(m_aSourceScale.Origin >>= rExplicitScale.Origin);
+
+ // automatic scale minimum
+ if( bAutoMinimum )
+ {
+ if( m_aSourceScale.AxisType==AxisType::PERCENT )
+ rExplicitScale.Minimum = 0.0;
+ else if( std::isnan( m_fValueMinimum ) )
+ {
+ if( m_aSourceScale.AxisType==AxisType::DATE )
+ rExplicitScale.Minimum = 36526.0; //1.1.2000
+ else
+ rExplicitScale.Minimum = 0.0; //@todo get Minimum from scaling or from plotter????
+ }
+ else
+ rExplicitScale.Minimum = m_fValueMinimum;
+ }
+
+ // automatic scale maximum
+ if( bAutoMaximum )
+ {
+ if( m_aSourceScale.AxisType==AxisType::PERCENT )
+ rExplicitScale.Maximum = 1.0;
+ else if( std::isnan( m_fValueMaximum ) )
+ {
+ if( m_aSourceScale.AxisType==AxisType::DATE )
+ rExplicitScale.Maximum = 40179.0; //1.1.2010
+ else
+ rExplicitScale.Maximum = 10.0; //@todo get Maximum from scaling or from plotter????
+ }
+ else
+ rExplicitScale.Maximum = m_fValueMaximum;
+ }
+
+ //fill explicit increment
+
+ rExplicitScale.m_bShiftedCategoryPosition = m_aSourceScale.ShiftedCategoryPosition;
+ bool bIsLogarithm = false;
+
+ //minimum and maximum of the ExplicitScaleData may be changed if allowed
+ if( m_aSourceScale.AxisType==AxisType::DATE )
+ calculateExplicitIncrementAndScaleForDateTimeAxis( rExplicitScale, rExplicitIncrement, bAutoMinimum, bAutoMaximum );
+ else if( m_aSourceScale.AxisType==AxisType::CATEGORY || m_aSourceScale.AxisType==AxisType::SERIES )
+ calculateExplicitIncrementAndScaleForCategory( rExplicitScale, rExplicitIncrement, bAutoMinimum, bAutoMaximum );
+ else
+ {
+ bIsLogarithm = AxisHelper::isLogarithmic( rExplicitScale.Scaling );
+ if( bIsLogarithm )
+ calculateExplicitIncrementAndScaleForLogarithmic( rExplicitScale, rExplicitIncrement, bAutoMinimum, bAutoMaximum );
+ else
+ calculateExplicitIncrementAndScaleForLinear( rExplicitScale, rExplicitIncrement, bAutoMinimum, bAutoMaximum );
+ }
+
+ // automatic origin
+ if( bAutoOrigin )
+ {
+ // #i71415# automatic origin for logarithmic axis
+ double fDefaulOrigin = bIsLogarithm ? 1.0 : 0.0;
+
+ if( fDefaulOrigin < rExplicitScale.Minimum )
+ fDefaulOrigin = rExplicitScale.Minimum;
+ else if( fDefaulOrigin > rExplicitScale.Maximum )
+ fDefaulOrigin = rExplicitScale.Maximum;
+
+ rExplicitScale.Origin = fDefaulOrigin;
+ }
+}
+
+void ScaleAutomatism::calculateExplicitIncrementAndScaleForCategory(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const
+{
+ // no scaling for categories
+ rExplicitScale.Scaling.clear();
+
+ if( rExplicitScale.m_bShiftedCategoryPosition )
+ rExplicitScale.Maximum += 1.0;
+
+ // ensure that at least one category is visible
+ if( rExplicitScale.Maximum <= rExplicitScale.Minimum )
+ rExplicitScale.Maximum = rExplicitScale.Minimum + 1.0;
+
+ // default increment settings
+ rExplicitIncrement.PostEquidistant = true; // does not matter anyhow
+ rExplicitIncrement.Distance = 1.0; // category axis always have a main increment of 1
+ rExplicitIncrement.BaseValue = 0.0; // category axis always have a base of 0
+
+ // automatic minimum and maximum
+ if( bAutoMinimum && m_bExpandBorderToIncrementRhythm )
+ rExplicitScale.Minimum = EquidistantTickFactory::getMinimumAtIncrement( rExplicitScale.Minimum, rExplicitIncrement );
+ if( bAutoMaximum && m_bExpandBorderToIncrementRhythm )
+ rExplicitScale.Maximum = EquidistantTickFactory::getMaximumAtIncrement( rExplicitScale.Maximum, rExplicitIncrement );
+
+ //prevent performance killover
+ double fDistanceCount = ::rtl::math::approxFloor( (rExplicitScale.Maximum-rExplicitScale.Minimum) / rExplicitIncrement.Distance );
+ if( static_cast< sal_Int32 >( fDistanceCount ) > MAXIMUM_MANUAL_INCREMENT_COUNT )
+ {
+ double fMinimumFloor = ::rtl::math::approxFloor( rExplicitScale.Minimum );
+ double fMaximumCeil = ::rtl::math::approxCeil( rExplicitScale.Maximum );
+ rExplicitIncrement.Distance = ::rtl::math::approxCeil( (fMaximumCeil - fMinimumFloor) / MAXIMUM_MANUAL_INCREMENT_COUNT );
+ }
+
+ //fill explicit sub increment
+ sal_Int32 nSubCount = m_aSourceScale.IncrementData.SubIncrements.getLength();
+ for( sal_Int32 nN=0; nN<nSubCount; nN++ )
+ {
+ ExplicitSubIncrement aExplicitSubIncrement;
+ const SubIncrement& rSubIncrement= m_aSourceScale.IncrementData.SubIncrements[nN];
+ if(!(rSubIncrement.IntervalCount>>=aExplicitSubIncrement.IntervalCount))
+ {
+ //scaling dependent
+ //@todo autocalculate IntervalCount dependent on MainIncrement and scaling
+ aExplicitSubIncrement.IntervalCount = 2;
+ }
+ lcl_ensureMaximumSubIncrementCount( aExplicitSubIncrement.IntervalCount );
+ if(!(rSubIncrement.PostEquidistant>>=aExplicitSubIncrement.PostEquidistant))
+ {
+ //scaling dependent
+ aExplicitSubIncrement.PostEquidistant = false;
+ }
+ rExplicitIncrement.SubIncrements.push_back(aExplicitSubIncrement);
+ }
+}
+
+void ScaleAutomatism::calculateExplicitIncrementAndScaleForLogarithmic(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const
+{
+ // *** STEP 1: initialize the range data ***
+
+ const double fInputMinimum = rExplicitScale.Minimum;
+ const double fInputMaximum = rExplicitScale.Maximum;
+
+ double fSourceMinimum = rExplicitScale.Minimum;
+ double fSourceMaximum = rExplicitScale.Maximum;
+
+ // set automatic PostEquidistant to true (maybe scaling dependent?)
+ // Note: scaling with PostEquidistant==false is untested and needs review
+ if( !(m_aSourceScale.IncrementData.PostEquidistant >>= rExplicitIncrement.PostEquidistant) )
+ rExplicitIncrement.PostEquidistant = true;
+
+ /* All following scaling code will operate on the logarithms of the source
+ values. In the last step, the original values will be restored. */
+ uno::Reference< XScaling > xScaling = rExplicitScale.Scaling;
+ if( !xScaling.is() )
+ xScaling.set( AxisHelper::createLogarithmicScaling() );
+ uno::Reference< XScaling > xInverseScaling = xScaling->getInverseScaling();
+
+ fSourceMinimum = xScaling->doScaling( fSourceMinimum );
+ if( !std::isfinite( fSourceMinimum ) )
+ fSourceMinimum = 0.0;
+ else if( ::rtl::math::approxEqual( fSourceMinimum, ::rtl::math::approxFloor( fSourceMinimum ) ) )
+ fSourceMinimum = ::rtl::math::approxFloor( fSourceMinimum );
+
+ fSourceMaximum = xScaling->doScaling( fSourceMaximum );
+ if( !std::isfinite( fSourceMaximum ) )
+ fSourceMaximum = 0.0;
+ else if( ::rtl::math::approxEqual( fSourceMaximum, ::rtl::math::approxFloor( fSourceMaximum ) ) )
+ fSourceMaximum = ::rtl::math::approxFloor( fSourceMaximum );
+
+ /* If range is invalid (minimum greater than maximum), change one of the
+ variable limits to validate the range. In this step, a zero-sized range
+ is still allowed. */
+ if( fSourceMinimum > fSourceMaximum )
+ {
+ // force changing the maximum, if both limits are fixed
+ if( bAutoMaximum || !bAutoMinimum )
+ fSourceMaximum = fSourceMinimum;
+ else
+ fSourceMinimum = fSourceMaximum;
+ }
+
+ /* If maximum is less than 0 (and therefore minimum too), minimum and
+ maximum will be negated and swapped to make the following algorithms
+ easier. Example: Both ranges [2,5] and [-5,-2] will be processed as
+ [2,5], and the latter will be swapped back later. The range [0,0] is
+ explicitly excluded from swapping (this would result in [-1,0] instead
+ of the expected [0,1]). */
+ bool bSwapAndNegateRange = (fSourceMinimum < 0.0) && (fSourceMaximum <= 0.0);
+ if( bSwapAndNegateRange )
+ {
+ double fTempValue = fSourceMinimum;
+ fSourceMinimum = -fSourceMaximum;
+ fSourceMaximum = -fTempValue;
+ std::swap( bAutoMinimum, bAutoMaximum );
+ }
+
+ // *** STEP 2: find temporary (unrounded) axis minimum and maximum ***
+
+ double fTempMinimum = fSourceMinimum;
+ double fTempMaximum = fSourceMaximum;
+
+ /* If minimum is variable and greater than 0 (and therefore maximum too),
+ means all original values are greater than 1 (or all values are less
+ than 1, and the range has been swapped above), then: */
+ if( bAutoMinimum && (fTempMinimum > 0.0) )
+ {
+ double fMinimumFloor = ::rtl::math::approxFloor( fTempMinimum );
+ double fMaximumFloor = ::rtl::math::approxFloor( fTempMaximum );
+ // handle the exact value B^(n+1) to be in the range [B^n,B^(n+1)]
+ if( ::rtl::math::approxEqual( fTempMaximum, fMaximumFloor ) )
+ fMaximumFloor -= 1.0;
+
+ if( fMinimumFloor == fMaximumFloor )
+ {
+ /* if minimum and maximum are in one increment interval, expand
+ minimum toward 0 to make the 'shorter' data points visible. */
+ if( m_bExpandNarrowValuesTowardZero )
+ fTempMinimum -= 1.0;
+ }
+ }
+
+ /* If range is still zero-sized (e.g. when minimum is fixed), set minimum
+ to 0, which makes the axis start/stop at the value 1. */
+ if( fTempMinimum == fTempMaximum )
+ {
+ if( bAutoMinimum && (fTempMaximum > 0.0) )
+ fTempMinimum = 0.0;
+ else
+ fTempMaximum += 1.0; // always add one interval, even if maximum is fixed
+ }
+
+ // *** STEP 3: calculate main interval size ***
+
+ // base value (anchor position of the intervals), already scaled
+ if( !(m_aSourceScale.IncrementData.BaseValue >>= rExplicitIncrement.BaseValue) )
+ {
+ //scaling dependent
+ //@maybe todo is this default also plotter dependent ??
+ if( !bAutoMinimum )
+ rExplicitIncrement.BaseValue = fTempMinimum;
+ else if( !bAutoMaximum )
+ rExplicitIncrement.BaseValue = fTempMaximum;
+ else
+ rExplicitIncrement.BaseValue = 0.0;
+ }
+
+ // calculate automatic interval
+ bool bAutoDistance = !(m_aSourceScale.IncrementData.Distance >>= rExplicitIncrement.Distance);
+ if( bAutoDistance )
+ rExplicitIncrement.Distance = 0.0;
+
+ /* Restrict number of allowed intervals with user-defined distance to
+ MAXIMUM_MANUAL_INCREMENT_COUNT. */
+ sal_Int32 nMaxMainIncrementCount = bAutoDistance ?
+ m_nMaximumAutoMainIncrementCount : MAXIMUM_MANUAL_INCREMENT_COUNT;
+
+ // repeat calculation until number of intervals are valid
+ bool bNeedIteration = true;
+ bool bHasCalculatedDistance = false;
+ while( bNeedIteration )
+ {
+ if( bAutoDistance )
+ {
+ // first iteration: calculate interval size from axis limits
+ if( !bHasCalculatedDistance )
+ {
+ double fMinimumFloor = ::rtl::math::approxFloor( fTempMinimum );
+ double fMaximumCeil = ::rtl::math::approxCeil( fTempMaximum );
+ rExplicitIncrement.Distance = ::rtl::math::approxCeil( (fMaximumCeil - fMinimumFloor) / nMaxMainIncrementCount );
+ }
+ else
+ {
+ // following iterations: increase distance
+ rExplicitIncrement.Distance += 1.0;
+ }
+
+ // for next iteration: distance calculated -> use else path to increase
+ bHasCalculatedDistance = true;
+ }
+
+ // *** STEP 4: additional space above or below the data points ***
+
+ double fAxisMinimum = fTempMinimum;
+ double fAxisMaximum = fTempMaximum;
+
+ // round to entire multiples of the distance and add additional space
+ if( bAutoMinimum && m_bExpandBorderToIncrementRhythm )
+ {
+ fAxisMinimum = EquidistantTickFactory::getMinimumAtIncrement( fAxisMinimum, rExplicitIncrement );
+
+ //ensure valid values after scaling #i100995#
+ if( !bAutoDistance )
+ {
+ double fCheck = xInverseScaling->doScaling( fAxisMinimum );
+ if( !std::isfinite( fCheck ) || fCheck <= 0 )
+ {
+ bAutoDistance = true;
+ bHasCalculatedDistance = false;
+ continue;
+ }
+ }
+ }
+ if( bAutoMaximum && m_bExpandBorderToIncrementRhythm )
+ {
+ fAxisMaximum = EquidistantTickFactory::getMaximumAtIncrement( fAxisMaximum, rExplicitIncrement );
+
+ //ensure valid values after scaling #i100995#
+ if( !bAutoDistance )
+ {
+ double fCheck = xInverseScaling->doScaling( fAxisMaximum );
+ if( !std::isfinite( fCheck ) || fCheck <= 0 )
+ {
+ bAutoDistance = true;
+ bHasCalculatedDistance = false;
+ continue;
+ }
+ }
+ }
+
+ // set the resulting limits (swap back to negative range if needed)
+ if( bSwapAndNegateRange )
+ {
+ rExplicitScale.Minimum = -fAxisMaximum;
+ rExplicitScale.Maximum = -fAxisMinimum;
+ }
+ else
+ {
+ rExplicitScale.Minimum = fAxisMinimum;
+ rExplicitScale.Maximum = fAxisMaximum;
+ }
+
+ /* If the number of intervals is too high (e.g. due to invalid fixed
+ distance or due to added space above or below data points),
+ calculate again with increased distance. */
+ double fDistanceCount = ::rtl::math::approxFloor( (fAxisMaximum - fAxisMinimum) / rExplicitIncrement.Distance );
+ bNeedIteration = static_cast< sal_Int32 >( fDistanceCount ) > nMaxMainIncrementCount;
+ // if manual distance is invalid, trigger automatic calculation
+ if( bNeedIteration )
+ bAutoDistance = true;
+
+ // convert limits back to logarithmic scale
+ rExplicitScale.Minimum = xInverseScaling->doScaling( rExplicitScale.Minimum );
+ rExplicitScale.Maximum = xInverseScaling->doScaling( rExplicitScale.Maximum );
+
+ //ensure valid values after scaling #i100995#
+ if( !std::isfinite( rExplicitScale.Minimum ) || rExplicitScale.Minimum <= 0)
+ {
+ rExplicitScale.Minimum = fInputMinimum;
+ if( !std::isfinite( rExplicitScale.Minimum ) || rExplicitScale.Minimum <= 0 )
+ rExplicitScale.Minimum = 1.0;
+ }
+ if( !std::isfinite( rExplicitScale.Maximum) || rExplicitScale.Maximum <= 0 )
+ {
+ rExplicitScale.Maximum= fInputMaximum;
+ if( !std::isfinite( rExplicitScale.Maximum) || rExplicitScale.Maximum <= 0 )
+ rExplicitScale.Maximum = 10.0;
+ }
+ if( rExplicitScale.Maximum < rExplicitScale.Minimum )
+ std::swap( rExplicitScale.Maximum, rExplicitScale.Minimum );
+ }
+
+ //fill explicit sub increment
+ sal_Int32 nSubCount = m_aSourceScale.IncrementData.SubIncrements.getLength();
+ for( sal_Int32 nN=0; nN<nSubCount; nN++ )
+ {
+ ExplicitSubIncrement aExplicitSubIncrement;
+ const SubIncrement& rSubIncrement = m_aSourceScale.IncrementData.SubIncrements[nN];
+ if(!(rSubIncrement.IntervalCount>>=aExplicitSubIncrement.IntervalCount))
+ {
+ //scaling dependent
+ //@todo autocalculate IntervalCount dependent on MainIncrement and scaling
+ aExplicitSubIncrement.IntervalCount = 9;
+ }
+ lcl_ensureMaximumSubIncrementCount( aExplicitSubIncrement.IntervalCount );
+ if(!(rSubIncrement.PostEquidistant>>=aExplicitSubIncrement.PostEquidistant))
+ {
+ //scaling dependent
+ aExplicitSubIncrement.PostEquidistant = false;
+ }
+ rExplicitIncrement.SubIncrements.push_back(aExplicitSubIncrement);
+ }
+}
+
+void ScaleAutomatism::calculateExplicitIncrementAndScaleForDateTimeAxis(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const
+{
+ Date aMinDate(m_aNullDate); aMinDate.AddDays(::rtl::math::approxFloor(rExplicitScale.Minimum));
+ Date aMaxDate(m_aNullDate); aMaxDate.AddDays(::rtl::math::approxFloor(rExplicitScale.Maximum));
+ rExplicitIncrement.PostEquidistant = false;
+
+ if( aMinDate > aMaxDate )
+ {
+ std::swap(aMinDate,aMaxDate);
+ }
+
+ if( !(m_aSourceScale.TimeIncrement.TimeResolution >>= rExplicitScale.TimeResolution) )
+ rExplicitScale.TimeResolution = m_nTimeResolution;
+
+ rExplicitScale.Scaling = new DateScaling(m_aNullDate,rExplicitScale.TimeResolution,false);
+
+ // choose min and max suitable to time resolution
+ switch( rExplicitScale.TimeResolution )
+ {
+ case DAY:
+ if( rExplicitScale.m_bShiftedCategoryPosition )
+ ++aMaxDate; //for explicit scales we need one interval more (maximum excluded)
+ break;
+ case MONTH:
+ aMinDate.SetDay(1);
+ aMaxDate.SetDay(1);
+ if( rExplicitScale.m_bShiftedCategoryPosition )
+ aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate,1);//for explicit scales we need one interval more (maximum excluded)
+ if( DateHelper::IsLessThanOneMonthAway( aMinDate, aMaxDate ) )
+ {
+ if( bAutoMaximum || !bAutoMinimum )
+ aMaxDate = DateHelper::GetDateSomeMonthsAway(aMinDate,1);
+ else
+ aMinDate = DateHelper::GetDateSomeMonthsAway(aMaxDate,-1);
+ }
+ break;
+ case YEAR:
+ aMinDate.SetDay(1);
+ aMinDate.SetMonth(1);
+ aMaxDate.SetDay(1);
+ aMaxDate.SetMonth(1);
+ if( rExplicitScale.m_bShiftedCategoryPosition )
+ aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate,1);//for explicit scales we need one interval more (maximum excluded)
+ if( DateHelper::IsLessThanOneYearAway( aMinDate, aMaxDate ) )
+ {
+ if( bAutoMaximum || !bAutoMinimum )
+ aMaxDate = DateHelper::GetDateSomeYearsAway(aMinDate,1);
+ else
+ aMinDate = DateHelper::GetDateSomeYearsAway(aMaxDate,-1);
+ }
+ break;
+ }
+
+ // set the resulting limits (swap back to negative range if needed)
+ rExplicitScale.Minimum = aMinDate - m_aNullDate;
+ rExplicitScale.Maximum = aMaxDate - m_aNullDate;
+
+ bool bAutoMajor = !(m_aSourceScale.TimeIncrement.MajorTimeInterval >>= rExplicitIncrement.MajorTimeInterval);
+ bool bAutoMinor = !(m_aSourceScale.TimeIncrement.MinorTimeInterval >>= rExplicitIncrement.MinorTimeInterval);
+
+ sal_Int32 nMaxMainIncrementCount = bAutoMajor ?
+ m_nMaximumAutoMainIncrementCount : MAXIMUM_MANUAL_INCREMENT_COUNT;
+ if( nMaxMainIncrementCount > 1 )
+ nMaxMainIncrementCount--;
+
+ //choose major time interval:
+ tools::Long nDayCount = aMaxDate - aMinDate;
+ tools::Long nMainIncrementCount = 1;
+ if( !bAutoMajor )
+ {
+ tools::Long nIntervalDayCount = rExplicitIncrement.MajorTimeInterval.Number;
+ if( rExplicitIncrement.MajorTimeInterval.TimeUnit < rExplicitScale.TimeResolution )
+ rExplicitIncrement.MajorTimeInterval.TimeUnit = rExplicitScale.TimeResolution;
+ switch( rExplicitIncrement.MajorTimeInterval.TimeUnit )
+ {
+ case DAY:
+ break;
+ case MONTH:
+ nIntervalDayCount*=31;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ...
+ break;
+ case YEAR:
+ nIntervalDayCount*=365;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ...
+ break;
+ }
+ nMainIncrementCount = nDayCount/nIntervalDayCount;
+ if( nMainIncrementCount > nMaxMainIncrementCount )
+ bAutoMajor = true;
+ }
+ if( bAutoMajor )
+ {
+ tools::Long nNumer = 1;
+ tools::Long nIntervalDays = nDayCount / nMaxMainIncrementCount;
+ double nDaysPerInterval = 1.0;
+ if( nIntervalDays>365 || rExplicitScale.TimeResolution==YEAR )
+ {
+ rExplicitIncrement.MajorTimeInterval.TimeUnit = YEAR;
+ nDaysPerInterval = 365.0;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ...
+ }
+ else if( nIntervalDays>31 || rExplicitScale.TimeResolution==MONTH )
+ {
+ rExplicitIncrement.MajorTimeInterval.TimeUnit = MONTH;
+ nDaysPerInterval = 31.0;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ...
+ }
+ else
+ {
+ rExplicitIncrement.MajorTimeInterval.TimeUnit = DAY;
+ nDaysPerInterval = 1.0;
+ }
+
+ nNumer = static_cast<sal_Int32>( rtl::math::approxFloor( nIntervalDays/nDaysPerInterval ) );
+ if(nNumer<=0)
+ nNumer=1;
+ if( rExplicitIncrement.MajorTimeInterval.TimeUnit == DAY )
+ {
+ if( nNumer>2 && nNumer<7 )
+ nNumer=7;
+ else if( nNumer>7 )
+ {
+ rExplicitIncrement.MajorTimeInterval.TimeUnit = MONTH;
+ nDaysPerInterval = 31.0;
+ nNumer = static_cast<sal_Int32>( rtl::math::approxFloor( nIntervalDays/nDaysPerInterval ) );
+ if(nNumer<=0)
+ nNumer=1;
+ }
+ }
+ rExplicitIncrement.MajorTimeInterval.Number = nNumer;
+ nMainIncrementCount = static_cast<tools::Long>(nDayCount/(nNumer*nDaysPerInterval));
+ }
+
+ //choose minor time interval:
+ if( !bAutoMinor )
+ {
+ if( rExplicitIncrement.MinorTimeInterval.TimeUnit > rExplicitIncrement.MajorTimeInterval.TimeUnit )
+ rExplicitIncrement.MinorTimeInterval.TimeUnit = rExplicitIncrement.MajorTimeInterval.TimeUnit;
+ tools::Long nIntervalDayCount = rExplicitIncrement.MinorTimeInterval.Number;
+ switch( rExplicitIncrement.MinorTimeInterval.TimeUnit )
+ {
+ case DAY:
+ break;
+ case MONTH:
+ nIntervalDayCount*=31;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ...
+ break;
+ case YEAR:
+ nIntervalDayCount*=365;//todo: maybe different for other calendars... get localized calendar according to set number format at axis ...
+ break;
+ }
+ if( nDayCount/nIntervalDayCount > nMaxMainIncrementCount )
+ bAutoMinor = true;
+ }
+ if( !bAutoMinor )
+ return;
+
+ rExplicitIncrement.MinorTimeInterval.TimeUnit = rExplicitIncrement.MajorTimeInterval.TimeUnit;
+ rExplicitIncrement.MinorTimeInterval.Number = 1;
+ if( nMainIncrementCount > 100 )
+ rExplicitIncrement.MinorTimeInterval.Number = rExplicitIncrement.MajorTimeInterval.Number;
+ else
+ {
+ if( rExplicitIncrement.MajorTimeInterval.Number >= 2 )
+ {
+ if( !(rExplicitIncrement.MajorTimeInterval.Number%2) )
+ rExplicitIncrement.MinorTimeInterval.Number = rExplicitIncrement.MajorTimeInterval.Number/2;
+ else if( !(rExplicitIncrement.MajorTimeInterval.Number%3) )
+ rExplicitIncrement.MinorTimeInterval.Number = rExplicitIncrement.MajorTimeInterval.Number/3;
+ else if( !(rExplicitIncrement.MajorTimeInterval.Number%5) )
+ rExplicitIncrement.MinorTimeInterval.Number = rExplicitIncrement.MajorTimeInterval.Number/5;
+ else if( rExplicitIncrement.MajorTimeInterval.Number > 50 )
+ rExplicitIncrement.MinorTimeInterval.Number = rExplicitIncrement.MajorTimeInterval.Number;
+ }
+ else
+ {
+ switch( rExplicitIncrement.MajorTimeInterval.TimeUnit )
+ {
+ case DAY:
+ break;
+ case MONTH:
+ if( rExplicitScale.TimeResolution == DAY )
+ rExplicitIncrement.MinorTimeInterval.TimeUnit = DAY;
+ break;
+ case YEAR:
+ if( rExplicitScale.TimeResolution <= MONTH )
+ rExplicitIncrement.MinorTimeInterval.TimeUnit = MONTH;
+ break;
+ }
+ }
+ }
+
+}
+
+void ScaleAutomatism::calculateExplicitIncrementAndScaleForLinear(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const
+{
+ // *** STEP 1: initialize the range data ***
+
+ double fSourceMinimum = rExplicitScale.Minimum;
+ double fSourceMaximum = rExplicitScale.Maximum;
+
+ // set automatic PostEquidistant to true (maybe scaling dependent?)
+ if( !(m_aSourceScale.IncrementData.PostEquidistant >>= rExplicitIncrement.PostEquidistant) )
+ rExplicitIncrement.PostEquidistant = true;
+
+ /* If range is invalid (minimum greater than maximum), change one of the
+ variable limits to validate the range. In this step, a zero-sized range
+ is still allowed. */
+ if( fSourceMinimum > fSourceMaximum )
+ {
+ // force changing the maximum, if both limits are fixed
+ if( bAutoMaximum || !bAutoMinimum )
+ fSourceMaximum = fSourceMinimum;
+ else
+ fSourceMinimum = fSourceMaximum;
+ }
+
+ /* If maximum is zero or negative (and therefore minimum too), minimum and
+ maximum will be negated and swapped to make the following algorithms
+ easier. Example: Both ranges [2,5] and [-5,-2] will be processed as
+ [2,5], and the latter will be swapped back later. The range [0,0] is
+ explicitly excluded from swapping (this would result in [-1,0] instead
+ of the expected [0,1]). */
+ bool bSwapAndNegateRange = (fSourceMinimum < 0.0) && (fSourceMaximum <= 0.0);
+ if( bSwapAndNegateRange )
+ {
+ double fTempValue = fSourceMinimum;
+ fSourceMinimum = -fSourceMaximum;
+ fSourceMaximum = -fTempValue;
+ std::swap( bAutoMinimum, bAutoMaximum );
+ }
+
+ // *** STEP 2: find temporary (unrounded) axis minimum and maximum ***
+
+ double fTempMinimum = fSourceMinimum;
+ double fTempMaximum = fSourceMaximum;
+
+ /* If minimum is variable and greater than 0 (and therefore maximum too),
+ means all values are positive (or all values are negative, and the
+ range has been swapped above), then: */
+ if( bAutoMinimum && (fTempMinimum > 0.0) )
+ {
+ /* If minimum equals maximum, or if minimum is less than 5/6 of
+ maximum, set minimum to 0. */
+ if( (fTempMinimum == fTempMaximum) || (fTempMinimum / fTempMaximum < 5.0 / 6.0) )
+ {
+ if( m_bExpandWideValuesToZero )
+ fTempMinimum = 0.0;
+ }
+ /* Else (minimum is greater than or equal to 5/6 of maximum), add half
+ of the visible range (expand minimum toward 0) to make the
+ 'shorter' data points visible. */
+ else
+ {
+ if( m_bExpandNarrowValuesTowardZero )
+ fTempMinimum -= (fTempMaximum - fTempMinimum) / 2.0;
+ }
+ }
+
+ /* If range is still zero-sized (e.g. when minimum is fixed), add some
+ space to a variable limit. */
+ if( fTempMinimum == fTempMaximum )
+ {
+ if( bAutoMaximum || !bAutoMinimum )
+ {
+ // change 0 to 1, otherwise double the value
+ if( fTempMaximum == 0.0 )
+ fTempMaximum = 1.0;
+ else
+ fTempMaximum *= 2.0;
+ }
+ else
+ {
+ // change 0 to -1, otherwise halve the value
+ if( fTempMinimum == 0.0 )
+ fTempMinimum = -1.0;
+ else
+ fTempMinimum /= 2.0;
+ }
+ }
+
+ // *** STEP 3: calculate main interval size ***
+
+ // base value (anchor position of the intervals)
+ if( !(m_aSourceScale.IncrementData.BaseValue >>= rExplicitIncrement.BaseValue) )
+ {
+ if( !bAutoMinimum )
+ rExplicitIncrement.BaseValue = fTempMinimum;
+ else if( !bAutoMaximum )
+ rExplicitIncrement.BaseValue = fTempMaximum;
+ else
+ rExplicitIncrement.BaseValue = 0.0;
+ }
+
+ // calculate automatic interval
+ bool bAutoDistance = !(m_aSourceScale.IncrementData.Distance >>= rExplicitIncrement.Distance);
+ /* Restrict number of allowed intervals with user-defined distance to
+ MAXIMUM_MANUAL_INCREMENT_COUNT. */
+ sal_Int32 nMaxMainIncrementCount = bAutoDistance ?
+ m_nMaximumAutoMainIncrementCount : MAXIMUM_MANUAL_INCREMENT_COUNT;
+
+ double fDistanceMagnitude = 0.0;
+ double fDistanceNormalized = 0.0;
+ bool bHasNormalizedDistance = false;
+
+ // repeat calculation until number of intervals are valid
+ bool bNeedIteration = true;
+ while( bNeedIteration )
+ {
+ if( bAutoDistance )
+ {
+ // first iteration: calculate interval size from axis limits
+ if( !bHasNormalizedDistance )
+ {
+ // raw size of an interval
+ double fDistance = (fTempMaximum - fTempMinimum) / nMaxMainIncrementCount;
+
+ // if distance of is less than 1e-307, do not do anything
+ if( fDistance <= 1.0e-307 )
+ {
+ fDistanceNormalized = 1.0;
+ fDistanceMagnitude = 1.0e-307;
+ }
+ else if ( !std::isfinite(fDistance) )
+ {
+ // fdo#43703: Handle values bigger than limits correctly
+ fDistanceNormalized = 1.0;
+ fDistanceMagnitude = std::numeric_limits<double>::max();
+ }
+ else
+ {
+ // distance magnitude (a power of 10)
+ int nExponent = static_cast< int >( ::rtl::math::approxFloor( log10( fDistance ) ) );
+ fDistanceMagnitude = ::rtl::math::pow10Exp( 1.0, nExponent );
+
+ // stick normalized distance to a few predefined values
+ fDistanceNormalized = fDistance / fDistanceMagnitude;
+ if( fDistanceNormalized <= 1.0 )
+ fDistanceNormalized = 1.0;
+ else if( fDistanceNormalized <= 2.0 )
+ fDistanceNormalized = 2.0;
+ else if( fDistanceNormalized <= 5.0 )
+ fDistanceNormalized = 5.0;
+ else
+ {
+ fDistanceNormalized = 1.0;
+ fDistanceMagnitude *= 10;
+ }
+ }
+ // for next iteration: distance is normalized -> use else path to increase distance
+ bHasNormalizedDistance = true;
+ }
+ // following iterations: increase distance, use only allowed values
+ else
+ {
+ if( fDistanceNormalized == 1.0 )
+ fDistanceNormalized = 2.0;
+ else if( fDistanceNormalized == 2.0 )
+ fDistanceNormalized = 5.0;
+ else
+ {
+ fDistanceNormalized = 1.0;
+ fDistanceMagnitude *= 10;
+ }
+ }
+
+ // set the resulting distance
+ rExplicitIncrement.Distance = fDistanceNormalized * fDistanceMagnitude;
+ }
+
+ // *** STEP 4: additional space above or below the data points ***
+
+ double fAxisMinimum = fTempMinimum;
+ double fAxisMaximum = fTempMaximum;
+
+ // round to entire multiples of the distance and add additional space
+ if( bAutoMinimum )
+ {
+ // round to entire multiples of the distance, based on the base value
+ if( m_bExpandBorderToIncrementRhythm )
+ fAxisMinimum = EquidistantTickFactory::getMinimumAtIncrement( fAxisMinimum, rExplicitIncrement );
+ // additional space, if source minimum is to near at axis minimum
+ if( m_bExpandIfValuesCloseToBorder )
+ if( (fAxisMinimum != 0.0) && ((fAxisMaximum - fSourceMinimum) / (fAxisMaximum - fAxisMinimum) > 20.0 / 21.0) )
+ fAxisMinimum -= rExplicitIncrement.Distance;
+ }
+ if( bAutoMaximum )
+ {
+ // round to entire multiples of the distance, based on the base value
+ if( m_bExpandBorderToIncrementRhythm )
+ fAxisMaximum = EquidistantTickFactory::getMaximumAtIncrement( fAxisMaximum, rExplicitIncrement );
+ // additional space, if source maximum is to near at axis maximum
+ if( m_bExpandIfValuesCloseToBorder )
+ if( (fAxisMaximum != 0.0) && ((fSourceMaximum - fAxisMinimum) / (fAxisMaximum - fAxisMinimum) > 20.0 / 21.0) )
+ fAxisMaximum += rExplicitIncrement.Distance;
+ }
+
+ // set the resulting limits (swap back to negative range if needed)
+ if( bSwapAndNegateRange )
+ {
+ rExplicitScale.Minimum = -fAxisMaximum;
+ rExplicitScale.Maximum = -fAxisMinimum;
+ }
+ else
+ {
+ rExplicitScale.Minimum = fAxisMinimum;
+ rExplicitScale.Maximum = fAxisMaximum;
+ }
+
+ /* If the number of intervals is too high (e.g. due to invalid fixed
+ distance or due to added space above or below data points),
+ calculate again with increased distance. */
+ double fDistanceCount = ::rtl::math::approxFloor( (fAxisMaximum - fAxisMinimum) / rExplicitIncrement.Distance );
+ bNeedIteration = static_cast< sal_Int32 >( fDistanceCount ) > nMaxMainIncrementCount;
+ // if manual distance is invalid, trigger automatic calculation
+ if( bNeedIteration )
+ bAutoDistance = true;
+ }
+
+ //fill explicit sub increment
+ sal_Int32 nSubCount = m_aSourceScale.IncrementData.SubIncrements.getLength();
+ for( sal_Int32 nN=0; nN<nSubCount; nN++ )
+ {
+ ExplicitSubIncrement aExplicitSubIncrement;
+ const SubIncrement& rSubIncrement= m_aSourceScale.IncrementData.SubIncrements[nN];
+ if(!(rSubIncrement.IntervalCount>>=aExplicitSubIncrement.IntervalCount))
+ {
+ //scaling dependent
+ //@todo autocalculate IntervalCount dependent on MainIncrement and scaling
+ aExplicitSubIncrement.IntervalCount = 2;
+ }
+ lcl_ensureMaximumSubIncrementCount( aExplicitSubIncrement.IntervalCount );
+ if(!(rSubIncrement.PostEquidistant>>=aExplicitSubIncrement.PostEquidistant))
+ {
+ //scaling dependent
+ aExplicitSubIncrement.PostEquidistant = false;
+ }
+ rExplicitIncrement.SubIncrements.push_back(aExplicitSubIncrement);
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/TickmarkProperties.hxx b/chart2/source/view/axes/TickmarkProperties.hxx
new file mode 100644
index 0000000000..cbb0398b6a
--- /dev/null
+++ b/chart2/source/view/axes/TickmarkProperties.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <VLineProperties.hxx>
+
+namespace chart
+{
+struct TickmarkProperties
+{
+ sal_Int32
+ RelativePos; //Position in screen values relative to the axis where the tickmark line starts
+ sal_Int32 Length; //Length of the tickmark line in screen values
+
+ VLineProperties aLineProperties;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/Tickmarks.cxx b/chart2/source/view/axes/Tickmarks.cxx
new file mode 100644
index 0000000000..c30f2f25d5
--- /dev/null
+++ b/chart2/source/view/axes/Tickmarks.cxx
@@ -0,0 +1,318 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Tickmarks.hxx"
+#include "Tickmarks_Equidistant.hxx"
+#include "Tickmarks_Dates.hxx"
+#include <ViewDefines.hxx>
+#include "VAxisProperties.hxx"
+#include <osl/diagnose.h>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <utility>
+
+using namespace ::com::sun::star;
+using ::basegfx::B2DVector;
+
+namespace chart {
+
+TickInfo::TickInfo( uno::Reference<chart2::XScaling> xInverse )
+: fScaledTickValue( 0.0 )
+, xInverseScaling(std::move( xInverse ))
+, aTickScreenPosition(0.0,0.0)
+, nFactorForLimitedTextWidth(1)
+, bPaintIt( true )
+{
+}
+
+double TickInfo::getUnscaledTickValue() const
+{
+ if( xInverseScaling.is() )
+ return xInverseScaling->doScaling( fScaledTickValue );
+ else
+ return fScaledTickValue;
+}
+
+sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const
+{
+ //return the positive distance between the two first tickmarks in screen values
+
+ B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition;
+ sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength());
+ if(nRet<0)
+ nRet *= -1;
+ return nRet;
+}
+
+PureTickIter::PureTickIter( TickInfoArrayType& rTickInfoVector )
+ : m_rTickVector(rTickInfoVector)
+ , m_aTickIter(m_rTickVector.begin())
+{
+}
+PureTickIter::~PureTickIter()
+{
+}
+TickInfo* PureTickIter::firstInfo()
+{
+ m_aTickIter = m_rTickVector.begin();
+ if(m_aTickIter!=m_rTickVector.end())
+ return &*m_aTickIter;
+ return nullptr;
+}
+TickInfo* PureTickIter::nextInfo()
+{
+ if(m_aTickIter!=m_rTickVector.end())
+ {
+ ++m_aTickIter;
+ if(m_aTickIter!=m_rTickVector.end())
+ return &*m_aTickIter;
+ }
+ return nullptr;
+}
+
+TickFactory::TickFactory(
+ ExplicitScaleData aScale, ExplicitIncrementData aIncrement )
+ : m_rScale(std::move( aScale ))
+ , m_rIncrement(std::move( aIncrement ))
+{
+ //@todo: make sure that the scale is valid for the scaling
+
+ if( m_rScale.Scaling.is() )
+ {
+ m_xInverseScaling = m_rScale.Scaling->getInverseScaling();
+ OSL_ENSURE( m_xInverseScaling.is(), "each Scaling needs to return an inverse Scaling" );
+ }
+
+ m_fScaledVisibleMin = m_rScale.Minimum;
+ if( m_xInverseScaling.is() )
+ m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin);
+
+ m_fScaledVisibleMax = m_rScale.Maximum;
+ if( m_xInverseScaling.is() )
+ m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax);
+}
+
+TickFactory::~TickFactory()
+{
+}
+
+bool TickFactory::isDateAxis() const
+{
+ return m_rScale.AxisType == chart2::AxisType::DATE;
+}
+
+void TickFactory::getAllTicks( TickInfoArraysType& rAllTickInfos ) const
+{
+ if( isDateAxis() )
+ DateTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos );
+ else
+ EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos );
+}
+
+void TickFactory::getAllTicksShifted( TickInfoArraysType& rAllTickInfos ) const
+{
+ if( isDateAxis() )
+ DateTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos );
+ else
+ EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos );
+}
+
+// ___TickFactory_2D___
+TickFactory2D::TickFactory2D(
+ const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement
+ //, double fStretch_SceneToScreen, double fOffset_SceneToScreen )
+ , const B2DVector& rStartScreenPos, const B2DVector& rEndScreenPos
+ , const B2DVector& rAxisLineToLabelLineShift )
+ : TickFactory( rScale, rIncrement )
+ , m_aAxisStartScreenPosition2D(rStartScreenPos)
+ , m_aAxisEndScreenPosition2D(rEndScreenPos)
+ , m_aAxisLineToLabelLineShift(rAxisLineToLabelLineShift)
+ , m_fStretch_LogicToScreen(1.0)
+ , m_fOffset_LogicToScreen(0.0)
+{
+ double fWidthY = m_fScaledVisibleMax - m_fScaledVisibleMin;
+ if (m_rScale.Orientation == chart2::AxisOrientation_MATHEMATICAL)
+ {
+ m_fStretch_LogicToScreen = 1.0/fWidthY;
+ m_fOffset_LogicToScreen = -m_fScaledVisibleMin;
+ }
+ else
+ {
+ B2DVector aSwap(m_aAxisStartScreenPosition2D);
+ m_aAxisStartScreenPosition2D = m_aAxisEndScreenPosition2D;
+ m_aAxisEndScreenPosition2D = aSwap;
+
+ m_fStretch_LogicToScreen = -1.0/fWidthY;
+ m_fOffset_LogicToScreen = -m_fScaledVisibleMax;
+ }
+}
+
+TickFactory2D::~TickFactory2D()
+{
+}
+
+bool TickFactory2D::isHorizontalAxis() const
+{
+ // check trivial cases:
+ if ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() )
+ return true;
+ if ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() )
+ return false;
+
+ // for skew axes compare angle with horizontal vector
+ double fInclination = std::abs(B2DVector(m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D).angle(B2DVector(1.0, 0.0)));
+ return fInclination < M_PI_4 || fInclination > (M_PI-M_PI_4);
+}
+bool TickFactory2D::isVerticalAxis() const
+{
+ // check trivial cases:
+ if ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() )
+ return true;
+ if ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() )
+ return false;
+
+ // for skew axes compare angle with vertical vector
+ double fInclination = std::abs(B2DVector(m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D).angle(B2DVector(0.0, -1.0)));
+ return fInclination < M_PI_4 || fInclination > (M_PI-M_PI_4);
+}
+//static
+sal_Int32 TickFactory2D::getTickScreenDistance( TickIter& rIter )
+{
+ //return the positive distance between the two first tickmarks in screen values
+ //if there are less than two tickmarks -1 is returned
+
+ const TickInfo* pFirstTickInfo = rIter.firstInfo();
+ const TickInfo* pSecondTickInfo = rIter.nextInfo();
+ if(!pSecondTickInfo || !pFirstTickInfo)
+ return -1;
+
+ return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo );
+}
+
+B2DVector TickFactory2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const
+{
+ B2DVector aRet(m_aAxisStartScreenPosition2D);
+ aRet += (m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D)
+ *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStretch_LogicToScreen);
+ return aRet;
+}
+
+void TickFactory2D::addPointSequenceForTickLine( drawing::PointSequenceSequence& rPoints
+ , sal_Int32 nSequenceIndex
+ , double fScaledLogicTickValue, double fInnerDirectionSign
+ , const TickmarkProperties& rTickmarkProperties
+ , bool bPlaceAtLabels ) const
+{
+ if( fInnerDirectionSign==0.0 )
+ fInnerDirectionSign = 1.0;
+
+ B2DVector aTickScreenPosition = getTickScreenPosition2D(fScaledLogicTickValue);
+ if( bPlaceAtLabels )
+ aTickScreenPosition += m_aAxisLineToLabelLineShift;
+
+ B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
+ aMainDirection.normalize();
+ B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
+ aOrthoDirection *= fInnerDirectionSign;
+ aOrthoDirection.normalize();
+
+ B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos;
+ B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length;
+
+ rPoints.getArray()[nSequenceIndex]
+ = { { static_cast<sal_Int32>(aStart.getX()), static_cast<sal_Int32>(aStart.getY()) },
+ { static_cast<sal_Int32>(aEnd.getX()), static_cast<sal_Int32>(aEnd.getY()) } };
+}
+
+B2DVector TickFactory2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const
+{
+ bool bFarAwayLabels = false;
+ if( rAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_START
+ || rAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_END )
+ bFarAwayLabels = true;
+
+ double fInnerDirectionSign = rAxisProperties.maLabelAlignment.mfInnerTickDirection;
+ if( fInnerDirectionSign==0.0 )
+ fInnerDirectionSign = 1.0;
+
+ B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
+ aMainDirection.normalize();
+ B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
+ aOrthoDirection *= fInnerDirectionSign;
+ aOrthoDirection.normalize();
+
+ B2DVector aStart(0,0), aEnd(0,0);
+ if( bFarAwayLabels )
+ {
+ TickmarkProperties aProps( AxisProperties::getBiggestTickmarkProperties() );
+ aStart = aOrthoDirection*aProps.RelativePos;
+ aEnd = aStart - aOrthoDirection*aProps.Length;
+ }
+ else
+ {
+ for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;)
+ {
+ const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN];
+ B2DVector aNewStart = aOrthoDirection*rProps.RelativePos;
+ B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length;
+ if(aNewStart.getLength()>aStart.getLength())
+ aStart=aNewStart;
+ if(aNewEnd.getLength()>aEnd.getLength())
+ aEnd=aNewEnd;
+ }
+ }
+
+ B2DVector aLabelDirection(aStart);
+ if (rAxisProperties.maLabelAlignment.mfInnerTickDirection != rAxisProperties.maLabelAlignment.mfLabelDirection)
+ aLabelDirection = aEnd;
+
+ B2DVector aOrthoLabelDirection(aOrthoDirection);
+ if (rAxisProperties.maLabelAlignment.mfInnerTickDirection != rAxisProperties.maLabelAlignment.mfLabelDirection)
+ aOrthoLabelDirection*=-1.0;
+ aOrthoLabelDirection.normalize();
+ if( bIncludeSpaceBetweenTickAndText )
+ aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING;
+ if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo )
+ aLabelDirection += m_aAxisLineToLabelLineShift;
+ return aLabelDirection;
+}
+
+void TickFactory2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const
+{
+ rPoints.getArray()[0] = { { static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX()),
+ static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY()) },
+ { static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX()),
+ static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY()) } };
+}
+
+void TickFactory2D::updateScreenValues( TickInfoArraysType& rAllTickInfos ) const
+{
+ //get the transformed screen values for all tickmarks in rAllTickInfos
+ for (auto & tickInfos : rAllTickInfos)
+ {
+ for (auto & tickInfo : tickInfos)
+ {
+ tickInfo.aTickScreenPosition =
+ getTickScreenPosition2D(tickInfo.fScaledTickValue);
+ }
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/Tickmarks.hxx b/chart2/source/view/axes/Tickmarks.hxx
new file mode 100644
index 0000000000..2266c03c91
--- /dev/null
+++ b/chart2/source/view/axes/Tickmarks.hxx
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <chartview/ExplicitScaleValues.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+#include <vector>
+
+namespace chart { struct AxisProperties; }
+namespace chart { struct TickmarkProperties; }
+namespace com::sun::star::chart2 { class XScaling; }
+namespace com::sun::star::drawing { class XShape; }
+
+namespace chart {
+
+struct TickInfo
+{
+ double fScaledTickValue;
+ css::uno::Reference<css::chart2::XScaling> xInverseScaling;
+ rtl::Reference<SvxShapeText> xTextShape;
+ OUString aText;//used only for complex categories so far
+ ::basegfx::B2DVector aTickScreenPosition;
+ sal_Int32 nFactorForLimitedTextWidth;//categories in higher levels of complex categories can have more place than a single simple category
+ bool bPaintIt;
+
+//methods:
+ TickInfo() = delete;
+ explicit TickInfo( css::uno::Reference<css::chart2::XScaling> xInverse );
+
+ /**
+ * Return a value associated with the tick mark. It's normally an original
+ * value from the data source, or 1-based integer index in case the axis
+ * is a category axis.
+ */
+ double getUnscaledTickValue() const;
+ sal_Int32 getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const;
+};
+
+typedef std::vector<TickInfo> TickInfoArrayType;
+typedef std::vector<TickInfoArrayType> TickInfoArraysType;
+
+class TickIter
+{
+public:
+ virtual ~TickIter() {}
+ virtual TickInfo* firstInfo() = 0;
+ virtual TickInfo* nextInfo() = 0;
+};
+
+class PureTickIter : public TickIter
+{
+public:
+ explicit PureTickIter( TickInfoArrayType& rTickInfoVector );
+ virtual ~PureTickIter() override;
+ virtual TickInfo* firstInfo() override;
+ virtual TickInfo* nextInfo() override;
+
+private:
+ TickInfoArrayType& m_rTickVector;
+ TickInfoArrayType::iterator m_aTickIter;
+};
+
+class TickFactory
+{
+public:
+ TickFactory(
+ ExplicitScaleData aScale
+ , ExplicitIncrementData aIncrement );
+ virtual ~TickFactory();
+
+ void getAllTicks( TickInfoArraysType& rAllTickInfos ) const;
+ void getAllTicksShifted( TickInfoArraysType& rAllTickInfos ) const;
+
+private: //methods
+ bool isDateAxis() const;
+
+protected: //member
+ ExplicitScaleData m_rScale;
+ ExplicitIncrementData m_rIncrement;
+ css::uno::Reference< css::chart2::XScaling > m_xInverseScaling;
+
+ //minimum and maximum of the visible range after scaling
+ double m_fScaledVisibleMin;
+ double m_fScaledVisibleMax;
+};
+
+class TickFactory2D final : public TickFactory
+{
+public:
+ TickFactory2D(
+ const ExplicitScaleData& rScale
+ , const ExplicitIncrementData& rIncrement
+ , const ::basegfx::B2DVector& rStartScreenPos, const ::basegfx::B2DVector& rEndScreenPos
+ , const ::basegfx::B2DVector& rAxisLineToLabelLineShift );
+
+ virtual ~TickFactory2D() override;
+
+ static sal_Int32 getTickScreenDistance( TickIter& rIter );
+
+ void createPointSequenceForAxisMainLine( css::drawing::PointSequenceSequence& rPoints ) const;
+ void addPointSequenceForTickLine( css::drawing::PointSequenceSequence& rPoints
+ , sal_Int32 nSequenceIndex
+ , double fScaledLogicTickValue, double fInnerDirectionSign
+ , const TickmarkProperties& rTickmarkProperties, bool bPlaceAtLabels ) const;
+ ::basegfx::B2DVector getDistanceAxisTickToText( const AxisProperties& rAxisProperties
+ , bool bIncludeFarAwayDistanceIfSo = false
+ , bool bIncludeSpaceBetweenTickAndText = true ) const;
+
+ /**
+ * Determine the screen positions of all ticks based on their numeric values.
+ */
+ void updateScreenValues( TickInfoArraysType& rAllTickInfos ) const;
+
+ bool isHorizontalAxis() const;
+ bool isVerticalAxis() const;
+
+ const ::basegfx::B2DVector & getXaxisStartPos() const
+ {
+ return m_aAxisStartScreenPosition2D;
+ }
+
+ const ::basegfx::B2DVector & getXaxisEndPos() const
+ {
+ return m_aAxisEndScreenPosition2D;
+ }
+
+private:
+ ::basegfx::B2DVector getTickScreenPosition2D( double fScaledLogicTickValue ) const;
+
+ ::basegfx::B2DVector m_aAxisStartScreenPosition2D;
+ ::basegfx::B2DVector m_aAxisEndScreenPosition2D;
+
+ //labels might be positioned high or low on the border of the diagram far away from the axis
+ //add this vector to go from the axis line to the label line (border of the diagram)
+ ::basegfx::B2DVector m_aAxisLineToLabelLineShift;
+
+ double m_fStretch_LogicToScreen;
+ double m_fOffset_LogicToScreen;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/Tickmarks_Dates.cxx b/chart2/source/view/axes/Tickmarks_Dates.cxx
new file mode 100644
index 0000000000..869d46603f
--- /dev/null
+++ b/chart2/source/view/axes/Tickmarks_Dates.cxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Tickmarks_Dates.hxx"
+#include "DateScaling.hxx"
+#include <rtl/math.hxx>
+#include <osl/diagnose.h>
+#include <DateHelper.hxx>
+#include <com/sun/star/chart/TimeUnit.hpp>
+#include <utility>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::rtl::math;
+using ::com::sun::star::chart::TimeUnit::DAY;
+using ::com::sun::star::chart::TimeUnit::MONTH;
+using ::com::sun::star::chart::TimeUnit::YEAR;
+
+DateTickFactory::DateTickFactory(
+ ExplicitScaleData aScale, ExplicitIncrementData aIncrement )
+ : m_aScale(std::move( aScale ))
+ , m_aIncrement(std::move( aIncrement ))
+{
+ //@todo: make sure that the scale is valid for the scaling
+
+ if( m_aScale.Scaling.is() )
+ {
+ m_xInverseScaling = m_aScale.Scaling->getInverseScaling();
+ OSL_ENSURE( m_xInverseScaling.is(), "each Scaling needs to return an inverse Scaling" );
+ }
+}
+
+DateTickFactory::~DateTickFactory()
+{
+}
+
+void DateTickFactory::getAllTicks( TickInfoArraysType& rAllTickInfos, bool bShifted ) const
+{
+ rAllTickInfos.resize(2);
+ TickInfoArrayType& rMajorTicks = rAllTickInfos[0];
+ TickInfoArrayType& rMinorTicks = rAllTickInfos[1];
+ rMajorTicks.clear();
+ rMinorTicks.clear();
+
+ Date aNull(m_aScale.NullDate);
+
+ Date aDate = aNull + static_cast<sal_Int32>(::rtl::math::approxFloor(m_aScale.Minimum));
+ Date aMaxDate = aNull + static_cast<sal_Int32>(::rtl::math::approxFloor(m_aScale.Maximum));
+
+ uno::Reference< chart2::XScaling > xScaling(m_aScale.Scaling);
+ uno::Reference< chart2::XScaling > xInverseScaling(m_xInverseScaling);
+ if( bShifted )
+ {
+ xScaling = new DateScaling(aNull,m_aScale.TimeResolution,true/*bShifted*/);
+ xInverseScaling = xScaling->getInverseScaling();
+ }
+
+ //create major date tickinfos
+ while( aDate<= aMaxDate )
+ {
+ if( bShifted && aDate==aMaxDate )
+ break;
+
+ TickInfo aNewTick(xInverseScaling); aNewTick.fScaledTickValue = aDate - aNull;
+
+ if( xInverseScaling.is() )
+ aNewTick.fScaledTickValue = xScaling->doScaling(aNewTick.fScaledTickValue);
+ rMajorTicks.push_back( aNewTick );
+
+ if(m_aIncrement.MajorTimeInterval.Number<=0)
+ break;
+
+ //find next major date
+ switch( m_aIncrement.MajorTimeInterval.TimeUnit )
+ {
+ case DAY:
+ aDate.AddDays( m_aIncrement.MajorTimeInterval.Number );
+ break;
+ case YEAR:
+ aDate = DateHelper::GetDateSomeYearsAway( aDate, m_aIncrement.MajorTimeInterval.Number );
+ break;
+ case MONTH:
+ default:
+ aDate = DateHelper::GetDateSomeMonthsAway( aDate, m_aIncrement.MajorTimeInterval.Number );
+ break;
+ }
+ }
+
+ //create minor date tickinfos
+ aDate = aNull + static_cast<sal_Int32>(::rtl::math::approxFloor(m_aScale.Minimum));
+ while( aDate<= aMaxDate )
+ {
+ if( bShifted && aDate==aMaxDate )
+ break;
+
+ TickInfo aNewTick(xInverseScaling); aNewTick.fScaledTickValue = aDate - aNull;
+ if( xInverseScaling.is() )
+ aNewTick.fScaledTickValue = xScaling->doScaling(aNewTick.fScaledTickValue);
+ rMinorTicks.push_back( aNewTick );
+
+ if(m_aIncrement.MinorTimeInterval.Number<=0)
+ break;
+
+ //find next minor date
+ switch( m_aIncrement.MinorTimeInterval.TimeUnit )
+ {
+ case DAY:
+ aDate.AddDays( m_aIncrement.MinorTimeInterval.Number );
+ break;
+ case YEAR:
+ aDate = DateHelper::GetDateSomeYearsAway( aDate, m_aIncrement.MinorTimeInterval.Number );
+ break;
+ case MONTH:
+ default:
+ aDate = DateHelper::GetDateSomeMonthsAway( aDate, m_aIncrement.MinorTimeInterval.Number );
+ break;
+ }
+ }
+}
+
+void DateTickFactory::getAllTicks( TickInfoArraysType& rAllTickInfos ) const
+{
+ getAllTicks( rAllTickInfos, false );
+}
+
+void DateTickFactory::getAllTicksShifted( TickInfoArraysType& rAllTickInfos ) const
+{
+ getAllTicks( rAllTickInfos, true );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/Tickmarks_Dates.hxx b/chart2/source/view/axes/Tickmarks_Dates.hxx
new file mode 100644
index 0000000000..bc75bad4e0
--- /dev/null
+++ b/chart2/source/view/axes/Tickmarks_Dates.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "Tickmarks.hxx"
+
+namespace chart
+{
+
+class DateTickFactory
+{
+public:
+ DateTickFactory(
+ ExplicitScaleData aScale
+ , ExplicitIncrementData aIncrement );
+ ~DateTickFactory();
+
+ void getAllTicks( TickInfoArraysType& rAllTickInfos ) const;
+ void getAllTicksShifted( TickInfoArraysType& rAllTickInfos ) const;
+
+private: //methods
+ void getAllTicks( TickInfoArraysType& rAllTickInfos, bool bShifted ) const;
+
+private: //member
+ ExplicitScaleData m_aScale;
+ ExplicitIncrementData m_aIncrement;
+ css::uno::Reference< css::chart2::XScaling >
+ m_xInverseScaling;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/Tickmarks_Equidistant.cxx b/chart2/source/view/axes/Tickmarks_Equidistant.cxx
new file mode 100644
index 0000000000..c1991fb3ba
--- /dev/null
+++ b/chart2/source/view/axes/Tickmarks_Equidistant.cxx
@@ -0,0 +1,626 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Tickmarks_Equidistant.hxx"
+#include <rtl/math.hxx>
+#include <osl/diagnose.h>
+#include <float.h>
+
+#include <limits>
+#include <utility>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::rtl::math;
+
+//static
+double EquidistantTickFactory::getMinimumAtIncrement( double fMin, const ExplicitIncrementData& rIncrement )
+{
+ //the returned value will be <= fMin and on a Major Tick given by rIncrement
+ if(rIncrement.Distance<=0.0)
+ return fMin;
+
+ double fRet = rIncrement.BaseValue +
+ floor( approxSub( fMin, rIncrement.BaseValue )
+ / rIncrement.Distance)
+ *rIncrement.Distance;
+
+ if( fRet > fMin )
+ {
+ if( !approxEqual(fRet, fMin) )
+ fRet -= rIncrement.Distance;
+ }
+ return fRet;
+}
+//static
+double EquidistantTickFactory::getMaximumAtIncrement( double fMax, const ExplicitIncrementData& rIncrement )
+{
+ //the returned value will be >= fMax and on a Major Tick given by rIncrement
+ if(rIncrement.Distance<=0.0)
+ return fMax;
+
+ double fRet = rIncrement.BaseValue +
+ floor( approxSub( fMax, rIncrement.BaseValue )
+ / rIncrement.Distance)
+ *rIncrement.Distance;
+
+ if( fRet < fMax )
+ {
+ if( !approxEqual(fRet, fMax) )
+ fRet += rIncrement.Distance;
+ }
+ return fRet;
+}
+
+EquidistantTickFactory::EquidistantTickFactory(
+ ExplicitScaleData aScale, ExplicitIncrementData aIncrement )
+ : m_rScale(std::move( aScale ))
+ , m_rIncrement(std::move( aIncrement ))
+{
+ //@todo: make sure that the scale is valid for the scaling
+
+ m_pfCurrentValues.reset( new double[getTickDepth()] );
+
+ if( m_rScale.Scaling.is() )
+ {
+ m_xInverseScaling = m_rScale.Scaling->getInverseScaling();
+ OSL_ENSURE( m_xInverseScaling.is(), "each Scaling needs to return an inverse Scaling" );
+ }
+
+ double fMin = m_fScaledVisibleMin = m_rScale.Minimum;
+ if( m_xInverseScaling.is() )
+ {
+ m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin);
+ if(m_rIncrement.PostEquidistant )
+ fMin = m_fScaledVisibleMin;
+ }
+
+ double fMax = m_fScaledVisibleMax = m_rScale.Maximum;
+ if( m_xInverseScaling.is() )
+ {
+ m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax);
+ if(m_rIncrement.PostEquidistant )
+ fMax = m_fScaledVisibleMax;
+ }
+
+ m_fOuterMajorTickBorderMin = EquidistantTickFactory::getMinimumAtIncrement( fMin, m_rIncrement );
+ m_fOuterMajorTickBorderMax = EquidistantTickFactory::getMaximumAtIncrement( fMax, m_rIncrement );
+
+ m_fOuterMajorTickBorderMin_Scaled = m_fOuterMajorTickBorderMin;
+ m_fOuterMajorTickBorderMax_Scaled = m_fOuterMajorTickBorderMax;
+ if(m_rIncrement.PostEquidistant || !m_xInverseScaling.is())
+ return;
+
+ m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin);
+ m_fOuterMajorTickBorderMax_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMax);
+
+ //check validity of new range: m_fOuterMajorTickBorderMin <-> m_fOuterMajorTickBorderMax
+ //it is assumed here, that the original range in the given Scale is valid
+ if( !std::isfinite(m_fOuterMajorTickBorderMin_Scaled) )
+ {
+ m_fOuterMajorTickBorderMin += m_rIncrement.Distance;
+ m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin);
+ }
+ if( !std::isfinite(m_fOuterMajorTickBorderMax_Scaled) )
+ {
+ m_fOuterMajorTickBorderMax -= m_rIncrement.Distance;
+ m_fOuterMajorTickBorderMax_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMax);
+ }
+}
+
+EquidistantTickFactory::~EquidistantTickFactory()
+{
+}
+
+sal_Int32 EquidistantTickFactory::getTickDepth() const
+{
+ return static_cast<sal_Int32>(m_rIncrement.SubIncrements.size()) + 1;
+}
+
+void EquidistantTickFactory::addSubTicks( sal_Int32 nDepth, uno::Sequence< uno::Sequence< double > >& rParentTicks ) const
+{
+ EquidistantTickIter aIter( rParentTicks, m_rIncrement, nDepth-1 );
+ double* pfNextParentTick = aIter.firstValue();
+ if(!pfNextParentTick)
+ return;
+ double fLastParentTick = *pfNextParentTick;
+ pfNextParentTick = aIter.nextValue();
+ if(!pfNextParentTick)
+ return;
+
+ sal_Int32 nMaxSubTickCount = getMaxTickCount( nDepth );
+ if(!nMaxSubTickCount)
+ return;
+
+ uno::Sequence< double > aSubTicks(nMaxSubTickCount);
+ auto pSubTicks = aSubTicks.getArray();
+ sal_Int32 nRealSubTickCount = 0;
+ sal_Int32 nIntervalCount = m_rIncrement.SubIncrements[nDepth-1].IntervalCount;
+
+ double* pValue = nullptr;
+ for(; pfNextParentTick; fLastParentTick=*pfNextParentTick, pfNextParentTick = aIter.nextValue())
+ {
+ for( sal_Int32 nPartTick = 1; nPartTick<nIntervalCount; nPartTick++ )
+ {
+ pValue = getMinorTick( nPartTick, nDepth
+ , fLastParentTick, *pfNextParentTick );
+ if(!pValue)
+ continue;
+
+ pSubTicks[nRealSubTickCount] = *pValue;
+ nRealSubTickCount++;
+ }
+ }
+
+ aSubTicks.realloc(nRealSubTickCount);
+ rParentTicks.getArray()[nDepth] = aSubTicks;
+ if(static_cast<sal_Int32>(m_rIncrement.SubIncrements.size())>nDepth)
+ addSubTicks( nDepth+1, rParentTicks );
+}
+
+sal_Int32 EquidistantTickFactory::getMaxTickCount( sal_Int32 nDepth ) const
+{
+ //return the maximum amount of ticks
+ //possibly open intervals at the two ends of the region are handled as if they were completely visible
+ //(this is necessary for calculating the sub ticks at the borders correctly)
+
+ if( nDepth >= getTickDepth() )
+ return 0;
+ if( m_fOuterMajorTickBorderMax < m_fOuterMajorTickBorderMin )
+ return 0;
+ if( m_rIncrement.Distance<=0.0)
+ return 0;
+
+ double fSub;
+ if(m_rIncrement.PostEquidistant )
+ fSub = approxSub( m_fScaledVisibleMax, m_fScaledVisibleMin );
+ else
+ fSub = approxSub( m_rScale.Maximum, m_rScale.Minimum );
+
+ if (!std::isfinite(fSub))
+ return 0;
+
+ double fIntervalCount = fSub / m_rIncrement.Distance;
+ if (fIntervalCount > std::numeric_limits<sal_Int32>::max())
+ // Interval count too high! Bail out.
+ return 0;
+
+ sal_Int32 nIntervalCount = static_cast<sal_Int32>(fIntervalCount);
+
+ nIntervalCount+=3;
+ for(sal_Int32 nN=0; nN<nDepth-1; nN++)
+ {
+ if( m_rIncrement.SubIncrements[nN].IntervalCount>1 )
+ nIntervalCount *= m_rIncrement.SubIncrements[nN].IntervalCount;
+ }
+
+ sal_Int32 nTickCount = nIntervalCount;
+ if(nDepth>0 && m_rIncrement.SubIncrements[nDepth-1].IntervalCount>1)
+ nTickCount = nIntervalCount * (m_rIncrement.SubIncrements[nDepth-1].IntervalCount-1);
+
+ return nTickCount;
+}
+
+double* EquidistantTickFactory::getMajorTick( sal_Int32 nTick ) const
+{
+ m_pfCurrentValues[0] = m_fOuterMajorTickBorderMin + nTick*m_rIncrement.Distance;
+
+ if(m_pfCurrentValues[0]>m_fOuterMajorTickBorderMax)
+ {
+ if( !approxEqual(m_pfCurrentValues[0],m_fOuterMajorTickBorderMax) )
+ return nullptr;
+ }
+ if(m_pfCurrentValues[0]<m_fOuterMajorTickBorderMin)
+ {
+ if( !approxEqual(m_pfCurrentValues[0],m_fOuterMajorTickBorderMin) )
+ return nullptr;
+ }
+
+ //return always the value after scaling
+ if(!m_rIncrement.PostEquidistant && m_xInverseScaling.is() )
+ m_pfCurrentValues[0] = m_rScale.Scaling->doScaling( m_pfCurrentValues[0] );
+
+ return &m_pfCurrentValues[0];
+}
+
+double* EquidistantTickFactory::getMinorTick( sal_Int32 nTick, sal_Int32 nDepth
+ , double fStartParentTick, double fNextParentTick ) const
+{
+ //check validity of arguments
+ {
+ //OSL_ENSURE( fStartParentTick < fNextParentTick, "fStartParentTick >= fNextParentTick");
+ if(fStartParentTick >= fNextParentTick)
+ return nullptr;
+ if(nDepth>static_cast<sal_Int32>(m_rIncrement.SubIncrements.size()) || nDepth<=0)
+ return nullptr;
+
+ //subticks are only calculated if they are laying between parent ticks:
+ if(nTick<=0)
+ return nullptr;
+ if(nTick>=m_rIncrement.SubIncrements[nDepth-1].IntervalCount)
+ return nullptr;
+ }
+
+ bool bPostEquidistant = m_rIncrement.SubIncrements[nDepth-1].PostEquidistant;
+
+ double fAdaptedStartParent = fStartParentTick;
+ double fAdaptedNextParent = fNextParentTick;
+
+ if( !bPostEquidistant && m_xInverseScaling.is() )
+ {
+ fAdaptedStartParent = m_xInverseScaling->doScaling(fStartParentTick);
+ fAdaptedNextParent = m_xInverseScaling->doScaling(fNextParentTick);
+ }
+
+ double fDistance = (fAdaptedNextParent - fAdaptedStartParent)/m_rIncrement.SubIncrements[nDepth-1].IntervalCount;
+
+ m_pfCurrentValues[nDepth] = fAdaptedStartParent + nTick*fDistance;
+
+ //return always the value after scaling
+ if(!bPostEquidistant && m_xInverseScaling.is() )
+ m_pfCurrentValues[nDepth] = m_rScale.Scaling->doScaling( m_pfCurrentValues[nDepth] );
+
+ if( !isWithinOuterBorder( m_pfCurrentValues[nDepth] ) )
+ return nullptr;
+
+ return &m_pfCurrentValues[nDepth];
+}
+
+bool EquidistantTickFactory::isWithinOuterBorder( double fScaledValue ) const
+{
+ if(fScaledValue>m_fOuterMajorTickBorderMax_Scaled)
+ return false;
+ if(fScaledValue<m_fOuterMajorTickBorderMin_Scaled)
+ return false;
+
+ return true;
+}
+
+bool EquidistantTickFactory::isVisible( double fScaledValue ) const
+{
+ if(fScaledValue>m_fScaledVisibleMax)
+ {
+ if( !approxEqual(fScaledValue,m_fScaledVisibleMax) )
+ return false;
+ }
+ if(fScaledValue<m_fScaledVisibleMin)
+ {
+ if( !approxEqual(fScaledValue,m_fScaledVisibleMin) )
+ return false;
+ }
+ return true;
+}
+
+void EquidistantTickFactory::getAllTicks( TickInfoArraysType& rAllTickInfos ) const
+{
+ //create point sequences for each tick depth
+ const sal_Int32 nDepthCount = getTickDepth();
+ const sal_Int32 nMaxMajorTickCount = getMaxTickCount(0);
+
+ if (nDepthCount <= 0 || nMaxMajorTickCount <= 0)
+ return;
+
+ uno::Sequence< uno::Sequence< double > > aAllTicks(nDepthCount);
+ auto pAllTicks = aAllTicks.getArray();
+ pAllTicks[0].realloc(nMaxMajorTickCount);
+ auto pAllTicks0 = pAllTicks[0].getArray();
+
+ sal_Int32 nRealMajorTickCount = 0;
+ for( sal_Int32 nMajorTick=0; nMajorTick<nMaxMajorTickCount; nMajorTick++ )
+ {
+ double* pValue = getMajorTick( nMajorTick );
+ if(!pValue)
+ continue;
+ pAllTicks0[nRealMajorTickCount] = *pValue;
+ nRealMajorTickCount++;
+ }
+ if(!nRealMajorTickCount)
+ return;
+ pAllTicks[0].realloc(nRealMajorTickCount);
+
+ addSubTicks(1, aAllTicks);
+
+ //so far we have added all ticks between the outer major tick marks
+ //this was necessary to create sub ticks correctly
+ //now we reduce all ticks to the visible ones that lie between the real borders
+ sal_Int32 nDepth = 0;
+ sal_Int32 nTick = 0;
+ for( nDepth = 0; nDepth < nDepthCount; nDepth++)
+ {
+ sal_Int32 nInvisibleAtLowerBorder = 0;
+ sal_Int32 nInvisibleAtUpperBorder = 0;
+ //we need only to check all ticks within the first major interval at each border
+ sal_Int32 nCheckCount = 1;
+ for(sal_Int32 nN=0; nN<nDepth; nN++)
+ {
+ if( m_rIncrement.SubIncrements[nN].IntervalCount>1 )
+ nCheckCount *= m_rIncrement.SubIncrements[nN].IntervalCount;
+ }
+ uno::Sequence< double >& rTicks = pAllTicks[nDepth];
+ sal_Int32 nCount = rTicks.getLength();
+ //check lower border
+ for( nTick=0; nTick<nCheckCount && nTick<nCount; nTick++)
+ {
+ if( !isVisible( rTicks[nTick] ) )
+ nInvisibleAtLowerBorder++;
+ }
+ //check upper border
+ for( nTick=nCount-1; nTick>nCount-1-nCheckCount && nTick>=0; nTick--)
+ {
+ if( !isVisible( rTicks[nTick] ) )
+ nInvisibleAtUpperBorder++;
+ }
+ //resize sequence
+ if( !nInvisibleAtLowerBorder && !nInvisibleAtUpperBorder)
+ continue;
+ if( !nInvisibleAtLowerBorder )
+ rTicks.realloc(nCount-nInvisibleAtUpperBorder);
+ else
+ {
+ sal_Int32 nNewCount = nCount-nInvisibleAtUpperBorder-nInvisibleAtLowerBorder;
+ if(nNewCount<0)
+ nNewCount=0;
+
+ uno::Sequence< double > aOldTicks(rTicks);
+ rTicks.realloc(nNewCount);
+ auto pTicks = rTicks.getArray();
+ for(nTick = 0; nTick<nNewCount; nTick++)
+ pTicks[nTick] = aOldTicks[nInvisibleAtLowerBorder+nTick];
+ }
+ }
+
+ //fill return value
+ rAllTickInfos.resize(aAllTicks.getLength());
+ for( nDepth=0 ;nDepth<aAllTicks.getLength(); nDepth++ )
+ {
+ sal_Int32 nCount = aAllTicks[nDepth].getLength();
+
+ TickInfoArrayType& rTickInfoVector = rAllTickInfos[nDepth];
+ rTickInfoVector.clear();
+ rTickInfoVector.reserve( nCount );
+ for(sal_Int32 nN = 0; nN<nCount; nN++)
+ {
+ TickInfo aTickInfo(m_xInverseScaling);
+ aTickInfo.fScaledTickValue = aAllTicks[nDepth][nN];
+ rTickInfoVector.push_back(aTickInfo);
+ }
+ }
+}
+
+void EquidistantTickFactory::getAllTicksShifted( TickInfoArraysType& rAllTickInfos ) const
+{
+ ExplicitIncrementData aShiftedIncrement( m_rIncrement );
+ aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0;
+ EquidistantTickFactory( m_rScale, aShiftedIncrement ).getAllTicks(rAllTickInfos);
+}
+
+EquidistantTickIter::EquidistantTickIter( const uno::Sequence< uno::Sequence< double > >& rTicks
+ , const ExplicitIncrementData& rIncrement
+ , sal_Int32 nMaxDepth )
+ : m_pSimpleTicks(&rTicks)
+ , m_pInfoTicks(nullptr)
+ , m_rIncrement(rIncrement)
+ , m_nMaxDepth(0)
+ , m_nTickCount(0)
+ , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 )
+{
+ initIter( nMaxDepth );
+}
+
+EquidistantTickIter::EquidistantTickIter( TickInfoArraysType& rTicks
+ , const ExplicitIncrementData& rIncrement
+ , sal_Int32 nMaxDepth )
+ : m_pSimpleTicks(nullptr)
+ , m_pInfoTicks(&rTicks)
+ , m_rIncrement(rIncrement)
+ , m_nMaxDepth(0)
+ , m_nTickCount(0)
+ , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 )
+{
+ initIter( nMaxDepth );
+}
+
+void EquidistantTickIter::initIter( sal_Int32 nMaxDepth )
+{
+ m_nMaxDepth = nMaxDepth;
+ if(nMaxDepth<0 || m_nMaxDepth>getMaxDepth())
+ m_nMaxDepth=getMaxDepth();
+
+ sal_Int32 nDepth = 0;
+ for( nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ )
+ m_nTickCount += getTickCount(nDepth);
+
+ if(!m_nTickCount)
+ return;
+
+ m_pnPositions.reset( new sal_Int32[m_nMaxDepth+1] );
+
+ m_pnPreParentCount.reset( new sal_Int32[m_nMaxDepth+1] );
+ m_pbIntervalFinished.reset( new bool[m_nMaxDepth+1] );
+ m_pnPreParentCount[0] = 0;
+ m_pbIntervalFinished[0] = false;
+ double fParentValue = getTickValue(0,0);
+ for( nDepth = 1; nDepth<=m_nMaxDepth ;nDepth++ )
+ {
+ m_pbIntervalFinished[nDepth] = false;
+
+ sal_Int32 nPreParentCount = 0;
+ sal_Int32 nCount = getTickCount(nDepth);
+ for(sal_Int32 nN = 0; nN<nCount; nN++)
+ {
+ if(getTickValue(nDepth,nN) < fParentValue)
+ nPreParentCount++;
+ else
+ break;
+ }
+ m_pnPreParentCount[nDepth] = nPreParentCount;
+ if(nCount)
+ {
+ double fNextParentValue = getTickValue(nDepth,0);
+ if( fNextParentValue < fParentValue )
+ fParentValue = fNextParentValue;
+ }
+ }
+}
+
+EquidistantTickIter::~EquidistantTickIter()
+{
+}
+
+sal_Int32 EquidistantTickIter::getStartDepth() const
+{
+ //find the depth of the first visible tickmark:
+ //it is the depth of the smallest value
+ sal_Int32 nReturnDepth=0;
+ double fMinValue = DBL_MAX;
+ for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ )
+ {
+ sal_Int32 nCount = getTickCount(nDepth);
+ if( !nCount )
+ continue;
+ double fThisValue = getTickValue(nDepth,0);
+ if(fThisValue<fMinValue)
+ {
+ nReturnDepth = nDepth;
+ fMinValue = fThisValue;
+ }
+ }
+ return nReturnDepth;
+}
+
+double* EquidistantTickIter::firstValue()
+{
+ if( gotoFirst() )
+ {
+ m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]);
+ return &m_fCurrentValue;
+ }
+ return nullptr;
+}
+
+TickInfo* EquidistantTickIter::firstInfo()
+{
+ if( m_pInfoTicks && gotoFirst() )
+ return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]];
+ return nullptr;
+}
+
+sal_Int32 EquidistantTickIter::getIntervalCount( sal_Int32 nDepth )
+{
+ if(nDepth>static_cast<sal_Int32>(m_rIncrement.SubIncrements.size()) || nDepth<0)
+ return 0;
+
+ if(!nDepth)
+ return m_nTickCount;
+
+ return m_rIncrement.SubIncrements[nDepth-1].IntervalCount;
+}
+
+bool EquidistantTickIter::isAtLastPartTick()
+{
+ if(!m_nCurrentDepth)
+ return false;
+ sal_Int32 nIntervalCount = getIntervalCount( m_nCurrentDepth );
+ if(!nIntervalCount || nIntervalCount == 1)
+ return true;
+ if( m_pbIntervalFinished[m_nCurrentDepth] )
+ return false;
+ sal_Int32 nPos = m_pnPositions[m_nCurrentDepth]+1;
+ if(m_pnPreParentCount[m_nCurrentDepth])
+ nPos += nIntervalCount-1 - m_pnPreParentCount[m_nCurrentDepth];
+ bool bRet = nPos && nPos % (nIntervalCount-1) == 0;
+ if(!nPos && !m_pnPreParentCount[m_nCurrentDepth]
+ && m_pnPositions[m_nCurrentDepth-1]==-1 )
+ bRet = true;
+ return bRet;
+}
+
+bool EquidistantTickIter::gotoFirst()
+{
+ if( m_nMaxDepth<0 )
+ return false;
+ if( !m_nTickCount )
+ return false;
+
+ for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ )
+ m_pnPositions[nDepth] = -1;
+
+ m_nCurrentPos = 0;
+ m_nCurrentDepth = getStartDepth();
+ m_pnPositions[m_nCurrentDepth] = 0;
+ return true;
+}
+
+bool EquidistantTickIter::gotoNext()
+{
+ if( m_nCurrentPos < 0 )
+ return false;
+ m_nCurrentPos++;
+
+ if( m_nCurrentPos >= m_nTickCount )
+ return false;
+
+ if( m_nCurrentDepth==m_nMaxDepth && isAtLastPartTick() )
+ {
+ do
+ {
+ m_pbIntervalFinished[m_nCurrentDepth] = true;
+ m_nCurrentDepth--;
+ }
+ while( m_nCurrentDepth && isAtLastPartTick() );
+ }
+ else if( m_nCurrentDepth<m_nMaxDepth )
+ {
+ do
+ {
+ m_nCurrentDepth++;
+ }
+ while( m_nCurrentDepth<m_nMaxDepth );
+ }
+ m_pbIntervalFinished[m_nCurrentDepth] = false;
+ m_pnPositions[m_nCurrentDepth] = m_pnPositions[m_nCurrentDepth]+1;
+ return true;
+}
+
+double* EquidistantTickIter::nextValue()
+{
+ if( gotoNext() )
+ {
+ m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]);
+ return &m_fCurrentValue;
+ }
+ return nullptr;
+}
+
+TickInfo* EquidistantTickIter::nextInfo()
+{
+ if( m_pInfoTicks && gotoNext() &&
+ static_cast< sal_Int32 >(
+ (*m_pInfoTicks)[m_nCurrentDepth].size()) > m_pnPositions[m_nCurrentDepth] )
+ {
+ return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]];
+ }
+ return nullptr;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/Tickmarks_Equidistant.hxx b/chart2/source/view/axes/Tickmarks_Equidistant.hxx
new file mode 100644
index 0000000000..6068903cb6
--- /dev/null
+++ b/chart2/source/view/axes/Tickmarks_Equidistant.hxx
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "Tickmarks.hxx"
+#include <memory>
+
+#include <o3tl/safeint.hxx>
+
+namespace chart
+{
+
+class EquidistantTickIter : public TickIter
+{
+public:
+ EquidistantTickIter( const css::uno::Sequence< css::uno::Sequence< double > >& rTicks
+ , const ExplicitIncrementData& rIncrement
+ , sal_Int32 nMaxDepth );
+ EquidistantTickIter( TickInfoArraysType& rTickInfos
+ , const ExplicitIncrementData& rIncrement
+ , sal_Int32 nMaxDepth );
+ virtual ~EquidistantTickIter() override;
+
+ double* firstValue();
+ double* nextValue();
+
+ virtual TickInfo* firstInfo() override;
+ virtual TickInfo* nextInfo() override;
+
+private: //methods
+ sal_Int32 getIntervalCount( sal_Int32 nDepth );
+ bool isAtLastPartTick();
+
+ void initIter( sal_Int32 nMaxDepth );
+ sal_Int32 getStartDepth() const;
+
+ bool gotoFirst();
+ bool gotoNext();
+
+ double getTickValue(sal_Int32 nDepth, sal_Int32 nIndex) const
+ {
+ if(m_pSimpleTicks)
+ return (*m_pSimpleTicks)[nDepth][nIndex];
+ else
+ {
+ if ((*m_pInfoTicks)[nDepth].size() <= o3tl::make_unsigned(nIndex))
+ return std::numeric_limits<double>::max();
+ return (((*m_pInfoTicks)[nDepth])[nIndex]).fScaledTickValue;
+ }
+ }
+ sal_Int32 getTickCount( sal_Int32 nDepth ) const
+ {
+ if(m_pSimpleTicks)
+ return (*m_pSimpleTicks)[nDepth].getLength();
+ else
+ return (*m_pInfoTicks)[nDepth].size();
+ }
+ sal_Int32 getMaxDepth() const
+ {
+ if(m_pSimpleTicks)
+ return (*m_pSimpleTicks).getLength()-1;
+ else
+ return (*m_pInfoTicks).size()-1;
+ }
+
+private: //member
+ const css::uno::Sequence< css::uno::Sequence< double > >* m_pSimpleTicks;
+ TickInfoArraysType* m_pInfoTicks;
+ const ExplicitIncrementData& m_rIncrement;
+ sal_Int32 m_nMaxDepth;
+ sal_Int32 m_nTickCount;
+ std::unique_ptr<sal_Int32[]>
+ m_pnPositions; //current positions in the different sequences
+ std::unique_ptr<sal_Int32[]>
+ m_pnPreParentCount; //the tickmarks do not start with a major tick always,
+ //the PreParentCount states for each depth how many subtickmarks are available in front of the first parent tickmark
+ std::unique_ptr<bool[]>
+ m_pbIntervalFinished;
+ sal_Int32 m_nCurrentDepth;
+ sal_Int32 m_nCurrentPos;
+ double m_fCurrentValue;
+};
+
+class EquidistantTickFactory
+{
+public:
+ EquidistantTickFactory(
+ ExplicitScaleData aScale
+ , ExplicitIncrementData aIncrement );
+ ~EquidistantTickFactory();
+
+ void getAllTicks( TickInfoArraysType& rAllTickInfos ) const;
+ void getAllTicksShifted( TickInfoArraysType& rAllTickInfos ) const;
+
+ static double getMinimumAtIncrement( double fMin, const ExplicitIncrementData& rIncrement );
+ static double getMaximumAtIncrement( double fMax, const ExplicitIncrementData& rIncrement );
+
+private: //methods
+ void addSubTicks( sal_Int32 nDepth,
+ css::uno::Sequence< css::uno::Sequence< double > >& rParentTicks ) const;
+ double* getMajorTick( sal_Int32 nTick ) const;
+ double* getMinorTick( sal_Int32 nTick, sal_Int32 nDepth
+ , double fStartParentTick, double fNextParentTick ) const;
+ sal_Int32 getMaxTickCount( sal_Int32 nDepth ) const;
+ sal_Int32 getTickDepth() const;
+
+ bool isVisible( double fValue ) const;
+ bool isWithinOuterBorder( double fScaledValue ) const; //all within the outer major tick marks
+
+private: //member
+ ExplicitScaleData m_rScale;
+ ExplicitIncrementData m_rIncrement;
+ css::uno::Reference< css::chart2::XScaling > m_xInverseScaling;
+
+ //minimum and maximum of the visible range after scaling
+ double m_fScaledVisibleMin;
+ double m_fScaledVisibleMax;
+
+ std::unique_ptr<double[]>
+ m_pfCurrentValues;
+ //major-tick positions that may lay outside the visible range but complete partly visible intervals at the borders
+ double m_fOuterMajorTickBorderMin;
+ double m_fOuterMajorTickBorderMax;
+ double m_fOuterMajorTickBorderMin_Scaled;
+ double m_fOuterMajorTickBorderMax_Scaled;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VAxisBase.cxx b/chart2/source/view/axes/VAxisBase.cxx
new file mode 100644
index 0000000000..30aead187d
--- /dev/null
+++ b/chart2/source/view/axes/VAxisBase.cxx
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VAxisBase.hxx"
+#include <ShapeFactory.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include "Tickmarks.hxx"
+#include <Axis.hxx>
+#include <VSeriesPlotter.hxx>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+
+#include <osl/diagnose.h>
+
+#include <memory>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+VAxisBase::VAxisBase( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , const AxisProperties& rAxisProperties
+ , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+ : VAxisOrGridBase( nDimensionIndex, nDimensionCount )
+ , m_xNumberFormatsSupplier( xNumberFormatsSupplier )
+ , m_aAxisProperties( rAxisProperties )
+ , m_bUseTextLabels( false )
+ , m_bReCreateAllTickInfos( true )
+ , m_bRecordMaximumTextSize(false)
+ , m_nMaximumTextWidthSoFar(0)
+ , m_nMaximumTextHeightSoFar(0)
+{
+}
+
+VAxisBase::~VAxisBase()
+{
+}
+
+void VAxisBase::initAxisLabelProperties( const css::awt::Size& rFontReferenceSize
+ , const css::awt::Rectangle& rMaximumSpaceForLabels )
+{
+ m_aAxisLabelProperties.m_aFontReferenceSize = rFontReferenceSize;
+ m_aAxisLabelProperties.m_aMaximumSpaceForLabels = rMaximumSpaceForLabels;
+
+ if( !m_aAxisProperties.m_bDisplayLabels )
+ return;
+
+ if( m_aAxisProperties.m_nAxisType==AxisType::SERIES )
+ {
+ if( m_aAxisProperties.m_xAxisTextProvider.is() )
+ m_aTextLabels = m_aAxisProperties.m_xAxisTextProvider->getTextualData();
+
+ m_bUseTextLabels = true;
+ if( m_aTextLabels.getLength() == 1 )
+ {
+ //don't show a single series name
+ m_aAxisProperties.m_bDisplayLabels = false;
+ return;
+ }
+ }
+ else if( m_aAxisProperties.m_nAxisType==AxisType::CATEGORY )
+ {
+ if( m_aAxisProperties.m_pExplicitCategoriesProvider )
+ m_aTextLabels = m_aAxisProperties.m_pExplicitCategoriesProvider->getSimpleCategories();
+
+ m_bUseTextLabels = true;
+ }
+
+ m_aAxisLabelProperties.m_nNumberFormatKey = m_aAxisProperties.m_nNumberFormatKey;
+ m_aAxisLabelProperties.init(m_aAxisProperties.m_xAxisModel);
+ if( m_aAxisProperties.m_bComplexCategories && m_aAxisProperties.m_nAxisType == AxisType::CATEGORY )
+ m_aAxisLabelProperties.m_eStaggering = AxisLabelStaggering::SideBySide;
+}
+
+bool VAxisBase::isDateAxis() const
+{
+ return m_aScale.AxisType == AxisType::DATE;
+}
+bool VAxisBase::isComplexCategoryAxis() const
+{
+ return m_aAxisProperties.m_bComplexCategories && m_bUseTextLabels;
+}
+
+void VAxisBase::recordMaximumTextSize( SvxShape& xShape, double fRotationAngleDegree )
+{
+ if( m_bRecordMaximumTextSize )
+ {
+ awt::Size aSize( ShapeFactory::getSizeAfterRotation(
+ xShape, fRotationAngleDegree ) );
+
+ m_nMaximumTextWidthSoFar = std::max( m_nMaximumTextWidthSoFar, aSize.Width );
+ m_nMaximumTextHeightSoFar = std::max( m_nMaximumTextHeightSoFar, aSize.Height );
+ }
+}
+
+sal_Int32 VAxisBase::estimateMaximumAutoMainIncrementCount()
+{
+ return 10;
+}
+
+void VAxisBase::setExtraLinePositionAtOtherAxis( double fCrossingAt )
+{
+ m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis = fCrossingAt;
+}
+
+sal_Int32 VAxisBase::getDimensionCount() const
+{
+ return m_nDimension;
+}
+
+bool VAxisBase::isAnythingToDraw()
+{
+ if( !m_aAxisProperties.m_xAxisModel.is() )
+ return false;
+
+ OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"Axis is not proper initialized");
+ if(!(m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return false;
+
+ if( m_aAxisProperties.m_xAxisModel.is() )
+ {
+ bool bShow = false;
+ m_aAxisProperties.m_xAxisModel->getPropertyValue( "Show" ) >>= bShow;
+ if( !bShow )
+ return false;
+ }
+ return true;
+}
+
+void VAxisBase::setExplicitScaleAndIncrement(
+ const ExplicitScaleData& rScale
+ , const ExplicitIncrementData& rIncrement )
+{
+ m_bReCreateAllTickInfos = true;
+ m_aScale = rScale;
+ m_aIncrement = rIncrement;
+}
+
+void VAxisBase::createAllTickInfos( TickInfoArraysType& rAllTickInfos )
+{
+ std::unique_ptr< TickFactory > apTickFactory( createTickFactory() );
+ if( m_aScale.m_bShiftedCategoryPosition )
+ apTickFactory->getAllTicksShifted( rAllTickInfos );
+ else
+ apTickFactory->getAllTicks( rAllTickInfos );
+}
+
+bool VAxisBase::prepareShapeCreation()
+{
+ //returns true if all is ready for further shape creation and any shapes need to be created
+ if( !isAnythingToDraw() )
+ return false;
+
+ if( m_bReCreateAllTickInfos )
+ {
+ //create all scaled tickmark values
+ removeTextShapesFromTicks();
+
+ createAllTickInfos(m_aAllTickInfos);
+ m_bReCreateAllTickInfos = false;
+ }
+
+ if( m_xGroupShape_Shapes.is() )
+ return true;
+
+ //create named group shape
+ m_xGroupShape_Shapes = createGroupShape( m_xLogicTarget, m_nDimension==2 ? m_aCID : "");
+
+ if (m_aAxisProperties.m_bDisplayLabels)
+ m_xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget, m_aCID );
+ if (m_aAxisProperties.m_bDisplayDataTable)
+ m_xDataTableTarget = ShapeFactory::createGroup2D(m_xFinalTarget);
+
+ return true;
+}
+
+size_t VAxisBase::getIndexOfLongestLabel( const uno::Sequence<OUString>& rLabels )
+{
+ sal_Int32 nRet = 0;
+ sal_Int32 nLength = 0;
+ sal_Int32 nN = 0;
+ for( nN=0; nN<rLabels.getLength(); nN++ )
+ {
+ //todo: get real text width (without creating shape) instead of character count
+ if( rLabels[nN].getLength() > nLength )
+ {
+ nLength = rLabels[nN].getLength();
+ nRet = nN;
+ }
+ }
+
+ assert(nRet >= 0);
+ return nRet;
+}
+
+void VAxisBase::removeTextShapesFromTicks()
+{
+ if( !m_xTextTarget.is() )
+ return;
+
+ for (auto & tickInfos : m_aAllTickInfos)
+ {
+ for (auto & tickInfo : tickInfos)
+ {
+ if(tickInfo.xTextShape.is())
+ {
+ m_xTextTarget->remove(tickInfo.xTextShape);
+ tickInfo.xTextShape = nullptr;
+ }
+ }
+ }
+}
+
+void VAxisBase::updateUnscaledValuesAtTicks( TickIter& rIter )
+{
+ Reference< XScaling > xInverseScaling;
+ if( m_aScale.Scaling.is() )
+ xInverseScaling = m_aScale.Scaling->getInverseScaling();
+
+ for( TickInfo* pTickInfo = rIter.firstInfo()
+ ; pTickInfo; pTickInfo = rIter.nextInfo() )
+ {
+ //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling );
+ }
+}
+
+void VAxisBase::createDataTableView(std::vector<std::unique_ptr<VSeriesPlotter>>& /*rSeriesPlotterList*/,
+ uno::Reference<util::XNumberFormatsSupplier> const& /*xNumberFormatsSupplier*/,
+ rtl::Reference<::chart::ChartModel> const& /*xChartDoc*/,
+ css::uno::Reference<css::uno::XComponentContext> const& /*rComponentContext*/)
+{
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VAxisBase.hxx b/chart2/source/view/axes/VAxisBase.hxx
new file mode 100644
index 0000000000..4ee4f5e288
--- /dev/null
+++ b/chart2/source/view/axes/VAxisBase.hxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "VAxisOrGridBase.hxx"
+#include "VAxisProperties.hxx"
+#include "Tickmarks.hxx"
+
+namespace com::sun::star::util { class XNumberFormatsSupplier; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+
+class VSeriesPlotter;
+class DataTableView;
+class ChartModel;
+class LegendEntryProvider;
+
+class VAxisBase : public VAxisOrGridBase
+{
+public:
+ VAxisBase( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , const AxisProperties& rAxisProperties
+ , const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier );
+ virtual ~VAxisBase() override;
+
+ /**
+ * Return the number of dimensions the diagram has. 2 for x and y, and 3
+ * for x, y, and z.
+ */
+ sal_Int32 getDimensionCount() const;
+
+ virtual void createMaximumLabels()=0;
+ virtual void createLabels()=0;
+ virtual void updatePositions()=0;
+
+ virtual bool isAnythingToDraw();
+ virtual void initAxisLabelProperties(
+ const css::awt::Size& rFontReferenceSize
+ , const css::awt::Rectangle& rMaximumSpaceForLabels );
+
+ virtual void setExplicitScaleAndIncrement(
+ const ExplicitScaleData& rScale
+ , const ExplicitIncrementData& rIncrement ) override;
+
+ virtual sal_Int32 estimateMaximumAutoMainIncrementCount();
+ virtual void createAllTickInfos( TickInfoArraysType& rAllTickInfos );
+
+ void setExtraLinePositionAtOtherAxis( double fCrossingAt );
+
+ virtual void createDataTableView(std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList,
+ css::uno::Reference<css::util::XNumberFormatsSupplier> const& xNumberFormatsSupplier,
+ rtl::Reference<::chart::ChartModel> const& xChartDoc,
+ css::uno::Reference<css::uno::XComponentContext> const& rComponentContext);
+
+ std::shared_ptr<DataTableView> getDataTableView() { return m_pDataTableView; }
+
+protected: //methods
+ static size_t getIndexOfLongestLabel( const css::uno::Sequence<OUString>& rLabels );
+ void removeTextShapesFromTicks();
+ void updateUnscaledValuesAtTicks( TickIter& rIter );
+
+ virtual bool prepareShapeCreation();
+ void recordMaximumTextSize( SvxShape& xShape, double fRotationAngleDegree );
+
+ bool isDateAxis() const;
+ bool isComplexCategoryAxis() const;
+
+protected: //member
+ css::uno::Reference< css::util::XNumberFormatsSupplier > m_xNumberFormatsSupplier;
+ AxisProperties m_aAxisProperties;
+ AxisLabelProperties m_aAxisLabelProperties;
+ css::uno::Sequence< OUString > m_aTextLabels;
+ bool m_bUseTextLabels;
+
+ rtl::Reference< SvxShapeGroupAnyD > m_xGroupShape_Shapes;
+ rtl::Reference< SvxShapeGroupAnyD > m_xTextTarget;
+ rtl::Reference< SvxShapeGroupAnyD > m_xDataTableTarget;
+
+ std::shared_ptr<DataTableView> m_pDataTableView;
+
+ /**
+ * This typically consists of 2 TickInfo vectors (i.e. the outer vector
+ * has 2 child vector elements) for normal axis. The first vector
+ * corresponds with the major ticks while the second corresponds with the
+ * minor ticks.
+ *
+ * It may have more than 2 TickInfo vectors for complex category axis
+ * which has multi-level axis labels.
+ */
+ TickInfoArraysType m_aAllTickInfos;
+ bool m_bReCreateAllTickInfos;
+
+ bool m_bRecordMaximumTextSize;
+ sal_Int32 m_nMaximumTextWidthSoFar;
+ sal_Int32 m_nMaximumTextHeightSoFar;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VAxisOrGridBase.cxx b/chart2/source/view/axes/VAxisOrGridBase.cxx
new file mode 100644
index 0000000000..290f3a3688
--- /dev/null
+++ b/chart2/source/view/axes/VAxisOrGridBase.cxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VAxisOrGridBase.hxx"
+#include <CommonConverters.hxx>
+#include "Tickmarks.hxx"
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+VAxisOrGridBase::VAxisOrGridBase( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount )
+ : PlotterBase( nDimensionCount )
+ , m_nDimensionIndex( nDimensionIndex )
+ , m_eLeftWallPos(CuboidPlanePosition_Left)
+ , m_eBackWallPos(CuboidPlanePosition_Back)
+ , m_eBottomPos(CuboidPlanePosition_Bottom)
+{
+}
+
+VAxisOrGridBase::~VAxisOrGridBase()
+{
+}
+
+void VAxisOrGridBase::setExplicitScaleAndIncrement(
+ const ExplicitScaleData& rScale
+ , const ExplicitIncrementData& rIncrement )
+{
+ m_aScale = rScale;
+ m_aIncrement = rIncrement;
+}
+
+void VAxisOrGridBase::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix )
+{
+ m_aMatrixScreenToScene = HomogenMatrixToB3DHomMatrix(rMatrix);
+ PlotterBase::setTransformationSceneToScreen( rMatrix);
+}
+
+void VAxisOrGridBase::set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos )
+{
+ m_eLeftWallPos = eLeftWallPos;
+ m_eBackWallPos = eBackWallPos;
+ m_eBottomPos = eBottomPos;
+}
+
+TickFactory* VAxisOrGridBase::createTickFactory()
+{
+ return new TickFactory( m_aScale, m_aIncrement );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VAxisOrGridBase.hxx b/chart2/source/view/axes/VAxisOrGridBase.hxx
new file mode 100644
index 0000000000..1defc154a8
--- /dev/null
+++ b/chart2/source/view/axes/VAxisOrGridBase.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <PlotterBase.hxx>
+#include <ThreeDHelper.hxx>
+#include <chartview/ExplicitScaleValues.hxx>
+
+#include <basegfx/matrix/b3dhommatrix.hxx>
+
+namespace com::sun::star::drawing { struct HomogenMatrix; }
+
+namespace chart
+{
+
+class TickFactory;
+
+class VAxisOrGridBase : public PlotterBase
+{
+public:
+ VAxisOrGridBase( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount );
+ virtual ~VAxisOrGridBase() override;
+
+ virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix ) override;
+ /// @throws css::uno::RuntimeException
+ virtual void setExplicitScaleAndIncrement(
+ const ExplicitScaleData& rScale
+ , const ExplicitIncrementData& rIncrement );
+ void set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos );
+
+ virtual TickFactory* createTickFactory();
+
+protected: //member
+ ExplicitScaleData m_aScale;
+ ExplicitIncrementData m_aIncrement;
+ sal_Int32 m_nDimensionIndex;
+
+ ::basegfx::B3DHomMatrix m_aMatrixScreenToScene;
+
+ CuboidPlanePosition m_eLeftWallPos;
+ CuboidPlanePosition m_eBackWallPos;
+ CuboidPlanePosition m_eBottomPos;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VAxisProperties.cxx b/chart2/source/view/axes/VAxisProperties.cxx
new file mode 100644
index 0000000000..c521489b62
--- /dev/null
+++ b/chart2/source/view/axes/VAxisProperties.cxx
@@ -0,0 +1,413 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VAxisProperties.hxx"
+#include <ViewDefines.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <ChartModelHelper.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+
+#include <comphelper/diagnose_ex.hxx>
+#include <rtl/math.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+namespace chart {
+
+AxisLabelAlignment::AxisLabelAlignment() :
+ mfLabelDirection(1.0),
+ mfInnerTickDirection(1.0),
+ meAlignment(LABEL_ALIGN_RIGHT_TOP) {}
+
+static sal_Int32 lcl_calcTickLengthForDepth(sal_Int32 nDepth,sal_Int32 nTickmarkStyle)
+{
+ sal_Int32 const nWidth = AXIS2D_TICKLENGTH; //@maybefuturetodo this length could be offered by the model
+ double fPercent = 1.0;
+ switch(nDepth)
+ {
+ case 0:
+ fPercent = 1.0;
+ break;
+ case 1:
+ fPercent = 0.75;//percentage like in the old chart
+ break;
+ case 2:
+ fPercent = 0.5;
+ break;
+ default:
+ fPercent = 0.3;
+ break;
+ }
+ if(nTickmarkStyle==3)//inner and outer tickmarks
+ fPercent*=2.0;
+ return static_cast<sal_Int32>(nWidth*fPercent);
+}
+
+static double lcl_getTickOffset(sal_Int32 nLength,sal_Int32 nTickmarkStyle)
+{
+ double fPercent = 0.0; //0<=fPercent<=1
+ //0.0: completely inner
+ //1.0: completely outer
+ //0.5: half and half
+
+ /*
+ nTickmarkStyle:
+ 1: inner tickmarks
+ 2: outer tickmarks
+ 3: inner and outer tickmarks
+ */
+ switch(nTickmarkStyle)
+ {
+ case 1:
+ fPercent = 0.0;
+ break;
+ case 2:
+ fPercent = 1.0;
+ break;
+ default:
+ fPercent = 0.5;
+ break;
+ }
+ return fPercent*nLength;
+}
+
+TickmarkProperties AxisProperties::makeTickmarkProperties(
+ sal_Int32 nDepth ) const
+{
+ /*
+ nTickmarkStyle:
+ 1: inner tickmarks
+ 2: outer tickmarks
+ 3: inner and outer tickmarks
+ */
+ sal_Int32 nTickmarkStyle = 1;
+ if(nDepth==0)
+ {
+ nTickmarkStyle = m_nMajorTickmarks;
+ if(!nTickmarkStyle)
+ {
+ //create major tickmarks as if they were minor tickmarks
+ nDepth = 1;
+ nTickmarkStyle = m_nMinorTickmarks;
+ }
+ }
+ else if( nDepth==1)
+ {
+ nTickmarkStyle = m_nMinorTickmarks;
+ }
+
+ if (maLabelAlignment.mfInnerTickDirection == 0.0)
+ {
+ if( nTickmarkStyle != 0 )
+ nTickmarkStyle = 3; //inner and outer tickmarks
+ }
+
+ TickmarkProperties aTickmarkProperties;
+ aTickmarkProperties.Length = lcl_calcTickLengthForDepth(nDepth,nTickmarkStyle);
+ aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length,nTickmarkStyle));
+ aTickmarkProperties.aLineProperties = makeLinePropertiesForDepth();
+ return aTickmarkProperties;
+}
+
+TickmarkProperties AxisProperties::makeTickmarkPropertiesForComplexCategories(
+ sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis ) const
+{
+ sal_Int32 nTickmarkStyle = (maLabelAlignment.mfLabelDirection == maLabelAlignment.mfInnerTickDirection) ? 2/*outside*/ : 1/*inside*/;
+
+ TickmarkProperties aTickmarkProperties;
+ aTickmarkProperties.Length = nTickLength;// + nTextLevel*( lcl_calcTickLengthForDepth(0,nTickmarkStyle) );
+ aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length+nTickStartDistanceToAxis,nTickmarkStyle));
+ aTickmarkProperties.aLineProperties = makeLinePropertiesForDepth();
+ return aTickmarkProperties;
+}
+
+TickmarkProperties AxisProperties::getBiggestTickmarkProperties()
+{
+ TickmarkProperties aTickmarkProperties;
+ sal_Int32 nTickmarkStyle = 3;//inner and outer tickmarks
+ aTickmarkProperties.Length = lcl_calcTickLengthForDepth( 0/*nDepth*/,nTickmarkStyle );
+ aTickmarkProperties.RelativePos = static_cast<sal_Int32>( lcl_getTickOffset( aTickmarkProperties.Length, nTickmarkStyle ) );
+ return aTickmarkProperties;
+}
+
+AxisProperties::AxisProperties(rtl::Reference<::chart::Axis> xAxisModel,
+ ExplicitCategoriesProvider* pExplicitCategoriesProvider,
+ rtl::Reference<::chart::DataTable> const& xDataTableModel)
+ : m_xAxisModel(std::move(xAxisModel))
+ , m_nDimensionIndex(0)
+ , m_bIsMainAxis(true)
+ , m_bSwapXAndY(false)
+ , m_eCrossoverType( css::chart::ChartAxisPosition_ZERO )
+ , m_eLabelPos( css::chart::ChartAxisLabelPosition_NEAR_AXIS )
+ , m_eTickmarkPos( css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS )
+ , m_bCrossingAxisHasReverseDirection(false)
+ , m_bCrossingAxisIsCategoryAxes(false)
+ , m_bDisplayDataTable(false)
+ , m_bDataTableAlignAxisValuesWithColumns(false)
+ , m_bDisplayLabels( true )
+ , m_bTryStaggeringFirst( false )
+ , m_nNumberFormatKey(0)
+ , m_nMajorTickmarks(1)
+ , m_nMinorTickmarks(1)
+ , m_nAxisType(AxisType::REALNUMBER)
+ , m_bComplexCategories(false)
+ , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider)
+ , m_bLimitSpaceForLabels(false)
+ , m_xDataTableModel(xDataTableModel)
+{
+}
+
+static LabelAlignment lcl_getLabelAlignmentForZAxis( const AxisProperties& rAxisProperties )
+{
+ LabelAlignment aRet( LABEL_ALIGN_RIGHT );
+ if (rAxisProperties.maLabelAlignment.mfLabelDirection < 0)
+ aRet = LABEL_ALIGN_LEFT;
+ return aRet;
+}
+
+static LabelAlignment lcl_getLabelAlignmentForYAxis( const AxisProperties& rAxisProperties )
+{
+ LabelAlignment aRet( LABEL_ALIGN_RIGHT );
+ if (rAxisProperties.maLabelAlignment.mfLabelDirection < 0)
+ aRet = LABEL_ALIGN_LEFT;
+ return aRet;
+}
+
+static LabelAlignment lcl_getLabelAlignmentForXAxis( const AxisProperties& rAxisProperties )
+{
+ LabelAlignment aRet( LABEL_ALIGN_BOTTOM );
+ if (rAxisProperties.maLabelAlignment.mfLabelDirection < 0)
+ aRet = LABEL_ALIGN_TOP;
+ return aRet;
+}
+
+void AxisProperties::initAxisPositioning( const uno::Reference< beans::XPropertySet >& xAxisProp )
+{
+ if( !xAxisProp.is() )
+ return;
+ try
+ {
+ if( AxisHelper::isAxisPositioningEnabled() )
+ {
+ xAxisProp->getPropertyValue("CrossoverPosition") >>= m_eCrossoverType;
+ if( m_eCrossoverType == css::chart::ChartAxisPosition_VALUE )
+ {
+ double fValue = 0.0;
+ xAxisProp->getPropertyValue("CrossoverValue") >>= fValue;
+
+ if( m_bCrossingAxisIsCategoryAxes )
+ fValue = ::rtl::math::round(fValue);
+ m_pfMainLinePositionAtOtherAxis = fValue;
+ }
+ else if( m_eCrossoverType == css::chart::ChartAxisPosition_ZERO )
+ m_pfMainLinePositionAtOtherAxis = 0.0;
+
+ xAxisProp->getPropertyValue("LabelPosition") >>= m_eLabelPos;
+ xAxisProp->getPropertyValue("MarkPosition") >>= m_eTickmarkPos;
+ }
+ else
+ {
+ m_eCrossoverType = css::chart::ChartAxisPosition_START;
+ if( m_bIsMainAxis == m_bCrossingAxisHasReverseDirection )
+ m_eCrossoverType = css::chart::ChartAxisPosition_END;
+ m_eLabelPos = css::chart::ChartAxisLabelPosition_NEAR_AXIS;
+ m_eTickmarkPos = css::chart::ChartAxisMarkPosition_AT_LABELS;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void AxisProperties::init( bool bCartesian )
+{
+ if( !m_xAxisModel.is() )
+ return;
+
+ if( m_nDimensionIndex<2 )
+ initAxisPositioning( m_xAxisModel );
+
+ ScaleData aScaleData = m_xAxisModel->getScaleData();
+ if( m_nDimensionIndex==0 )
+ AxisHelper::checkDateAxis( aScaleData, m_pExplicitCategoriesProvider, bCartesian );
+ m_nAxisType = aScaleData.AxisType;
+
+ if( bCartesian )
+ {
+ if ((!m_bSwapXAndY && m_nDimensionIndex == 0) || (m_bSwapXAndY && m_nDimensionIndex == 1))
+ {
+ m_bDisplayDataTable = m_xDataTableModel.is();
+ }
+
+ if( m_nDimensionIndex == 0 && m_nAxisType == AxisType::CATEGORY
+ && m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() )
+ m_bComplexCategories = true;
+
+ if( m_eCrossoverType == css::chart::ChartAxisPosition_END )
+ maLabelAlignment.mfInnerTickDirection = m_bCrossingAxisHasReverseDirection ? 1.0 : -1.0;
+ else
+ maLabelAlignment.mfInnerTickDirection = m_bCrossingAxisHasReverseDirection ? -1.0 : 1.0;
+
+ if( m_eLabelPos == css::chart::ChartAxisLabelPosition_NEAR_AXIS )
+ maLabelAlignment.mfLabelDirection = maLabelAlignment.mfInnerTickDirection;
+ else if( m_eLabelPos == css::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE )
+ maLabelAlignment.mfLabelDirection = -maLabelAlignment.mfInnerTickDirection;
+ else if( m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_START )
+ maLabelAlignment.mfLabelDirection = m_bCrossingAxisHasReverseDirection ? -1 : 1;
+ else if( m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_END )
+ maLabelAlignment.mfLabelDirection = m_bCrossingAxisHasReverseDirection ? 1 : -1;
+
+ if( m_nDimensionIndex==2 )
+ maLabelAlignment.meAlignment = lcl_getLabelAlignmentForZAxis(*this);
+ else
+ {
+ bool bIsYAxisPosition = (m_nDimensionIndex==1 && !m_bSwapXAndY)
+ || (m_nDimensionIndex==0 && m_bSwapXAndY);
+ if( bIsYAxisPosition )
+ {
+ maLabelAlignment.mfLabelDirection *= -1.0;
+ maLabelAlignment.mfInnerTickDirection *= -1.0;
+
+ maLabelAlignment.meAlignment = lcl_getLabelAlignmentForYAxis(*this);
+ }
+ else
+ maLabelAlignment.meAlignment = lcl_getLabelAlignmentForXAxis(*this);
+ }
+ }
+
+ try
+ {
+ //init LineProperties
+ m_aLineProperties.initFromPropertySet( m_xAxisModel );
+
+ //init display labels
+ m_xAxisModel->getPropertyValue( "DisplayLabels" ) >>= m_bDisplayLabels;
+
+ // Init layout strategy hint for axis labels.
+ // Compatibility option: starting from LibreOffice 5.1 the rotated
+ // layout is preferred to staggering for axis labels.
+ m_xAxisModel->getPropertyValue( "TryStaggeringFirst" ) >>= m_bTryStaggeringFirst;
+
+ //init TickmarkProperties
+ m_xAxisModel->getPropertyValue( "MajorTickmarks" ) >>= m_nMajorTickmarks;
+ m_xAxisModel->getPropertyValue( "MinorTickmarks" ) >>= m_nMinorTickmarks;
+
+ sal_Int32 nMaxDepth = 0;
+ if(m_nMinorTickmarks!=0)
+ nMaxDepth=2;
+ else if(m_nMajorTickmarks!=0)
+ nMaxDepth=1;
+
+ m_aTickmarkPropertiesList.clear();
+ for( sal_Int32 nDepth=0; nDepth<nMaxDepth; nDepth++ )
+ {
+ TickmarkProperties aTickmarkProperties = makeTickmarkProperties( nDepth );
+ m_aTickmarkPropertiesList.push_back( aTickmarkProperties );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ if (m_bDisplayDataTable)
+ {
+ m_bDataTableAlignAxisValuesWithColumns = (m_nDimensionIndex == 0);
+
+ if (m_nDimensionIndex == 0)
+ {
+ m_bDisplayLabels = false;
+ }
+
+ }
+}
+
+AxisLabelProperties::AxisLabelProperties()
+ : m_aFontReferenceSize( ChartModelHelper::getDefaultPageSize() )
+ , m_aMaximumSpaceForLabels( 0 , 0, m_aFontReferenceSize.Width, m_aFontReferenceSize.Height )
+ , m_nNumberFormatKey(0)
+ , m_eStaggering( AxisLabelStaggering::SideBySide )
+ , m_bLineBreakAllowed( false )
+ , m_bOverlapAllowed( false )
+ , m_bStackCharacters( false )
+ , m_fRotationAngleDegree( 0.0 )
+ , m_nRhythm( 1 )
+{
+
+}
+
+void AxisLabelProperties::init( const rtl::Reference< Axis >& xAxisModel )
+{
+ if(!xAxisModel.is())
+ return;
+
+ try
+ {
+ xAxisModel->getPropertyValue( "TextBreak" ) >>= m_bLineBreakAllowed;
+ xAxisModel->getPropertyValue( "TextOverlap" ) >>= m_bOverlapAllowed;
+ xAxisModel->getPropertyValue( "StackCharacters" ) >>= m_bStackCharacters;
+ xAxisModel->getPropertyValue( "TextRotation" ) >>= m_fRotationAngleDegree;
+
+ css::chart::ChartAxisArrangeOrderType eArrangeOrder;
+ xAxisModel->getPropertyValue( "ArrangeOrder" ) >>= eArrangeOrder;
+ switch(eArrangeOrder)
+ {
+ case css::chart::ChartAxisArrangeOrderType_SIDE_BY_SIDE:
+ m_eStaggering = AxisLabelStaggering::SideBySide;
+ break;
+ case css::chart::ChartAxisArrangeOrderType_STAGGER_EVEN:
+ m_eStaggering = AxisLabelStaggering::StaggerEven;
+ break;
+ case css::chart::ChartAxisArrangeOrderType_STAGGER_ODD:
+ m_eStaggering = AxisLabelStaggering::StaggerOdd;
+ break;
+ default:
+ m_eStaggering = AxisLabelStaggering::StaggerAuto;
+ break;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+bool AxisLabelProperties::isStaggered() const
+{
+ return ( m_eStaggering == AxisLabelStaggering::StaggerOdd || m_eStaggering == AxisLabelStaggering::StaggerEven );
+}
+
+void AxisLabelProperties::autoRotate45()
+{
+ m_fRotationAngleDegree = 45;
+ m_bLineBreakAllowed = false;
+ m_eStaggering = AxisLabelStaggering::SideBySide;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VAxisProperties.hxx b/chart2/source/view/axes/VAxisProperties.hxx
new file mode 100644
index 0000000000..0cc23602b5
--- /dev/null
+++ b/chart2/source/view/axes/VAxisProperties.hxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "TickmarkProperties.hxx"
+#include <Axis.hxx>
+#include <LabelAlignment.hxx>
+#include <DataTable.hxx>
+
+#include <com/sun/star/chart/ChartAxisLabelPosition.hpp>
+#include <com/sun/star/chart/ChartAxisMarkPosition.hpp>
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <rtl/ref.hxx>
+
+#include <vector>
+#include <optional>
+
+namespace chart { class ExplicitCategoriesProvider; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XAxis; }
+namespace com::sun::star::chart2::data { class XTextualDataSequence; }
+
+namespace chart
+{
+
+//These properties describe how a couple of labels are arranged one to another.
+//The couple can contain all labels for all tickmark depth or just the labels for one single depth or
+//the labels from a coherent range of tick depths (e.g. the major and first minor tickmarks should be handled together).
+//... only allow side by side for different tick depth
+enum class AxisLabelStaggering
+{
+ SideBySide
+ , StaggerEven
+ , StaggerOdd
+ , StaggerAuto
+};
+
+struct AxisLabelProperties final
+{
+ AxisLabelProperties();
+
+ css::awt::Size m_aFontReferenceSize;//reference size to calculate the font height
+ css::awt::Rectangle m_aMaximumSpaceForLabels;//Labels need to be clipped in order to fit into this rectangle
+
+ sal_Int32 m_nNumberFormatKey;
+
+ AxisLabelStaggering m_eStaggering;
+
+ bool m_bLineBreakAllowed;
+ bool m_bOverlapAllowed;
+
+ bool m_bStackCharacters;
+ double m_fRotationAngleDegree;
+
+ sal_Int32 m_nRhythm; //show only each nth label with n==nRhythm
+
+ //methods:
+ void init( const rtl::Reference< ::chart::Axis >& xAxisModel );
+
+ bool isStaggered() const;
+
+ void autoRotate45();
+};
+
+struct AxisLabelAlignment
+{
+ double mfLabelDirection; /// which direction the labels are to be drawn.
+ double mfInnerTickDirection; /// which direction the inner tickmarks are to be drawn.
+
+ LabelAlignment meAlignment;
+
+ AxisLabelAlignment();
+};
+
+struct AxisProperties final
+{
+ rtl::Reference<::chart::Axis> m_xAxisModel;
+
+ sal_Int32 m_nDimensionIndex;
+ bool m_bIsMainAxis;//not secondary axis
+ bool m_bSwapXAndY;
+
+ css::chart::ChartAxisPosition m_eCrossoverType;
+ css::chart::ChartAxisLabelPosition m_eLabelPos;
+ css::chart::ChartAxisMarkPosition m_eTickmarkPos;
+
+ std::optional<double> m_pfMainLinePositionAtOtherAxis;
+ std::optional<double> m_pfExrtaLinePositionAtOtherAxis;
+
+ bool m_bCrossingAxisHasReverseDirection;
+ bool m_bCrossingAxisIsCategoryAxes;
+
+ AxisLabelAlignment maLabelAlignment;
+
+ // Data table
+ bool m_bDisplayDataTable;
+ bool m_bDataTableAlignAxisValuesWithColumns;
+
+ bool m_bDisplayLabels;
+
+ // Compatibility option: starting from LibreOffice 5.1 the rotated
+ // layout is preferred to staggering for axis labels.
+ // So the default value of this flag for new documents is `false`.
+ bool m_bTryStaggeringFirst;
+
+ sal_Int32 m_nNumberFormatKey;
+
+ /*
+ 0: no tickmarks 1: inner tickmarks
+ 2: outer tickmarks 3: inner and outer tickmarks
+ */
+ sal_Int32 m_nMajorTickmarks;
+ sal_Int32 m_nMinorTickmarks;
+ std::vector<TickmarkProperties> m_aTickmarkPropertiesList;
+
+ VLineProperties m_aLineProperties;
+
+ //for category axes ->
+ sal_Int32 m_nAxisType;//REALNUMBER, CATEGORY etc. type css::chart2::AxisType
+ bool m_bComplexCategories;
+ ExplicitCategoriesProvider* m_pExplicitCategoriesProvider;/*no ownership here*/
+ css::uno::Reference<css::chart2::data::XTextualDataSequence> m_xAxisTextProvider; //for categories or series names
+ //<- category axes
+
+ bool m_bLimitSpaceForLabels;
+
+ rtl::Reference<::chart::DataTable> m_xDataTableModel;
+
+ //methods:
+
+ AxisProperties(rtl::Reference<::chart::Axis> xAxisModel,
+ ExplicitCategoriesProvider* pExplicitCategoriesProvider,
+ rtl::Reference<::chart::DataTable> const& xDataTableModel);
+
+ void init(bool bCartesian=false);//init from model data (m_xAxisModel)
+
+ void initAxisPositioning( const css::uno::Reference< css::beans::XPropertySet >& xAxisProp );
+
+ static TickmarkProperties getBiggestTickmarkProperties();
+ TickmarkProperties makeTickmarkPropertiesForComplexCategories( sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis ) const;
+
+private:
+ AxisProperties() = delete;
+
+ TickmarkProperties makeTickmarkProperties( sal_Int32 nDepth ) const;
+ //@todo get this from somewhere; maybe for each subincrement
+ //so far the model does not offer different settings for each tick depth
+ const VLineProperties& makeLinePropertiesForDepth() const { return m_aLineProperties; }
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx
new file mode 100644
index 0000000000..8163058ad5
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianAxis.cxx
@@ -0,0 +1,2028 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VCartesianAxis.hxx"
+#include <PlottingPositionHelper.hxx>
+#include <ShapeFactory.hxx>
+#include <PropertyMapper.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <LabelPositionHelper.hxx>
+#include <BaseGFXHelper.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include "Tickmarks_Equidistant.hxx"
+#include <ExplicitCategoriesProvider.hxx>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <o3tl/safeint.hxx>
+#include <rtl/math.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/color.hxx>
+#include <svx/unoshape.hxx>
+#include <svx/unoshtxt.hxx>
+#include <VSeriesPlotter.hxx>
+#include <DataTableView.hxx>
+#include <ChartModel.hxx>
+
+#include <comphelper/scopeguard.hxx>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <algorithm>
+#include <limits>
+#include <memory>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::basegfx::B2DVector;
+using ::basegfx::B2DPolygon;
+using ::basegfx::B2DPolyPolygon;
+
+namespace chart {
+
+VCartesianAxis::VCartesianAxis( const AxisProperties& rAxisProperties
+ , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , PlottingPositionHelper* pPosHelper )//takes ownership
+ : VAxisBase( nDimensionIndex, nDimensionCount, rAxisProperties, xNumberFormatsSupplier )
+{
+ if( pPosHelper )
+ m_pPosHelper = pPosHelper;
+ else
+ m_pPosHelper = new PlottingPositionHelper();
+}
+
+VCartesianAxis::~VCartesianAxis()
+{
+ delete m_pPosHelper;
+ m_pPosHelper = nullptr;
+}
+
+static void lcl_ResizeTextShapeToFitAvailableSpace( SvxShapeText& rShape2DText,
+ const AxisLabelProperties& rAxisLabelProperties,
+ std::u16string_view rLabel,
+ const tNameSequence& rPropNames,
+ const tAnySequence& rPropValues,
+ const bool bIsHorizontalAxis )
+{
+ bool bTextHorizontal = rAxisLabelProperties.m_fRotationAngleDegree != 0.0;
+ bool bIsDirectionVertical = bIsHorizontalAxis && bTextHorizontal;
+ const sal_Int32 nFullSize = bIsDirectionVertical ? rAxisLabelProperties.m_aFontReferenceSize.Height : rAxisLabelProperties.m_aFontReferenceSize.Width;
+
+ if( !nFullSize || rLabel.empty() )
+ return;
+
+ const sal_Int32 nAvgCharWidth = rShape2DText.getSize().Width / rLabel.size();
+
+ sal_Int32 nMaxLabelsSize = bIsDirectionVertical ? rAxisLabelProperties.m_aMaximumSpaceForLabels.Height : rAxisLabelProperties.m_aMaximumSpaceForLabels.Width;
+
+ awt::Size aSizeAfterRotation = ShapeFactory::getSizeAfterRotation(rShape2DText, rAxisLabelProperties.m_fRotationAngleDegree);
+
+ const sal_Int32 nTextSize = bIsDirectionVertical ? aSizeAfterRotation.Height : aSizeAfterRotation.Width;
+
+ if( !nAvgCharWidth )
+ return;
+
+ static constexpr OUString sDots = u"..."_ustr;
+ const sal_Int32 nCharsToRemove = ( nTextSize - nMaxLabelsSize ) / nAvgCharWidth + 1;
+ sal_Int32 nNewLen = rLabel.size() - nCharsToRemove - sDots.getLength();
+ // Prevent from showing only dots
+ if (nNewLen < 0)
+ nNewLen = ( sal_Int32(rLabel.size()) >= sDots.getLength() ) ? sDots.getLength() : rLabel.size();
+
+ bool bCrop = nCharsToRemove > 0;
+ if( !bCrop )
+ return;
+
+ OUString aNewLabel( rLabel.substr( 0, nNewLen ) );
+ if( nNewLen > sDots.getLength() )
+ aNewLabel += sDots;
+ rShape2DText.setString( aNewLabel );
+
+ PropertyMapper::setMultiProperties( rPropNames, rPropValues, rShape2DText );
+}
+
+static rtl::Reference<SvxShapeText> createSingleLabel(
+ const rtl::Reference< SvxShapeGroupAnyD >& xTarget
+ , const awt::Point& rAnchorScreenPosition2D
+ , const OUString& rLabel
+ , const AxisLabelProperties& rAxisLabelProperties
+ , const AxisProperties& rAxisProperties
+ , const tNameSequence& rPropNames
+ , const tAnySequence& rPropValues
+ , const bool bIsHorizontalAxis
+ )
+{
+ if(rLabel.isEmpty())
+ return nullptr;
+
+ // #i78696# use mathematically correct rotation now
+ const double fRotationAnglePi(-basegfx::deg2rad(rAxisLabelProperties.m_fRotationAngleDegree));
+ uno::Any aATransformation = ShapeFactory::makeTransformation( rAnchorScreenPosition2D, fRotationAnglePi );
+ OUString aLabel = ShapeFactory::getStackedString( rLabel, rAxisLabelProperties.m_bStackCharacters );
+
+ rtl::Reference<SvxShapeText> xShape2DText =
+ ShapeFactory::createText( xTarget, aLabel, rPropNames, rPropValues, aATransformation );
+
+ if( rAxisProperties.m_bLimitSpaceForLabels )
+ lcl_ResizeTextShapeToFitAvailableSpace(*xShape2DText, rAxisLabelProperties, aLabel, rPropNames, rPropValues, bIsHorizontalAxis);
+
+ LabelPositionHelper::correctPositionForRotation( xShape2DText
+ , rAxisProperties.maLabelAlignment.meAlignment, rAxisLabelProperties.m_fRotationAngleDegree, rAxisProperties.m_bComplexCategories );
+
+ return xShape2DText;
+}
+
+static bool lcl_doesShapeOverlapWithTickmark( SvxShape& rShape
+ , double fRotationAngleDegree
+ , const basegfx::B2DVector& rTickScreenPosition )
+{
+ ::basegfx::B2IRectangle aShapeRect = BaseGFXHelper::makeRectangle(rShape.getPosition(), ShapeFactory::getSizeAfterRotation( rShape, fRotationAngleDegree ));
+
+ basegfx::B2IVector aPosition(
+ static_cast<sal_Int32>( rTickScreenPosition.getX() )
+ , static_cast<sal_Int32>( rTickScreenPosition.getY() ) );
+ return aShapeRect.isInside(aPosition);
+}
+
+static void lcl_getRotatedPolygon( B2DPolygon &aPoly, const ::basegfx::B2DRectangle &aRect, const awt::Point &aPos, const double fRotationAngleDegree )
+{
+ aPoly = basegfx::utils::createPolygonFromRect( aRect );
+
+ // For rotating the rectangle we use the opposite angle,
+ // since `B2DHomMatrix` class used for
+ // representing the transformation, performs rotations in the positive
+ // direction (from the X axis to the Y axis). However since the coordinate
+ // system used by the chart has the Y-axis pointing downward, a rotation in
+ // the positive direction means a clockwise rotation. On the contrary text
+ // labels are rotated counterclockwise.
+ // The rotation is performed around the top-left vertex of the rectangle
+ // which is then moved to its final position by using the top-left
+ // vertex of the text label bounding box (aPos) as the translation vector.
+ ::basegfx::B2DHomMatrix aMatrix;
+ aMatrix.rotate(-basegfx::deg2rad(fRotationAngleDegree));
+ aMatrix.translate( aPos.X, aPos.Y);
+ aPoly.transform( aMatrix );
+}
+
+static bool doesOverlap( const rtl::Reference<SvxShapeText>& xShape1
+ , const rtl::Reference<SvxShapeText>& xShape2
+ , double fRotationAngleDegree )
+{
+ if( !xShape1.is() || !xShape2.is() )
+ return false;
+
+ ::basegfx::B2DRectangle aRect1( BaseGFXHelper::makeRectangle( awt::Point(0,0), xShape1->getSize()));
+ ::basegfx::B2DRectangle aRect2( BaseGFXHelper::makeRectangle( awt::Point(0,0), xShape2->getSize()));
+
+ B2DPolygon aPoly1;
+ B2DPolygon aPoly2;
+ lcl_getRotatedPolygon( aPoly1, aRect1, xShape1->getPosition(), fRotationAngleDegree );
+ lcl_getRotatedPolygon( aPoly2, aRect2, xShape2->getPosition(), fRotationAngleDegree );
+
+ B2DPolyPolygon aPolyPoly1, aPolyPoly2;
+ aPolyPoly1.append( aPoly1 );
+ aPolyPoly2.append( aPoly2 );
+ B2DPolyPolygon overlapPoly = ::basegfx::utils::clipPolyPolygonOnPolyPolygon( aPolyPoly1, aPolyPoly2, true, false );
+
+ return (overlapPoly.count() > 0);
+}
+
+static void removeShapesAtWrongRhythm( TickIter& rIter
+ , sal_Int32 nCorrectRhythm
+ , sal_Int32 nMaxTickToCheck
+ , const rtl::Reference< SvxShapeGroupAnyD >& xTarget )
+{
+ sal_Int32 nTick = 0;
+ for( TickInfo* pTickInfo = rIter.firstInfo()
+ ; pTickInfo && nTick <= nMaxTickToCheck
+ ; pTickInfo = rIter.nextInfo(), nTick++ )
+ {
+ //remove labels which does not fit into the rhythm
+ if( nTick%nCorrectRhythm != 0)
+ {
+ if(pTickInfo->xTextShape.is())
+ {
+ xTarget->remove(pTickInfo->xTextShape);
+ pTickInfo->xTextShape = nullptr;
+ }
+ }
+ }
+}
+
+namespace {
+
+/**
+ * If the labels are staggered and bInnerLine is true we iterate through
+ * only those labels that are closer to the diagram.
+ *
+ * If the labels are staggered and bInnerLine is false we iterate through
+ * only those that are farther from the diagram.
+ *
+ * If the labels are not staggered we iterate through all labels.
+ */
+class LabelIterator : public TickIter
+{
+public:
+ LabelIterator( TickInfoArrayType& rTickInfoVector
+ , const AxisLabelStaggering eAxisLabelStaggering
+ , bool bInnerLine );
+
+ virtual TickInfo* firstInfo() override;
+ virtual TickInfo* nextInfo() override;
+
+private: //member
+ PureTickIter m_aPureTickIter;
+ const AxisLabelStaggering m_eAxisLabelStaggering;
+ bool m_bInnerLine;
+};
+
+}
+
+LabelIterator::LabelIterator( TickInfoArrayType& rTickInfoVector
+ , const AxisLabelStaggering eAxisLabelStaggering
+ , bool bInnerLine )
+ : m_aPureTickIter( rTickInfoVector )
+ , m_eAxisLabelStaggering(eAxisLabelStaggering)
+ , m_bInnerLine(bInnerLine)
+{
+}
+
+TickInfo* LabelIterator::firstInfo()
+{
+ TickInfo* pTickInfo = m_aPureTickIter.firstInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() )
+ pTickInfo = m_aPureTickIter.nextInfo();
+ if(!pTickInfo)
+ return nullptr;
+ if( (m_eAxisLabelStaggering==AxisLabelStaggering::StaggerEven && m_bInnerLine)
+ ||
+ (m_eAxisLabelStaggering==AxisLabelStaggering::StaggerOdd && !m_bInnerLine)
+ )
+ {
+ //skip first label
+ do
+ pTickInfo = m_aPureTickIter.nextInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() );
+ }
+ if(!pTickInfo)
+ return nullptr;
+ return pTickInfo;
+}
+
+TickInfo* LabelIterator::nextInfo()
+{
+ TickInfo* pTickInfo = nullptr;
+ //get next label
+ do
+ pTickInfo = m_aPureTickIter.nextInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() );
+
+ if( m_eAxisLabelStaggering==AxisLabelStaggering::StaggerEven
+ || m_eAxisLabelStaggering==AxisLabelStaggering::StaggerOdd )
+ {
+ //skip one label
+ do
+ pTickInfo = m_aPureTickIter.nextInfo();
+ while( pTickInfo && !pTickInfo->xTextShape.is() );
+ }
+ return pTickInfo;
+}
+
+static B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDistanceTickToText, double fRotationAngleDegree )
+{
+ //calculates the height or width of a line of labels
+ //thus a following line of labels can be shifted for that distance
+
+ B2DVector aRet(0,0);
+
+ sal_Int32 nDistanceTickToText = static_cast<sal_Int32>( rDistanceTickToText.getLength() );
+ if( nDistanceTickToText==0.0)
+ return aRet;
+
+ B2DVector aStaggerDirection(rDistanceTickToText);
+ aStaggerDirection.normalize();
+
+ sal_Int32 nDistance=0;
+ rtl::Reference< SvxShapeText > xShape2DText;
+ for( TickInfo* pTickInfo = rIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = rIter.nextInfo() )
+ {
+ xShape2DText = pTickInfo->xTextShape;
+ if( xShape2DText.is() )
+ {
+ awt::Size aSize = ShapeFactory::getSizeAfterRotation( *xShape2DText, fRotationAngleDegree );
+ if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY()))
+ nDistance = std::max(nDistance,aSize.Width);
+ else
+ nDistance = std::max(nDistance,aSize.Height);
+ }
+ }
+
+ aRet = aStaggerDirection*nDistance;
+
+ //add extra distance for vertical distance
+ if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY()))
+ aRet += rDistanceTickToText;
+
+ return aRet;
+}
+
+static void lcl_shiftLabels( TickIter& rIter, const B2DVector& rStaggerDistance )
+{
+ if(rStaggerDistance.getLength()==0.0)
+ return;
+ for( TickInfo* pTickInfo = rIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = rIter.nextInfo() )
+ {
+ const rtl::Reference<SvxShapeText>& xShape2DText = pTickInfo->xTextShape;
+ if( xShape2DText.is() )
+ {
+ awt::Point aPos = xShape2DText->getPosition();
+ aPos.X += static_cast<sal_Int32>(rStaggerDistance.getX());
+ aPos.Y += static_cast<sal_Int32>(rStaggerDistance.getY());
+ xShape2DText->setPosition( aPos );
+ }
+ }
+}
+
+static bool lcl_hasWordBreak( const rtl::Reference<SvxShapeText>& xShape )
+{
+ if (!xShape.is())
+ return false;
+
+ SvxTextEditSource* pTextEditSource = dynamic_cast<SvxTextEditSource*>(xShape->GetEditSource());
+ if (!pTextEditSource)
+ return false;
+
+ pTextEditSource->UpdateOutliner();
+ SvxTextForwarder* pTextForwarder = pTextEditSource->GetTextForwarder();
+ if (!pTextForwarder)
+ return false;
+
+ sal_Int32 nParaCount = pTextForwarder->GetParagraphCount();
+ for ( sal_Int32 nPara = 0; nPara < nParaCount; ++nPara )
+ {
+ sal_Int32 nLineCount = pTextForwarder->GetLineCount( nPara );
+ for ( sal_Int32 nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ sal_Int32 nLineStart = 0;
+ sal_Int32 nLineEnd = 0;
+ pTextForwarder->GetLineBoundaries( nLineStart, nLineEnd, nPara, nLine );
+ assert(nLineStart >= 0);
+ sal_Int32 nWordStart = 0;
+ sal_Int32 nWordEnd = 0;
+ if ( pTextForwarder->GetWordIndices( nPara, nLineStart, nWordStart, nWordEnd ) &&
+ ( nWordStart != nLineStart ) )
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static OUString getTextLabelString(
+ const FixedNumberFormatter& rFixedNumberFormatter, const uno::Sequence<OUString>* pCategories,
+ const TickInfo* pTickInfo, bool bComplexCat, Color& rExtraColor, bool& rHasExtraColor )
+{
+ if (pCategories)
+ {
+ // This is a normal category axis. Get the label string from the
+ // label string array.
+ sal_Int32 nIndex = static_cast<sal_Int32>(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0
+ if( nIndex>=0 && nIndex<pCategories->getLength() )
+ return (*pCategories)[nIndex];
+
+ return OUString();
+ }
+ else if (bComplexCat)
+ {
+ // This is a complex category axis. The label is stored in the tick.
+ return pTickInfo->aText;
+ }
+
+ // This is a numeric axis. Format the original tick value per number format.
+ return rFixedNumberFormatter.getFormattedString(pTickInfo->getUnscaledTickValue(), rExtraColor, rHasExtraColor);
+}
+
+static void getAxisLabelProperties(
+ tNameSequence& rPropNames, tAnySequence& rPropValues, const AxisProperties& rAxisProp,
+ const AxisLabelProperties& rAxisLabelProp,
+ sal_Int32 nLimitedSpaceForText, bool bLimitedHeight )
+{
+ Reference<beans::XPropertySet> xProps(rAxisProp.m_xAxisModel);
+
+ PropertyMapper::getTextLabelMultiPropertyLists(
+ xProps, rPropNames, rPropValues, false, nLimitedSpaceForText, bLimitedHeight, false);
+
+ LabelPositionHelper::doDynamicFontResize(
+ rPropValues, rPropNames, xProps, rAxisLabelProp.m_aFontReferenceSize);
+
+ LabelPositionHelper::changeTextAdjustment(
+ rPropValues, rPropNames, rAxisProp.maLabelAlignment.meAlignment);
+}
+
+namespace {
+
+/**
+ * Iterate through only 3 ticks including the one that has the longest text
+ * length. When the first tick has the longest text, it iterates through
+ * the first 3 ticks. Otherwise it iterates through 3 ticks such that the
+ * 2nd tick is the one with the longest text.
+ */
+class MaxLabelTickIter : public TickIter
+{
+public:
+ MaxLabelTickIter( TickInfoArrayType& rTickInfoVector, size_t nLongestLabelIndex );
+
+ virtual TickInfo* firstInfo() override;
+ virtual TickInfo* nextInfo() override;
+
+private:
+ TickInfoArrayType& m_rTickInfoVector;
+ std::vector<size_t> m_aValidIndices;
+ size_t m_nCurrentIndex;
+};
+
+}
+
+MaxLabelTickIter::MaxLabelTickIter(
+ TickInfoArrayType& rTickInfoVector, size_t nLongestLabelIndex ) :
+ m_rTickInfoVector(rTickInfoVector), m_nCurrentIndex(0)
+{
+ assert(!rTickInfoVector.empty()); // should be checked by the caller.
+ assert(nLongestLabelIndex < rTickInfoVector.size());
+
+ size_t nMaxIndex = m_rTickInfoVector.size()-1;
+ if (nLongestLabelIndex >= nMaxIndex-1)
+ nLongestLabelIndex = 0;
+
+ if (nLongestLabelIndex > 0)
+ m_aValidIndices.push_back(nLongestLabelIndex-1);
+
+ m_aValidIndices.push_back(nLongestLabelIndex);
+
+ while (m_aValidIndices.size() < 3)
+ {
+ ++nLongestLabelIndex;
+ if (nLongestLabelIndex > nMaxIndex)
+ break;
+
+ m_aValidIndices.push_back(nLongestLabelIndex);
+ }
+}
+
+TickInfo* MaxLabelTickIter::firstInfo()
+{
+ m_nCurrentIndex = 0;
+ if (m_nCurrentIndex < m_aValidIndices.size())
+ return &m_rTickInfoVector[m_aValidIndices[m_nCurrentIndex]];
+ return nullptr;
+}
+
+TickInfo* MaxLabelTickIter::nextInfo()
+{
+ m_nCurrentIndex++;
+ if (m_nCurrentIndex < m_aValidIndices.size())
+ return &m_rTickInfoVector[m_aValidIndices[m_nCurrentIndex]];
+ return nullptr;
+}
+
+bool VCartesianAxis::isBreakOfLabelsAllowed(
+ const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis, bool bIsVerticalAxis) const
+{
+ if( m_aTextLabels.getLength() > 100 )
+ return false;
+ if( !rAxisLabelProperties.m_bLineBreakAllowed )
+ return false;
+ if( rAxisLabelProperties.m_bStackCharacters )
+ return false;
+ //no break for value axis
+ if( !m_bUseTextLabels )
+ return false;
+ if( !( rAxisLabelProperties.m_fRotationAngleDegree == 0.0 ||
+ rAxisLabelProperties.m_fRotationAngleDegree == 90.0 ||
+ rAxisLabelProperties.m_fRotationAngleDegree == 270.0 ) )
+ return false;
+ //no break for complex vertical category axis
+ if( !m_aAxisProperties.m_bSwapXAndY )
+ return bIsHorizontalAxis;
+ else if( m_aAxisProperties.m_bSwapXAndY && !m_aAxisProperties.m_bComplexCategories )
+ return bIsVerticalAxis;
+ else
+ return false;
+}
+namespace{
+
+bool canAutoAdjustLabelPlacement(
+ const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis, bool bIsVerticalAxis)
+{
+ // joined prerequisite checks for auto rotate and auto stagger
+ if( rAxisLabelProperties.m_bOverlapAllowed )
+ return false;
+ if( rAxisLabelProperties.m_bLineBreakAllowed ) // auto line break may conflict with...
+ return false;
+ if( rAxisLabelProperties.m_fRotationAngleDegree != 0.0 )
+ return false;
+ // automatic adjusting labels only works for
+ // horizontal axis with horizontal text
+ // or vertical axis with vertical text
+ if( bIsHorizontalAxis )
+ return !rAxisLabelProperties.m_bStackCharacters;
+ if( bIsVerticalAxis )
+ return rAxisLabelProperties.m_bStackCharacters;
+ return false;
+}
+
+bool isAutoStaggeringOfLabelsAllowed(
+ const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis, bool bIsVerticalAxis )
+{
+ if( rAxisLabelProperties.m_eStaggering != AxisLabelStaggering::StaggerAuto )
+ return false;
+ return canAutoAdjustLabelPlacement(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis);
+}
+
+// make clear that we check for auto rotation prerequisites
+const auto& isAutoRotatingOfLabelsAllowed = canAutoAdjustLabelPlacement;
+
+} // namespace
+void VCartesianAxis::createAllTickInfosFromComplexCategories( TickInfoArraysType& rAllTickInfos, bool bShiftedPosition )
+{
+ //no minor tickmarks will be generated!
+ //order is: inner labels first , outer labels last (that is different to all other TickIter cases)
+ if(!bShiftedPosition)
+ {
+ rAllTickInfos.clear();
+ sal_Int32 nLevel=0;
+ sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
+ for( ; nLevel<nLevelCount; nLevel++ )
+ {
+ TickInfoArrayType aTickInfoVector;
+ const std::vector<ComplexCategory>* pComplexCategories =
+ m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel(nLevel);
+
+ if (!pComplexCategories)
+ continue;
+
+ sal_Int32 nCatIndex = 0;
+
+ for (auto const& complexCategory : *pComplexCategories)
+ {
+ TickInfo aTickInfo(nullptr);
+ sal_Int32 nCount = complexCategory.Count;
+ if( nCatIndex + 1.0 + nCount >= m_aScale.Maximum )
+ {
+ nCount = static_cast<sal_Int32>(m_aScale.Maximum - 1.0 - nCatIndex);
+ if( nCount <= 0 )
+ nCount = 1;
+ }
+ aTickInfo.fScaledTickValue = nCatIndex + 1.0 + nCount/2.0;
+ aTickInfo.nFactorForLimitedTextWidth = nCount;
+ aTickInfo.aText = complexCategory.Text;
+ aTickInfoVector.push_back(aTickInfo);
+ nCatIndex += nCount;
+ if( nCatIndex + 1.0 >= m_aScale.Maximum )
+ break;
+ }
+ rAllTickInfos.push_back(aTickInfoVector);
+ }
+ }
+ else //bShiftedPosition==false
+ {
+ rAllTickInfos.clear();
+ sal_Int32 nLevel=0;
+ sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
+ for( ; nLevel<nLevelCount; nLevel++ )
+ {
+ TickInfoArrayType aTickInfoVector;
+ const std::vector<ComplexCategory>* pComplexCategories =
+ m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel(nLevel);
+ sal_Int32 nCatIndex = 0;
+ if (pComplexCategories)
+ {
+ for (auto const& complexCategory : *pComplexCategories)
+ {
+ TickInfo aTickInfo(nullptr);
+ aTickInfo.fScaledTickValue = nCatIndex + 1.0;
+ aTickInfoVector.push_back(aTickInfo);
+ nCatIndex += complexCategory.Count;
+ if( nCatIndex + 1.0 > m_aScale.Maximum )
+ break;
+ }
+ }
+
+ //fill up with single ticks until maximum scale
+ while( nCatIndex + 1.0 < m_aScale.Maximum )
+ {
+ TickInfo aTickInfo(nullptr);
+ aTickInfo.fScaledTickValue = nCatIndex + 1.0;
+ aTickInfoVector.push_back(aTickInfo);
+ nCatIndex ++;
+ if( nLevel>0 )
+ break;
+ }
+ //add an additional tick at the end
+ {
+ TickInfo aTickInfo(nullptr);
+ aTickInfo.fScaledTickValue = m_aScale.Maximum;
+ aTickInfoVector.push_back(aTickInfo);
+ }
+ rAllTickInfos.push_back(aTickInfoVector);
+ }
+ }
+}
+
+void VCartesianAxis::createAllTickInfos( TickInfoArraysType& rAllTickInfos )
+{
+ if( isComplexCategoryAxis() )
+ createAllTickInfosFromComplexCategories( rAllTickInfos, false );
+ else
+ VAxisBase::createAllTickInfos(rAllTickInfos);
+}
+
+TickIter* VCartesianAxis::createLabelTickIterator( sal_Int32 nTextLevel )
+{
+ if( nTextLevel>=0 && o3tl::make_unsigned(nTextLevel) < m_aAllTickInfos.size() )
+ return new PureTickIter( m_aAllTickInfos[nTextLevel] );
+ return nullptr;
+}
+
+TickIter* VCartesianAxis::createMaximumLabelTickIterator( sal_Int32 nTextLevel )
+{
+ if( isComplexCategoryAxis() || isDateAxis() )
+ {
+ return createLabelTickIterator( nTextLevel ); //mmmm maybe todo: create less than all texts here
+ }
+ else
+ {
+ if(nTextLevel==0)
+ {
+ if( !m_aAllTickInfos.empty() )
+ {
+ size_t nLongestLabelIndex = m_bUseTextLabels ? getIndexOfLongestLabel(m_aTextLabels) : 0;
+ if (nLongestLabelIndex >= m_aAllTickInfos[0].size())
+ return nullptr;
+
+ return new MaxLabelTickIter( m_aAllTickInfos[0], nLongestLabelIndex );
+ }
+ }
+ }
+ return nullptr;
+}
+
+sal_Int32 VCartesianAxis::getTextLevelCount() const
+{
+ sal_Int32 nTextLevelCount = 1;
+ if( isComplexCategoryAxis() )
+ nTextLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
+ return nTextLevelCount;
+}
+
+bool VCartesianAxis::createTextShapes(
+ const rtl::Reference< SvxShapeGroupAnyD >& xTarget, TickIter& rTickIter,
+ AxisLabelProperties& rAxisLabelProperties, TickFactory2D const * pTickFactory,
+ sal_Int32 nScreenDistanceBetweenTicks )
+{
+ const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis();
+ const bool bIsVerticalAxis = pTickFactory->isVerticalAxis();
+
+ if( m_bUseTextLabels && (m_aAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_NEAR_AXIS ||
+ m_aAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_START))
+ {
+ if (bIsHorizontalAxis)
+ {
+ rAxisLabelProperties.m_aMaximumSpaceForLabels.Y = pTickFactory->getXaxisStartPos().getY();
+ rAxisLabelProperties.m_aMaximumSpaceForLabels.Height = rAxisLabelProperties.m_aFontReferenceSize.Height - rAxisLabelProperties.m_aMaximumSpaceForLabels.Y;
+ }
+ else if (bIsVerticalAxis)
+ {
+ rAxisLabelProperties.m_aMaximumSpaceForLabels.X = 0;
+ rAxisLabelProperties.m_aMaximumSpaceForLabels.Width = pTickFactory->getXaxisStartPos().getX();
+ }
+ }
+
+ bool bIsBreakOfLabelsAllowed = isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis );
+ if (!bIsBreakOfLabelsAllowed &&
+ !isAutoStaggeringOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) &&
+ !rAxisLabelProperties.isStaggered())
+ {
+ return createTextShapesSimple(xTarget, rTickIter, rAxisLabelProperties, pTickFactory);
+ }
+
+ FixedNumberFormatter aFixedNumberFormatter(
+ m_xNumberFormatsSupplier, rAxisLabelProperties.m_nNumberFormatKey );
+
+ bool bIsStaggered = rAxisLabelProperties.isStaggered();
+ B2DVector aTextToTickDistance = pTickFactory->getDistanceAxisTickToText(m_aAxisProperties, true);
+ sal_Int32 nLimitedSpaceForText = -1;
+
+ if (bIsBreakOfLabelsAllowed)
+ {
+ if (!m_aAxisProperties.m_bLimitSpaceForLabels)
+ {
+ basegfx::B2DVector nDeltaVector = pTickFactory->getXaxisEndPos() - pTickFactory->getXaxisStartPos();
+ nLimitedSpaceForText = nDeltaVector.getX();
+ }
+ if (nScreenDistanceBetweenTicks > 0)
+ nLimitedSpaceForText = nScreenDistanceBetweenTicks;
+
+ if( bIsStaggered )
+ nLimitedSpaceForText *= 2;
+
+ if( nLimitedSpaceForText > 0 )
+ { //reduce space for a small amount to have a visible distance between the labels:
+ sal_Int32 nReduce = (nLimitedSpaceForText*5)/100;
+ if(!nReduce)
+ nReduce = 1;
+ nLimitedSpaceForText -= nReduce;
+ }
+
+ // recalculate the nLimitedSpaceForText in case of 90 and 270 degree if the text break is true
+ if ( rAxisLabelProperties.m_fRotationAngleDegree == 90.0 || rAxisLabelProperties.m_fRotationAngleDegree == 270.0 )
+ {
+ nLimitedSpaceForText = rAxisLabelProperties.m_aMaximumSpaceForLabels.Height;
+ m_aAxisProperties.m_bLimitSpaceForLabels = false;
+ }
+
+ // recalculate the nLimitedSpaceForText in case of vertical category axis if the text break is true
+ if ( m_aAxisProperties.m_bSwapXAndY && bIsVerticalAxis && rAxisLabelProperties.m_fRotationAngleDegree == 0.0 )
+ {
+ nLimitedSpaceForText = pTickFactory->getXaxisStartPos().getX();
+ m_aAxisProperties.m_bLimitSpaceForLabels = false;
+ }
+ }
+
+ // Stores an array of text label strings in case of a normal
+ // (non-complex) category axis.
+ const uno::Sequence<OUString>* pCategories = nullptr;
+ if( m_bUseTextLabels && !m_aAxisProperties.m_bComplexCategories )
+ pCategories = &m_aTextLabels;
+
+ bool bLimitedHeight;
+ if( !m_aAxisProperties.m_bSwapXAndY )
+ bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY());
+ else
+ bLimitedHeight = fabs(aTextToTickDistance.getX()) < fabs(aTextToTickDistance.getY());
+ //prepare properties for multipropertyset-interface of shape
+ tNameSequence aPropNames;
+ tAnySequence aPropValues;
+ getAxisLabelProperties(aPropNames, aPropValues, m_aAxisProperties, rAxisLabelProperties, nLimitedSpaceForText, bLimitedHeight);
+
+ uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,u"CharColor");
+ Color nColor = COL_AUTO;
+ if(pColorAny)
+ *pColorAny >>= nColor;
+
+ uno::Any* pLimitedSpaceAny = PropertyMapper::getValuePointerForLimitedSpace(aPropValues,aPropNames,bLimitedHeight);
+
+ const TickInfo* pPreviousVisibleTickInfo = nullptr;
+ const TickInfo* pPREPreviousVisibleTickInfo = nullptr;
+ sal_Int32 nTick = 0;
+ for( TickInfo* pTickInfo = rTickIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = rTickIter.nextInfo(), nTick++ )
+ {
+ const TickInfo* pLastVisibleNeighbourTickInfo = bIsStaggered ?
+ pPREPreviousVisibleTickInfo : pPreviousVisibleTickInfo;
+
+ //don't create labels which does not fit into the rhythm
+ if( nTick%rAxisLabelProperties.m_nRhythm != 0 )
+ continue;
+
+ //don't create labels for invisible ticks
+ if( !pTickInfo->bPaintIt )
+ continue;
+
+ if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.m_bOverlapAllowed )
+ {
+ // Overlapping is not allowed. If the label overlaps with its
+ // neighboring label, try increasing the tick interval (or rhythm
+ // as it's called) and start over.
+
+ if( lcl_doesShapeOverlapWithTickmark( *pLastVisibleNeighbourTickInfo->xTextShape
+ , rAxisLabelProperties.m_fRotationAngleDegree
+ , pTickInfo->aTickScreenPosition ) )
+ {
+ // This tick overlaps with its neighbor. Try to stagger (if
+ // auto staggering is allowed) to avoid overlapping.
+
+ bool bOverlapsAfterAutoStagger = true;
+ if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) )
+ {
+ bIsStaggered = true;
+ rAxisLabelProperties.m_eStaggering = AxisLabelStaggering::StaggerEven;
+ pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo;
+ if( !pLastVisibleNeighbourTickInfo ||
+ !lcl_doesShapeOverlapWithTickmark( *pLastVisibleNeighbourTickInfo->xTextShape
+ , rAxisLabelProperties.m_fRotationAngleDegree
+ , pTickInfo->aTickScreenPosition ) )
+ bOverlapsAfterAutoStagger = false;
+ }
+
+ if (bOverlapsAfterAutoStagger)
+ {
+ // Still overlaps with its neighbor even after staggering.
+ // Increment the visible tick intervals (if that's
+ // allowed) and start over.
+
+ rAxisLabelProperties.m_nRhythm++;
+ removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.m_nRhythm, nTick, xTarget );
+ return false;
+ }
+ }
+ }
+
+ bool bHasExtraColor=false;
+ Color nExtraColor;
+
+ OUString aLabel = getTextLabelString(
+ aFixedNumberFormatter, pCategories, pTickInfo, isComplexCategoryAxis(),
+ nExtraColor, bHasExtraColor);
+
+ if(pColorAny)
+ *pColorAny <<= bHasExtraColor?nExtraColor:nColor;
+ if(pLimitedSpaceAny)
+ *pLimitedSpaceAny <<= sal_Int32(nLimitedSpaceForText*pTickInfo->nFactorForLimitedTextWidth);
+
+ B2DVector aTickScreenPos2D = pTickInfo->aTickScreenPosition;
+ aTickScreenPos2D += aTextToTickDistance;
+ awt::Point aAnchorScreenPosition2D(
+ static_cast<sal_Int32>(aTickScreenPos2D.getX())
+ ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
+
+ //create single label
+ if(!pTickInfo->xTextShape.is())
+ {
+ pTickInfo->xTextShape = createSingleLabel( xTarget
+ , aAnchorScreenPosition2D, aLabel
+ , rAxisLabelProperties, m_aAxisProperties
+ , aPropNames, aPropValues, bIsHorizontalAxis );
+ }
+ if(!pTickInfo->xTextShape.is())
+ continue;
+
+ recordMaximumTextSize( *pTickInfo->xTextShape, rAxisLabelProperties.m_fRotationAngleDegree );
+
+ // Label has multiple lines and the words are broken
+ if (nLimitedSpaceForText > 0
+ && !rAxisLabelProperties.m_bOverlapAllowed
+ && rAxisLabelProperties.m_fRotationAngleDegree == 0.0
+ && nTick > 0
+ && lcl_hasWordBreak(pTickInfo->xTextShape))
+ {
+ // Label has multiple lines and belongs to a complex category
+ // axis. Rotate 90 degrees to try to avoid overlaps.
+ if ( m_aAxisProperties.m_bComplexCategories )
+ {
+ rAxisLabelProperties.m_fRotationAngleDegree = 90;
+ }
+ rAxisLabelProperties.m_bLineBreakAllowed = false;
+ m_aAxisLabelProperties.m_fRotationAngleDegree = rAxisLabelProperties.m_fRotationAngleDegree;
+ removeTextShapesFromTicks();
+ return false;
+ }
+
+ //if NO OVERLAP -> remove overlapping shapes
+ if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.m_bOverlapAllowed )
+ {
+ // Check if the label still overlaps with its neighbor.
+ if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.m_fRotationAngleDegree ) )
+ {
+ // It overlaps. Check if staggering helps.
+ bool bOverlapsAfterAutoStagger = true;
+ if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) )
+ {
+ // Compatibility option: starting from LibreOffice 5.1 the rotated
+ // layout is preferred to staggering for axis labels.
+ if( !isAutoRotatingOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis)
+ || m_aAxisProperties.m_bTryStaggeringFirst )
+ {
+ bIsStaggered = true;
+ rAxisLabelProperties.m_eStaggering = AxisLabelStaggering::StaggerEven;
+ pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo;
+ if( !pLastVisibleNeighbourTickInfo ||
+ !lcl_doesShapeOverlapWithTickmark( *pLastVisibleNeighbourTickInfo->xTextShape
+ , rAxisLabelProperties.m_fRotationAngleDegree
+ , pTickInfo->aTickScreenPosition ) )
+ bOverlapsAfterAutoStagger = false;
+ }
+ }
+
+ if (bOverlapsAfterAutoStagger)
+ {
+ // Staggering didn't solve the overlap.
+ if( isAutoRotatingOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) )
+ {
+ // Try auto-rotating the labels at 45 degrees and
+ // start over. This rotation angle will be stored for
+ // all future text shape creation runs.
+ // The nRhythm parameter is reset to 1 since the layout
+ // used for text labels is changed.
+ rAxisLabelProperties.autoRotate45();
+ m_aAxisLabelProperties.m_fRotationAngleDegree = rAxisLabelProperties.m_fRotationAngleDegree; // Store it for future runs.
+ removeTextShapesFromTicks();
+ rAxisLabelProperties.m_nRhythm = 1;
+ return false;
+ }
+
+ // Try incrementing the tick interval and start over.
+ rAxisLabelProperties.m_nRhythm++;
+ removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.m_nRhythm, nTick, xTarget );
+ return false;
+ }
+ }
+ }
+
+ pPREPreviousVisibleTickInfo = pPreviousVisibleTickInfo;
+ pPreviousVisibleTickInfo = pTickInfo;
+ }
+ return true;
+}
+
+bool VCartesianAxis::createTextShapesSimple(
+ const rtl::Reference< SvxShapeGroupAnyD >& xTarget, TickIter& rTickIter,
+ AxisLabelProperties& rAxisLabelProperties, TickFactory2D const * pTickFactory )
+{
+ FixedNumberFormatter aFixedNumberFormatter(
+ m_xNumberFormatsSupplier, rAxisLabelProperties.m_nNumberFormatKey );
+
+ const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis();
+ const bool bIsVerticalAxis = pTickFactory->isVerticalAxis();
+ B2DVector aTextToTickDistance = pTickFactory->getDistanceAxisTickToText(m_aAxisProperties, true);
+
+ // Stores an array of text label strings in case of a normal
+ // (non-complex) category axis.
+ const uno::Sequence<OUString>* pCategories = nullptr;
+ if( m_bUseTextLabels && !m_aAxisProperties.m_bComplexCategories )
+ pCategories = &m_aTextLabels;
+
+ bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY());
+
+ //prepare properties for multipropertyset-interface of shape
+ tNameSequence aPropNames;
+ tAnySequence aPropValues;
+ getAxisLabelProperties(aPropNames, aPropValues, m_aAxisProperties, rAxisLabelProperties, -1, bLimitedHeight);
+
+ uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,u"CharColor");
+ Color nColor = COL_AUTO;
+ if(pColorAny)
+ *pColorAny >>= nColor;
+
+ uno::Any* pLimitedSpaceAny = PropertyMapper::getValuePointerForLimitedSpace(aPropValues,aPropNames,bLimitedHeight);
+
+ const TickInfo* pPreviousVisibleTickInfo = nullptr;
+ sal_Int32 nTick = 0;
+ for( TickInfo* pTickInfo = rTickIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = rTickIter.nextInfo(), nTick++ )
+ {
+ const TickInfo* pLastVisibleNeighbourTickInfo = pPreviousVisibleTickInfo;
+
+ //don't create labels which does not fit into the rhythm
+ if( nTick%rAxisLabelProperties.m_nRhythm != 0 )
+ continue;
+
+ //don't create labels for invisible ticks
+ if( !pTickInfo->bPaintIt )
+ continue;
+
+ if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.m_bOverlapAllowed )
+ {
+ // Overlapping is not allowed. If the label overlaps with its
+ // neighboring label, try increasing the tick interval (or rhythm
+ // as it's called) and start over.
+
+ if( lcl_doesShapeOverlapWithTickmark( *pLastVisibleNeighbourTickInfo->xTextShape
+ , rAxisLabelProperties.m_fRotationAngleDegree
+ , pTickInfo->aTickScreenPosition ) )
+ {
+ // This tick overlaps with its neighbor. Increment the visible
+ // tick intervals (if that's allowed) and start over.
+
+ rAxisLabelProperties.m_nRhythm++;
+ removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.m_nRhythm, nTick, xTarget );
+ return false;
+ }
+ }
+
+ bool bHasExtraColor=false;
+ Color nExtraColor;
+
+ OUString aLabel = getTextLabelString(
+ aFixedNumberFormatter, pCategories, pTickInfo, isComplexCategoryAxis(),
+ nExtraColor, bHasExtraColor);
+
+ if(pColorAny)
+ *pColorAny <<= bHasExtraColor?nExtraColor:nColor;
+ if(pLimitedSpaceAny)
+ *pLimitedSpaceAny <<= sal_Int32(-1*pTickInfo->nFactorForLimitedTextWidth);
+
+ B2DVector aTickScreenPos2D = pTickInfo->aTickScreenPosition;
+ aTickScreenPos2D += aTextToTickDistance;
+ awt::Point aAnchorScreenPosition2D(
+ static_cast<sal_Int32>(aTickScreenPos2D.getX())
+ ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
+
+ //create single label
+ if(!pTickInfo->xTextShape.is())
+ pTickInfo->xTextShape = createSingleLabel( xTarget
+ , aAnchorScreenPosition2D, aLabel
+ , rAxisLabelProperties, m_aAxisProperties
+ , aPropNames, aPropValues, bIsHorizontalAxis );
+ if(!pTickInfo->xTextShape.is())
+ continue;
+
+ recordMaximumTextSize( *pTickInfo->xTextShape, rAxisLabelProperties.m_fRotationAngleDegree );
+
+ //if NO OVERLAP -> remove overlapping shapes
+ if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.m_bOverlapAllowed )
+ {
+ // Check if the label still overlaps with its neighbor.
+ if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.m_fRotationAngleDegree ) )
+ {
+ // It overlaps.
+ if( isAutoRotatingOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) )
+ {
+ // Try auto-rotating the labels at 45 degrees and
+ // start over. This rotation angle will be stored for
+ // all future text shape creation runs.
+ // The nRhythm parameter is reset to 1 since the layout
+ // used for text labels is changed.
+ rAxisLabelProperties.autoRotate45();
+ m_aAxisLabelProperties.m_fRotationAngleDegree = rAxisLabelProperties.m_fRotationAngleDegree; // Store it for future runs.
+ removeTextShapesFromTicks();
+ rAxisLabelProperties.m_nRhythm = 1;
+ return false;
+ }
+
+ // Try incrementing the tick interval and start over.
+ rAxisLabelProperties.m_nRhythm++;
+ removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.m_nRhythm, nTick, xTarget );
+ return false;
+ }
+ }
+
+ pPreviousVisibleTickInfo = pTickInfo;
+ }
+ return true;
+}
+
+double VCartesianAxis::getAxisIntersectionValue() const
+{
+ if (m_aAxisProperties.m_pfMainLinePositionAtOtherAxis)
+ return *m_aAxisProperties.m_pfMainLinePositionAtOtherAxis;
+
+ double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
+ double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
+
+ return (m_aAxisProperties.m_eCrossoverType == css::chart::ChartAxisPosition_END) ? fMax : fMin;
+}
+
+double VCartesianAxis::getLabelLineIntersectionValue() const
+{
+ if (m_aAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_START)
+ return (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
+
+ if (m_aAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_END)
+ return (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
+
+ return getAxisIntersectionValue();
+}
+
+double VCartesianAxis::getExtraLineIntersectionValue() const
+{
+ if( !m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis )
+ return std::numeric_limits<double>::quiet_NaN();
+
+ double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
+ double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
+
+ if( *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis <= fMin
+ || *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis >= fMax )
+ return std::numeric_limits<double>::quiet_NaN();
+
+ return *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis;
+}
+
+B2DVector VCartesianAxis::getScreenPosition( double fLogicX, double fLogicY, double fLogicZ ) const
+{
+ B2DVector aRet(0,0);
+
+ if( m_pPosHelper )
+ {
+ drawing::Position3D aScenePos = m_pPosHelper->transformLogicToScene( fLogicX, fLogicY, fLogicZ, true );
+ if(m_nDimension==3)
+ {
+ if (m_xLogicTarget.is())
+ {
+ tPropertyNameMap aDummyPropertyNameMap;
+ rtl::Reference<Svx3DExtrudeObject> xShape3DAnchor = ShapeFactory::createCube( m_xLogicTarget
+ , aScenePos,drawing::Direction3D(1,1,1), 0, nullptr, aDummyPropertyNameMap);
+ awt::Point a2DPos = xShape3DAnchor->getPosition(); //get 2D position from xShape3DAnchor
+ m_xLogicTarget->remove(xShape3DAnchor);
+ aRet.setX( a2DPos.X );
+ aRet.setY( a2DPos.Y );
+ }
+ else
+ {
+ OSL_FAIL("cannot calculate screen position in VCartesianAxis::getScreenPosition");
+ }
+ }
+ else
+ {
+ aRet.setX( aScenePos.PositionX );
+ aRet.setY( aScenePos.PositionY );
+ }
+ }
+
+ return aRet;
+}
+
+VCartesianAxis::ScreenPosAndLogicPos VCartesianAxis::getScreenPosAndLogicPos( double fLogicX_, double fLogicY_, double fLogicZ_ ) const
+{
+ ScreenPosAndLogicPos aRet;
+ aRet.fLogicX = fLogicX_;
+ aRet.fLogicY = fLogicY_;
+ aRet.fLogicZ = fLogicZ_;
+ aRet.aScreenPos = getScreenPosition( fLogicX_, fLogicY_, fLogicZ_ );
+ return aRet;
+}
+
+typedef std::vector< VCartesianAxis::ScreenPosAndLogicPos > tScreenPosAndLogicPosList;
+
+namespace {
+
+struct lcl_LessXPos
+{
+ bool operator() ( const VCartesianAxis::ScreenPosAndLogicPos& rPos1, const VCartesianAxis::ScreenPosAndLogicPos& rPos2 )
+ {
+ return ( rPos1.aScreenPos.getX() < rPos2.aScreenPos.getX() );
+ }
+};
+
+struct lcl_GreaterYPos
+{
+ bool operator() ( const VCartesianAxis::ScreenPosAndLogicPos& rPos1, const VCartesianAxis::ScreenPosAndLogicPos& rPos2 )
+ {
+ return ( rPos1.aScreenPos.getY() > rPos2.aScreenPos.getY() );
+ }
+};
+
+}
+
+void VCartesianAxis::get2DAxisMainLine(
+ B2DVector& rStart, B2DVector& rEnd, AxisLabelAlignment& rAlignment, double fCrossesOtherAxis ) const
+{
+ //m_aAxisProperties might get updated and changed here because
+ // the label alignment and inner direction sign depends exactly of the choice of the axis line position which is made here in this method
+
+ double const fMinX = m_pPosHelper->getLogicMinX();
+ double const fMinY = m_pPosHelper->getLogicMinY();
+ double const fMinZ = m_pPosHelper->getLogicMinZ();
+ double const fMaxX = m_pPosHelper->getLogicMaxX();
+ double const fMaxY = m_pPosHelper->getLogicMaxY();
+ double const fMaxZ = m_pPosHelper->getLogicMaxZ();
+
+ double fXOnXPlane = fMinX;
+ double fXOther = fMaxX;
+ int nDifferentValue = !m_pPosHelper->isMathematicalOrientationX() ? -1 : 1;
+ if( !m_pPosHelper->isSwapXAndY() )
+ nDifferentValue *= (m_eLeftWallPos != CuboidPlanePosition_Left) ? -1 : 1;
+ else
+ nDifferentValue *= (m_eBottomPos != CuboidPlanePosition_Bottom) ? -1 : 1;
+ if( nDifferentValue<0 )
+ {
+ fXOnXPlane = fMaxX;
+ fXOther = fMinX;
+ }
+
+ double fYOnYPlane = fMinY;
+ double fYOther = fMaxY;
+ nDifferentValue = !m_pPosHelper->isMathematicalOrientationY() ? -1 : 1;
+ if( !m_pPosHelper->isSwapXAndY() )
+ nDifferentValue *= (m_eBottomPos != CuboidPlanePosition_Bottom) ? -1 : 1;
+ else
+ nDifferentValue *= (m_eLeftWallPos != CuboidPlanePosition_Left) ? -1 : 1;
+ if( nDifferentValue<0 )
+ {
+ fYOnYPlane = fMaxY;
+ fYOther = fMinY;
+ }
+
+ double fZOnZPlane = fMaxZ;
+ double fZOther = fMinZ;
+ nDifferentValue = !m_pPosHelper->isMathematicalOrientationZ() ? -1 : 1;
+ nDifferentValue *= (m_eBackWallPos != CuboidPlanePosition_Back) ? -1 : 1;
+ if( nDifferentValue<0 )
+ {
+ fZOnZPlane = fMinZ;
+ fZOther = fMaxZ;
+ }
+
+ double fXStart = fMinX;
+ double fYStart = fMinY;
+ double fZStart = fMinZ;
+ double fXEnd;
+ double fYEnd;
+ double fZEnd = fZStart;
+
+ if( m_nDimensionIndex==0 ) //x-axis
+ {
+ if( fCrossesOtherAxis < fMinY )
+ fCrossesOtherAxis = fMinY;
+ else if( fCrossesOtherAxis > fMaxY )
+ fCrossesOtherAxis = fMaxY;
+
+ fYStart = fYEnd = fCrossesOtherAxis;
+ fXEnd=m_pPosHelper->getLogicMaxX();
+
+ if(m_nDimension==3)
+ {
+ if( AxisHelper::isAxisPositioningEnabled() )
+ {
+ if( ::rtl::math::approxEqual( fYOther, fYStart) )
+ fZStart = fZEnd = fZOnZPlane;
+ else
+ fZStart = fZEnd = fZOther;
+ }
+ else
+ {
+ rStart = getScreenPosition( fXStart, fYStart, fZStart );
+ rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
+
+ double fDeltaX = rEnd.getX() - rStart.getX();
+ double fDeltaY = rEnd.getY() - rStart.getY();
+
+ //only those points are candidates which are lying on exactly one wall as these are outer edges
+ tScreenPosAndLogicPosList aPosList { getScreenPosAndLogicPos( fMinX, fYOnYPlane, fZOther ), getScreenPosAndLogicPos( fMinX, fYOther, fZOnZPlane ) };
+
+ if( fabs(fDeltaY) > fabs(fDeltaX) )
+ {
+ rAlignment.meAlignment = LABEL_ALIGN_LEFT;
+ //choose most left positions
+ std::sort( aPosList.begin(), aPosList.end(), lcl_LessXPos() );
+ rAlignment.mfLabelDirection = (fDeltaY < 0) ? -1.0 : 1.0;
+ }
+ else
+ {
+ rAlignment.meAlignment = LABEL_ALIGN_BOTTOM;
+ //choose most bottom positions
+ std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
+ rAlignment.mfLabelDirection = (fDeltaX < 0) ? -1.0 : 1.0;
+ }
+ ScreenPosAndLogicPos aBestPos( aPosList[0] );
+ fYStart = fYEnd = aBestPos.fLogicY;
+ fZStart = fZEnd = aBestPos.fLogicZ;
+ if( !m_pPosHelper->isMathematicalOrientationX() )
+ rAlignment.mfLabelDirection *= -1.0;
+ }
+ }//end 3D x axis
+ }
+ else if( m_nDimensionIndex==1 ) //y-axis
+ {
+ if( fCrossesOtherAxis < fMinX )
+ fCrossesOtherAxis = fMinX;
+ else if( fCrossesOtherAxis > fMaxX )
+ fCrossesOtherAxis = fMaxX;
+
+ fXStart = fXEnd = fCrossesOtherAxis;
+ fYEnd=m_pPosHelper->getLogicMaxY();
+
+ if(m_nDimension==3)
+ {
+ if( AxisHelper::isAxisPositioningEnabled() )
+ {
+ if( ::rtl::math::approxEqual( fXOther, fXStart) )
+ fZStart = fZEnd = fZOnZPlane;
+ else
+ fZStart = fZEnd = fZOther;
+ }
+ else
+ {
+ rStart = getScreenPosition( fXStart, fYStart, fZStart );
+ rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
+
+ double fDeltaX = rEnd.getX() - rStart.getX();
+ double fDeltaY = rEnd.getY() - rStart.getY();
+
+ //only those points are candidates which are lying on exactly one wall as these are outer edges
+ tScreenPosAndLogicPosList aPosList { getScreenPosAndLogicPos( fXOnXPlane, fMinY, fZOther ), getScreenPosAndLogicPos( fXOther, fMinY, fZOnZPlane ) };
+
+ if( fabs(fDeltaY) > fabs(fDeltaX) )
+ {
+ rAlignment.meAlignment = LABEL_ALIGN_LEFT;
+ //choose most left positions
+ std::sort( aPosList.begin(), aPosList.end(), lcl_LessXPos() );
+ rAlignment.mfLabelDirection = (fDeltaY < 0) ? -1.0 : 1.0;
+ }
+ else
+ {
+ rAlignment.meAlignment = LABEL_ALIGN_BOTTOM;
+ //choose most bottom positions
+ std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
+ rAlignment.mfLabelDirection = (fDeltaX < 0) ? -1.0 : 1.0;
+ }
+ ScreenPosAndLogicPos aBestPos( aPosList[0] );
+ fXStart = fXEnd = aBestPos.fLogicX;
+ fZStart = fZEnd = aBestPos.fLogicZ;
+ if( !m_pPosHelper->isMathematicalOrientationY() )
+ rAlignment.mfLabelDirection *= -1.0;
+ }
+ }//end 3D y axis
+ }
+ else //z-axis
+ {
+ fZEnd = m_pPosHelper->getLogicMaxZ();
+ if( AxisHelper::isAxisPositioningEnabled() )
+ {
+ if( !m_aAxisProperties.m_bSwapXAndY )
+ {
+ if( fCrossesOtherAxis < fMinY )
+ fCrossesOtherAxis = fMinY;
+ else if( fCrossesOtherAxis > fMaxY )
+ fCrossesOtherAxis = fMaxY;
+ fYStart = fYEnd = fCrossesOtherAxis;
+
+ if( ::rtl::math::approxEqual( fYOther, fYStart) )
+ fXStart = fXEnd = fXOnXPlane;
+ else
+ fXStart = fXEnd = fXOther;
+ }
+ else
+ {
+ if( fCrossesOtherAxis < fMinX )
+ fCrossesOtherAxis = fMinX;
+ else if( fCrossesOtherAxis > fMaxX )
+ fCrossesOtherAxis = fMaxX;
+ fXStart = fXEnd = fCrossesOtherAxis;
+
+ if( ::rtl::math::approxEqual( fXOther, fXStart) )
+ fYStart = fYEnd = fYOnYPlane;
+ else
+ fYStart = fYEnd = fYOther;
+ }
+ }
+ else
+ {
+ if( !m_pPosHelper->isSwapXAndY() )
+ {
+ fXStart = fXEnd = m_pPosHelper->isMathematicalOrientationX() ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMinX();
+ fYStart = fYEnd = m_pPosHelper->isMathematicalOrientationY() ? m_pPosHelper->getLogicMinY() : m_pPosHelper->getLogicMaxY();
+ }
+ else
+ {
+ fXStart = fXEnd = m_pPosHelper->isMathematicalOrientationX() ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMaxX();
+ fYStart = fYEnd = m_pPosHelper->isMathematicalOrientationY() ? m_pPosHelper->getLogicMaxY() : m_pPosHelper->getLogicMinY();
+ }
+
+ if(m_nDimension==3)
+ {
+ rStart = getScreenPosition( fXStart, fYStart, fZStart );
+ rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
+
+ double fDeltaX = rEnd.getX() - rStart.getX();
+
+ //only those points are candidates which are lying on exactly one wall as these are outer edges
+ tScreenPosAndLogicPosList aPosList { getScreenPosAndLogicPos( fXOther, fYOnYPlane, fMinZ ), getScreenPosAndLogicPos( fXOnXPlane, fYOther, fMinZ ) };
+
+ std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
+ ScreenPosAndLogicPos aBestPos( aPosList[0] );
+ ScreenPosAndLogicPos aNotSoGoodPos( aPosList[1] );
+
+ //choose most bottom positions
+ if( fDeltaX != 0.0 ) // prefer left-right alignments
+ {
+ if( aBestPos.aScreenPos.getX() > aNotSoGoodPos.aScreenPos.getX() )
+ rAlignment.meAlignment = LABEL_ALIGN_RIGHT;
+ else
+ rAlignment.meAlignment = LABEL_ALIGN_LEFT;
+ }
+ else
+ {
+ if( aBestPos.aScreenPos.getY() > aNotSoGoodPos.aScreenPos.getY() )
+ rAlignment.meAlignment = LABEL_ALIGN_BOTTOM;
+ else
+ rAlignment.meAlignment = LABEL_ALIGN_TOP;
+ }
+
+ rAlignment.mfLabelDirection = (fDeltaX < 0) ? -1.0 : 1.0;
+ if( !m_pPosHelper->isMathematicalOrientationZ() )
+ rAlignment.mfLabelDirection *= -1.0;
+
+ fXStart = fXEnd = aBestPos.fLogicX;
+ fYStart = fYEnd = aBestPos.fLogicY;
+ }
+ }//end 3D z axis
+ }
+
+ rStart = getScreenPosition( fXStart, fYStart, fZStart );
+ rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
+
+ if(m_nDimension==3 && !AxisHelper::isAxisPositioningEnabled() )
+ rAlignment.mfInnerTickDirection = rAlignment.mfLabelDirection;//to behave like before
+
+ if(!(m_nDimension==3 && AxisHelper::isAxisPositioningEnabled()) )
+ return;
+
+ double fDeltaX = rEnd.getX() - rStart.getX();
+ double fDeltaY = rEnd.getY() - rStart.getY();
+
+ if( m_nDimensionIndex==2 )
+ {
+ if( m_eLeftWallPos != CuboidPlanePosition_Left )
+ {
+ rAlignment.mfLabelDirection *= -1.0;
+ rAlignment.mfInnerTickDirection *= -1.0;
+ }
+
+ rAlignment.meAlignment =
+ (rAlignment.mfLabelDirection < 0) ?
+ LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+
+ if( ( fDeltaY<0 && m_aScale.Orientation == chart2::AxisOrientation_REVERSE ) ||
+ ( fDeltaY>0 && m_aScale.Orientation == chart2::AxisOrientation_MATHEMATICAL ) )
+ rAlignment.meAlignment =
+ (rAlignment.meAlignment == LABEL_ALIGN_RIGHT) ?
+ LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+ }
+ else if( fabs(fDeltaY) > fabs(fDeltaX) )
+ {
+ if( m_eBackWallPos != CuboidPlanePosition_Back )
+ {
+ rAlignment.mfLabelDirection *= -1.0;
+ rAlignment.mfInnerTickDirection *= -1.0;
+ }
+
+ rAlignment.meAlignment =
+ (rAlignment.mfLabelDirection < 0) ?
+ LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+
+ if( ( fDeltaY<0 && m_aScale.Orientation == chart2::AxisOrientation_REVERSE ) ||
+ ( fDeltaY>0 && m_aScale.Orientation == chart2::AxisOrientation_MATHEMATICAL ) )
+ rAlignment.meAlignment =
+ (rAlignment.meAlignment == LABEL_ALIGN_RIGHT) ?
+ LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+ }
+ else
+ {
+ if( m_eBackWallPos != CuboidPlanePosition_Back )
+ {
+ rAlignment.mfLabelDirection *= -1.0;
+ rAlignment.mfInnerTickDirection *= -1.0;
+ }
+
+ rAlignment.meAlignment =
+ (rAlignment.mfLabelDirection < 0) ?
+ LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
+
+ if( ( fDeltaX>0 && m_aScale.Orientation == chart2::AxisOrientation_REVERSE ) ||
+ ( fDeltaX<0 && m_aScale.Orientation == chart2::AxisOrientation_MATHEMATICAL ) )
+ rAlignment.meAlignment =
+ (rAlignment.meAlignment == LABEL_ALIGN_TOP) ?
+ LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
+ }
+}
+
+TickFactory* VCartesianAxis::createTickFactory()
+{
+ return createTickFactory2D();
+}
+
+TickFactory2D* VCartesianAxis::createTickFactory2D()
+{
+ AxisLabelAlignment aLabelAlign = m_aAxisProperties.maLabelAlignment;
+ B2DVector aStart, aEnd;
+ get2DAxisMainLine(aStart, aEnd, aLabelAlign, getAxisIntersectionValue());
+
+ B2DVector aLabelLineStart, aLabelLineEnd;
+ get2DAxisMainLine(aLabelLineStart, aLabelLineEnd, aLabelAlign, getLabelLineIntersectionValue());
+ m_aAxisProperties.maLabelAlignment = aLabelAlign;
+
+ return new TickFactory2D( m_aScale, m_aIncrement, aStart, aEnd, aLabelLineStart-aStart );
+}
+
+static void lcl_hideIdenticalScreenValues( TickIter& rTickIter )
+{
+ TickInfo* pPrevTickInfo = rTickIter.firstInfo();
+ if (!pPrevTickInfo)
+ return;
+
+ pPrevTickInfo->bPaintIt = true;
+ for( TickInfo* pTickInfo = rTickIter.nextInfo(); pTickInfo; pTickInfo = rTickIter.nextInfo())
+ {
+ pTickInfo->bPaintIt = (pTickInfo->aTickScreenPosition != pPrevTickInfo->aTickScreenPosition);
+ pPrevTickInfo = pTickInfo;
+ }
+}
+
+//'hide' tickmarks with identical screen values in aAllTickInfos
+void VCartesianAxis::hideIdenticalScreenValues( TickInfoArraysType& rTickInfos ) const
+{
+ if( isComplexCategoryAxis() || isDateAxis() )
+ {
+ sal_Int32 nCount = rTickInfos.size();
+ for( sal_Int32 nN=0; nN<nCount; nN++ )
+ {
+ PureTickIter aTickIter( rTickInfos[nN] );
+ lcl_hideIdenticalScreenValues( aTickIter );
+ }
+ }
+ else
+ {
+ EquidistantTickIter aTickIter( rTickInfos, m_aIncrement, -1 );
+ lcl_hideIdenticalScreenValues( aTickIter );
+ }
+}
+
+sal_Int32 VCartesianAxis::estimateMaximumAutoMainIncrementCount()
+{
+ sal_Int32 nRet = 10;
+
+ if( m_nMaximumTextWidthSoFar==0 && m_nMaximumTextHeightSoFar==0 )
+ return nRet;
+
+ B2DVector aStart, aEnd;
+ AxisLabelAlignment aLabelAlign = m_aAxisProperties.maLabelAlignment;
+ get2DAxisMainLine(aStart, aEnd, aLabelAlign, getAxisIntersectionValue());
+ m_aAxisProperties.maLabelAlignment = aLabelAlign;
+
+ sal_Int32 nMaxHeight = static_cast<sal_Int32>(fabs(aEnd.getY()-aStart.getY()));
+ sal_Int32 nMaxWidth = static_cast<sal_Int32>(fabs(aEnd.getX()-aStart.getX()));
+
+ sal_Int32 nTotalAvailable = nMaxHeight;
+ sal_Int32 nSingleNeeded = m_nMaximumTextHeightSoFar;
+ sal_Int32 nMaxSameLabel = 0;
+
+ // tdf#48041: do not duplicate the value labels because of rounding
+ if (m_aAxisProperties.m_nAxisType != css::chart2::AxisType::DATE)
+ {
+ FixedNumberFormatter aFixedNumberFormatterTest(m_xNumberFormatsSupplier, m_aAxisLabelProperties.m_nNumberFormatKey);
+ OUString sPreviousValueLabel;
+ sal_Int32 nSameLabel = 0;
+ for (auto const & nLabel: m_aAllTickInfos[0])
+ {
+ Color nColor = COL_AUTO;
+ bool bHasColor = false;
+ OUString sValueLabel = aFixedNumberFormatterTest.getFormattedString(nLabel.fScaledTickValue, nColor, bHasColor);
+ if (sValueLabel == sPreviousValueLabel)
+ {
+ nSameLabel++;
+ if (nSameLabel > nMaxSameLabel)
+ nMaxSameLabel = nSameLabel;
+ }
+ else
+ nSameLabel = 0;
+ sPreviousValueLabel = sValueLabel;
+ }
+ }
+ //for horizontal axis:
+ if( (m_nDimensionIndex == 0 && !m_aAxisProperties.m_bSwapXAndY)
+ || (m_nDimensionIndex == 1 && m_aAxisProperties.m_bSwapXAndY) )
+ {
+ nTotalAvailable = nMaxWidth;
+ nSingleNeeded = m_nMaximumTextWidthSoFar;
+ }
+
+ if( nSingleNeeded>0 )
+ nRet = nTotalAvailable/nSingleNeeded;
+
+ if ( nMaxSameLabel > 0 )
+ {
+ sal_Int32 nRetNoSameLabel = m_aAllTickInfos[0].size() / (nMaxSameLabel + 1);
+ if ( nRet > nRetNoSameLabel )
+ nRet = nRetNoSameLabel;
+ }
+
+ return nRet;
+}
+
+void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties, TickFactory2D const * pTickFactory2D )
+{
+ if( !pTickFactory2D )
+ return;
+
+ if( isComplexCategoryAxis() )
+ {
+ sal_Int32 nTextLevelCount = getTextLevelCount();
+ B2DVector aCumulatedLabelsDistance(0,0);
+ for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
+ {
+ std::unique_ptr<TickIter> apTickIter(createLabelTickIterator(nTextLevel));
+ if (apTickIter)
+ {
+ double fRotationAngleDegree = m_aAxisLabelProperties.m_fRotationAngleDegree;
+ if( nTextLevel>0 )
+ {
+ lcl_shiftLabels(*apTickIter, aCumulatedLabelsDistance);
+ //multilevel labels: 0 or 90 by default
+ if( m_aAxisProperties.m_bSwapXAndY )
+ fRotationAngleDegree = 90.0;
+ else
+ fRotationAngleDegree = 0.0;
+ }
+ aCumulatedLabelsDistance += lcl_getLabelsDistance(
+ *apTickIter, pTickFactory2D->getDistanceAxisTickToText(m_aAxisProperties),
+ fRotationAngleDegree);
+ }
+ }
+ }
+ else if (rAxisLabelProperties.isStaggered())
+ {
+ if( !m_aAllTickInfos.empty() )
+ {
+ LabelIterator aInnerIter( m_aAllTickInfos[0], rAxisLabelProperties.m_eStaggering, true );
+ LabelIterator aOuterIter( m_aAllTickInfos[0], rAxisLabelProperties.m_eStaggering, false );
+
+ lcl_shiftLabels( aOuterIter
+ , lcl_getLabelsDistance( aInnerIter
+ , pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties ), 0.0 ) );
+ }
+ }
+}
+
+void VCartesianAxis::createDataTableShape(std::unique_ptr<TickFactory2D> const& rpTickFactory2D)
+{
+ // Check if we can create the data table shape
+ // Data table view and m_bDisplayDataTable must be true
+ if (!m_pDataTableView || !m_aAxisProperties.m_bDisplayDataTable)
+ return;
+
+ m_pDataTableView->initializeShapes(m_xDataTableTarget);
+ basegfx::B2DVector aStart = rpTickFactory2D->getXaxisStartPos();
+ basegfx::B2DVector aEnd = rpTickFactory2D->getXaxisEndPos();
+
+ rpTickFactory2D->updateScreenValues(m_aAllTickInfos);
+
+ sal_Int32 nDistance = -1;
+
+ std::unique_ptr<TickIter> apTickIter(createLabelTickIterator(0));
+ if (apTickIter)
+ {
+ nDistance = TickFactory2D::getTickScreenDistance(*apTickIter);
+ if (getTextLevelCount() > 1)
+ nDistance *= 2;
+ }
+
+ if (nDistance > 0)
+ {
+ m_pDataTableView->createShapes(aStart, aEnd, nDistance);
+ }
+}
+
+void VCartesianAxis::createLabels()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ std::unique_ptr<TickFactory2D> apTickFactory2D(createTickFactory2D()); // throws on failure
+
+ createDataTableShape(apTickFactory2D);
+
+ //create labels
+ if (!m_aAxisProperties.m_bDisplayLabels)
+ return;
+
+ TickFactory2D* pTickFactory2D = apTickFactory2D.get();
+
+ //get the transformed screen values for all tickmarks in aAllTickInfos
+ pTickFactory2D->updateScreenValues( m_aAllTickInfos );
+ //'hide' tickmarks with identical screen values in aAllTickInfos
+ hideIdenticalScreenValues( m_aAllTickInfos );
+
+ removeTextShapesFromTicks();
+
+ //create tick mark text shapes
+ sal_Int32 nTextLevelCount = getTextLevelCount();
+ sal_Int32 nScreenDistanceBetweenTicks = -1;
+ for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
+ {
+ std::unique_ptr< TickIter > apTickIter(createLabelTickIterator( nTextLevel ));
+ if(apTickIter)
+ {
+ if(nTextLevel==0)
+ {
+ nScreenDistanceBetweenTicks = TickFactory2D::getTickScreenDistance(*apTickIter);
+ if( nTextLevelCount>1 )
+ nScreenDistanceBetweenTicks*=2; //the above used tick iter does contain also the sub ticks -> thus the given distance is only the half
+ }
+
+ AxisLabelProperties aComplexProps(m_aAxisLabelProperties);
+ if( m_aAxisProperties.m_bComplexCategories )
+ {
+ aComplexProps.m_bLineBreakAllowed = true;
+ aComplexProps.m_bOverlapAllowed = aComplexProps.m_fRotationAngleDegree != 0.0;
+ if( nTextLevel > 0 )
+ {
+ //multilevel labels: 0 or 90 by default
+ if( m_aAxisProperties.m_bSwapXAndY )
+ aComplexProps.m_fRotationAngleDegree = 90.0;
+ else
+ aComplexProps.m_fRotationAngleDegree = 0.0;
+ }
+ }
+ AxisLabelProperties& rAxisLabelProperties = m_aAxisProperties.m_bComplexCategories ? aComplexProps : m_aAxisLabelProperties;
+ while (!createTextShapes(m_xTextTarget, *apTickIter, rAxisLabelProperties,
+ pTickFactory2D, nScreenDistanceBetweenTicks))
+ {
+ };
+ }
+ }
+ doStaggeringOfLabels( m_aAxisLabelProperties, pTickFactory2D );
+
+ if (m_pDataTableView)
+ {
+ sal_Int32 x = m_xTextTarget->getPosition().X;
+ sal_Int32 y = m_xTextTarget->getPosition().Y;
+ sal_Int32 height = m_xTextTarget->getSize().Height;
+ m_pDataTableView->changePosition(x, y + height);
+ }
+}
+
+void VCartesianAxis::createMaximumLabels()
+{
+ m_bRecordMaximumTextSize = true;
+ const comphelper::ScopeGuard aGuard([this]() { m_bRecordMaximumTextSize = false; });
+
+ if( !prepareShapeCreation() )
+ return;
+
+ //create labels
+ if (!m_aAxisProperties.m_bDisplayLabels)
+ return;
+
+ std::unique_ptr<TickFactory2D> apTickFactory2D(createTickFactory2D()); // throws on failure
+ TickFactory2D* pTickFactory2D = apTickFactory2D.get();
+
+ //get the transformed screen values for all tickmarks in aAllTickInfos
+ pTickFactory2D->updateScreenValues( m_aAllTickInfos );
+
+ //create tick mark text shapes
+ //@todo: iterate through all tick depth which should be labeled
+
+ AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties );
+ if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickFactory2D->isHorizontalAxis(), pTickFactory2D->isVerticalAxis() ) )
+ aAxisLabelProperties.m_eStaggering = AxisLabelStaggering::StaggerEven;
+
+ aAxisLabelProperties.m_bOverlapAllowed = true;
+ aAxisLabelProperties.m_bLineBreakAllowed = false;
+ sal_Int32 nTextLevelCount = getTextLevelCount();
+ for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
+ {
+ std::unique_ptr< TickIter > apTickIter(createMaximumLabelTickIterator( nTextLevel ));
+ if(apTickIter)
+ {
+ while (!createTextShapes(m_xTextTarget, *apTickIter, aAxisLabelProperties,
+ pTickFactory2D, -1))
+ {
+ };
+ }
+ }
+ doStaggeringOfLabels( aAxisLabelProperties, pTickFactory2D );
+}
+
+void VCartesianAxis::updatePositions()
+{
+ //update positions of labels
+ if (!m_aAxisProperties.m_bDisplayLabels)
+ return;
+
+ std::unique_ptr<TickFactory2D> apTickFactory2D(createTickFactory2D()); // throws on failure
+ TickFactory2D* pTickFactory2D = apTickFactory2D.get();
+
+ //update positions of all existing text shapes
+ pTickFactory2D->updateScreenValues( m_aAllTickInfos );
+
+ sal_Int32 nDepth=0;
+ for (auto const& tickInfos : m_aAllTickInfos)
+ {
+ for (auto const& tickInfo : tickInfos)
+ {
+ const rtl::Reference<SvxShapeText> & xShape2DText(tickInfo.xTextShape);
+ if( xShape2DText.is() )
+ {
+ B2DVector aTextToTickDistance( pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, true ) );
+ B2DVector aTickScreenPos2D(tickInfo.aTickScreenPosition);
+ aTickScreenPos2D += aTextToTickDistance;
+ awt::Point aAnchorScreenPosition2D(
+ static_cast<sal_Int32>(aTickScreenPos2D.getX())
+ ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
+
+ double fRotationAngleDegree = m_aAxisLabelProperties.m_fRotationAngleDegree;
+ if( nDepth > 0 )
+ {
+ //multilevel labels: 0 or 90 by default
+ if( pTickFactory2D->isHorizontalAxis() )
+ fRotationAngleDegree = 0.0;
+ else
+ fRotationAngleDegree = 90;
+ }
+
+ // #i78696# use mathematically correct rotation now
+ const double fRotationAnglePi(-basegfx::deg2rad(fRotationAngleDegree));
+ uno::Any aATransformation = ShapeFactory::makeTransformation(aAnchorScreenPosition2D, fRotationAnglePi);
+
+ //set new position
+ try
+ {
+ xShape2DText->SvxShape::setPropertyValue( "Transformation", aATransformation );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ //correctPositionForRotation
+ LabelPositionHelper::correctPositionForRotation( xShape2DText
+ , m_aAxisProperties.maLabelAlignment.meAlignment, fRotationAngleDegree, m_aAxisProperties.m_bComplexCategories );
+ }
+ }
+ ++nDepth;
+ }
+
+ doStaggeringOfLabels( m_aAxisLabelProperties, pTickFactory2D );
+}
+
+void VCartesianAxis::createTickMarkLineShapes( TickInfoArrayType& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickFactory2D const & rTickFactory2D, bool bOnlyAtLabels )
+{
+ sal_Int32 nPointCount = rTickInfos.size();
+ drawing::PointSequenceSequence aPoints(2*nPointCount);
+
+ sal_Int32 nN = 0;
+ for (auto const& tickInfo : rTickInfos)
+ {
+ if( !tickInfo.bPaintIt )
+ continue;
+
+ bool bTicksAtLabels = ( m_aAxisProperties.m_eTickmarkPos != css::chart::ChartAxisMarkPosition_AT_AXIS );
+ double fInnerDirectionSign = m_aAxisProperties.maLabelAlignment.mfInnerTickDirection;
+ if( bTicksAtLabels && m_aAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_END )
+ fInnerDirectionSign *= -1.0;
+ bTicksAtLabels = bTicksAtLabels || bOnlyAtLabels;
+ //add ticks at labels:
+ rTickFactory2D.addPointSequenceForTickLine( aPoints, nN++, tickInfo.fScaledTickValue
+ , fInnerDirectionSign , rTickmarkProperties, bTicksAtLabels );
+ //add ticks at axis (without labels):
+ if( !bOnlyAtLabels && m_aAxisProperties.m_eTickmarkPos == css::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS )
+ rTickFactory2D.addPointSequenceForTickLine( aPoints, nN++, tickInfo.fScaledTickValue
+ , m_aAxisProperties.maLabelAlignment.mfInnerTickDirection, rTickmarkProperties, !bTicksAtLabels );
+ }
+ aPoints.realloc(nN);
+ ShapeFactory::createLine2D( m_xGroupShape_Shapes, aPoints
+ , &rTickmarkProperties.aLineProperties );
+}
+
+void VCartesianAxis::createShapes()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ //create line shapes
+ if(m_nDimension==2)
+ {
+ std::unique_ptr<TickFactory2D> apTickFactory2D(createTickFactory2D()); // throws on failure
+ TickFactory2D* pTickFactory2D = apTickFactory2D.get();
+
+ //create extra long ticks to separate complex categories (create them only there where the labels are)
+ if( isComplexCategoryAxis() )
+ {
+ TickInfoArraysType aComplexTickInfos;
+ createAllTickInfosFromComplexCategories( aComplexTickInfos, true );
+ pTickFactory2D->updateScreenValues( aComplexTickInfos );
+ hideIdenticalScreenValues( aComplexTickInfos );
+
+ std::vector<TickmarkProperties> aTickmarkPropertiesList;
+ static const bool bIncludeSpaceBetweenTickAndText = false;
+ sal_Int32 nOffset = static_cast<sal_Int32>(pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, false, bIncludeSpaceBetweenTickAndText ).getLength());
+ sal_Int32 nTextLevelCount = getTextLevelCount();
+ for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
+ {
+ std::unique_ptr< TickIter > apTickIter(createLabelTickIterator( nTextLevel ));
+ if( apTickIter )
+ {
+ double fRotationAngleDegree = m_aAxisLabelProperties.m_fRotationAngleDegree;
+ if( nTextLevel > 0 )
+ {
+ //Multi-level Labels: default to 0 or 90
+ if( m_aAxisProperties.m_bSwapXAndY )
+ fRotationAngleDegree = 90.0;
+ else
+ fRotationAngleDegree = 0.0;
+ }
+ B2DVector aLabelsDistance(lcl_getLabelsDistance(
+ *apTickIter, pTickFactory2D->getDistanceAxisTickToText(m_aAxisProperties),
+ fRotationAngleDegree));
+ sal_Int32 nCurrentLength = static_cast<sal_Int32>(aLabelsDistance.getLength());
+ aTickmarkPropertiesList.push_back( m_aAxisProperties.makeTickmarkPropertiesForComplexCategories( nOffset + nCurrentLength, 0 ) );
+ nOffset += nCurrentLength;
+ }
+ }
+
+ sal_Int32 nTickmarkPropertiesCount = aTickmarkPropertiesList.size();
+ TickInfoArraysType::iterator aDepthIter = aComplexTickInfos.begin();
+ const TickInfoArraysType::const_iterator aDepthEnd = aComplexTickInfos.end();
+ for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; ++aDepthIter, nDepth++ )
+ {
+ if(nDepth==0 && !m_aAxisProperties.m_nMajorTickmarks)
+ continue;
+ createTickMarkLineShapes( *aDepthIter, aTickmarkPropertiesList[nDepth], *pTickFactory2D, true /*bOnlyAtLabels*/ );
+ }
+ }
+ //create normal ticks for major and minor intervals
+ {
+ TickInfoArraysType aUnshiftedTickInfos;
+ if( m_aScale.m_bShiftedCategoryPosition )// if m_bShiftedCategoryPosition==true the tickmarks in m_aAllTickInfos are shifted
+ {
+ pTickFactory2D->getAllTicks( aUnshiftedTickInfos );
+ pTickFactory2D->updateScreenValues( aUnshiftedTickInfos );
+ hideIdenticalScreenValues( aUnshiftedTickInfos );
+ }
+ TickInfoArraysType& rAllTickInfos = m_aScale.m_bShiftedCategoryPosition ? aUnshiftedTickInfos : m_aAllTickInfos;
+
+ if (rAllTickInfos.empty())
+ return;
+
+ sal_Int32 nDepth = 0;
+ sal_Int32 nTickmarkPropertiesCount = m_aAxisProperties.m_aTickmarkPropertiesList.size();
+ for( auto& rTickInfos : rAllTickInfos )
+ {
+ if (nDepth == nTickmarkPropertiesCount)
+ break;
+
+ createTickMarkLineShapes( rTickInfos, m_aAxisProperties.m_aTickmarkPropertiesList[nDepth], *pTickFactory2D, false /*bOnlyAtLabels*/ );
+ nDepth++;
+ }
+ }
+ //create axis main lines
+ //it serves also as the handle shape for the axis selection
+ {
+ drawing::PointSequenceSequence aPoints(1);
+ apTickFactory2D->createPointSequenceForAxisMainLine( aPoints );
+ rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D(
+ m_xGroupShape_Shapes, aPoints
+ , &m_aAxisProperties.m_aLineProperties );
+ //because of this name this line will be used for marking the axis
+ ::chart::ShapeFactory::setShapeName( xShape, "MarkHandles" );
+ }
+ //create an additional line at NULL
+ if( !AxisHelper::isAxisPositioningEnabled() )
+ {
+ double fExtraLineCrossesOtherAxis = getExtraLineIntersectionValue();
+ if (!std::isnan(fExtraLineCrossesOtherAxis))
+ {
+ B2DVector aStart, aEnd;
+ AxisLabelAlignment aLabelAlign = m_aAxisProperties.maLabelAlignment;
+ get2DAxisMainLine(aStart, aEnd, aLabelAlign, fExtraLineCrossesOtherAxis);
+ m_aAxisProperties.maLabelAlignment = aLabelAlign;
+ drawing::PointSequenceSequence aPoints{{
+ {static_cast<sal_Int32>(aStart.getX()), static_cast<sal_Int32>(aStart.getY())},
+ {static_cast<sal_Int32>(aEnd.getX()), static_cast<sal_Int32>(aEnd.getY())} }};
+ ShapeFactory::createLine2D(
+ m_xGroupShape_Shapes, aPoints, &m_aAxisProperties.m_aLineProperties );
+ }
+ }
+ }
+
+ createLabels();
+}
+
+void VCartesianAxis::createDataTableView(std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList,
+ Reference<util::XNumberFormatsSupplier> const& xNumberFormatsSupplier,
+ rtl::Reference<::chart::ChartModel> const& xChartDoc,
+ css::uno::Reference<css::uno::XComponentContext> const& rComponentContext)
+{
+ if (!m_aAxisProperties.m_bDisplayDataTable)
+ return;
+
+ m_pDataTableView.reset(new DataTableView(xChartDoc, m_aAxisProperties.m_xDataTableModel, rComponentContext, m_aAxisProperties.m_bDataTableAlignAxisValuesWithColumns));
+ m_pDataTableView->initializeValues(rSeriesPlotterList);
+ m_xNumberFormatsSupplier = xNumberFormatsSupplier;
+}
+
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VCartesianAxis.hxx b/chart2/source/view/axes/VCartesianAxis.hxx
new file mode 100644
index 0000000000..210f36dd48
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianAxis.hxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "VAxisBase.hxx"
+#include <basegfx/vector/b2dvector.hxx>
+
+namespace chart
+{
+class VCartesianAxis : public VAxisBase
+{
+ // public methods
+public:
+ VCartesianAxis( const AxisProperties& rAxisProperties
+ , const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , PlottingPositionHelper* pPosHelper = nullptr //takes ownership
+ );
+
+ virtual ~VCartesianAxis() override;
+
+ virtual void createMaximumLabels() override;
+ virtual void createLabels() override;
+ virtual void updatePositions() override;
+
+ virtual void createShapes() override;
+
+ virtual sal_Int32 estimateMaximumAutoMainIncrementCount() override;
+ virtual void createAllTickInfos( TickInfoArraysType& rAllTickInfos ) override;
+ void createAllTickInfosFromComplexCategories( TickInfoArraysType& rAllTickInfos, bool bShiftedPosition );
+
+ TickIter* createLabelTickIterator( sal_Int32 nTextLevel );
+ TickIter* createMaximumLabelTickIterator( sal_Int32 nTextLevel );
+ sal_Int32 getTextLevelCount() const;
+
+ virtual TickFactory* createTickFactory() override;
+
+ /**
+ * Get the value at which the other axis crosses.
+ */
+ double getAxisIntersectionValue() const;
+
+ /**
+ * Get the value at which label line crosses the other axis.
+ */
+ double getLabelLineIntersectionValue() const;
+
+ /**
+ * Get the value at which extra line crosses the other axis.
+ *
+ * @return a NaN if the line doesn't cross the other axis, a non-NaN value
+ * otherwise.
+ */
+ double getExtraLineIntersectionValue() const;
+
+ void get2DAxisMainLine(
+ basegfx::B2DVector& rStart, basegfx::B2DVector& rEnd, AxisLabelAlignment& rLabelAlignment,
+ double fCrossesOtherAxis ) const;
+
+ //Layout interface for cartesian axes:
+
+ //the returned value describes the minimum size that is necessary
+ //for the text labels in the direction orthogonal to the axis
+ //(for an y-axis a width is returned; in case of an x-axis the value describes a height)
+ //the return value is measured in screen dimension
+ //As an example the MinimumOrthogonalSize of an x-axis equals the
+ //Font Height if the label properties allow for labels parallel to the axis.
+// sal_Int32 calculateMinimumOrthogonalSize( /*... parallel...*/ );
+ //Minimum->Preferred
+
+ //returns true if the MinimumOrthogonalSize can be calculated
+ //with the creation of at most one text shape
+ //(this is e.g. true if the parameters allow for labels parallel to the axis.)
+// sal_bool canQuicklyCalculateMinimumOrthogonalSize();
+
+ struct ScreenPosAndLogicPos
+ {
+ double fLogicX;
+ double fLogicY;
+ double fLogicZ;
+
+ ::basegfx::B2DVector aScreenPos;
+ };
+
+ void createDataTableView(std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList,
+ css::uno::Reference<css::util::XNumberFormatsSupplier> const& xNumberFormatsSupplier,
+ rtl::Reference<::chart::ChartModel> const& xChartDoc,
+ css::uno::Reference<css::uno::XComponentContext> const& rComponentContext) override;
+private: //methods
+ /**
+ * Go through all tick label positions and decide which labels to display
+ * based on the text shape geometry, overlap setting, tick interval,
+ * auto-stagger setting etc.
+ *
+ * When the auto-stagger setting is on, try to avoid overlaps by
+ * staggering labels or set the labels at an angle. This method may
+ * change the axis label properties especially when the auto staggering is
+ * performed. But the screen label positions will not be shifted in this
+ * method; it will be done in the doStaggeringOfLabels method.
+ *
+ * @return true if the text shapes have been successfully created,
+ * otherwise false. Returning false means the AxisLabelProperties
+ * have changed during the call, and the caller needs to call this
+ * method once again to get the text shapes created.
+ */
+ bool createTextShapes(
+ const rtl::Reference< SvxShapeGroupAnyD >& xTarget,
+ TickIter& rTickIter, AxisLabelProperties& rAxisLabelProperties,
+ TickFactory2D const * pTickFactory, sal_Int32 nScreenDistanceBetweenTicks );
+
+ /**
+ * Variant of createTextShapes where none of auto-staggering and
+ * link-breaking are allowed in case of overlaps. Overlaps of text shapes
+ * are to be resolved only by adjusting the label tick interval.
+ */
+ bool createTextShapesSimple(
+ const rtl::Reference< SvxShapeGroupAnyD >& xTarget,
+ TickIter& rTickIter, AxisLabelProperties& rAxisLabelProperties,
+ TickFactory2D const * pTickFactory );
+
+ void createTickMarkLineShapes( TickInfoArrayType& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickFactory2D const & rTickFactory2D, bool bOnlyAtLabels );
+
+ TickFactory2D* createTickFactory2D();
+ void hideIdenticalScreenValues( TickInfoArraysType& rTickInfos ) const;
+
+ /**
+ * Shift the screen positions of the tick labels according to the stagger
+ * settings. Final stagger setting is decided during the createTextShapes
+ * call, but this method does the physical shifting of the label
+ * positions based on the final stagger setting.
+ */
+ void doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties
+ , TickFactory2D const * pTickFactory2D );
+
+ /**
+ * @return true if we can break a single line label text into multiple
+ * lines for better fitting, otherwise false.
+ */
+ bool isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis, bool bIsVerticalAxis ) const;
+
+ ::basegfx::B2DVector getScreenPosition( double fLogicX, double fLogicY, double fLogicZ ) const;
+ ScreenPosAndLogicPos getScreenPosAndLogicPos( double fLogicX, double fLogicY, double fLogicZ ) const;
+
+ void createDataTableShape(std::unique_ptr<TickFactory2D> const& rTickFactory2D);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VCartesianCoordinateSystem.cxx b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx
new file mode 100644
index 0000000000..81fa369c2f
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianCoordinateSystem.cxx
@@ -0,0 +1,222 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VCartesianCoordinateSystem.hxx"
+#include "VCartesianGrid.hxx"
+#include "VCartesianAxis.hxx"
+#include <BaseCoordinateSystem.hxx>
+#include <AxisIndexDefines.hxx>
+#include <Axis.hxx>
+#include <DataTable.hxx>
+#include <Diagram.hxx>
+#include <AxisHelper.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <ChartModel.hxx>
+#include <GridProperties.hxx>
+#include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+namespace {
+
+class TextualDataProvider : public ::cppu::WeakImplHelper<
+ css::chart2::data::XTextualDataSequence
+ >
+{
+public:
+ explicit TextualDataProvider( const uno::Sequence< OUString >& rTextSequence )
+ : m_aTextSequence( rTextSequence )
+ {
+ }
+
+ //XTextualDataSequence
+ virtual uno::Sequence< OUString > SAL_CALL getTextualData() override
+ {
+ return m_aTextSequence;
+ }
+
+private: //member
+ uno::Sequence< OUString > m_aTextSequence;
+};
+
+}
+
+VCartesianCoordinateSystem::VCartesianCoordinateSystem( const rtl::Reference< BaseCoordinateSystem >& xCooSys )
+ : VCoordinateSystem(xCooSys)
+{
+}
+
+VCartesianCoordinateSystem::~VCartesianCoordinateSystem()
+{
+}
+
+void VCartesianCoordinateSystem::createGridShapes()
+{
+ if(!m_xLogicTargetForGrids.is() || !m_xFinalTarget.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = getPropertySwapXAndYAxis();
+
+ for( sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
+ {
+ sal_Int32 nAxisIndex = MAIN_AXIS_INDEX;
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, nAxisIndex, m_xCooSysModel );
+ if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel ))
+ continue;
+
+ VCartesianGrid aGrid(nDimensionIndex,nDimensionCount, getGridListFromAxis( xAxis ));
+ aGrid.setExplicitScaleAndIncrement( getExplicitScale(nDimensionIndex,nAxisIndex)
+ , getExplicitIncrement(nDimensionIndex,nAxisIndex) );
+ aGrid.set3DWallPositions( m_eLeftWallPos, m_eBackWallPos, m_eBottomPos );
+
+ aGrid.initPlotter(m_xLogicTargetForGrids,m_xFinalTarget
+ , createCIDForGrid( nDimensionIndex,nAxisIndex ) );
+ if(nDimensionCount==2)
+ aGrid.setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ aGrid.setScales( getExplicitScales(nDimensionIndex,nAxisIndex), bSwapXAndY );
+ aGrid.createShapes();
+ }
+}
+
+void VCartesianCoordinateSystem::createVAxisList(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc,
+ const awt::Size& rFontReferenceSize,
+ const awt::Rectangle& rMaximumSpaceForLabels,
+ bool bLimitSpaceForLabels,
+ std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList,
+ uno::Reference<uno::XComponentContext> const& rComponentContext)
+{
+ // note: using xChartDoc itself as XNumberFormatsSupplier would cause
+ // a leak from VCartesianAxis due to cyclic reference
+ uno::Reference<util::XNumberFormatsSupplier> const xNumberFormatsSupplier(
+ xChartDoc->getNumberFormatsSupplier());
+
+ m_aAxisMap.clear();
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = getPropertySwapXAndYAxis();
+
+ if(nDimensionCount<=0)
+ return;
+
+ sal_Int32 nDimensionIndex = 0;
+
+ // dimension index -> x, y or z axis.
+ for( nDimensionIndex = 0; nDimensionIndex < nDimensionCount; nDimensionIndex++ )
+ {
+ // axis index -> primary or secondary axis.
+ sal_Int32 nMaxAxisIndex = m_xCooSysModel->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ )
+ {
+ rtl::Reference< Axis > xAxis = getAxisByDimension(nDimensionIndex,nAxisIndex);
+ if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel ))
+ continue;
+
+ rtl::Reference<Diagram> xDiagram(xChartDoc->getFirstChartDiagram());
+ AxisProperties aAxisProperties(xAxis, getExplicitCategoriesProvider(), xDiagram->getDataTableRef());
+ aAxisProperties.m_nDimensionIndex = nDimensionIndex;
+ aAxisProperties.m_bSwapXAndY = bSwapXAndY;
+ aAxisProperties.m_bIsMainAxis = (nAxisIndex==0);
+ aAxisProperties.m_bLimitSpaceForLabels = bLimitSpaceForLabels;
+ rtl::Reference< Axis > xCrossingMainAxis = AxisHelper::getCrossingMainAxis( xAxis, m_xCooSysModel );
+ if( xCrossingMainAxis.is() )
+ {
+ ScaleData aCrossingScale( xCrossingMainAxis->getScaleData() );
+ aAxisProperties.m_bCrossingAxisHasReverseDirection = (aCrossingScale.Orientation==AxisOrientation_REVERSE);
+
+ if( aCrossingScale.AxisType == AxisType::CATEGORY )
+ aAxisProperties.m_bCrossingAxisIsCategoryAxes = true;
+ }
+
+ if( nDimensionIndex == 2 )
+ {
+ aAxisProperties.m_xAxisTextProvider = new TextualDataProvider( m_aSeriesNamesForZAxis );
+
+ //for the z axis copy the positioning properties from the x axis (or from the y axis for swapped coordinate systems)
+ rtl::Reference< Axis > xSisterAxis = AxisHelper::getCrossingMainAxis( xCrossingMainAxis, m_xCooSysModel );
+ aAxisProperties.initAxisPositioning( xSisterAxis );
+ }
+ aAxisProperties.init(true);
+ if(aAxisProperties.m_bDisplayLabels)
+ aAxisProperties.m_nNumberFormatKey = getNumberFormatKeyForAxis(xAxis, xChartDoc);
+
+ auto apVAxis = std::make_shared<VCartesianAxis>(aAxisProperties,xNumberFormatsSupplier,nDimensionIndex,nDimensionCount);
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ m_aAxisMap[aFullAxisIndex] = apVAxis;
+ apVAxis->set3DWallPositions( m_eLeftWallPos, m_eBackWallPos, m_eBottomPos );
+
+ apVAxis->initAxisLabelProperties(rFontReferenceSize,rMaximumSpaceForLabels);
+ apVAxis->createDataTableView(rSeriesPlotterList, xNumberFormatsSupplier, xChartDoc, rComponentContext);
+ }
+ }
+}
+
+void VCartesianCoordinateSystem::initVAxisInList()
+{
+ if(!m_xLogicTargetForAxes.is() || !m_xFinalTarget.is() || !m_xCooSysModel.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = getPropertySwapXAndYAxis();
+
+ for (auto const& [nIndexPair, pVAxis] : m_aAxisMap)
+ {
+ if (pVAxis)
+ {
+ auto [nDimensionIndex, nAxisIndex] = nIndexPair;
+ pVAxis->setExplicitScaleAndIncrement( getExplicitScale( nDimensionIndex, nAxisIndex ), getExplicitIncrement( nDimensionIndex, nAxisIndex ) );
+ pVAxis->initPlotter(m_xLogicTargetForAxes, m_xFinalTarget, createCIDForAxis( nDimensionIndex, nAxisIndex ) );
+ if(nDimensionCount==2)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->setScales( getExplicitScales(nDimensionIndex,nAxisIndex), bSwapXAndY );
+ }
+ }
+}
+
+void VCartesianCoordinateSystem::updateScalesAndIncrementsOnAxes()
+{
+ if(!m_xLogicTargetForAxes.is() || !m_xFinalTarget.is() || !m_xCooSysModel.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = getPropertySwapXAndYAxis();
+
+ for (auto const& [nIndexPair, pVAxis] : m_aAxisMap)
+ {
+ if (pVAxis)
+ {
+ auto [nDimensionIndex, nAxisIndex] = nIndexPair;
+
+ pVAxis->setExplicitScaleAndIncrement( getExplicitScale( nDimensionIndex, nAxisIndex ), getExplicitIncrement( nDimensionIndex, nAxisIndex ) );
+ if(nDimensionCount==2)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->setScales( getExplicitScales(nDimensionIndex,nAxisIndex), bSwapXAndY );
+ }
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VCartesianCoordinateSystem.hxx b/chart2/source/view/axes/VCartesianCoordinateSystem.hxx
new file mode 100644
index 0000000000..968d97a210
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianCoordinateSystem.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <VCoordinateSystem.hxx>
+
+namespace chart
+{
+
+class VCartesianCoordinateSystem : public VCoordinateSystem
+{
+public:
+ VCartesianCoordinateSystem() = delete;
+ explicit VCartesianCoordinateSystem( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys );
+ virtual ~VCartesianCoordinateSystem() override;
+
+ virtual void createVAxisList(
+ const rtl::Reference<::chart::ChartModel> &ChartDoc,
+ const css::awt::Size& rFontReferenceSize,
+ const css::awt::Rectangle& rMaximumSpaceForLabels,
+ bool bLimitSpaceForLabels,
+ std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList,
+ css::uno::Reference<css::uno::XComponentContext> const& rComponentContext) override;
+
+ virtual void initVAxisInList() override;
+ virtual void updateScalesAndIncrementsOnAxes() override;
+
+ virtual void createGridShapes() override;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VCartesianGrid.cxx b/chart2/source/view/axes/VCartesianGrid.cxx
new file mode 100644
index 0000000000..9916ebac0b
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianGrid.cxx
@@ -0,0 +1,298 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VCartesianGrid.hxx"
+#include "Tickmarks.hxx"
+#include <PlottingPositionHelper.hxx>
+#include <ShapeFactory.hxx>
+#include <ObjectIdentifier.hxx>
+#include <CommonConverters.hxx>
+#include <AxisHelper.hxx>
+#include <VLineProperties.hxx>
+#include <GridProperties.hxx>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+
+#include <memory>
+#include <vector>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace {
+
+struct GridLinePoints
+{
+ Sequence< double > P0;
+ Sequence< double > P1;
+ Sequence< double > P2;
+
+ GridLinePoints( const PlottingPositionHelper* pPosHelper, sal_Int32 nDimensionIndex
+ , CuboidPlanePosition eLeftWallPos=CuboidPlanePosition_Left
+ , CuboidPlanePosition eBackWallPos=CuboidPlanePosition_Back
+ , CuboidPlanePosition eBottomPos=CuboidPlanePosition_Bottom );
+ void update( double fScaledTickValue );
+
+ sal_Int32 m_nDimensionIndex;
+};
+
+}
+
+GridLinePoints::GridLinePoints( const PlottingPositionHelper* pPosHelper, sal_Int32 nDimensionIndex
+ , CuboidPlanePosition eLeftWallPos
+ , CuboidPlanePosition eBackWallPos
+ , CuboidPlanePosition eBottomPos )
+ : m_nDimensionIndex(nDimensionIndex)
+{
+ double MinX = pPosHelper->getLogicMinX();
+ double MinY = pPosHelper->getLogicMinY();
+ double MinZ = pPosHelper->getLogicMinZ();
+ double MaxX = pPosHelper->getLogicMaxX();
+ double MaxY = pPosHelper->getLogicMaxY();
+ double MaxZ = pPosHelper->getLogicMaxZ();
+
+ pPosHelper->doLogicScaling( &MinX,&MinY,&MinZ );
+ pPosHelper->doLogicScaling( &MaxX,&MaxY,&MaxZ );
+
+ if(!pPosHelper->isMathematicalOrientationX())
+ std::swap( MinX, MaxX );
+ if(!pPosHelper->isMathematicalOrientationY())
+ std::swap( MinY, MaxY );
+ if(pPosHelper->isMathematicalOrientationZ())//z axis in draw is reverse to mathematical
+ std::swap( MinZ, MaxZ );
+ bool bSwapXY = pPosHelper->isSwapXAndY();
+
+ //P0: point on 'back' wall, not on 'left' wall
+ //P1: point on both walls
+ //P2: point on 'left' wall not on 'back' wall
+
+ const double v0 = (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MinX : MaxX;
+ const double v1 = (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MinY : MaxY;
+ const double v2 = (eBackWallPos == CuboidPlanePosition_Back) ? MinZ : MaxZ;
+ P0 = P1 = P2 = { v0, v1, v2 };
+
+ if(m_nDimensionIndex==0)
+ {
+ P0.getArray()[1] = (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MaxY : MinY;
+ P2.getArray()[2]= (eBackWallPos == CuboidPlanePosition_Back) ? MaxZ : MinZ;
+ if( eBottomPos != CuboidPlanePosition_Bottom && !bSwapXY )
+ P2=P1;
+ }
+ else if(m_nDimensionIndex==1)
+ {
+ P0.getArray()[0]= (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MaxX : MinX;
+ P2.getArray()[2]= (eBackWallPos == CuboidPlanePosition_Back) ? MaxZ : MinZ;
+ if( eBottomPos != CuboidPlanePosition_Bottom && bSwapXY )
+ P2=P1;
+ }
+ else if(m_nDimensionIndex==2)
+ {
+ P0.getArray()[0]= (eLeftWallPos == CuboidPlanePosition_Left || bSwapXY) ? MaxX : MinX;
+ P2.getArray()[1]= (eLeftWallPos == CuboidPlanePosition_Left || !bSwapXY) ? MaxY : MinY;
+ if( eBottomPos != CuboidPlanePosition_Bottom )
+ {
+ if( !bSwapXY )
+ P0=P1;
+ else
+ P2=P1;
+ }
+ }
+}
+
+void GridLinePoints::update( double fScaledTickValue )
+{
+ P0.getArray()[m_nDimensionIndex] = P1.getArray()[m_nDimensionIndex] = P2.getArray()[m_nDimensionIndex] = fScaledTickValue;
+}
+
+static void addLine2D( drawing::PointSequenceSequence& rPoints, sal_Int32 nIndex
+ , const GridLinePoints& rScaledLogicPoints
+ , const XTransformation2& rTransformation
+ )
+{
+ drawing::Position3D aPA = rTransformation.transform( SequenceToPosition3D(rScaledLogicPoints.P0) );
+ drawing::Position3D aPB = rTransformation.transform( SequenceToPosition3D(rScaledLogicPoints.P1) );
+
+ rPoints.getArray()[nIndex]
+ = { { static_cast<sal_Int32>(aPA.PositionX), static_cast<sal_Int32>(aPA.PositionY) },
+ { static_cast<sal_Int32>(aPB.PositionX), static_cast<sal_Int32>(aPB.PositionY) } };
+}
+
+static void addLine3D( std::vector<std::vector<css::drawing::Position3D>>& rPoints, sal_Int32 nIndex
+ , const GridLinePoints& rBasePoints
+ , const XTransformation2 & rTransformation )
+{
+ drawing::Position3D aPoint =rTransformation.transform( rBasePoints.P0 );
+ AddPointToPoly( rPoints, aPoint, nIndex );
+ aPoint = rTransformation.transform( rBasePoints.P1 );
+ AddPointToPoly( rPoints, aPoint, nIndex );
+ aPoint = rTransformation.transform( rBasePoints.P2 );
+ AddPointToPoly( rPoints, aPoint, nIndex );
+}
+
+VCartesianGrid::VCartesianGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , std::vector< rtl::Reference< ::chart::GridProperties > > aGridPropertiesList )
+ : VAxisOrGridBase( nDimensionIndex, nDimensionCount )
+ , m_aGridPropertiesList( std::move(aGridPropertiesList) )
+{
+ m_pPosHelper = new PlottingPositionHelper();
+}
+
+VCartesianGrid::~VCartesianGrid()
+{
+ delete m_pPosHelper;
+ m_pPosHelper = nullptr;
+}
+
+void VCartesianGrid::fillLinePropertiesFromGridModel( std::vector<VLineProperties>& rLinePropertiesList
+ , const std::vector< rtl::Reference< ::chart::GridProperties > > & rGridPropertiesList )
+{
+ rLinePropertiesList.clear();
+ if( rGridPropertiesList.empty() )
+ return;
+
+ VLineProperties aLineProperties;
+ for( const auto & rxPropSet : rGridPropertiesList )
+ {
+ if(!AxisHelper::isGridVisible( rxPropSet ))
+ aLineProperties.LineStyle <<= drawing::LineStyle_NONE;
+ else
+ aLineProperties.initFromPropertySet( rxPropSet );
+ rLinePropertiesList.push_back(aLineProperties);
+ }
+};
+
+void VCartesianGrid::createShapes()
+{
+ if(m_aGridPropertiesList.empty())
+ return;
+ //somehow equal to axis tickmarks
+
+ //create named group shape
+ rtl::Reference< SvxShapeGroupAnyD > xGroupShape_Shapes(
+ createGroupShape( m_xLogicTarget, m_aCID ) );
+
+ if(!xGroupShape_Shapes.is())
+ return;
+
+ std::vector<VLineProperties> aLinePropertiesList;
+ fillLinePropertiesFromGridModel( aLinePropertiesList, m_aGridPropertiesList );
+
+ //create all scaled tickmark values
+ std::unique_ptr< TickFactory > apTickFactory( createTickFactory() );
+ TickFactory& aTickFactory = *apTickFactory;
+ TickInfoArraysType aAllTickInfos;
+ aTickFactory.getAllTicks( aAllTickInfos );
+
+ //create tick mark line shapes
+
+ if(aAllTickInfos.empty())//no tickmarks at all
+ return;
+
+ TickInfoArraysType::iterator aDepthIter = aAllTickInfos.begin();
+ const TickInfoArraysType::const_iterator aDepthEnd = aAllTickInfos.end();
+
+ sal_Int32 nLinePropertiesCount = aLinePropertiesList.size();
+ for( sal_Int32 nDepth=0
+ ; aDepthIter != aDepthEnd && nDepth < nLinePropertiesCount
+ ; ++aDepthIter, nDepth++ )
+ {
+ if( !aLinePropertiesList[nDepth].isLineVisible() )
+ continue;
+
+ rtl::Reference< SvxShapeGroupAnyD > xTarget( xGroupShape_Shapes );
+ if( nDepth > 0 )
+ {
+ xTarget = createGroupShape( m_xLogicTarget
+ , ObjectIdentifier::addChildParticle( m_aCID, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_SUBGRID, nDepth-1 ) )
+ );
+ if(!xTarget.is())
+ xTarget = xGroupShape_Shapes;
+ }
+
+ if(m_nDimension==2)
+ {
+
+ GridLinePoints aGridLinePoints( m_pPosHelper, m_nDimensionIndex );
+
+ sal_Int32 nPointCount = (*aDepthIter).size();
+ drawing::PointSequenceSequence aPoints(nPointCount);
+
+ sal_Int32 nRealPointCount = 0;
+ for (auto const& tick : *aDepthIter)
+ {
+ if( !tick.bPaintIt )
+ continue;
+ aGridLinePoints.update( tick.fScaledTickValue );
+ addLine2D( aPoints, nRealPointCount, aGridLinePoints, *m_pPosHelper->getTransformationScaledLogicToScene() );
+ nRealPointCount++;
+ }
+ aPoints.realloc(nRealPointCount);
+ ShapeFactory::createLine2D( xTarget, aPoints, &aLinePropertiesList[nDepth] );
+
+ //prepare polygon for handle shape:
+ drawing::PointSequenceSequence aHandlesPoints(1);
+ auto pHandlesPoints = aHandlesPoints.getArray();
+ pHandlesPoints[0].realloc(nRealPointCount);
+ auto pHandlesPoints0 = pHandlesPoints[0].getArray();
+ for( sal_Int32 nN = 0; nN<nRealPointCount; nN++)
+ pHandlesPoints0[nN] = aPoints[nN][1];
+
+ //create handle shape:
+ VLineProperties aHandleLineProperties;
+ aHandleLineProperties.LineStyle <<= drawing::LineStyle_NONE;
+ rtl::Reference<SvxShapePolyPolygon> xHandleShape =
+ ShapeFactory::createLine2D( xTarget, aHandlesPoints, &aHandleLineProperties );
+ ::chart::ShapeFactory::setShapeName( xHandleShape, "HandlesOnly" );
+ }
+ else //if(2!=m_nDimension)
+ {
+ GridLinePoints aGridLinePoints( m_pPosHelper, m_nDimensionIndex, m_eLeftWallPos, m_eBackWallPos, m_eBottomPos );
+
+ sal_Int32 nPointCount = (*aDepthIter).size();
+ std::vector<std::vector<css::drawing::Position3D>> aPoints;
+ aPoints.resize(nPointCount);
+
+ sal_Int32 nRealPointCount = 0;
+ sal_Int32 nPolyIndex = 0;
+ for (auto const& tick : *aDepthIter)
+ {
+ if( !tick.bPaintIt )
+ {
+ ++nPolyIndex;
+ continue;
+ }
+
+ aGridLinePoints.update( tick.fScaledTickValue );
+ addLine3D( aPoints, nPolyIndex, aGridLinePoints, *m_pPosHelper->getTransformationScaledLogicToScene() );
+ nRealPointCount+=3;
+ ++nPolyIndex;
+ }
+ aPoints.resize(nRealPointCount);
+ ShapeFactory::createLine3D( xTarget, aPoints, aLinePropertiesList[nDepth] );
+ }
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VCartesianGrid.hxx b/chart2/source/view/axes/VCartesianGrid.hxx
new file mode 100644
index 0000000000..d41bcc4d46
--- /dev/null
+++ b/chart2/source/view/axes/VCartesianGrid.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "VAxisOrGridBase.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+namespace chart
+{
+class GridProperties;
+struct VLineProperties;
+
+class VCartesianGrid : public VAxisOrGridBase
+{
+// public methods
+public:
+ VCartesianGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , std::vector<
+ rtl::Reference< ::chart::GridProperties > > aGridPropertiesList //main grid, subgrid, subsubgrid etc
+ );
+ virtual ~VCartesianGrid() override;
+
+ virtual void createShapes() override;
+
+ static void fillLinePropertiesFromGridModel( std::vector<VLineProperties>& rLinePropertiesList
+ , const std::vector<
+ rtl::Reference< ::chart::GridProperties > >& rGridPropertiesList );
+
+private:
+ std::vector<
+ rtl::Reference< ::chart::GridProperties > > m_aGridPropertiesList; //main grid, subgrid, subsubgrid etc
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VCoordinateSystem.cxx b/chart2/source/view/axes/VCoordinateSystem.cxx
new file mode 100644
index 0000000000..6266f989ae
--- /dev/null
+++ b/chart2/source/view/axes/VCoordinateSystem.cxx
@@ -0,0 +1,579 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <BaseGFXHelper.hxx>
+#include <DateHelper.hxx>
+#include <VCoordinateSystem.hxx>
+#include "VCartesianCoordinateSystem.hxx"
+#include "VPolarCoordinateSystem.hxx"
+#include <BaseCoordinateSystem.hxx>
+#include <GridProperties.hxx>
+#include <ChartModel.hxx>
+#include <ScaleAutomatism.hxx>
+#include <ShapeFactory.hxx>
+#include <servicenames_coosystems.hxx>
+#include <ObjectIdentifier.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <Axis.hxx>
+#include "VAxisBase.hxx"
+#include <defines.hxx>
+#include <chartview/ExplicitValueProvider.hxx>
+#include <com/sun/star/chart/TimeUnit.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <comphelper/sequence.hxx>
+#include <rtl/math.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+#include <limits>
+#include <utility>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+std::unique_ptr<VCoordinateSystem> VCoordinateSystem::createCoordinateSystem(
+ const rtl::Reference< BaseCoordinateSystem >& xCooSysModel )
+{
+ if( !xCooSysModel.is() )
+ return nullptr;
+
+ OUString aViewServiceName = xCooSysModel->getViewServiceName();
+
+ //@todo: in future the coordinatesystems should be instantiated via service factory
+ std::unique_ptr<VCoordinateSystem> pRet;
+ if( aViewServiceName == CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME )
+ pRet.reset( new VCartesianCoordinateSystem(xCooSysModel) );
+ else if( aViewServiceName == CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME )
+ pRet.reset( new VPolarCoordinateSystem(xCooSysModel) );
+ if(!pRet)
+ pRet.reset( new VCoordinateSystem(xCooSysModel) );
+ return pRet;
+}
+
+VCoordinateSystem::VCoordinateSystem( rtl::Reference< BaseCoordinateSystem > xCooSys )
+ : m_xCooSysModel(std::move(xCooSys))
+ , m_eLeftWallPos(CuboidPlanePosition_Left)
+ , m_eBackWallPos(CuboidPlanePosition_Back)
+ , m_eBottomPos(CuboidPlanePosition_Bottom)
+ , m_aExplicitScales(3)
+ , m_aExplicitIncrements(3)
+{
+ if( !m_xCooSysModel.is() || m_xCooSysModel->getDimension()<3 )
+ {
+ m_aExplicitScales[2].Minimum = 1.0;
+ m_aExplicitScales[2].Maximum = 2.0;
+ m_aExplicitScales[2].Orientation = AxisOrientation_MATHEMATICAL;
+ }
+}
+VCoordinateSystem::~VCoordinateSystem()
+{
+}
+
+void VCoordinateSystem::initPlottingTargets( const rtl::Reference< SvxShapeGroupAnyD >& xLogicTarget
+ , const rtl::Reference< SvxShapeGroupAnyD >& xFinalTarget
+ , rtl::Reference<SvxShapeGroupAnyD>& xLogicTargetForSeriesBehindAxis )
+{
+ OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is(),"no proper initialization parameters");
+ //is only allowed to be called once
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ //create group shape for grids first thus axes are always painted above grids
+ if(nDimensionCount==2)
+ {
+ //create and add to target
+ m_xLogicTargetForGrids = ShapeFactory::createGroup2D( xLogicTarget );
+ xLogicTargetForSeriesBehindAxis = ShapeFactory::createGroup2D( xLogicTarget );
+ m_xLogicTargetForAxes = ShapeFactory::createGroup2D( xLogicTarget );
+ }
+ else
+ {
+ //create and added to target
+ m_xLogicTargetForGrids = ShapeFactory::createGroup3D( xLogicTarget );
+ xLogicTargetForSeriesBehindAxis = ShapeFactory::createGroup3D( xLogicTarget );
+ m_xLogicTargetForAxes = ShapeFactory::createGroup3D( xLogicTarget );
+ }
+ m_xFinalTarget = xFinalTarget;
+}
+
+void VCoordinateSystem::setParticle( const OUString& rCooSysParticle )
+{
+ m_aCooSysParticle = rCooSysParticle;
+}
+
+void VCoordinateSystem::setTransformationSceneToScreen(
+ const drawing::HomogenMatrix& rMatrix )
+{
+ m_aMatrixSceneToScreen = rMatrix;
+
+ //correct transformation for axis
+ for (auto const& elem : m_aAxisMap)
+ {
+ VAxisBase* pVAxis = elem.second.get();
+ if( pVAxis )
+ {
+ if(pVAxis->getDimensionCount()==2)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ }
+ }
+}
+
+//better performance for big data
+uno::Sequence< sal_Int32 > VCoordinateSystem::getCoordinateSystemResolution(
+ const awt::Size& rPageSize, const awt::Size& rPageResolution )
+{
+ uno::Sequence<sal_Int32> aResolution(
+ std::max<sal_Int32>(m_xCooSysModel->getDimension(), 2));
+ auto aResolutionRange = asNonConstRange(aResolution);
+ for( auto& i : aResolutionRange )
+ i = 1000;
+
+ ::basegfx::B3DTuple aScale( BaseGFXHelper::GetScaleFromMatrix(
+ BaseGFXHelper::HomogenMatrixToB3DHomMatrix(
+ m_aMatrixSceneToScreen ) ) );
+
+ double fCoosysWidth = fabs(aScale.getX()*FIXED_SIZE_FOR_3D_CHART_VOLUME);
+ double fCoosysHeight = fabs(aScale.getY()*FIXED_SIZE_FOR_3D_CHART_VOLUME);
+
+ double fPageWidth = rPageSize.Width;
+ double fPageHeight = rPageSize.Height;
+
+ //factor 2 to avoid rounding problems
+ sal_Int32 nXResolution = static_cast<sal_Int32>(2.0*static_cast<double>(rPageResolution.Width)*fCoosysWidth/fPageWidth);
+ sal_Int32 nYResolution = static_cast<sal_Int32>(2.0*static_cast<double>(rPageResolution.Height)*fCoosysHeight/fPageHeight);
+
+ if( nXResolution < 10 )
+ nXResolution = 10;
+ if( nYResolution < 10 )
+ nYResolution = 10;
+
+ if( getPropertySwapXAndYAxis() )
+ std::swap(nXResolution,nYResolution);
+
+ //2D
+ if( aResolution.getLength() == 2 )
+ {
+ aResolutionRange[0]=nXResolution;
+ aResolutionRange[1]=nYResolution;
+ }
+ else
+ {
+ //this maybe can be optimized further ...
+ sal_Int32 nMaxResolution = std::max( nXResolution, nYResolution );
+ nMaxResolution*=2;
+ for( auto& i : asNonConstRange(aResolution) )
+ i = nMaxResolution;
+ }
+
+ return aResolution;
+}
+
+rtl::Reference< Axis > VCoordinateSystem::getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ if( m_xCooSysModel.is() )
+ return m_xCooSysModel->getAxisByDimension2( nDimensionIndex, nAxisIndex );
+ return nullptr;
+}
+
+std::vector< rtl::Reference< ::chart::GridProperties > > VCoordinateSystem::getGridListFromAxis( const rtl::Reference< Axis >& xAxis )
+{
+ std::vector< rtl::Reference< ::chart::GridProperties > > aRet;
+
+ if( xAxis.is() )
+ {
+ aRet.push_back( xAxis->getGridProperties2() );
+ std::vector<rtl::Reference<::chart::GridProperties>> aSubGrids = xAxis->getSubGridProperties2();
+ aRet.insert( aRet.end(), aSubGrids.begin(), aSubGrids.end() );
+ }
+
+ return aRet;
+}
+
+void VCoordinateSystem::impl_adjustDimension( sal_Int32& rDimensionIndex )
+{
+ rDimensionIndex = std::clamp<sal_Int32>(rDimensionIndex, 0, 2);
+}
+
+void VCoordinateSystem::impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex, sal_Int32& rAxisIndex ) const
+{
+ impl_adjustDimension( rDimensionIndex );
+
+ if( rAxisIndex < 0 || rAxisIndex > getMaximumAxisIndexByDimension(rDimensionIndex) )
+ rAxisIndex = 0;
+}
+
+void VCoordinateSystem::setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider /*takes ownership*/ )
+{
+ m_apExplicitCategoriesProvider.reset(pExplicitCategoriesProvider);
+}
+
+ExplicitCategoriesProvider* VCoordinateSystem::getExplicitCategoriesProvider()
+{
+ return m_apExplicitCategoriesProvider.get();
+}
+
+std::vector< ExplicitScaleData > VCoordinateSystem::getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ std::vector< ExplicitScaleData > aRet(m_aExplicitScales);
+
+ impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
+ aRet[nDimensionIndex]=getExplicitScale( nDimensionIndex, nAxisIndex );
+
+ return aRet;
+}
+
+std::vector< ExplicitIncrementData > VCoordinateSystem::getExplicitIncrements( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ std::vector< ExplicitIncrementData > aRet(m_aExplicitIncrements);
+
+ impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
+ aRet[nDimensionIndex]=getExplicitIncrement( nDimensionIndex, nAxisIndex );
+
+ return aRet;
+}
+
+ExplicitScaleData VCoordinateSystem::getExplicitScale( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ ExplicitScaleData aRet;
+
+ impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
+
+ if( nAxisIndex == 0)
+ {
+ aRet = m_aExplicitScales[nDimensionIndex];
+ }
+ else
+ {
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ tFullExplicitScaleMap::const_iterator aIt = m_aSecondaryExplicitScales.find( aFullAxisIndex );
+ if( aIt != m_aSecondaryExplicitScales.end() )
+ aRet = aIt->second;
+ else
+ aRet = m_aExplicitScales[nDimensionIndex];
+ }
+
+ return aRet;
+}
+
+ExplicitIncrementData VCoordinateSystem::getExplicitIncrement( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
+{
+ ExplicitIncrementData aRet;
+
+ impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
+
+ if( nAxisIndex == 0)
+ {
+ aRet = m_aExplicitIncrements[nDimensionIndex];
+ }
+ else
+ {
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ tFullExplicitIncrementMap::const_iterator aIt = m_aSecondaryExplicitIncrements.find( aFullAxisIndex );
+ if( aIt != m_aSecondaryExplicitIncrements.end() )
+ aRet = aIt->second;
+ else
+ aRet = m_aExplicitIncrements[nDimensionIndex];
+ }
+
+ return aRet;
+}
+
+OUString VCoordinateSystem::createCIDForAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ OUString aAxisParticle( ObjectIdentifier::createParticleForAxis( nDimensionIndex, nAxisIndex ) );
+ return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle, aAxisParticle );
+}
+OUString VCoordinateSystem::createCIDForGrid( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ OUString aGridParticle( ObjectIdentifier::createParticleForGrid( nDimensionIndex, nAxisIndex ) );
+ return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle, aGridParticle );
+}
+
+sal_Int32 VCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex ) const
+{
+ sal_Int32 nRet = 0;
+ for (auto const& elem : m_aSecondaryExplicitScales)
+ {
+ if(elem.first.first==nDimensionIndex)
+ {
+ sal_Int32 nLocalIdx = elem.first.second;
+ if( nRet < nLocalIdx )
+ nRet = nLocalIdx;
+ }
+ }
+ return nRet;
+}
+
+void VCoordinateSystem::createVAxisList(
+ const rtl::Reference<::chart::ChartModel> & /* xChartDoc */,
+ const awt::Size& /* rFontReferenceSize */,
+ const awt::Rectangle& /* rMaximumSpaceForLabels */,
+ bool /* bLimitSpaceForLabels */,
+ std::vector<std::unique_ptr<VSeriesPlotter>>& /*rSeriesPlotterList*/,
+ uno::Reference<uno::XComponentContext> const& /*rComponentContext*/)
+{
+}
+
+void VCoordinateSystem::initVAxisInList()
+{
+}
+void VCoordinateSystem::updateScalesAndIncrementsOnAxes()
+{
+}
+
+void VCoordinateSystem::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex )
+{
+ bool bDateAxisX = (rScaleAutomatism.getScale().AxisType == AxisType::DATE) && (nDimIndex == 0);
+ if( bDateAxisX )
+ {
+ // This is a date X dimension. Determine proper time resolution.
+ sal_Int32 nTimeResolution = css::chart::TimeUnit::MONTH;
+ if( !(rScaleAutomatism.getScale().TimeIncrement.TimeResolution >>= nTimeResolution) )
+ {
+ nTimeResolution = m_aMergedMinMaxSupplier.calculateTimeResolutionOnXAxis();
+ rScaleAutomatism.setAutomaticTimeResolution( nTimeResolution );
+ }
+ m_aMergedMinMaxSupplier.setTimeResolutionOnXAxis( nTimeResolution, rScaleAutomatism.getNullDate() );
+ }
+
+ double fMin = std::numeric_limits<double>::infinity();
+ double fMax = -std::numeric_limits<double>::infinity();
+ if( nDimIndex == 0 )
+ {
+ // x dimension
+ fMin = m_aMergedMinMaxSupplier.getMinimumX();
+ fMax = m_aMergedMinMaxSupplier.getMaximumX();
+ }
+ else if( nDimIndex == 1 )
+ {
+ // y dimension
+ ExplicitScaleData aScale = getExplicitScale( 0, 0 );
+ double fMaximum = aScale.Maximum;
+ if (!aScale.m_bShiftedCategoryPosition && aScale.AxisType == AxisType::DATE)
+ {
+ // tdf#146066 Increase maximum date value by one month/year,
+ // because the automatic scaling of the Y axis was incorrect when the last Y value was the highest value.
+ Date aMaxDate(aScale.NullDate);
+ aMaxDate.AddDays(::rtl::math::approxFloor(fMaximum));
+ switch (aScale.TimeResolution)
+ {
+ case css::chart::TimeUnit::MONTH:
+ aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate, 1);
+ break;
+ case css::chart::TimeUnit::YEAR:
+ aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate, 1);
+ break;
+ }
+ fMaximum = aMaxDate - aScale.NullDate;
+ }
+ fMin = m_aMergedMinMaxSupplier.getMinimumYInRange(aScale.Minimum,aScale.Maximum, nAxisIndex);
+ fMax = m_aMergedMinMaxSupplier.getMaximumYInRange(aScale.Minimum, fMaximum, nAxisIndex);
+ }
+ else if( nDimIndex == 2 )
+ {
+ // z dimension
+ fMin = m_aMergedMinMaxSupplier.getMinimumZ();
+ fMax = m_aMergedMinMaxSupplier.getMaximumZ();
+ }
+
+ //merge our values with those already contained in rScaleAutomatism
+ rScaleAutomatism.expandValueRange( fMin, fMax );
+
+ rScaleAutomatism.setAutoScalingOptions(
+ m_aMergedMinMaxSupplier.isExpandBorderToIncrementRhythm( nDimIndex ),
+ m_aMergedMinMaxSupplier.isExpandIfValuesCloseToBorder( nDimIndex ),
+ m_aMergedMinMaxSupplier.isExpandWideValuesToZero( nDimIndex ),
+ m_aMergedMinMaxSupplier.isExpandNarrowValuesTowardZero( nDimIndex ) );
+
+ if (bDateAxisX)
+ return;
+
+ VAxisBase* pVAxis = getVAxis(nDimIndex, nAxisIndex);
+ if( pVAxis )
+ rScaleAutomatism.setMaximumAutoMainIncrementCount( pVAxis->estimateMaximumAutoMainIncrementCount() );
+}
+
+VAxisBase* VCoordinateSystem::getVAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ VAxisBase* pRet = nullptr;
+
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+
+ tVAxisMap::const_iterator aIt = m_aAxisMap.find( aFullAxisIndex );
+ if (aIt != m_aAxisMap.cend())
+ pRet = aIt->second.get();
+
+ return pRet;
+}
+
+void VCoordinateSystem::setExplicitScaleAndIncrement(
+ sal_Int32 nDimensionIndex
+ , sal_Int32 nAxisIndex
+ , const ExplicitScaleData& rExplicitScale
+ , const ExplicitIncrementData& rExplicitIncrement )
+{
+ impl_adjustDimension( nDimensionIndex );
+
+ if( nAxisIndex==0 )
+ {
+ m_aExplicitScales[nDimensionIndex]=rExplicitScale;
+ m_aExplicitIncrements[nDimensionIndex]=rExplicitIncrement;
+ }
+ else
+ {
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ m_aSecondaryExplicitScales[aFullAxisIndex] = rExplicitScale;
+ m_aSecondaryExplicitIncrements[aFullAxisIndex] = rExplicitIncrement;
+ }
+}
+
+void VCoordinateSystem::set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos )
+{
+ m_eLeftWallPos = eLeftWallPos;
+ m_eBackWallPos = eBackWallPos;
+ m_eBottomPos = eBottomPos;
+}
+
+void VCoordinateSystem::createMaximumAxesLabels()
+{
+ for (auto const&[unused, pVAxis] : m_aAxisMap)
+ {
+ (void)unused;
+ if (pVAxis)
+ {
+ if (pVAxis->getDimensionCount() == 2)
+ pVAxis->setTransformationSceneToScreen(m_aMatrixSceneToScreen);
+ pVAxis->createMaximumLabels();
+ }
+ }
+}
+void VCoordinateSystem::createAxesLabels()
+{
+ for (auto const&[unused, pVAxis] : m_aAxisMap)
+ {
+ (void)unused;
+ if (pVAxis)
+ {
+ if (pVAxis->getDimensionCount() == 2)
+ pVAxis->setTransformationSceneToScreen(m_aMatrixSceneToScreen);
+ pVAxis->createLabels();
+ }
+ }
+}
+
+void VCoordinateSystem::updatePositions()
+{
+ for (auto const&[unused, pVAxis] : m_aAxisMap)
+ {
+ (void)unused;
+ if (pVAxis)
+ {
+ if (pVAxis->getDimensionCount() == 2)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->updatePositions();
+ }
+ }
+}
+
+void VCoordinateSystem::createAxesShapes()
+{
+ for (auto const&[aFullAxisIndex, pVAxis] : m_aAxisMap)
+ {
+ if (pVAxis)
+ {
+ auto const&[nDimensionIndex, nAxisIndex] = aFullAxisIndex;
+
+ if (pVAxis->getDimensionCount() == 2)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+
+ if (nAxisIndex == 0)
+ {
+ if (nDimensionIndex == 0)
+ {
+ if( m_aExplicitScales[1].AxisType!=AxisType::CATEGORY )
+ pVAxis->setExtraLinePositionAtOtherAxis(
+ m_aExplicitScales[1].Origin );
+ }
+ else if (nDimensionIndex == 1)
+ {
+ if( m_aExplicitScales[0].AxisType!=AxisType::CATEGORY )
+ pVAxis->setExtraLinePositionAtOtherAxis(
+ m_aExplicitScales[0].Origin );
+ }
+ }
+
+ pVAxis->createShapes();
+ }
+ }
+}
+void VCoordinateSystem::createGridShapes()
+{
+}
+void VCoordinateSystem::addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
+{
+ m_aMergedMinMaxSupplier.addMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier);
+}
+
+bool VCoordinateSystem::hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
+{
+ return m_aMergedMinMaxSupplier.hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier);
+}
+
+void VCoordinateSystem::clearMinimumAndMaximumSupplierList()
+{
+ m_aMergedMinMaxSupplier.clearMinimumAndMaximumSupplierList();
+}
+
+bool VCoordinateSystem::getPropertySwapXAndYAxis() const
+{
+ bool bSwapXAndY = false;
+ if( m_xCooSysModel.is()) try
+ {
+ m_xCooSysModel->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return bSwapXAndY;
+}
+
+bool VCoordinateSystem::needSeriesNamesForAxis() const
+{
+ return ( m_xCooSysModel.is() && m_xCooSysModel->getDimension() == 3 );
+}
+void VCoordinateSystem::setSeriesNamesForAxis( const Sequence< OUString >& rSeriesNames )
+{
+ m_aSeriesNamesForZAxis = rSeriesNames;
+}
+
+sal_Int32 VCoordinateSystem::getNumberFormatKeyForAxis(
+ const rtl::Reference< Axis >& xAxis
+ , const rtl::Reference<::chart::ChartModel>& xChartDoc)
+{
+ return ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
+ xAxis, m_xCooSysModel, xChartDoc);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VPolarAngleAxis.cxx b/chart2/source/view/axes/VPolarAngleAxis.cxx
new file mode 100644
index 0000000000..13f66cec9c
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAngleAxis.cxx
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <basegfx/numeric/ftools.hxx>
+
+#include "VPolarAngleAxis.hxx"
+#include "VPolarGrid.hxx"
+#include <ShapeFactory.hxx>
+#include <Axis.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <PolarLabelPositionHelper.hxx>
+#include <PlottingPositionHelper.hxx>
+#include <tools/color.hxx>
+
+#include <memory>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+VPolarAngleAxis::VPolarAngleAxis( const AxisProperties& rAxisProperties
+ , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionCount )
+ : VPolarAxis( rAxisProperties, xNumberFormatsSupplier, 0/*nDimensionIndex*/, nDimensionCount )
+{
+}
+
+VPolarAngleAxis::~VPolarAngleAxis()
+{
+}
+
+void VPolarAngleAxis::createTextShapes_ForAngleAxis(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , EquidistantTickIter& rTickIter
+ , AxisLabelProperties const & rAxisLabelProperties
+ , double fLogicRadius
+ , double fLogicZ )
+{
+ FixedNumberFormatter aFixedNumberFormatter(
+ m_xNumberFormatsSupplier, rAxisLabelProperties.m_nNumberFormatKey );
+
+ //prepare text properties for multipropertyset-interface of shape
+ tNameSequence aPropNames;
+ tAnySequence aPropValues;
+
+ uno::Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel );
+ PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false, -1, false, false );
+ LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps
+ , rAxisLabelProperties.m_aFontReferenceSize );
+
+ uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,u"CharColor");
+ Color nColor = COL_AUTO;
+ if(pColorAny)
+ *pColorAny >>= nColor;
+
+ const uno::Sequence< OUString >* pLabels = m_bUseTextLabels? &m_aTextLabels : nullptr;
+
+ //TickInfo* pLastVisibleNeighbourTickInfo = NULL;
+ sal_Int32 nTick = 0;
+
+ for( TickInfo* pTickInfo = rTickIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = rTickIter.nextInfo(), nTick++ )
+ {
+ //don't create labels which does not fit into the rhythm
+ if( nTick%rAxisLabelProperties.m_nRhythm != 0)
+ continue;
+
+ //don't create labels for invisible ticks
+ if( !pTickInfo->bPaintIt )
+ continue;
+
+ //if NO OVERLAP -> don't create labels where the
+ //anchor position is the same as for the last label
+ //@todo
+
+ if(!pTickInfo->xTextShape.is())
+ {
+ //create single label
+ bool bHasExtraColor=false;
+ Color nExtraColor;
+
+ OUString aLabel;
+ if(pLabels)
+ {
+ sal_Int32 nIndex = static_cast< sal_Int32 >(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0
+ if( nIndex>=0 && nIndex<pLabels->getLength() )
+ aLabel = (*pLabels)[nIndex];
+ }
+ else
+ aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->getUnscaledTickValue(), nExtraColor, bHasExtraColor );
+
+ if(pColorAny)
+ *pColorAny <<= bHasExtraColor?nExtraColor:nColor;
+
+ double fLogicAngle = pTickInfo->getUnscaledTickValue();
+
+ LabelAlignment eLabelAlignment(LABEL_ALIGN_CENTER);
+ PolarLabelPositionHelper aPolarLabelPositionHelper(m_pPosHelper.get(), 2/*nDimensionCount*/, xTarget);
+ sal_Int32 nScreenValueOffsetInRadiusDirection = m_aAxisLabelProperties.m_aMaximumSpaceForLabels.Height/15;
+ awt::Point aAnchorScreenPosition2D( aPolarLabelPositionHelper.getLabelScreenPositionAndAlignmentForLogicValues(
+ eLabelAlignment, fLogicAngle, fLogicRadius, fLogicZ, nScreenValueOffsetInRadiusDirection ));
+ LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, eLabelAlignment );
+
+ // #i78696# use mathematically correct rotation now
+ const double fRotationAnglePi(-basegfx::deg2rad(rAxisLabelProperties.m_fRotationAngleDegree));
+
+ uno::Any aATransformation = ShapeFactory::makeTransformation( aAnchorScreenPosition2D, fRotationAnglePi );
+ OUString aStackedLabel = ShapeFactory::getStackedString( aLabel, rAxisLabelProperties.m_bStackCharacters );
+
+ pTickInfo->xTextShape = ShapeFactory::createText( xTarget, aStackedLabel, aPropNames, aPropValues, aATransformation );
+ }
+
+ //if NO OVERLAP -> remove overlapping shapes
+ //@todo
+ }
+}
+
+void VPolarAngleAxis::createMaximumLabels()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ createLabels();
+}
+
+void VPolarAngleAxis::updatePositions()
+{
+ //todo: really only update the positions
+
+ if( !prepareShapeCreation() )
+ return;
+
+ createLabels();
+}
+
+void VPolarAngleAxis::createLabels()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ double fLogicRadius = m_pPosHelper->getOuterLogicRadius();
+
+ if( !m_aAxisProperties.m_bDisplayLabels )
+ return;
+
+ //create tick mark text shapes
+ //@todo: iterate through all tick depth which should be labeled
+
+ EquidistantTickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0 );
+ updateUnscaledValuesAtTicks( aTickIter );
+
+ removeTextShapesFromTicks();
+
+ AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties );
+ aAxisLabelProperties.m_bOverlapAllowed = true;
+ double const fLogicZ = 1.0;//as defined
+ createTextShapes_ForAngleAxis( m_xTextTarget, aTickIter
+ , aAxisLabelProperties
+ , fLogicRadius, fLogicZ
+ );
+
+ //no staggering for polar angle axis
+}
+
+void VPolarAngleAxis::createShapes()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ double fLogicRadius = m_pPosHelper->getOuterLogicRadius();
+ double const fLogicZ = 1.0;//as defined
+
+ //create axis main lines
+ drawing::PointSequenceSequence aPoints(1);
+ VPolarGrid::createLinePointSequence_ForAngleAxis( aPoints, m_aAllTickInfos, m_aIncrement, m_aScale, m_pPosHelper.get(), fLogicRadius, fLogicZ );
+ rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D(
+ m_xGroupShape_Shapes, aPoints, &m_aAxisProperties.m_aLineProperties );
+ //because of this name this line will be used for marking the axis
+ ::chart::ShapeFactory::setShapeName( xShape, "MarkHandles" );
+
+ //create labels
+ createLabels();
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VPolarAngleAxis.hxx b/chart2/source/view/axes/VPolarAngleAxis.hxx
new file mode 100644
index 0000000000..0e0774e9eb
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAngleAxis.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "VPolarAxis.hxx"
+#include "Tickmarks_Equidistant.hxx"
+
+namespace chart
+{
+
+class VPolarAngleAxis : public VPolarAxis
+{
+public:
+ VPolarAngleAxis( const AxisProperties& rAxisProperties
+ , const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionCount );
+ virtual ~VPolarAngleAxis() override;
+
+ virtual void createMaximumLabels() override;
+ virtual void createLabels() override;
+ virtual void updatePositions() override;
+
+ virtual void createShapes() override;
+
+private: //methods
+ void createTextShapes_ForAngleAxis(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , EquidistantTickIter& rTickIter
+ , AxisLabelProperties const & rAxisLabelProperties
+ , double fLogicRadius, double fLogicZ );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VPolarAxis.cxx b/chart2/source/view/axes/VPolarAxis.cxx
new file mode 100644
index 0000000000..d9dfe08ec6
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAxis.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VPolarAxis.hxx"
+#include "VPolarAngleAxis.hxx"
+#include "VPolarRadiusAxis.hxx"
+#include <PlottingPositionHelper.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+std::shared_ptr<VPolarAxis> VPolarAxis::createAxis( const AxisProperties& rAxisProperties
+ , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount )
+{
+ if( nDimensionIndex==0 )
+ return std::make_shared<VPolarAngleAxis>( rAxisProperties, xNumberFormatsSupplier, nDimensionCount );
+ return std::make_shared<VPolarRadiusAxis>( rAxisProperties, xNumberFormatsSupplier, nDimensionCount );
+}
+
+VPolarAxis::VPolarAxis( const AxisProperties& rAxisProperties
+ , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount )
+ : VAxisBase( nDimensionIndex, nDimensionCount, rAxisProperties, xNumberFormatsSupplier )
+ , m_pPosHelper( new PolarPlottingPositionHelper() )
+{
+ PlotterBase::m_pPosHelper = m_pPosHelper.get();
+}
+
+VPolarAxis::~VPolarAxis()
+{
+}
+
+void VPolarAxis::setIncrements( std::vector< ExplicitIncrementData >&& rIncrements )
+{
+ m_aIncrements = std::move(rIncrements);
+}
+
+bool VPolarAxis::isAnythingToDraw()
+{
+ return ( m_nDimension==2 && VAxisBase::isAnythingToDraw() );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VPolarAxis.hxx b/chart2/source/view/axes/VPolarAxis.hxx
new file mode 100644
index 0000000000..42e22ae7df
--- /dev/null
+++ b/chart2/source/view/axes/VPolarAxis.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "VAxisBase.hxx"
+#include <memory>
+
+namespace chart
+{
+
+class PolarPlottingPositionHelper;
+
+class VPolarAxis : public VAxisBase
+{
+public:
+ static std::shared_ptr<VPolarAxis> createAxis( const AxisProperties& rAxisProperties
+ , const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount );
+
+ void setIncrements( std::vector< ExplicitIncrementData >&& rIncrements );
+
+ virtual bool isAnythingToDraw() override;
+
+ virtual ~VPolarAxis() override;
+
+protected:
+ VPolarAxis( const AxisProperties& rAxisProperties
+ , const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount );
+
+protected: //member
+ std::unique_ptr<PolarPlottingPositionHelper> m_pPosHelper;
+ std::vector< ExplicitIncrementData > m_aIncrements;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VPolarCoordinateSystem.cxx b/chart2/source/view/axes/VPolarCoordinateSystem.cxx
new file mode 100644
index 0000000000..b7d5b07c74
--- /dev/null
+++ b/chart2/source/view/axes/VPolarCoordinateSystem.cxx
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VPolarCoordinateSystem.hxx"
+#include "VPolarGrid.hxx"
+#include "VPolarAxis.hxx"
+#include <BaseCoordinateSystem.hxx>
+#include <AxisIndexDefines.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include <Diagram.hxx>
+#include <DataTable.hxx>
+#include <ChartModel.hxx>
+#include <GridProperties.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+VPolarCoordinateSystem::VPolarCoordinateSystem( const rtl::Reference< BaseCoordinateSystem >& xCooSys )
+ : VCoordinateSystem(xCooSys)
+{
+}
+
+VPolarCoordinateSystem::~VPolarCoordinateSystem()
+{
+}
+
+//better performance for big data
+uno::Sequence< sal_Int32 > VPolarCoordinateSystem::getCoordinateSystemResolution(
+ const awt::Size& rPageSize, const awt::Size& rPageResolution )
+{
+ uno::Sequence< sal_Int32 > aResolution( VCoordinateSystem::getCoordinateSystemResolution( rPageSize, rPageResolution) );
+
+ if( aResolution.getLength() >= 2 )
+ {
+ auto pResolution = aResolution.getArray();
+ if( getPropertySwapXAndYAxis() )
+ {
+ pResolution[0]/=2;//radius
+ pResolution[1]*=4;//outer circle resolution
+ }
+ else
+ {
+ pResolution[0]*=4;//outer circle resolution
+ pResolution[1]/=2;//radius
+ }
+ }
+
+ return aResolution;
+}
+
+void VPolarCoordinateSystem::createVAxisList(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc,
+ const awt::Size& rFontReferenceSize,
+ const awt::Rectangle& rMaximumSpaceForLabels,
+ bool /*bLimitSpaceForLabels*/,
+ std::vector<std::unique_ptr<VSeriesPlotter>>& /*rSeriesPlotterList*/,
+ css::uno::Reference<css::uno::XComponentContext> const& /*rComponentContext*/)
+{
+ // note: using xChartDoc itself as XNumberFormatsSupplier would cause
+ // a leak from VPolarAxis due to cyclic reference
+ uno::Reference<util::XNumberFormatsSupplier> const xNumberFormatsSupplier(
+ xChartDoc->getNumberFormatsSupplier());
+
+ m_aAxisMap.clear();
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ sal_Int32 nDimensionIndex = 0;
+
+ //create angle axis (dimension index 0)
+ for( nDimensionIndex = 0; nDimensionIndex < nDimensionCount; nDimensionIndex++ )
+ {
+ sal_Int32 nMaxAxisIndex = m_xCooSysModel->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for( sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; nAxisIndex++ )
+ {
+ rtl::Reference< Axis > xAxis = getAxisByDimension(nDimensionIndex,nAxisIndex);
+ if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel ))
+ continue;
+
+ rtl::Reference<Diagram> xDiagram(xChartDoc->getFirstChartDiagram());
+ AxisProperties aAxisProperties(xAxis,getExplicitCategoriesProvider(), xDiagram->getDataTableRef());
+ aAxisProperties.init();
+ if(aAxisProperties.m_bDisplayLabels)
+ aAxisProperties.m_nNumberFormatKey = getNumberFormatKeyForAxis(xAxis, xChartDoc);
+
+ std::shared_ptr< VAxisBase > apVAxis( VPolarAxis::createAxis( aAxisProperties,xNumberFormatsSupplier,nDimensionIndex,nDimensionCount) );
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ m_aAxisMap[aFullAxisIndex] = apVAxis;
+
+ apVAxis->initAxisLabelProperties(rFontReferenceSize,rMaximumSpaceForLabels);
+ }
+ }
+}
+
+void VPolarCoordinateSystem::initVAxisInList()
+{
+ if(!m_xLogicTargetForAxes.is() || !m_xFinalTarget.is() || !m_xCooSysModel.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = getPropertySwapXAndYAxis();
+
+ for (auto const& elem : m_aAxisMap)
+ {
+ VAxisBase* pVAxis = elem.second.get();
+ if( pVAxis )
+ {
+ sal_Int32 nDimensionIndex = elem.first.first;
+ sal_Int32 nAxisIndex = elem.first.second;
+ pVAxis->setExplicitScaleAndIncrement( getExplicitScale( nDimensionIndex, nAxisIndex ), getExplicitIncrement(nDimensionIndex, nAxisIndex) );
+ pVAxis->initPlotter(m_xLogicTargetForAxes,m_xFinalTarget
+ , createCIDForAxis( nDimensionIndex, nAxisIndex ) );
+ VPolarAxis* pVPolarAxis = dynamic_cast< VPolarAxis* >( pVAxis );
+ if( pVPolarAxis )
+ pVPolarAxis->setIncrements( getExplicitIncrements( nDimensionIndex, nAxisIndex ) );
+ if(nDimensionCount==2)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->setScales( getExplicitScales( nDimensionIndex, nAxisIndex ), bSwapXAndY );
+ }
+ }
+}
+
+void VPolarCoordinateSystem::updateScalesAndIncrementsOnAxes()
+{
+ if(!m_xLogicTargetForAxes.is() || !m_xFinalTarget.is() || !m_xCooSysModel.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = getPropertySwapXAndYAxis();
+
+ for (auto const& elem : m_aAxisMap)
+ {
+ VAxisBase* pVAxis = elem.second.get();
+ if( pVAxis )
+ {
+ sal_Int32 nDimensionIndex = elem.first.first;
+ sal_Int32 nAxisIndex = elem.first.second;
+ pVAxis->setExplicitScaleAndIncrement( getExplicitScale( nDimensionIndex, nAxisIndex ), getExplicitIncrement(nDimensionIndex, nAxisIndex) );
+ VPolarAxis* pVPolarAxis = dynamic_cast< VPolarAxis* >( pVAxis );
+ if( pVPolarAxis )
+ pVPolarAxis->setIncrements( getExplicitIncrements( nDimensionIndex, nAxisIndex ) );
+ if(nDimensionCount==2)
+ pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ pVAxis->setScales( getExplicitScales( nDimensionIndex, nAxisIndex ), bSwapXAndY );
+ }
+ }
+}
+
+void VPolarCoordinateSystem::createGridShapes()
+{
+ if(!m_xLogicTargetForGrids.is() || !m_xFinalTarget.is() )
+ return;
+
+ sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
+ bool bSwapXAndY = getPropertySwapXAndYAxis();
+
+ for( sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
+ {
+ sal_Int32 nAxisIndex = MAIN_AXIS_INDEX;
+
+ rtl::Reference< Axis > xAxis = AxisHelper::getAxis( nDimensionIndex, nAxisIndex, m_xCooSysModel );
+ if(!xAxis.is() || !AxisHelper::shouldAxisBeDisplayed( xAxis, m_xCooSysModel ))
+ continue;
+
+ VPolarGrid aGrid(nDimensionIndex,nDimensionCount,getGridListFromAxis( xAxis ));
+ aGrid.setIncrements( getExplicitIncrements( nDimensionIndex, nAxisIndex ) );
+ aGrid.initPlotter(m_xLogicTargetForGrids,m_xFinalTarget
+ , createCIDForGrid( nDimensionIndex, nAxisIndex ) );
+ if(nDimensionCount==2)
+ aGrid.setTransformationSceneToScreen( m_aMatrixSceneToScreen );
+ aGrid.setScales( getExplicitScales( nDimensionIndex, nAxisIndex), bSwapXAndY );
+ aGrid.createShapes();
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VPolarCoordinateSystem.hxx b/chart2/source/view/axes/VPolarCoordinateSystem.hxx
new file mode 100644
index 0000000000..a2ea0220f8
--- /dev/null
+++ b/chart2/source/view/axes/VPolarCoordinateSystem.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <VCoordinateSystem.hxx>
+
+namespace chart
+{
+
+class VPolarCoordinateSystem : public VCoordinateSystem
+{
+public:
+ VPolarCoordinateSystem() = delete;
+ explicit VPolarCoordinateSystem( const rtl::Reference< ::chart::BaseCoordinateSystem >& xCooSys );
+ virtual ~VPolarCoordinateSystem() override;
+
+ //better performance for big data
+ virtual css::uno::Sequence< sal_Int32 > getCoordinateSystemResolution( const css::awt::Size& rPageSize
+ , const css::awt::Size& rPageResolution ) override;
+
+ virtual void createVAxisList(
+ const rtl::Reference<::chart::ChartModel> &ChartDoc,
+ const css::awt::Size& rFontReferenceSize,
+ const css::awt::Rectangle& rMaximumSpaceForLabels,
+ bool bLimitSpaceForLabels,
+ std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList,
+ css::uno::Reference<css::uno::XComponentContext> const& rComponentContext) override;
+
+ virtual void initVAxisInList() override;
+ virtual void updateScalesAndIncrementsOnAxes() override;
+
+ virtual void createGridShapes() override;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VPolarGrid.cxx b/chart2/source/view/axes/VPolarGrid.cxx
new file mode 100644
index 0000000000..9a2929eac3
--- /dev/null
+++ b/chart2/source/view/axes/VPolarGrid.cxx
@@ -0,0 +1,248 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VPolarGrid.hxx"
+#include "VCartesianGrid.hxx"
+#include "Tickmarks.hxx"
+#include <GridProperties.hxx>
+#include <PlottingPositionHelper.hxx>
+#include <ShapeFactory.hxx>
+#include <ObjectIdentifier.hxx>
+#include <CommonConverters.hxx>
+#include <VLineProperties.hxx>
+#include "Tickmarks_Equidistant.hxx"
+
+#include <osl/diagnose.h>
+
+#include <vector>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+VPolarGrid::VPolarGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , std::vector< rtl::Reference< ::chart::GridProperties > > aGridPropertiesList )
+ : VAxisOrGridBase( nDimensionIndex, nDimensionCount )
+ , m_aGridPropertiesList( std::move(aGridPropertiesList) )
+ , m_pPosHelper( new PolarPlottingPositionHelper() )
+{
+ PlotterBase::m_pPosHelper = m_pPosHelper.get();
+}
+
+VPolarGrid::~VPolarGrid()
+{
+}
+
+void VPolarGrid::setIncrements( std::vector< ExplicitIncrementData >&& rIncrements )
+{
+ m_aIncrements = std::move(rIncrements);
+}
+
+void VPolarGrid::getAllTickInfos( sal_Int32 nDimensionIndex, TickInfoArraysType& rAllTickInfos ) const
+{
+ const std::vector<ExplicitScaleData>& rScales = m_pPosHelper->getScales();
+ TickFactory aTickFactory(rScales[nDimensionIndex], m_aIncrements[nDimensionIndex]);
+ aTickFactory.getAllTicks( rAllTickInfos );
+}
+
+void VPolarGrid::createLinePointSequence_ForAngleAxis(
+ drawing::PointSequenceSequence& rPoints
+ , TickInfoArraysType& rAllTickInfos
+ , const ExplicitIncrementData& rIncrement
+ , const ExplicitScaleData& rScale
+ , PolarPlottingPositionHelper const * pPosHelper
+ , double fLogicRadius, double fLogicZ )
+{
+ Reference< XScaling > xInverseScaling;
+ if( rScale.Scaling.is() )
+ xInverseScaling = rScale.Scaling->getInverseScaling();
+
+ sal_Int32 nTick = 0;
+ EquidistantTickIter aIter( rAllTickInfos, rIncrement, 0 );
+ auto pPoints = rPoints.getArray();
+ for( TickInfo* pTickInfo = aIter.firstInfo()
+ ; pTickInfo
+ ; pTickInfo = aIter.nextInfo(), nTick++ )
+ {
+ if(nTick>=rPoints[0].getLength())
+ pPoints[0].realloc(rPoints[0].getLength()+30);
+ auto pPoints0 = pPoints[0].getArray();
+
+ //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling );
+ double fLogicAngle = pTickInfo->getUnscaledTickValue();
+
+ drawing::Position3D aScenePosition3D( pPosHelper->transformAngleRadiusToScene( fLogicAngle, fLogicRadius, fLogicZ ) );
+ pPoints0[nTick].X = static_cast<sal_Int32>(aScenePosition3D.PositionX);
+ pPoints0[nTick].Y = static_cast<sal_Int32>(aScenePosition3D.PositionY);
+ }
+ if(rPoints[0].getLength()>1)
+ {
+ pPoints[0].realloc(nTick+1);
+ auto pPoints0 = pPoints[0].getArray();
+ pPoints0[nTick].X = rPoints[0][0].X;
+ pPoints0[nTick].Y = rPoints[0][0].Y;
+ }
+ else
+ pPoints[0].realloc(0);
+}
+#ifdef NOTYET
+void VPolarGrid::create2DAngleGrid( const Reference< drawing::XShapes >& xLogicTarget
+ , TickInfoArraysType& /* rRadiusTickInfos */
+ , TickInfoArraysType& rAngleTickInfos
+ , const std::vector<VLineProperties>& rLinePropertiesList )
+{
+ Reference< drawing::XShapes > xMainTarget(
+ createGroupShape( xLogicTarget, m_aCID ) );
+
+ const std::vector<ExplicitScaleData>& rScales = m_pPosHelper->getScales();
+ const ExplicitScaleData& rAngleScale = rScales[0];
+ Reference< XScaling > xInverseScaling( NULL );
+ if( rAngleScale.Scaling.is() )
+ xInverseScaling = rAngleScale.Scaling->getInverseScaling();
+
+ double fLogicInnerRadius = m_pPosHelper->getInnerLogicRadius();
+ double fLogicOuterRadius = m_pPosHelper->getOuterLogicRadius();
+
+ sal_Int32 nLinePropertiesCount = rLinePropertiesList.size();
+ if(nLinePropertiesCount)
+ {
+ double fLogicZ = 1.0;//as defined
+ sal_Int32 nDepth=0;
+ //create axis main lines
+ drawing::PointSequenceSequence aAllPoints;
+ for (auto const& tick : rAngleTickInfos[0])
+ {
+ if( !tick.bPaintIt )
+ continue;
+
+ //xxxxx rTickInfo.updateUnscaledValue( xInverseScaling );
+ double fLogicAngle = tick.getUnscaledTickValue();
+
+ drawing::PointSequenceSequence aPoints(1);
+ aPoints[0].realloc(2);
+ drawing::Position3D aScenePositionStart( m_pPosHelper->transformAngleRadiusToScene( fLogicAngle, fLogicInnerRadius, fLogicZ ) );
+ drawing::Position3D aScenePositionEnd( m_pPosHelper->transformAngleRadiusToScene( fLogicAngle, fLogicOuterRadius, fLogicZ ) );
+ aPoints[0][0].X = static_cast<sal_Int32>(aScenePositionStart.PositionX);
+ aPoints[0][0].Y = static_cast<sal_Int32>(aScenePositionStart.PositionY);
+ aPoints[0][1].X = static_cast<sal_Int32>(aScenePositionEnd.PositionX);
+ aPoints[0][1].Y = static_cast<sal_Int32>(aScenePositionEnd.PositionY);
+ appendPointSequence( aAllPoints, aPoints );
+ }
+
+ rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D(
+ xMainTarget, aAllPoints, &rLinePropertiesList[nDepth] );
+ //because of this name this line will be used for marking
+ m_pShapeFactory->setShapeName( xShape, "MarkHandles" );
+ }
+}
+#endif
+
+void VPolarGrid::create2DRadiusGrid( const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget
+ , TickInfoArraysType& rRadiusTickInfos
+ , TickInfoArraysType& rAngleTickInfos
+ , const std::vector<VLineProperties>& rLinePropertiesList )
+{
+ rtl::Reference<SvxShapeGroupAnyD> xMainTarget =
+ createGroupShape( xLogicTarget, m_aCID );
+
+ const std::vector<ExplicitScaleData>& rScales = m_pPosHelper->getScales();
+ const ExplicitScaleData& rRadiusScale = rScales[1];
+ const ExplicitScaleData& rAngleScale = rScales[0];
+ const ExplicitIncrementData& rAngleIncrement = m_aIncrements[0];
+ Reference< XScaling > xInverseRadiusScaling;
+ if( rRadiusScale.Scaling.is() )
+ xInverseRadiusScaling = rRadiusScale.Scaling->getInverseScaling();
+
+ sal_Int32 nLinePropertiesCount = rLinePropertiesList.size();
+ TickInfoArraysType::iterator aDepthIter = rRadiusTickInfos.begin();
+ const TickInfoArraysType::const_iterator aDepthEnd = rRadiusTickInfos.end();
+ for( sal_Int32 nDepth=0
+ ; aDepthIter != aDepthEnd && nDepth < nLinePropertiesCount
+ ; ++aDepthIter, nDepth++ )
+ {
+ if( !rLinePropertiesList[nDepth].isLineVisible() )
+ continue;
+
+ rtl::Reference<SvxShapeGroupAnyD> xTarget( xMainTarget );
+ if( nDepth > 0 )
+ {
+ xTarget = createGroupShape( xLogicTarget
+ , ObjectIdentifier::addChildParticle( m_aCID, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_SUBGRID, nDepth-1 ) )
+ );
+ if(!xTarget.is())
+ xTarget = xMainTarget;
+ }
+
+ //create axis main lines
+ drawing::PointSequenceSequence aAllPoints;
+ for (auto const& tick : *aDepthIter)
+ {
+ if( !tick.bPaintIt )
+ continue;
+
+ //xxxxx rTickInfo.updateUnscaledValue( xInverseRadiusScaling );
+ double fLogicRadius = tick.getUnscaledTickValue();
+ double const fLogicZ = 1.0;//as defined
+
+ drawing::PointSequenceSequence aPoints(1);
+ VPolarGrid::createLinePointSequence_ForAngleAxis( aPoints, rAngleTickInfos
+ , rAngleIncrement, rAngleScale, m_pPosHelper.get(), fLogicRadius, fLogicZ );
+ if(aPoints[0].getLength())
+ appendPointSequence( aAllPoints, aPoints );
+ }
+
+ rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D(
+ xTarget, aAllPoints, &rLinePropertiesList[nDepth] );
+ //because of this name this line will be used for marking
+ ::chart::ShapeFactory::setShapeName( xShape, "MarkHandles" );
+ }
+}
+
+void VPolarGrid::createShapes()
+{
+ OSL_PRECOND(m_xLogicTarget.is()&&m_xFinalTarget.is(),"Axis is not proper initialized");
+ if(!(m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+ if(m_aGridPropertiesList.empty())
+ return;
+
+ //create all scaled tickmark values
+ TickInfoArraysType aAngleTickInfos;
+ TickInfoArraysType aRadiusTickInfos;
+ getAllTickInfos( 0, aAngleTickInfos );
+ getAllTickInfos( 1, aRadiusTickInfos );
+
+ std::vector<VLineProperties> aLinePropertiesList;
+ VCartesianGrid::fillLinePropertiesFromGridModel( aLinePropertiesList, m_aGridPropertiesList );
+
+ //create tick mark line shapes
+ if(m_nDimension==2)
+ {
+ if(m_nDimensionIndex==1)
+ create2DRadiusGrid( m_xLogicTarget, aRadiusTickInfos, aAngleTickInfos, aLinePropertiesList );
+ //else //no Angle Grid so far as this equals exactly the y axis positions
+ // create2DAngleGrid( m_xLogicTarget, aRadiusTickInfos, aAngleTickInfos, aLinePropertiesList );
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VPolarGrid.hxx b/chart2/source/view/axes/VPolarGrid.hxx
new file mode 100644
index 0000000000..c451ae5d56
--- /dev/null
+++ b/chart2/source/view/axes/VPolarGrid.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "VAxisOrGridBase.hxx"
+#include "Tickmarks.hxx"
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <memory>
+
+namespace chart { struct VLineProperties; }
+
+namespace chart
+{
+class GridProperties;
+class PolarPlottingPositionHelper;
+
+class VPolarGrid : public VAxisOrGridBase
+{
+// public methods
+public:
+ VPolarGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
+ , std::vector<
+ rtl::Reference< ::chart::GridProperties > > aGridPropertiesList //main grid, subgrid, subsubgrid etc
+ );
+ virtual ~VPolarGrid() override;
+
+ virtual void createShapes() override;
+
+ void setIncrements( std::vector< ExplicitIncrementData >&& rIncrements );
+
+ static void createLinePointSequence_ForAngleAxis(
+ css::drawing::PointSequenceSequence& rPoints
+ , TickInfoArraysType& rAllTickInfos
+ , const ExplicitIncrementData& rIncrement
+ , const ExplicitScaleData& rScale
+ , PolarPlottingPositionHelper const * pPosHelper
+ , double fLogicRadius, double fLogicZ );
+
+private: //member
+ std::vector<
+ rtl::Reference< ::chart::GridProperties > > m_aGridPropertiesList;//main grid, subgrid, subsubgrid etc
+ std::unique_ptr<PolarPlottingPositionHelper> m_pPosHelper;
+ std::vector< ExplicitIncrementData > m_aIncrements;
+
+ void getAllTickInfos( sal_Int32 nDimensionIndex, TickInfoArraysType& rAllTickInfos ) const;
+
+ void create2DRadiusGrid( const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget
+ , TickInfoArraysType& rRadiusTickInfos
+ , TickInfoArraysType& rAngleTickInfos
+ , const std::vector<VLineProperties>& rLinePropertiesList );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VPolarRadiusAxis.cxx b/chart2/source/view/axes/VPolarRadiusAxis.cxx
new file mode 100644
index 0000000000..f93315410e
--- /dev/null
+++ b/chart2/source/view/axes/VPolarRadiusAxis.cxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VPolarRadiusAxis.hxx"
+#include "VCartesianAxis.hxx"
+#include <PlottingPositionHelper.hxx>
+#include <Axis.hxx>
+#include <CommonConverters.hxx>
+#include "Tickmarks_Equidistant.hxx"
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+VPolarRadiusAxis::VPolarRadiusAxis( const AxisProperties& rAxisProperties
+ , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionCount )
+ : VPolarAxis( rAxisProperties, xNumberFormatsSupplier, 1/*nDimensionIndex*/, nDimensionCount )
+{
+ m_aAxisProperties.maLabelAlignment.mfLabelDirection = 0.0;
+ m_aAxisProperties.maLabelAlignment.mfInnerTickDirection = 0.0;
+ m_aAxisProperties.maLabelAlignment.meAlignment = LABEL_ALIGN_RIGHT;
+ m_aAxisProperties.m_bIsMainAxis=false;
+ m_aAxisProperties.init();
+
+ m_apAxisWithLabels.reset( new VCartesianAxis(
+ m_aAxisProperties,xNumberFormatsSupplier,1/*nDimensionIndex*/,nDimensionCount
+ ,new PolarPlottingPositionHelper() ) );
+}
+
+VPolarRadiusAxis::~VPolarRadiusAxis()
+{
+}
+
+void VPolarRadiusAxis::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix)
+{
+ VPolarAxis::setTransformationSceneToScreen( rMatrix );
+ m_apAxisWithLabels->setTransformationSceneToScreen( rMatrix );
+}
+
+void VPolarRadiusAxis::setExplicitScaleAndIncrement(
+ const ExplicitScaleData& rScale
+ , const ExplicitIncrementData& rIncrement )
+{
+ VPolarAxis::setExplicitScaleAndIncrement( rScale, rIncrement );
+ m_apAxisWithLabels->setExplicitScaleAndIncrement( rScale, rIncrement );
+}
+
+void VPolarRadiusAxis::initPlotter( const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget
+ , const rtl::Reference<SvxShapeGroupAnyD>& xFinalTarget
+ , const OUString& rCID )
+{
+ VPolarAxis::initPlotter( xLogicTarget, xFinalTarget, rCID );
+ m_apAxisWithLabels->initPlotter( xLogicTarget, xFinalTarget, rCID );
+}
+
+void VPolarRadiusAxis::setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis )
+{
+ VPolarAxis::setScales( std::vector(rScales), bSwapXAndYAxis );
+ m_apAxisWithLabels->setScales( std::move(rScales), bSwapXAndYAxis );
+}
+
+void VPolarRadiusAxis::initAxisLabelProperties( const css::awt::Size& rFontReferenceSize
+ , const css::awt::Rectangle& rMaximumSpaceForLabels )
+{
+ VPolarAxis::initAxisLabelProperties( rFontReferenceSize, rMaximumSpaceForLabels );
+ m_apAxisWithLabels->initAxisLabelProperties( rFontReferenceSize, rMaximumSpaceForLabels );
+}
+
+sal_Int32 VPolarRadiusAxis::estimateMaximumAutoMainIncrementCount()
+{
+ return 2;
+}
+
+bool VPolarRadiusAxis::prepareShapeCreation()
+{
+ //returns true if all is ready for further shape creation and any shapes need to be created
+ if( !isAnythingToDraw() )
+ return false;
+
+ if( m_xGroupShape_Shapes.is() )
+ return true;
+
+ return true;
+}
+
+void VPolarRadiusAxis::createMaximumLabels()
+{
+ m_apAxisWithLabels->createMaximumLabels();
+}
+
+void VPolarRadiusAxis::updatePositions()
+{
+ m_apAxisWithLabels->updatePositions();
+}
+
+void VPolarRadiusAxis::createLabels()
+{
+ m_apAxisWithLabels->createLabels();
+}
+
+void VPolarRadiusAxis::createShapes()
+{
+ if( !prepareShapeCreation() )
+ return;
+
+ const ExplicitScaleData& rAngleScale = m_pPosHelper->getScales()[0];
+ const ExplicitIncrementData& rAngleIncrement = m_aIncrements[0];
+
+ TickInfoArraysType aAngleTickInfos;
+ TickFactory aAngleTickFactory( rAngleScale, rAngleIncrement );
+ aAngleTickFactory.getAllTicks( aAngleTickInfos );
+
+ uno::Reference< XScaling > xInverseScaling;
+ if( rAngleScale.Scaling.is() )
+ xInverseScaling = rAngleScale.Scaling->getInverseScaling();
+
+ AxisProperties aAxisProperties(m_aAxisProperties);
+
+ sal_Int32 nTick = 0;
+ EquidistantTickIter aIter( aAngleTickInfos, rAngleIncrement, 0 );
+ for( TickInfo* pTickInfo = aIter.firstInfo()
+ ; pTickInfo; pTickInfo = aIter.nextInfo(), nTick++ )
+ {
+ if( nTick == 0 )
+ {
+ m_apAxisWithLabels->createShapes();
+ continue;
+ }
+
+ //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling );
+ aAxisProperties.m_pfMainLinePositionAtOtherAxis = pTickInfo->getUnscaledTickValue();
+ aAxisProperties.m_bDisplayLabels=false;
+
+ VCartesianAxis aAxis(aAxisProperties,m_xNumberFormatsSupplier
+ ,1,2,new PolarPlottingPositionHelper());
+ aAxis.setExplicitScaleAndIncrement( m_aScale, m_aIncrement );
+ aAxis.initPlotter(m_xLogicTarget,m_xFinalTarget, m_aCID );
+ aAxis.setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( m_aMatrixScreenToScene ) );
+ aAxis.setScales( std::vector(m_pPosHelper->getScales()), false );
+ aAxis.initAxisLabelProperties(m_aAxisLabelProperties.m_aFontReferenceSize,m_aAxisLabelProperties.m_aMaximumSpaceForLabels);
+ aAxis.createShapes();
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VPolarRadiusAxis.hxx b/chart2/source/view/axes/VPolarRadiusAxis.hxx
new file mode 100644
index 0000000000..b2450e2362
--- /dev/null
+++ b/chart2/source/view/axes/VPolarRadiusAxis.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "VPolarAxis.hxx"
+#include <memory>
+
+namespace chart
+{
+
+class VCartesianAxis;
+
+class VPolarRadiusAxis : public VPolarAxis
+{
+public:
+ VPolarRadiusAxis( const AxisProperties& rAxisProperties
+ , const css::uno::Reference< css::util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , sal_Int32 nDimensionCount );
+ virtual ~VPolarRadiusAxis() override;
+
+ virtual void initPlotter(
+ const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget
+ , const rtl::Reference<SvxShapeGroupAnyD>& xFinalTarget
+ , const OUString& rCID
+ ) override;
+
+ virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix ) override;
+
+ virtual void setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ) override;
+
+ virtual void setExplicitScaleAndIncrement(
+ const ExplicitScaleData& rScale
+ , const ExplicitIncrementData& rIncrement ) override;
+
+ virtual void initAxisLabelProperties(
+ const css::awt::Size& rFontReferenceSize
+ , const css::awt::Rectangle& rMaximumSpaceForLabels ) override;
+
+ virtual sal_Int32 estimateMaximumAutoMainIncrementCount() override;
+
+ virtual void createMaximumLabels() override;
+ virtual void createLabels() override;
+ virtual void updatePositions() override;
+
+ virtual void createShapes() override;
+
+protected: //methods
+ virtual bool prepareShapeCreation() override;
+
+private: //member
+ std::unique_ptr<VCartesianAxis> m_apAxisWithLabels;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/AreaChart.cxx b/chart2/source/view/charttypes/AreaChart.cxx
new file mode 100644
index 0000000000..e8af8c86c8
--- /dev/null
+++ b/chart2/source/view/charttypes/AreaChart.cxx
@@ -0,0 +1,952 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "AreaChart.hxx"
+#include <PlottingPositionHelper.hxx>
+#include <ShapeFactory.hxx>
+#include <CommonConverters.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <ObjectIdentifier.hxx>
+#include "Splines.hxx"
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <LabelPositionHelper.hxx>
+#include <Clipping.hxx>
+#include <Stripe.hxx>
+#include <DateHelper.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+
+#include <sal/log.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <officecfg/Office/Compatibility.hxx>
+#include <officecfg/Office/Chart.hxx>
+
+#include <limits>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+AreaChart::AreaChart( const rtl::Reference<ChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bCategoryXAxis
+ , bool bNoArea
+ )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount, bCategoryXAxis )
+ , m_pMainPosHelper(new PlottingPositionHelper())
+ , m_bArea(!bNoArea)
+ , m_bLine(bNoArea)
+ , m_bSymbol( ChartTypeHelper::isSupportingSymbolProperties(xChartTypeModel,nDimensionCount) )
+ , m_eCurveStyle(CurveStyle_LINES)
+ , m_nCurveResolution(20)
+ , m_nSplineOrder(3)
+{
+ m_pMainPosHelper->AllowShiftXAxisPos(true);
+ m_pMainPosHelper->AllowShiftZAxisPos(true);
+
+ PlotterBase::m_pPosHelper = m_pMainPosHelper.get();
+ VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper.get();
+
+ try
+ {
+ if( m_xChartTypeModel.is() )
+ {
+ m_xChartTypeModel->getPropertyValue(CHART_UNONAME_CURVE_STYLE) >>= m_eCurveStyle;
+ m_xChartTypeModel->getPropertyValue(CHART_UNONAME_CURVE_RESOLUTION) >>= m_nCurveResolution;
+ m_xChartTypeModel->getPropertyValue(CHART_UNONAME_SPLINE_ORDER) >>= m_nSplineOrder;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ //the above properties are not supported by all charttypes supported by this class (e.g. area or net chart)
+ //in that cases this exception is ok
+ e.Context.is();//to have debug information without compilation warnings
+ }
+}
+
+AreaChart::~AreaChart()
+{
+}
+
+bool AreaChart::isSeparateStackingForDifferentSigns( sal_Int32 /*nDimensionIndex*/ )
+{
+ // no separate stacking in all types of line/area charts
+ return false;
+}
+
+LegendSymbolStyle AreaChart::getLegendSymbolStyle()
+{
+ if( m_bArea || m_nDimension == 3 )
+ return LegendSymbolStyle::Box;
+ return LegendSymbolStyle::Line;
+}
+
+uno::Any AreaChart::getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex )
+{
+ uno::Any aRet;
+
+ Symbol* pSymbolProperties = rSeries.getSymbolProperties( nPointIndex );
+ if( pSymbolProperties )
+ {
+ aRet <<= *pSymbolProperties;
+ }
+
+ return aRet;
+}
+
+drawing::Direction3D AreaChart::getPreferredDiagramAspectRatio() const
+{
+ drawing::Direction3D aRet(1,-1,1);
+ if( m_nDimension == 2 )
+ aRet = drawing::Direction3D(-1,-1,-1);
+ else if (m_pPosHelper)
+ {
+ drawing::Direction3D aScale( m_pPosHelper->getScaledLogicWidth() );
+ aRet.DirectionZ = aScale.DirectionZ*0.2;
+ if(aRet.DirectionZ>1.0)
+ aRet.DirectionZ=1.0;
+ if(aRet.DirectionZ>10)
+ aRet.DirectionZ=10;
+ }
+ return aRet;
+}
+
+void AreaChart::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
+{
+ if( m_bArea && pSeries )
+ {
+ sal_Int32 nMissingValueTreatment = pSeries->getMissingValueTreatment();
+ if( nMissingValueTreatment == css::chart::MissingValueTreatment::LEAVE_GAP )
+ pSeries->setMissingValueTreatment( css::chart::MissingValueTreatment::USE_ZERO );
+ }
+ if( m_nDimension == 3 && !m_bCategoryXAxis )
+ {
+ //3D xy always deep
+ OSL_ENSURE( zSlot==-1,"3D xy charts should be deep stacked in model also" );
+ zSlot=-1;
+ xSlot=0;
+ ySlot=0;
+ }
+ VSeriesPlotter::addSeries( std::move(pSeries), zSlot, xSlot, ySlot );
+}
+
+static void lcl_removeDuplicatePoints( std::vector<std::vector<css::drawing::Position3D>>& rPolyPoly, PlottingPositionHelper& rPosHelper )
+{
+ sal_Int32 nPolyCount = rPolyPoly.size();
+ if(!nPolyCount)
+ return;
+
+ // TODO we could do with without a temporary array
+ std::vector<std::vector<css::drawing::Position3D>> aTmp;
+ aTmp.resize(nPolyCount);
+
+ for( sal_Int32 nPolygonIndex = 0; nPolygonIndex<nPolyCount; nPolygonIndex++ )
+ {
+ std::vector<css::drawing::Position3D>* pOuterSource = &rPolyPoly[nPolygonIndex];
+ std::vector<css::drawing::Position3D>* pOuterTarget = &aTmp[nPolygonIndex];
+
+ sal_Int32 nPointCount = pOuterSource->size();
+ if( !nPointCount )
+ continue;
+
+ pOuterTarget->resize(nPointCount);
+
+ css::drawing::Position3D* pSource = pOuterSource->data();
+ css::drawing::Position3D* pTarget = pOuterTarget->data();
+
+ //copy first point
+ *pTarget=*pSource++;
+ sal_Int32 nTargetPointCount=1;
+
+ for( sal_Int32 nSource=1; nSource<nPointCount; nSource++ )
+ {
+ if( !rPosHelper.isSameForGivenResolution( pTarget->PositionX, pTarget->PositionY, pTarget->PositionZ
+ , pSource->PositionX, pSource->PositionY, pSource->PositionZ ) )
+ {
+ pTarget++;
+ *pTarget=*pSource;
+ nTargetPointCount++;
+ }
+ pSource++;
+ }
+
+ //free unused space
+ if( nTargetPointCount<nPointCount )
+ {
+ pOuterTarget->resize(nTargetPointCount);
+ }
+
+ pOuterSource->clear();
+ }
+
+ //free space
+ rPolyPoly.resize(nPolyCount);
+
+ rPolyPoly = std::move(aTmp);
+}
+
+bool AreaChart::create_stepped_line(
+ std::vector<std::vector<css::drawing::Position3D>> aStartPoly,
+ chart2::CurveStyle eCurveStyle,
+ PlottingPositionHelper const * pPosHelper,
+ std::vector<std::vector<css::drawing::Position3D>> &aPoly )
+{
+ sal_uInt32 nOuterCount = aStartPoly.size();
+ if ( !nOuterCount )
+ return false;
+
+ std::vector<std::vector<css::drawing::Position3D>> aSteppedPoly;
+ aSteppedPoly.resize(nOuterCount);
+
+ auto pSequence = aSteppedPoly.data();
+
+ for( sal_uInt32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+ {
+ if( aStartPoly[nOuter].size() <= 1 )
+ continue; //we need at least two points
+
+ sal_uInt32 nMaxIndexPoints = aStartPoly[nOuter].size()-1; // is >1
+ sal_uInt32 nNewIndexPoints = 0;
+ if ( eCurveStyle==CurveStyle_STEP_START || eCurveStyle==CurveStyle_STEP_END)
+ nNewIndexPoints = nMaxIndexPoints * 2 + 1;
+ else
+ nNewIndexPoints = nMaxIndexPoints * 3 + 1;
+
+ const css::drawing::Position3D* pOld = aStartPoly[nOuter].data();
+
+ pSequence[nOuter].resize( nNewIndexPoints );
+
+ css::drawing::Position3D* pNew = pSequence[nOuter].data();
+
+ pNew[0] = pOld[0];
+ for( sal_uInt32 oi = 0; oi < nMaxIndexPoints; oi++ )
+ {
+ switch ( eCurveStyle )
+ {
+ case CurveStyle_STEP_START:
+ /** O
+ |
+ |
+ |
+ O-----+
+ */
+ // create the intermediate point
+ pNew[1+oi*2].PositionX = pOld[oi+1].PositionX;
+ pNew[1+oi*2].PositionY = pOld[oi].PositionY;
+ pNew[1+oi*2].PositionZ = pOld[oi].PositionZ;
+ // and now the normal one
+ pNew[1+oi*2+1] = pOld[oi+1];
+ break;
+ case CurveStyle_STEP_END:
+ /** +------O
+ |
+ |
+ |
+ O
+ */
+ // create the intermediate point
+ pNew[1+oi*2].PositionX = pOld[oi].PositionX;
+ pNew[1+oi*2].PositionY = pOld[oi+1].PositionY;
+ pNew[1+oi*2].PositionZ = pOld[oi].PositionZ;
+ // and now the normal one
+ pNew[1+oi*2+1] = pOld[oi+1];
+ break;
+ case CurveStyle_STEP_CENTER_X:
+ /** +--O
+ |
+ |
+ |
+ O--+
+ */
+ // create the first intermediate point
+ pNew[1+oi*3].PositionX = (pOld[oi].PositionX + pOld[oi+1].PositionX) / 2;
+ pNew[1+oi*3].PositionY = pOld[oi].PositionY;
+ pNew[1+oi*3].PositionZ = pOld[oi].PositionZ;
+ // create the second intermediate point
+ pNew[1+oi*3+1].PositionX = (pOld[oi].PositionX + pOld[oi+1].PositionX) / 2;
+ pNew[1+oi*3+1].PositionY = pOld[oi+1].PositionY;
+ pNew[1+oi*3+1].PositionZ = pOld[oi].PositionZ;
+ // and now the normal one
+ pNew[1+oi*3+2] = pOld[oi+1];
+ break;
+ case CurveStyle_STEP_CENTER_Y:
+ /** O
+ |
+ +-----+
+ |
+ O
+ */
+ // create the first intermediate point
+ pNew[1+oi*3].PositionX = pOld[oi].PositionX;
+ pNew[1+oi*3].PositionY = (pOld[oi].PositionY + pOld[oi+1].PositionY) / 2;
+ pNew[1+oi*3].PositionZ = pOld[oi].PositionZ;
+ // create the second intermediate point
+ pNew[1+oi*3+1].PositionX = pOld[oi+1].PositionX;
+ pNew[1+oi*3+1].PositionY = (pOld[oi].PositionY + pOld[oi+1].PositionY) / 2;
+ pNew[1+oi*3+1].PositionZ = pOld[oi].PositionZ;
+ // and now the normal one
+ pNew[1+oi*3+2] = pOld[oi+1];
+ break;
+ default:
+ // this should never be executed
+ OSL_FAIL("Unknown curvestyle in AreaChart::create_stepped_line");
+ }
+ }
+ }
+ Clipping::clipPolygonAtRectangle( aSteppedPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+
+ return true;
+}
+
+bool AreaChart::impl_createLine( VDataSeries* pSeries
+ , std::vector<std::vector<css::drawing::Position3D>> const * pSeriesPoly
+ , PlottingPositionHelper* pPosHelper )
+{
+ //return true if a line was created successfully
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
+
+ std::vector<std::vector<css::drawing::Position3D>> aPoly;
+ if(m_eCurveStyle==CurveStyle_CUBIC_SPLINES)
+ {
+ std::vector<std::vector<css::drawing::Position3D>> aSplinePoly;
+ SplineCalculater::CalculateCubicSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution );
+ lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
+ Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+ }
+ else if(m_eCurveStyle==CurveStyle_B_SPLINES)
+ {
+ std::vector<std::vector<css::drawing::Position3D>> aSplinePoly;
+ SplineCalculater::CalculateBSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution, m_nSplineOrder );
+ lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
+ Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+ }
+ else if (m_eCurveStyle==CurveStyle_STEP_START ||
+ m_eCurveStyle==CurveStyle_STEP_END ||
+ m_eCurveStyle==CurveStyle_STEP_CENTER_Y ||
+ m_eCurveStyle==CurveStyle_STEP_CENTER_X
+ )
+ {
+ if (!create_stepped_line(*pSeriesPoly, m_eCurveStyle, pPosHelper, aPoly))
+ {
+ return false;
+ }
+ }
+ else
+ { // default to creating a straight line
+ SAL_WARN_IF(m_eCurveStyle != CurveStyle_LINES, "chart2.areachart", "Unknown curve style");
+ Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+ }
+
+ if(!ShapeFactory::hasPolygonAnyLines(aPoly))
+ return false;
+
+ //transformation 3) -> 4)
+ pPosHelper->transformScaledLogicToScene( aPoly );
+
+ //create line:
+ rtl::Reference< SvxShape > xShape;
+ if(m_nDimension==3)
+ {
+ double fDepth = getTransformedDepth();
+ sal_Int32 nPolyCount = aPoly.size();
+ for(sal_Int32 nPoly=0;nPoly<nPolyCount;nPoly++)
+ {
+ sal_Int32 nPointCount = aPoly[nPoly].size();
+ for(sal_Int32 nPoint=0;nPoint<nPointCount-1;nPoint++)
+ {
+ drawing::Position3D aPoint1, aPoint2;
+ aPoint1 = aPoly[nPoly][nPoint+1];
+ aPoint2 = aPoly[nPoly][nPoint];
+
+ ShapeFactory::createStripe(xSeriesGroupShape_Shapes
+ , Stripe( aPoint1, aPoint2, fDepth )
+ , pSeries->getPropertiesOfSeries(), PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), true, 1 );
+ }
+ }
+ }
+ else //m_nDimension!=3
+ {
+ xShape = ShapeFactory::createLine2D( xSeriesGroupShape_Shapes, aPoly );
+ PropertyMapper::setMappedProperties( *xShape
+ , pSeries->getPropertiesOfSeries()
+ , PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
+ //because of this name this line will be used for marking
+ ::chart::ShapeFactory::setShapeName(xShape, "MarkHandles");
+ }
+ return true;
+}
+
+bool AreaChart::impl_createArea( VDataSeries* pSeries
+ , std::vector<std::vector<css::drawing::Position3D>> const * pSeriesPoly
+ , std::vector<std::vector<css::drawing::Position3D>> const * pPreviousSeriesPoly
+ , PlottingPositionHelper const * pPosHelper )
+{
+ //return true if an area was created successfully
+
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
+ double zValue = pSeries->m_fLogicZPos;
+
+ std::vector<std::vector<css::drawing::Position3D>> aPoly( *pSeriesPoly );
+ //add second part to the polygon (grounding points or previous series points)
+ if(!pPreviousSeriesPoly)
+ {
+ double fMinX = pSeries->m_fLogicMinX;
+ double fMaxX = pSeries->m_fLogicMaxX;
+ double fY = pPosHelper->getBaseValueY();//logic grounding
+ if( m_nDimension==3 )
+ fY = pPosHelper->getLogicMinY();
+
+ //clip to scale
+ if(fMaxX<pPosHelper->getLogicMinX() || fMinX>pPosHelper->getLogicMaxX())
+ return false;//no visible shape needed
+ pPosHelper->clipLogicValues( &fMinX, &fY, nullptr );
+ pPosHelper->clipLogicValues( &fMaxX, nullptr, nullptr );
+
+ //apply scaling
+ {
+ pPosHelper->doLogicScaling( &fMinX, &fY, &zValue );
+ pPosHelper->doLogicScaling( &fMaxX, nullptr, nullptr );
+ }
+
+ AddPointToPoly( aPoly, drawing::Position3D( fMaxX,fY,zValue) );
+ AddPointToPoly( aPoly, drawing::Position3D( fMinX,fY,zValue) );
+ }
+ else
+ {
+ appendPoly( aPoly, *pPreviousSeriesPoly );
+ }
+ ShapeFactory::closePolygon(aPoly);
+
+ //apply clipping
+ {
+ std::vector<std::vector<css::drawing::Position3D>> aClippedPoly;
+ Clipping::clipPolygonAtRectangle( aPoly, pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly, false );
+ ShapeFactory::closePolygon(aClippedPoly); //again necessary after clipping
+ aPoly = aClippedPoly;
+ }
+
+ if(!ShapeFactory::hasPolygonAnyLines(aPoly))
+ return false;
+
+ //transformation 3) -> 4)
+ pPosHelper->transformScaledLogicToScene( aPoly );
+
+ //create area:
+ rtl::Reference< SvxShape > xShape;
+ if(m_nDimension==3)
+ {
+ xShape = ShapeFactory::createArea3D( xSeriesGroupShape_Shapes
+ , aPoly, getTransformedDepth() );
+ }
+ else //m_nDimension!=3
+ {
+ xShape = ShapeFactory::createArea2D( xSeriesGroupShape_Shapes
+ , aPoly );
+ }
+ PropertyMapper::setMappedProperties( *xShape
+ , pSeries->getPropertiesOfSeries()
+ , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ //because of this name this line will be used for marking
+ ::chart::ShapeFactory::setShapeName(xShape, "MarkHandles");
+ return true;
+}
+
+void AreaChart::impl_createSeriesShapes()
+{
+ //the polygon shapes for each series need to be created before
+
+ //iterate through all series again to create the series shapes
+ for( auto const& rZSlot : m_aZSlots )
+ {
+ for( auto const& rXSlot : rZSlot )
+ {
+ std::map< sal_Int32, std::vector<std::vector<css::drawing::Position3D>>* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex
+ std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly = nullptr;
+
+ //iterate through all series
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
+ PlottingPositionHelper& rPosHelper = getPlottingPositionHelper(nAttachedAxisIndex);
+ m_pPosHelper = &rPosHelper;
+
+ createRegressionCurvesShapes( *pSeries, m_xErrorBarTarget, m_xRegressionCurveEquationTarget,
+ m_pPosHelper->maySkipPointsInRegressionCalculation());
+
+ pSeriesPoly = &pSeries->m_aPolyPolygonShape3D;
+ if( m_bArea )
+ {
+ if (!impl_createArea(pSeries.get(), pSeriesPoly,
+ aPreviousSeriesPolyMap[nAttachedAxisIndex], &rPosHelper))
+ continue;
+ }
+ if( m_bLine )
+ {
+ if (!impl_createLine(pSeries.get(), pSeriesPoly, &rPosHelper))
+ continue;
+ }
+ aPreviousSeriesPolyMap[nAttachedAxisIndex] = pSeriesPoly;
+ }//next series in x slot (next y slot)
+ }//next x slot
+ }//next z slot
+}
+
+namespace
+{
+
+void lcl_reorderSeries( std::vector< std::vector< VDataSeriesGroup > >& rZSlots )
+{
+ std::vector< std::vector< VDataSeriesGroup > > aRet;
+ aRet.reserve( rZSlots.size() );
+
+ std::vector< std::vector< VDataSeriesGroup > >::reverse_iterator aZIt( rZSlots.rbegin() );
+ std::vector< std::vector< VDataSeriesGroup > >::reverse_iterator aZEnd( rZSlots.rend() );
+ for( ; aZIt != aZEnd; ++aZIt )
+ {
+ std::vector< VDataSeriesGroup > aXSlot;
+ aXSlot.reserve( aZIt->size() );
+
+ std::vector< VDataSeriesGroup >::reverse_iterator aXIt( aZIt->rbegin() );
+ std::vector< VDataSeriesGroup >::reverse_iterator aXEnd( aZIt->rend() );
+ for( ; aXIt != aXEnd; ++aXIt )
+ aXSlot.push_back(std::move(*aXIt));
+
+ aRet.push_back(std::move(aXSlot));
+ }
+
+ rZSlots = std::move(aRet);
+}
+
+//better performance for big data
+struct FormerPoint
+{
+ FormerPoint( double fX, double fY, double fZ )
+ : m_fX(fX), m_fY(fY), m_fZ(fZ)
+ {}
+ FormerPoint()
+ : m_fX(std::numeric_limits<double>::quiet_NaN())
+ , m_fY(std::numeric_limits<double>::quiet_NaN())
+ , m_fZ(std::numeric_limits<double>::quiet_NaN())
+ {
+ }
+
+ double m_fX;
+ double m_fY;
+ double m_fZ;
+};
+
+}//anonymous namespace
+
+void AreaChart::createShapes()
+{
+ if( m_aZSlots.empty() ) //no series
+ return;
+
+ //tdf#127813 Don't reverse the series in OOXML-heavy environments
+ if( officecfg::Office::Compatibility::View::ReverseSeriesOrderAreaAndNetChart::get() && m_nDimension == 2 && ( m_bArea || !m_bCategoryXAxis ) )
+ lcl_reorderSeries( m_aZSlots );
+
+ OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"AreaChart is not proper initialized");
+ if(!(m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+
+ //the text labels should be always on top of the other series shapes
+ //for area chart the error bars should be always on top of the other series shapes
+
+ //therefore create an own group for the texts and the error bars to move them to front
+ //(because the text group is created after the series group the texts are displayed on top)
+ m_xSeriesTarget = createGroupShape( m_xLogicTarget );
+ if( m_bArea )
+ m_xErrorBarTarget = createGroupShape( m_xLogicTarget );
+ else
+ m_xErrorBarTarget = m_xSeriesTarget;
+ m_xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget );
+ m_xRegressionCurveEquationTarget = ShapeFactory::createGroup2D( m_xFinalTarget );
+
+ //check necessary here that different Y axis can not be stacked in the same group? ... hm?
+
+ //update/create information for current group
+ double fLogicZ = 1.0;//as defined
+
+ sal_Int32 nStartIndex = 0; // inclusive ;..todo get somehow from x scale
+ sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
+ if(nEndIndex<=0)
+ nEndIndex=1;
+
+ //better performance for big data
+ std::map< VDataSeries*, FormerPoint > aSeriesFormerPointMap;
+ m_bPointsWereSkipped = false;
+ sal_Int32 nSkippedPoints = 0;
+ sal_Int32 nCreatedPoints = 0;
+
+ bool bDateCategory = (m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis());
+
+ std::vector<std::map< sal_Int32, double > > aLogicYSumMapByX(nEndIndex);//one for each different nAttachedAxisIndex
+ for( auto const& rZSlot : m_aZSlots )
+ {
+ //iterate through all x slots in this category to get 100percent sum
+ for( auto const& rXSlot : rZSlot )
+ {
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ if(!pSeries)
+ continue;
+
+ if (bDateCategory)
+ pSeries->doSortByXValues();
+
+ for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ )
+ {
+ std::map< sal_Int32, double >& rLogicYSumMap = aLogicYSumMapByX[nIndex];
+ sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
+ rLogicYSumMap.insert({nAttachedAxisIndex, 0.0});
+
+ m_pPosHelper = &getPlottingPositionHelper(nAttachedAxisIndex);
+
+ double fAdd = pSeries->getYValue( nIndex );
+ if( !std::isnan(fAdd) && !std::isinf(fAdd) )
+ rLogicYSumMap[nAttachedAxisIndex] += fabs( fAdd );
+ }
+ }
+ }
+ }
+
+ const bool bUseErrorRectangle = officecfg::Office::Chart::ErrorProperties::ErrorRectangle::get();
+
+ sal_Int32 nZ=1;
+ for( auto const& rZSlot : m_aZSlots )
+ {
+ //for the area chart there should be at most one x slot (no side by side stacking available)
+ //attention different: xSlots are always interpreted as independent areas one behind the other: @todo this doesn't work why not???
+ for( auto const& rXSlot : rZSlot )
+ {
+ std::vector<std::map< sal_Int32, double > > aLogicYForNextSeriesMapByX(nEndIndex); //one for each different nAttachedAxisIndex
+ //iterate through all series
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ if(!pSeries)
+ continue;
+
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeFrontChild(pSeries.get(), m_xSeriesTarget);
+
+ sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
+ double fXMin, fXMax;
+ pSeries->getMinMaxXValue(fXMin, fXMax);
+ PlottingPositionHelper& rPosHelper = getPlottingPositionHelper(nAttachedAxisIndex);
+ m_pPosHelper = &rPosHelper;
+
+ if(m_nDimension==3)
+ fLogicZ = nZ+0.5;
+ pSeries->m_fLogicZPos = fLogicZ;
+
+ for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ )
+ {
+
+ /* #i70133# ignore points outside of series length in standard area
+ charts. Stacked area charts will use missing points as zeros. In
+ standard charts, pSeriesList contains only one series. */
+ if( m_bArea && (rXSlot.m_aSeriesVector.size() == 1) && (nIndex >= pSeries->getTotalPointCount()) )
+ continue;
+
+ //collect data point information (logic coordinates, style ):
+ double fLogicX = pSeries->getXValue(nIndex);
+ if (bDateCategory)
+ {
+ if (std::isnan(fLogicX) || (fLogicX < fXMin || fLogicX > fXMax))
+ continue;
+
+ fLogicX = DateHelper::RasterizeDateValue( fLogicX, m_aNullDate, m_nTimeResolution );
+ }
+ double fLogicY = pSeries->getYValue(nIndex);
+
+ if( m_nDimension==3 && m_bArea && rXSlot.m_aSeriesVector.size()!=1 )
+ fLogicY = fabs( fLogicY );
+
+ double fLogicValueForLabeDisplay = fLogicY;
+ std::map< sal_Int32, double >& rLogicYSumMap = aLogicYSumMapByX[nIndex];
+ if (rPosHelper.isPercentY() && rLogicYSumMap[nAttachedAxisIndex] != 0.0)
+ {
+ fLogicY = fabs( fLogicY )/rLogicYSumMap[nAttachedAxisIndex];
+ }
+
+ if( std::isnan(fLogicX) || std::isinf(fLogicX)
+ || std::isnan(fLogicY) || std::isinf(fLogicY)
+ || std::isnan(fLogicZ) || std::isinf(fLogicZ) )
+ {
+ if( pSeries->getMissingValueTreatment() == css::chart::MissingValueTreatment::LEAVE_GAP )
+ {
+ std::vector<std::vector<css::drawing::Position3D>>& rPolygon = pSeries->m_aPolyPolygonShape3D;
+ sal_Int32& rIndex = pSeries->m_nPolygonIndex;
+ if( 0<= rIndex && o3tl::make_unsigned(rIndex) < rPolygon.size() )
+ {
+ if( !rPolygon[ rIndex ].empty() )
+ rIndex++; //start a new polygon for the next point if the current poly is not empty
+ }
+ }
+ continue;
+ }
+
+ std::map< sal_Int32, double >& rLogicYForNextSeriesMap = aLogicYForNextSeriesMapByX[nIndex];
+ rLogicYForNextSeriesMap.try_emplace(nAttachedAxisIndex, 0.0);
+
+ double fPreviousYValue = rLogicYForNextSeriesMap[nAttachedAxisIndex];
+ fLogicY += rLogicYForNextSeriesMap[nAttachedAxisIndex];
+ rLogicYForNextSeriesMap[nAttachedAxisIndex] = fLogicY;
+
+ bool bIsVisible = rPosHelper.isLogicVisible(fLogicX, fLogicY, fLogicZ);
+
+ //remind minimal and maximal x values for area 'grounding' points
+ //only for filled area
+ {
+ double& rfMinX = pSeries->m_fLogicMinX;
+ if(!nIndex||fLogicX<rfMinX)
+ rfMinX=fLogicX;
+ double& rfMaxX = pSeries->m_fLogicMaxX;
+ if(!nIndex||fLogicX>rfMaxX)
+ rfMaxX=fLogicX;
+ }
+
+ drawing::Position3D aUnscaledLogicPosition( fLogicX, fLogicY, fLogicZ );
+ drawing::Position3D aScaledLogicPosition(aUnscaledLogicPosition);
+ rPosHelper.doLogicScaling(aScaledLogicPosition);
+
+ //transformation 3) -> 4)
+ drawing::Position3D aScenePosition(
+ rPosHelper.transformLogicToScene(fLogicX, fLogicY, fLogicZ, false));
+
+ //better performance for big data
+ FormerPoint aFormerPoint( aSeriesFormerPointMap[pSeries.get()] );
+ rPosHelper.setCoordinateSystemResolution(m_aCoordinateSystemResolution);
+ if (!pSeries->isAttributedDataPoint(nIndex)
+ && rPosHelper.isSameForGivenResolution(
+ aFormerPoint.m_fX, aFormerPoint.m_fY, aFormerPoint.m_fZ,
+ aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY,
+ aScaledLogicPosition.PositionZ))
+ {
+ ++nSkippedPoints;
+ m_bPointsWereSkipped = true;
+ continue;
+ }
+ aSeriesFormerPointMap[pSeries.get()] = FormerPoint(aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ);
+
+ //store point information for series polygon
+ //for area and/or line (symbols only do not need this)
+ if( isValidPosition(aScaledLogicPosition) )
+ {
+ AddPointToPoly( pSeries->m_aPolyPolygonShape3D, aScaledLogicPosition, pSeries->m_nPolygonIndex );
+ }
+
+ //create a single datapoint if point is visible
+ //apply clipping:
+ if( !bIsVisible )
+ continue;
+
+ bool bCreateYErrorBar = false, bCreateXErrorBar = false;
+ {
+ uno::Reference< beans::XPropertySet > xErrorBarProp(pSeries->getYErrorBarProperties(nIndex));
+ if( xErrorBarProp.is() )
+ {
+ bool bShowPositive = false;
+ bool bShowNegative = false;
+ xErrorBarProp->getPropertyValue("ShowPositiveError") >>= bShowPositive;
+ xErrorBarProp->getPropertyValue("ShowNegativeError") >>= bShowNegative;
+ bCreateYErrorBar = bShowPositive || bShowNegative;
+ }
+
+ xErrorBarProp = pSeries->getXErrorBarProperties(nIndex);
+ if ( xErrorBarProp.is() )
+ {
+ bool bShowPositive = false;
+ bool bShowNegative = false;
+ xErrorBarProp->getPropertyValue("ShowPositiveError") >>= bShowPositive;
+ xErrorBarProp->getPropertyValue("ShowNegativeError") >>= bShowNegative;
+ bCreateXErrorBar = bShowPositive || bShowNegative;
+ }
+ }
+
+ Symbol* pSymbolProperties = m_bSymbol ? pSeries->getSymbolProperties( nIndex ) : nullptr;
+ bool bCreateSymbol = pSymbolProperties && (pSymbolProperties->Style != SymbolStyle_NONE);
+
+ if( !bCreateSymbol && !bCreateYErrorBar &&
+ !bCreateXErrorBar && !pSeries->getDataPointLabelIfLabel(nIndex) )
+ continue;
+
+ {
+ nCreatedPoints++;
+
+ //create data point
+ drawing::Direction3D aSymbolSize(0,0,0);
+ if( bCreateSymbol )
+ {
+ if(m_nDimension!=3)
+ {
+ //create a group shape for this point and add to the series shape:
+ OUString aPointCID = ObjectIdentifier::createPointCID(
+ pSeries->getPointCID_Stub(), nIndex );
+ rtl::Reference<SvxShapeGroupAnyD> xPointGroupShape_Shapes;
+ if (pSymbolProperties->Style == SymbolStyle_STANDARD || pSymbolProperties->Style == SymbolStyle_GRAPHIC)
+ xPointGroupShape_Shapes = createGroupShape(xSeriesGroupShape_Shapes,aPointCID);
+
+ if (pSymbolProperties->Style != SymbolStyle_NONE)
+ {
+ aSymbolSize.DirectionX = pSymbolProperties->Size.Width;
+ aSymbolSize.DirectionY = pSymbolProperties->Size.Height;
+ }
+
+ if (pSymbolProperties->Style == SymbolStyle_STANDARD)
+ {
+ sal_Int32 nSymbol = pSymbolProperties->StandardSymbol;
+ ShapeFactory::createSymbol2D(
+ xPointGroupShape_Shapes, aScenePosition, aSymbolSize,
+ nSymbol, pSymbolProperties->BorderColor,
+ pSymbolProperties->FillColor);
+ }
+ else if (pSymbolProperties->Style == SymbolStyle_GRAPHIC)
+ {
+ ShapeFactory::createGraphic2D(xPointGroupShape_Shapes,
+ aScenePosition, aSymbolSize,
+ pSymbolProperties->Graphic);
+ }
+ //@todo other symbol styles
+ }
+ }
+ //create error bars or rectangles, depending on configuration
+ if ( bUseErrorRectangle )
+ {
+ if ( bCreateXErrorBar || bCreateYErrorBar )
+ {
+ createErrorRectangle(
+ aUnscaledLogicPosition,
+ *pSeries,
+ nIndex,
+ m_xErrorBarTarget,
+ bCreateXErrorBar,
+ bCreateYErrorBar );
+ }
+ }
+ else
+ {
+ if (bCreateXErrorBar)
+ createErrorBar_X( aUnscaledLogicPosition, *pSeries, nIndex, m_xErrorBarTarget );
+
+ if (bCreateYErrorBar)
+ createErrorBar_Y( aUnscaledLogicPosition, *pSeries, nIndex, m_xErrorBarTarget, nullptr );
+ }
+
+ //create data point label
+ if( pSeries->getDataPointLabelIfLabel(nIndex) )
+ {
+ LabelAlignment eAlignment = LABEL_ALIGN_TOP;
+ sal_Int32 nLabelPlacement = pSeries->getLabelPlacement(
+ nIndex, m_xChartTypeModel, rPosHelper.isSwapXAndY());
+
+ if (m_bArea && nLabelPlacement == css::chart::DataLabelPlacement::CENTER)
+ {
+ if (fPreviousYValue)
+ fLogicY -= (fLogicY - fPreviousYValue) / 2.0;
+ else
+ fLogicY = (fLogicY + rPosHelper.getLogicMinY()) / 2.0;
+ aScenePosition = rPosHelper.transformLogicToScene(fLogicX, fLogicY, fLogicZ, false);
+ }
+
+ drawing::Position3D aScenePosition3D( aScenePosition.PositionX
+ , aScenePosition.PositionY
+ , aScenePosition.PositionZ+getTransformedDepth() );
+
+ switch(nLabelPlacement)
+ {
+ case css::chart::DataLabelPlacement::TOP:
+ aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_TOP;
+ break;
+ case css::chart::DataLabelPlacement::BOTTOM:
+ aScenePosition3D.PositionY += (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_BOTTOM;
+ break;
+ case css::chart::DataLabelPlacement::LEFT:
+ aScenePosition3D.PositionX -= (aSymbolSize.DirectionX/2+1);
+ eAlignment = LABEL_ALIGN_LEFT;
+ break;
+ case css::chart::DataLabelPlacement::RIGHT:
+ aScenePosition3D.PositionX += (aSymbolSize.DirectionX/2+1);
+ eAlignment = LABEL_ALIGN_RIGHT;
+ break;
+ case css::chart::DataLabelPlacement::CENTER:
+ eAlignment = LABEL_ALIGN_CENTER;
+ break;
+ default:
+ OSL_FAIL("this label alignment is not implemented yet");
+ aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_TOP;
+ break;
+ }
+
+ awt::Point aScreenPosition2D;//get the screen position for the labels
+ sal_Int32 nOffset = 100; //todo maybe calculate this font height dependent
+ {
+ if(eAlignment==LABEL_ALIGN_CENTER || m_nDimension == 3 )
+ nOffset = 0;
+ aScreenPosition2D = LabelPositionHelper(m_nDimension,m_xLogicTarget)
+ .transformSceneToScreenPosition( aScenePosition3D );
+ }
+
+ createDataLabel( m_xTextTarget, *pSeries, nIndex
+ , fLogicValueForLabeDisplay
+ , rLogicYSumMap[nAttachedAxisIndex], aScreenPosition2D, eAlignment, nOffset );
+ }
+ }
+ }
+
+ }//next series in x slot (next y slot)
+ }//next x slot
+ ++nZ;
+ }//next z slot
+
+ impl_createSeriesShapes();
+
+ /* @todo remove series shapes if empty
+ //remove and delete point-group-shape if empty
+ if(!xSeriesGroupShape_Shapes->getCount())
+ {
+ pSeries->m_xShape.set(NULL);
+ m_xLogicTarget->remove(xSeriesGroupShape_Shape);
+ }
+ */
+
+ //remove and delete series-group-shape if empty
+
+ //... todo
+
+ SAL_INFO(
+ "chart2",
+ "skipped points: " << nSkippedPoints << " created points: "
+ << nCreatedPoints);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/AreaChart.hxx b/chart2/source/view/charttypes/AreaChart.hxx
new file mode 100644
index 0000000000..2f7434f3c5
--- /dev/null
+++ b/chart2/source/view/charttypes/AreaChart.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <VSeriesPlotter.hxx>
+#include <com/sun/star/chart2/CurveStyle.hpp>
+
+namespace chart
+{
+
+class AreaChart : public VSeriesPlotter
+{
+ // public methods
+public:
+ AreaChart() = delete;
+
+ AreaChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bCategoryXAxis, bool bNoArea=false
+ );
+ virtual ~AreaChart() override;
+
+ virtual void createShapes() override;
+ virtual void addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot ) override;
+
+ virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override;
+
+ // MinimumAndMaximumSupplier
+ virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) override;
+
+ virtual LegendSymbolStyle getLegendSymbolStyle() override;
+ virtual css::uno::Any getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex/*-1 for series symbol*/ ) override;
+
+private: //methods
+ void impl_createSeriesShapes();
+ bool impl_createArea( VDataSeries* pSeries
+ , std::vector<std::vector<css::drawing::Position3D>> const * pSeriesPoly
+ , std::vector<std::vector<css::drawing::Position3D>> const * pPreviousSeriesPoly
+ , PlottingPositionHelper const * pPosHelper );
+ bool impl_createLine( VDataSeries* pSeries
+ , std::vector<std::vector<css::drawing::Position3D>> const * pSeriesPoly
+ , PlottingPositionHelper* pPosHelper );
+ static bool create_stepped_line( std::vector<std::vector<css::drawing::Position3D>> aStartPoly
+ , css::chart2::CurveStyle eCurveStyle
+ , PlottingPositionHelper const * pPosHelper
+ , std::vector<std::vector<css::drawing::Position3D>> &aPoly );
+
+private: //member
+ std::unique_ptr<PlottingPositionHelper>
+ m_pMainPosHelper;
+
+ bool m_bArea;//false -> line or symbol only
+ bool m_bLine;
+ bool m_bSymbol;
+
+ //Properties for splines:
+ css::chart2::CurveStyle m_eCurveStyle;
+ sal_Int32 m_nCurveResolution;
+ sal_Int32 m_nSplineOrder;
+
+ rtl::Reference<SvxShapeGroupAnyD> m_xSeriesTarget;
+ rtl::Reference<SvxShapeGroupAnyD> m_xErrorBarTarget;
+ rtl::Reference<SvxShapeGroupAnyD> m_xTextTarget;
+ rtl::Reference<SvxShapeGroupAnyD> m_xRegressionCurveEquationTarget;
+};
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/BarChart.cxx b/chart2/source/view/charttypes/BarChart.cxx
new file mode 100644
index 0000000000..eeb3026635
--- /dev/null
+++ b/chart2/source/view/charttypes/BarChart.cxx
@@ -0,0 +1,973 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "BarChart.hxx"
+#include "BarPositionHelper.hxx"
+
+#include <ChartType.hxx>
+#include <ShapeFactory.hxx>
+#include <CommonConverters.hxx>
+#include <ObjectIdentifier.hxx>
+#include <LabelPositionHelper.hxx>
+#include <AxisIndexDefines.hxx>
+#include <Clipping.hxx>
+#include <DateHelper.hxx>
+#include <svx/scene3d.hxx>
+#include <comphelper/scopeguard.hxx>
+
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+
+#include <com/sun/star/chart2/DataPointGeometry3D.hpp>
+#include <rtl/math.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::rtl::math;
+using namespace ::com::sun::star::chart2;
+
+BarChart::BarChart( const rtl::Reference<ChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount )
+ , m_pMainPosHelper( new BarPositionHelper() )
+{
+ PlotterBase::m_pPosHelper = m_pMainPosHelper.get();
+ VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper.get();
+
+ try
+ {
+ if( m_xChartTypeModel.is() )
+ {
+ m_xChartTypeModel->getPropertyValue( "OverlapSequence" ) >>= m_aOverlapSequence;
+ m_xChartTypeModel->getPropertyValue( "GapwidthSequence" ) >>= m_aGapwidthSequence;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+BarChart::~BarChart()
+{
+}
+
+PlottingPositionHelper& BarChart::getPlottingPositionHelper( sal_Int32 nAxisIndex ) const
+{
+ PlottingPositionHelper& rPosHelper = VSeriesPlotter::getPlottingPositionHelper( nAxisIndex );
+ BarPositionHelper* pBarPosHelper = dynamic_cast<BarPositionHelper*>(&rPosHelper);
+ if( pBarPosHelper && nAxisIndex >= 0 )
+ {
+ if( nAxisIndex < m_aOverlapSequence.getLength() )
+ pBarPosHelper->setInnerDistance( -m_aOverlapSequence[nAxisIndex]/100.0 );
+ if( nAxisIndex < m_aGapwidthSequence.getLength() )
+ pBarPosHelper->setOuterDistance( m_aGapwidthSequence[nAxisIndex]/100.0 );
+ }
+ return rPosHelper;
+}
+
+drawing::Direction3D BarChart::getPreferredDiagramAspectRatio() const
+{
+ drawing::Direction3D aRet(1.0,1.0,1.0);
+ if( m_nDimension == 3 )
+ {
+ aRet = drawing::Direction3D(1.0,-1.0,1.0);
+ BarPositionHelper* pPosHelper = dynamic_cast<BarPositionHelper*>(&( getPlottingPositionHelper( MAIN_AXIS_INDEX) ) );
+ if (pPosHelper)
+ {
+ drawing::Direction3D aScale( pPosHelper->getScaledLogicWidth() );
+ if(aScale.DirectionX!=0.0)
+ {
+ double fXSlotCount = 1.0;
+ if(!m_aZSlots.empty())
+ {
+ fXSlotCount = m_aZSlots.begin()->size();
+ }
+ aRet.DirectionZ = aScale.DirectionZ /
+ (aScale.DirectionX + aScale.DirectionX * (fXSlotCount-1.0) * pPosHelper->getScaledSlotWidth());
+ }
+ else
+ {
+ return VSeriesPlotter::getPreferredDiagramAspectRatio();
+ }
+ }
+ else
+ {
+ return VSeriesPlotter::getPreferredDiagramAspectRatio();
+ }
+
+ if(aRet.DirectionZ<0.05)
+ {
+ aRet.DirectionZ=0.05;
+ }
+ else if(aRet.DirectionZ>10)
+ {
+ aRet.DirectionZ=10;
+ }
+ if( m_pMainPosHelper && m_pMainPosHelper->isSwapXAndY() )
+ {
+ std::swap(aRet.DirectionX, aRet.DirectionY);
+ }
+ }
+ else
+ aRet = drawing::Direction3D(-1,-1,-1);
+ return aRet;
+}
+
+awt::Point BarChart::getLabelScreenPositionAndAlignment(
+ LabelAlignment& rAlignment, sal_Int32 nLabelPlacement
+ , double fScaledX, double fScaledLowerYValue, double fScaledUpperYValue, double fScaledZ
+ , double fScaledLowerBarDepth, double fScaledUpperBarDepth, double fBaseValue
+ , BarPositionHelper const * pPosHelper
+ ) const
+{
+ double fX = fScaledX;
+ double fY = fScaledUpperYValue;
+ double fZ = fScaledZ;
+ bool bReverse = !pPosHelper->isMathematicalOrientationY();
+ bool bNormalOutside = (!bReverse == (fBaseValue < fScaledUpperYValue));
+ double fDepth = fScaledUpperBarDepth;
+
+ switch(nLabelPlacement)
+ {
+ case css::chart::DataLabelPlacement::TOP:
+ {
+ if( !pPosHelper->isSwapXAndY() )
+ {
+ fY = bReverse ? fScaledLowerYValue : fScaledUpperYValue;
+ rAlignment = LABEL_ALIGN_TOP;
+ if(m_nDimension==3)
+ fDepth = bReverse ? fabs(fScaledLowerBarDepth) : fabs(fScaledUpperBarDepth);
+ }
+ else
+ {
+ fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
+ rAlignment = LABEL_ALIGN_CENTER;
+ OSL_FAIL( "top label placement is not really supported by horizontal bar charts" );
+ }
+ }
+ break;
+ case css::chart::DataLabelPlacement::BOTTOM:
+ {
+ if(!pPosHelper->isSwapXAndY())
+ {
+ fY = bReverse ? fScaledUpperYValue : fScaledLowerYValue;
+ rAlignment = LABEL_ALIGN_BOTTOM;
+ if(m_nDimension==3)
+ fDepth = bReverse ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
+ }
+ else
+ {
+ fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
+ rAlignment = LABEL_ALIGN_CENTER;
+ OSL_FAIL( "bottom label placement is not supported by horizontal bar charts" );
+ }
+ }
+ break;
+ case css::chart::DataLabelPlacement::LEFT:
+ {
+ if( pPosHelper->isSwapXAndY() )
+ {
+ fY = bReverse ? fScaledUpperYValue : fScaledLowerYValue;
+ rAlignment = LABEL_ALIGN_LEFT;
+ if(m_nDimension==3)
+ fDepth = bReverse ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
+ }
+ else
+ {
+ fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
+ rAlignment = LABEL_ALIGN_CENTER;
+ OSL_FAIL( "left label placement is not supported by column charts" );
+ }
+ }
+ break;
+ case css::chart::DataLabelPlacement::RIGHT:
+ {
+ if( pPosHelper->isSwapXAndY() )
+ {
+ fY = bReverse ? fScaledLowerYValue : fScaledUpperYValue;
+ rAlignment = LABEL_ALIGN_RIGHT;
+ if(m_nDimension==3)
+ fDepth = bReverse ? fabs(fScaledLowerBarDepth) : fabs(fScaledUpperBarDepth);
+ }
+ else
+ {
+ fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
+ rAlignment = LABEL_ALIGN_CENTER;
+ OSL_FAIL( "right label placement is not supported by column charts" );
+ }
+ }
+ break;
+ case css::chart::DataLabelPlacement::OUTSIDE:
+ {
+ fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue;
+ if( pPosHelper->isSwapXAndY() )
+ // if datapoint value is 0 the label will appear RIGHT in case of Bar Chart
+ if( fBaseValue == fScaledUpperYValue && fBaseValue == fScaledLowerYValue )
+ rAlignment = LABEL_ALIGN_RIGHT;
+ else
+ rAlignment = bNormalOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
+ else
+ // if datapoint value is 0 the label will appear TOP in case of Column Chart
+ if( fBaseValue == fScaledUpperYValue && fBaseValue == fScaledLowerYValue )
+ rAlignment = LABEL_ALIGN_TOP;
+ else
+ rAlignment = bNormalOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
+ if(m_nDimension==3)
+ fDepth = (fBaseValue < fScaledUpperYValue) ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
+ }
+ break;
+ case css::chart::DataLabelPlacement::INSIDE:
+ {
+ fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue;
+ if( pPosHelper->isSwapXAndY() )
+ rAlignment = bNormalOutside ? LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+ else
+ rAlignment = bNormalOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
+ if(m_nDimension==3)
+ fDepth = (fBaseValue < fScaledUpperYValue) ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
+ }
+ break;
+ case css::chart::DataLabelPlacement::NEAR_ORIGIN:
+ {
+ fY = (fBaseValue < fScaledUpperYValue) ? fScaledLowerYValue : fScaledUpperYValue;
+ if( pPosHelper->isSwapXAndY() )
+ // if datapoint value is 0 the label will appear RIGHT in case of Bar Chart
+ if( fBaseValue == fScaledUpperYValue && fBaseValue == fScaledLowerYValue )
+ rAlignment = LABEL_ALIGN_RIGHT;
+ else
+ rAlignment = bNormalOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
+ else
+ // if datapoint value is 0 the label will appear TOP in case of Column Chart
+ if( fBaseValue == fScaledUpperYValue && fBaseValue == fScaledLowerYValue )
+ rAlignment = LABEL_ALIGN_TOP;
+ else
+ rAlignment = bNormalOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
+ if(m_nDimension==3)
+ fDepth = (fBaseValue < fScaledUpperYValue) ? fabs(fScaledLowerBarDepth) : fabs(fScaledUpperBarDepth);
+ }
+ break;
+ case css::chart::DataLabelPlacement::CENTER:
+ fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
+ // if datapoint value is 0 the label will appear TOP/RIGHT in case of Column/Bar Charts
+ if( fBaseValue == fScaledUpperYValue && fBaseValue == fScaledLowerYValue )
+ if( pPosHelper->isSwapXAndY() )
+ rAlignment = LABEL_ALIGN_RIGHT;
+ else
+ rAlignment = LABEL_ALIGN_TOP;
+ else
+ rAlignment = LABEL_ALIGN_CENTER;
+ if(m_nDimension==3)
+ fDepth = fabs(fScaledUpperBarDepth-fScaledLowerBarDepth)/2.0;
+ break;
+ default:
+ OSL_FAIL("this label alignment is not implemented yet");
+
+ break;
+ }
+ if(m_nDimension==3)
+ fZ -= fDepth/2.0;
+
+ drawing::Position3D aScenePosition3D( pPosHelper->
+ transformScaledLogicToScene( fX, fY, fZ, true ) );
+ return LabelPositionHelper(m_nDimension,m_xLogicTarget)
+ .transformSceneToScreenPosition( aScenePosition3D );
+}
+
+rtl::Reference< SvxShape > BarChart::createDataPoint3D_Bar(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
+ , const uno::Reference< beans::XPropertySet >& xObjectProperties
+ , sal_Int32 nGeometry3D )
+{
+ bool bRoundedEdges = true;
+ try
+ {
+ if( xObjectProperties.is() )
+ {
+ sal_Int16 nPercentDiagonal = 0;
+ xObjectProperties->getPropertyValue( "PercentDiagonal" ) >>= nPercentDiagonal;
+ if( nPercentDiagonal < 5 )
+ bRoundedEdges = false;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ rtl::Reference< SvxShape > xShape;
+ switch( nGeometry3D )
+ {
+ case DataPointGeometry3D::CYLINDER:
+ xShape = ShapeFactory::createCylinder( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree );
+ break;
+ case DataPointGeometry3D::CONE:
+ xShape = ShapeFactory::createCone( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree );
+ break;
+ case DataPointGeometry3D::PYRAMID:
+ xShape = ShapeFactory::createPyramid( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree>0
+ , xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ break;
+ case DataPointGeometry3D::CUBOID:
+ default:
+ xShape = ShapeFactory::createCube( xTarget, rPosition, rSize
+ , nRotateZAngleHundredthDegree, xObjectProperties
+ , PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), bRoundedEdges );
+ return xShape;
+ }
+ if( nGeometry3D != DataPointGeometry3D::PYRAMID )
+ PropertyMapper::setMappedProperties( *xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ return xShape;
+}
+
+namespace
+{
+bool lcl_hasGeometry3DVariableWidth( sal_Int32 nGeometry3D )
+{
+ bool bRet = false;
+ switch( nGeometry3D )
+ {
+ case DataPointGeometry3D::PYRAMID:
+ case DataPointGeometry3D::CONE:
+ bRet = true;
+ break;
+ case DataPointGeometry3D::CUBOID:
+ case DataPointGeometry3D::CYLINDER:
+ default:
+ bRet = false;
+ break;
+ }
+ return bRet;
+}
+}// end anonymous namespace
+
+void BarChart::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
+{
+ if( !pSeries )
+ return;
+ if(m_nDimension==2)
+ {
+ //2ND_AXIS_IN_BARS put series on second scales to different z slot as temporary workaround
+ //this needs to be redesigned if 3d bars are also able to display secondary axes
+
+ sal_Int32 nAxisIndex = pSeries->getAttachedAxisIndex();
+ zSlot = nAxisIndex;
+
+ if( !pSeries->getGroupBarsPerAxis() )
+ zSlot = 0;
+ if(zSlot>=static_cast<sal_Int32>(m_aZSlots.size()))
+ m_aZSlots.resize(zSlot+1);
+ }
+ VSeriesPlotter::addSeries( std::move(pSeries), zSlot, xSlot, ySlot );
+}
+
+void BarChart::adaptOverlapAndGapwidthForGroupBarsPerAxis()
+{
+ //adapt m_aOverlapSequence and m_aGapwidthSequence for the groupBarsPerAxis feature
+ //thus the different series use the same settings
+
+ VDataSeries* pFirstSeries = getFirstSeries();
+ if(!pFirstSeries || pFirstSeries->getGroupBarsPerAxis())
+ return;
+
+ sal_Int32 nAxisIndex = pFirstSeries->getAttachedAxisIndex();
+ sal_Int32 nN = 0;
+ sal_Int32 nUseThisIndex = nAxisIndex;
+ if( nUseThisIndex < 0 || nUseThisIndex >= m_aOverlapSequence.getLength() )
+ nUseThisIndex = 0;
+ auto aOverlapSequenceRange = asNonConstRange(m_aOverlapSequence);
+ for( nN = 0; nN < m_aOverlapSequence.getLength(); nN++ )
+ {
+ if(nN!=nUseThisIndex)
+ aOverlapSequenceRange[nN] = m_aOverlapSequence[nUseThisIndex];
+ }
+
+ nUseThisIndex = nAxisIndex;
+ if( nUseThisIndex < 0 || nUseThisIndex >= m_aGapwidthSequence.getLength() )
+ nUseThisIndex = 0;
+ auto aGapwidthSequenceRange = asNonConstRange(m_aGapwidthSequence);
+ for( nN = 0; nN < m_aGapwidthSequence.getLength(); nN++ )
+ {
+ if(nN!=nUseThisIndex)
+ aGapwidthSequenceRange[nN] = m_aGapwidthSequence[nUseThisIndex];
+ }
+}
+
+void BarChart::createShapes()
+{
+ if( m_aZSlots.empty() ) //no series
+ return;
+
+ OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"BarChart is not proper initialized");
+ if(!(m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+
+ //the text labels should be always on top of the other series shapes
+ //therefore create an own group for the texts to move them to front
+ //(because the text group is created after the series group the texts are displayed on top)
+
+ //the regression curves should always be on top of the bars but beneath the text labels
+ //to achieve this the regression curve target is created after the series target and before the text target
+
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget = createGroupShape( m_xLogicTarget );
+ rtl::Reference<SvxShapeGroupAnyD> xRegressionCurveTarget = createGroupShape( m_xLogicTarget );
+ rtl::Reference<SvxShapeGroupAnyD> xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget );
+
+ rtl::Reference<SvxShapeGroupAnyD> xRegressionCurveEquationTarget =
+ ShapeFactory::createGroup2D( m_xFinalTarget );
+ //check necessary here that different Y axis can not be stacked in the same group? ... hm?
+
+ bool bDrawConnectionLines = false;
+ bool bDrawConnectionLinesInited = false;
+
+ std::unordered_set<rtl::Reference<SvxShape>> aShapeSet;
+
+ const comphelper::ScopeGuard aGuard([aShapeSet]() {
+
+ std::unordered_set<E3dScene*> aSceneSet;
+
+ for (rtl::Reference<SvxShape> const & rShape : aShapeSet)
+ {
+ if(E3dScene* pScene = DynCastE3dScene(rShape->GetSdrObject()))
+ {
+ aSceneSet.insert(pScene->getRootE3dSceneFromE3dObject());
+ }
+ }
+ for (E3dScene* pScene : aSceneSet)
+ {
+ pScene->ResumeReportingDirtyRects();
+ pScene->SetAllSceneRectsDirty();
+ }
+ });
+
+ adaptOverlapAndGapwidthForGroupBarsPerAxis();
+
+ //better performance for big data
+ std::map< VDataSeries*, FormerBarPoint > aSeriesFormerPointMap;
+ m_bPointsWereSkipped = false;
+
+ sal_Int32 nStartIndex = 0;
+ sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
+ //iterate through all x values per indices
+ for( sal_Int32 nPointIndex = nStartIndex; nPointIndex < nEndIndex; nPointIndex++ )
+ {
+ //sum up the values for all series in a complete z slot per attached axis
+ std::map< sal_Int32, double > aLogicYSumMap;
+ for( auto& rZSlot : m_aZSlots )
+ {
+ for( auto& rXSlot : rZSlot )
+ {
+ sal_Int32 nAttachedAxisIndex = rXSlot.getAttachedAxisIndexForFirstSeries();
+ aLogicYSumMap.insert({nAttachedAxisIndex, 0.0});
+
+ const sal_Int32 nSlotPoints = rXSlot.getPointCount();
+ if( nPointIndex >= nSlotPoints )
+ continue;
+
+ double fMinimumY = 0.0, fMaximumY = 0.0;
+ rXSlot.calculateYMinAndMaxForCategory( nPointIndex
+ , isSeparateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex );
+
+ if( !std::isnan( fMaximumY ) && fMaximumY > 0)
+ aLogicYSumMap[nAttachedAxisIndex] += fMaximumY;
+ if( !std::isnan( fMinimumY ) && fMinimumY < 0)
+ aLogicYSumMap[nAttachedAxisIndex] += fabs(fMinimumY);
+ }
+ }
+
+ sal_Int32 nZ=1;
+ for( auto& rZSlot : m_aZSlots )
+ {
+ doZSlot(bDrawConnectionLines, bDrawConnectionLinesInited, rZSlot, nZ, nPointIndex, nStartIndex,
+ xSeriesTarget, xRegressionCurveTarget, xRegressionCurveEquationTarget, xTextTarget,
+ aShapeSet, aSeriesFormerPointMap, aLogicYSumMap);
+ ++nZ;
+ }//next z slot
+ }//next category
+ if( bDrawConnectionLines )
+ {
+ for( auto const& rZSlot : m_aZSlots )
+ {
+ BarPositionHelper* pPosHelper = m_pMainPosHelper.get();
+ if( !rZSlot.empty() )
+ {
+ sal_Int32 nAttachedAxisIndex = rZSlot.front().getAttachedAxisIndexForFirstSeries();
+ //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
+ pPosHelper = dynamic_cast<BarPositionHelper*>(&( getPlottingPositionHelper( nAttachedAxisIndex ) ) );
+ if(!pPosHelper)
+ pPosHelper = m_pMainPosHelper.get();
+ }
+ PlotterBase::m_pPosHelper = pPosHelper;
+
+ //iterate through all x slots in this category
+ for( auto const& rXSlot : rZSlot )
+ {
+ //iterate through all series in this x slot
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ if(!pSeries)
+ continue;
+ std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly = &pSeries->m_aPolyPolygonShape3D;
+ if(!ShapeFactory::hasPolygonAnyLines(*pSeriesPoly))
+ continue;
+
+ std::vector<std::vector<css::drawing::Position3D>> aPoly;
+ Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+
+ if(!ShapeFactory::hasPolygonAnyLines(aPoly))
+ continue;
+
+ //transformation 3) -> 4)
+ pPosHelper->transformScaledLogicToScene( aPoly );
+
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes(
+ getSeriesGroupShape(pSeries.get(), xSeriesTarget) );
+ rtl::Reference<SvxShapePolyPolygon> xShape( ShapeFactory::createLine2D(
+ xSeriesGroupShape_Shapes, aPoly ) );
+ PropertyMapper::setMappedProperties( *xShape, pSeries->getPropertiesOfSeries()
+ , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ }
+ }
+ }
+ }
+
+ /* @todo remove series shapes if empty
+ */
+}
+
+void BarChart::doZSlot(
+ bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited,
+ const std::vector< VDataSeriesGroup >& rZSlot,
+ const sal_Int32 nZ, const sal_Int32 nPointIndex, const sal_Int32 nStartIndex,
+ const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget,
+ std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet,
+ std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap,
+ std::map< sal_Int32, double >& aLogicYSumMap)
+{
+ //iterate through all x slots in this category
+ double fSlotX=0;
+ for( auto& rXSlot : rZSlot )
+ {
+ sal_Int32 nAttachedAxisIndex = rXSlot.getAttachedAxisIndexForFirstSeries();
+ //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
+ BarPositionHelper* pPosHelper = dynamic_cast<BarPositionHelper*>(&( getPlottingPositionHelper( nAttachedAxisIndex ) ) );
+ if(!pPosHelper)
+ pPosHelper = m_pMainPosHelper.get();
+
+ PlotterBase::m_pPosHelper = pPosHelper;
+
+ //update/create information for current group
+ pPosHelper->updateSeriesCount( rZSlot.size() );
+ double fLogicBaseWidth = pPosHelper->getScaledSlotWidth();
+
+ // get distance from base value to maximum and minimum
+
+ double fMinimumY = 0.0, fMaximumY = 0.0;
+ if( nPointIndex < rXSlot.getPointCount())
+ rXSlot.calculateYMinAndMaxForCategory( nPointIndex
+ , isSeparateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex );
+
+ double fLogicPositiveYSum = 0.0;
+ if( !std::isnan( fMaximumY ) )
+ fLogicPositiveYSum = fMaximumY;
+
+ double fLogicNegativeYSum = 0.0;
+ if( !std::isnan( fMinimumY ) )
+ fLogicNegativeYSum = fMinimumY;
+
+ if( pPosHelper->isPercentY() )
+ {
+ /* #i70395# fLogicPositiveYSum contains sum of all positive
+ values, if any, otherwise the highest negative value.
+ fLogicNegativeYSum contains sum of all negative values,
+ if any, otherwise the lowest positive value.
+ Afterwards, fLogicPositiveYSum will contain the maximum
+ (positive) value that is related to 100%. */
+
+ // do nothing if there are positive values only
+ if( fLogicNegativeYSum < 0.0 )
+ {
+ // fLogicPositiveYSum<0 => negative values only, use absolute of negative sum
+ if( fLogicPositiveYSum < 0.0 )
+ fLogicPositiveYSum = -fLogicNegativeYSum;
+ // otherwise there are positive and negative values, calculate total distance
+ else
+ fLogicPositiveYSum -= fLogicNegativeYSum;
+ }
+ fLogicNegativeYSum = 0.0;
+ }
+
+ doXSlot(rXSlot, bDrawConnectionLines, bDrawConnectionLinesInited, nZ, nPointIndex, nStartIndex,
+ xSeriesTarget, xRegressionCurveTarget, xRegressionCurveEquationTarget, xTextTarget,
+ aShapeSet, aSeriesFormerPointMap, aLogicYSumMap,
+ fLogicBaseWidth, fSlotX, pPosHelper, fLogicPositiveYSum, fLogicNegativeYSum, nAttachedAxisIndex);
+
+ fSlotX+=1.0;
+ }//next x slot
+}
+
+
+void BarChart::doXSlot(
+ const VDataSeriesGroup& rXSlot,
+ bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited,
+ const sal_Int32 nZ, const sal_Int32 nPointIndex, const sal_Int32 nStartIndex,
+ const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget,
+ std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet,
+ std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap,
+ std::map< sal_Int32, double >& aLogicYSumMap,
+ const double fLogicBaseWidth, const double fSlotX,
+ BarPositionHelper* const pPosHelper,
+ const double fLogicPositiveYSum, const double fLogicNegativeYSum,
+ const sal_Int32 nAttachedAxisIndex)
+{
+ double fBaseValue = 0.0;
+ if( !pPosHelper->isPercentY() && rXSlot.m_aSeriesVector.size()<=1 )
+ fBaseValue = pPosHelper->getBaseValueY();
+ double fPositiveLogicYForNextSeries = fBaseValue;
+ double fNegativeLogicYForNextSeries = fBaseValue;
+
+ //iterate through all series in this x slot
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ if(!pSeries)
+ continue;
+
+ bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor");
+
+ bool bOnlyConnectionLinesForThisPoint = false;
+
+ if(nPointIndex==nStartIndex)//do not create a regression line for each point
+ createRegressionCurvesShapes( *pSeries, xRegressionCurveTarget, xRegressionCurveEquationTarget,
+ m_pPosHelper->maySkipPointsInRegressionCalculation());
+
+ if( !bDrawConnectionLinesInited )
+ {
+ bDrawConnectionLines = pSeries->getConnectBars();
+ if( m_nDimension==3 )
+ bDrawConnectionLines = false;
+ if( bDrawConnectionLines && rXSlot.m_aSeriesVector.size()==1 )
+ {
+ //detect whether we have a stacked chart or not:
+ StackingDirection eDirection = pSeries->getStackingDirection();
+ if( eDirection != StackingDirection_Y_STACKING )
+ bDrawConnectionLines = false;
+ }
+ bDrawConnectionLinesInited = true;
+ }
+
+ // Use another XShapes for background, so we can avoid needing to set the Z-order on all of them,
+ // which is expensive in bulk.
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes(getSeriesGroupShape(pSeries.get(), xSeriesTarget));
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesBackgroundShape_Shapes(getSeriesGroupShape(pSeries.get(), xSeriesTarget));
+ aShapeSet.insert(xSeriesGroupShape_Shapes);
+ aShapeSet.insert(xSeriesBackgroundShape_Shapes);
+ // Suspend setting rects dirty for the duration of this call
+ E3dScene* pScene = DynCastE3dScene(xSeriesGroupShape_Shapes->GetSdrObject());
+ if (pScene)
+ pScene->SuspendReportingDirtyRects();
+ pScene = DynCastE3dScene(xSeriesBackgroundShape_Shapes->GetSdrObject());
+ if (pScene)
+ pScene->SuspendReportingDirtyRects();
+
+ //collect data point information (logic coordinates, style ):
+ double fUnscaledLogicX = pSeries->getXValue( nPointIndex );
+ fUnscaledLogicX = DateHelper::RasterizeDateValue( fUnscaledLogicX, m_aNullDate, m_nTimeResolution );
+ if(std::isnan(fUnscaledLogicX))
+ continue;//point not visible
+ if(fUnscaledLogicX<pPosHelper->getLogicMinX())
+ continue;//point not visible
+ if(fUnscaledLogicX>pPosHelper->getLogicMaxX())
+ continue;//point not visible
+ if(pPosHelper->isStrongLowerRequested(0) && fUnscaledLogicX==pPosHelper->getLogicMaxX())
+ continue;//point not visible
+ double fLogicX = pPosHelper->getScaledSlotPos( fUnscaledLogicX, fSlotX );
+
+ double fLogicBarHeight = pSeries->getYValue( nPointIndex );
+ if( std::isnan( fLogicBarHeight )) //no value at this category
+ continue;
+
+ double fLogicValueForLabeDisplay = fLogicBarHeight;
+ fLogicBarHeight-=fBaseValue;
+
+ if( pPosHelper->isPercentY() )
+ {
+ if(fLogicPositiveYSum!=0.0)
+ fLogicBarHeight = fabs( fLogicBarHeight )/fLogicPositiveYSum;
+ else
+ fLogicBarHeight = 0.0;
+ }
+
+ // tdf#114141 to draw the top of the zero height 3D bar
+ // we set a small positive value, here the smallest one for the type double (DBL_MIN)
+ if( fLogicBarHeight == 0.0 )
+ fLogicBarHeight = DBL_MIN;
+
+ //sort negative and positive values, to display them on different sides of the x axis
+ bool bPositive = fLogicBarHeight >= 0.0;
+ double fLowerYValue = bPositive ? fPositiveLogicYForNextSeries : fNegativeLogicYForNextSeries;
+ double fUpperYValue = fLowerYValue+fLogicBarHeight;
+ if( bPositive )
+ fPositiveLogicYForNextSeries += fLogicBarHeight;
+ else
+ fNegativeLogicYForNextSeries += fLogicBarHeight;
+
+ double fLogicZ = 1.0;//as defined
+ if(m_nDimension==3)
+ fLogicZ = nZ+0.5;
+
+ drawing::Position3D aUnscaledLogicPosition( fUnscaledLogicX, fUpperYValue, fLogicZ );
+
+ //@todo ... start an iteration over the different breaks of the axis
+ //each subsystem may add an additional shape to form the whole point
+ //create a group shape for this point and add to the series shape:
+// uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( createGroupShape(xSeriesGroupShape_Shapes) );
+// uno::Reference<drawing::XShape> xPointGroupShape_Shape =
+// uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY );
+ //as long as we do not iterate we do not need to create an additional group for each point
+ uno::Reference< beans::XPropertySet > xDataPointProperties( pSeries->getPropertiesOfPoint( nPointIndex ) );
+ sal_Int32 nGeometry3D = DataPointGeometry3D::CUBOID;
+ if(m_nDimension==3) try
+ {
+ xDataPointProperties->getPropertyValue( "Geometry3D") >>= nGeometry3D;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ //@todo iterate through all subsystems to create partial points
+ {
+ //@todo select a suitable PositionHelper for this subsystem
+ BarPositionHelper* pSubPosHelper = pPosHelper;
+
+ double fUnclippedUpperYValue = fUpperYValue;
+
+ //apply clipping to Y
+ if( !pPosHelper->clipYRange(fLowerYValue,fUpperYValue) )
+ {
+ if( bDrawConnectionLines )
+ bOnlyConnectionLinesForThisPoint = true;
+ else
+ continue;
+ }
+ //@todo clipping of X and Z is not fully integrated so far, as there is a need to create different objects
+
+ //apply scaling to Y before calculating width (necessary to maintain gradient in clipped objects)
+ pSubPosHelper->doLogicScaling(nullptr,&fLowerYValue,nullptr);
+ pSubPosHelper->doLogicScaling(nullptr,&fUpperYValue,nullptr);
+ //scaling of X and Z is not provided as the created objects should be symmetric in that dimensions
+
+ pSubPosHelper->doLogicScaling(nullptr,&fUnclippedUpperYValue,nullptr);
+
+ //calculate resulting width
+ double fCompleteHeight = bPositive ? fLogicPositiveYSum : fLogicNegativeYSum;
+ if( pPosHelper->isPercentY() )
+ fCompleteHeight = 1.0;
+ double fLogicBarWidth = fLogicBaseWidth;
+ double fTopHeight=approxSub(fCompleteHeight,fUpperYValue);
+ if(!bPositive)
+ fTopHeight=approxSub(fCompleteHeight,fLowerYValue);
+ double fLogicYStart = bPositive ? fLowerYValue : fUpperYValue;
+ double fMiddleHeight = fUpperYValue-fLowerYValue;
+ if(!bPositive)
+ fMiddleHeight*=-1.0;
+ double fLogicBarDepth = 0.5;
+ if(m_nDimension==3)
+ {
+ if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 )
+ {
+ double fHeight = fCompleteHeight-fLowerYValue;
+ if(!bPositive)
+ fHeight = fCompleteHeight-fUpperYValue;
+ fLogicBarWidth = fLogicBaseWidth*fHeight/fCompleteHeight;
+ if(fLogicBarWidth<=0.0)
+ fLogicBarWidth=fLogicBaseWidth;
+ fLogicBarDepth = fLogicBarDepth*fHeight/fCompleteHeight;
+ if(fLogicBarDepth<=0.0)
+ fLogicBarDepth*=-1.0;
+ }
+ }
+
+ //better performance for big data
+ FormerBarPoint aFormerPoint( aSeriesFormerPointMap[pSeries.get()] );
+ pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution );
+ if( !pSeries->isAttributedDataPoint(nPointIndex)
+ &&
+ pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fUpperY, aFormerPoint.m_fZ
+ , fLogicX, fUpperYValue, fLogicZ )
+ &&
+ pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fLowerY, aFormerPoint.m_fZ
+ , fLogicX, fLowerYValue, fLogicZ )
+ )
+ {
+ m_bPointsWereSkipped = true;
+ continue;
+ }
+ aSeriesFormerPointMap[pSeries.get()] = FormerBarPoint(fLogicX,fUpperYValue,fLowerYValue,fLogicZ);
+
+ if( bDrawConnectionLines )
+ {
+ //store point information for connection lines
+
+ drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ );
+ drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ );
+
+ if( isValidPosition(aLeftUpperPoint) )
+ AddPointToPoly( pSeries->m_aPolyPolygonShape3D, aLeftUpperPoint );
+ if( isValidPosition(aRightUpperPoint) )
+ AddPointToPoly( pSeries->m_aPolyPolygonShape3D, aRightUpperPoint );
+ }
+
+ if( bOnlyConnectionLinesForThisPoint )
+ continue;
+
+ //maybe additional possibility for performance improvement
+ //bool bCreateLineInsteadOfComplexGeometryDueToMissingSpace = false;
+ //pPosHelper->isSameForGivenResolution( fLogicX-fLogicBarWidth/2.0, fLowerYValue, fLogicZ
+ // , fLogicX+fLogicBarWidth/2.0, fLowerYValue, fLogicZ );
+
+ //create partial point
+ if( !approxEqual(fLowerYValue,fUpperYValue) )
+ {
+ rtl::Reference< SvxShape > xShape;
+ if( m_nDimension==3 )
+ {
+ drawing::Position3D aLogicBottom (fLogicX,fLogicYStart,fLogicZ);
+ drawing::Position3D aLogicLeftBottomFront (fLogicX+fLogicBarWidth/2.0,fLogicYStart,fLogicZ-fLogicBarDepth/2.0);
+ drawing::Position3D aLogicRightDeepTop (fLogicX-fLogicBarWidth/2.0,fLogicYStart+fMiddleHeight,fLogicZ+fLogicBarDepth/2.0);
+ drawing::Position3D aLogicTopTop (fLogicX,fLogicYStart+fMiddleHeight+fTopHeight,fLogicZ);
+
+ ::chart::XTransformation2* pTransformation = pSubPosHelper->getTransformationScaledLogicToScene();
+
+ //transformation 3) -> 4)
+ drawing::Position3D aTransformedBottom ( pTransformation->transform( aLogicBottom ) );
+ drawing::Position3D aTransformedLeftBottomFront ( pTransformation->transform( aLogicLeftBottomFront ) );
+ drawing::Position3D aTransformedRightDeepTop ( pTransformation->transform( aLogicRightDeepTop ) );
+ drawing::Position3D aTransformedTopTop ( pTransformation->transform( aLogicTopTop ) );
+
+ drawing::Direction3D aSize = aTransformedRightDeepTop - aTransformedLeftBottomFront;
+ drawing::Direction3D aTopSize( aTransformedTopTop - aTransformedRightDeepTop );
+ fTopHeight = aTopSize.DirectionY;
+
+ sal_Int32 nRotateZAngleHundredthDegree = 0;
+ if( pPosHelper->isSwapXAndY() )
+ {
+ fTopHeight = aTopSize.DirectionX;
+ nRotateZAngleHundredthDegree = 90*100;
+ aSize = drawing::Direction3D(aSize.DirectionY,aSize.DirectionX,aSize.DirectionZ);
+ }
+
+ if( aSize.DirectionX < 0 )
+ aSize.DirectionX *= -1.0;
+ if( aSize.DirectionZ < 0 )
+ aSize.DirectionZ *= -1.0;
+ if( fTopHeight < 0 )
+ fTopHeight *= -1.0;
+
+ xShape = createDataPoint3D_Bar(
+ xSeriesGroupShape_Shapes, aTransformedBottom, aSize, fTopHeight, nRotateZAngleHundredthDegree
+ , xDataPointProperties, nGeometry3D );
+ }
+ else //m_nDimension!=3
+ {
+ drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
+ drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
+ std::vector<std::vector<css::drawing::Position3D>> aPoly
+ {
+ { // inner vector
+ drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ),
+ drawing::Position3D( fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ),
+ aRightUpperPoint,
+ aLeftUpperPoint,
+ drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ)
+ }
+ };
+ pPosHelper->transformScaledLogicToScene( aPoly );
+ xShape = ShapeFactory::createArea2D( xSeriesGroupShape_Shapes, aPoly );
+ PropertyMapper::setMappedProperties( *xShape, xDataPointProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ }
+
+ if(bHasFillColorMapping)
+ {
+ double nPropVal = pSeries->getValueByProperty(nPointIndex, "FillColor");
+ if(!std::isnan(nPropVal))
+ {
+ xShape->setPropertyValue("FillColor", uno::Any(static_cast<sal_Int32>(nPropVal)));
+ }
+ }
+ //set name/classified ObjectID (CID)
+ ShapeFactory::setShapeName(xShape
+ , ObjectIdentifier::createPointCID(
+ pSeries->getPointCID_Stub(),nPointIndex) );
+ }
+
+ //create error bar
+ createErrorBar_Y( aUnscaledLogicPosition, *pSeries, nPointIndex, m_xLogicTarget, &fLogicX );
+
+ //create data point label
+ if( pSeries->getDataPointLabelIfLabel(nPointIndex) )
+ {
+ double fLogicSum = aLogicYSumMap[nAttachedAxisIndex];
+
+ LabelAlignment eAlignment(LABEL_ALIGN_CENTER);
+ sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nPointIndex, m_xChartTypeModel, pPosHelper->isSwapXAndY() );
+
+ double fLowerBarDepth = fLogicBarDepth;
+ double fUpperBarDepth = fLogicBarDepth;
+ {
+ if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 )
+ {
+ double fOuterBarDepth = fLogicBarDepth * fTopHeight/(fabs(fCompleteHeight));
+ fLowerBarDepth = (fBaseValue < fUpperYValue) ? fabs(fLogicBarDepth) : fabs(fOuterBarDepth);
+ fUpperBarDepth = (fBaseValue < fUpperYValue) ? fabs(fOuterBarDepth) : fabs(fLogicBarDepth);
+ }
+ }
+
+ awt::Point aScreenPosition2D = getLabelScreenPositionAndAlignment(
+ eAlignment, nLabelPlacement, fLogicX, fLowerYValue, fUpperYValue, fLogicZ,
+ fLowerBarDepth, fUpperBarDepth, fBaseValue, pPosHelper);
+ sal_Int32 nOffset = 0;
+ if(eAlignment!=LABEL_ALIGN_CENTER)
+ {
+ nOffset = 100;//add some spacing //@todo maybe get more intelligent values
+ if( m_nDimension == 3 )
+ nOffset = 260;
+ }
+ createDataLabel(
+ xTextTarget, *pSeries, nPointIndex,
+ fLogicValueForLabeDisplay, fLogicSum, aScreenPosition2D, eAlignment, nOffset);
+ }
+
+ }//end iteration through partial points
+
+ }//next series in x slot (next y slot)
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/BarChart.hxx b/chart2/source/view/charttypes/BarChart.hxx
new file mode 100644
index 0000000000..52c3b61777
--- /dev/null
+++ b/chart2/source/view/charttypes/BarChart.hxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <VSeriesPlotter.hxx>
+
+namespace chart
+{
+class BarPositionHelper;
+
+class BarChart : public VSeriesPlotter
+{
+ // public methods
+public:
+ BarChart() = delete;
+
+ BarChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount );
+ virtual ~BarChart() override;
+
+ virtual void createShapes() override;
+ virtual void addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot ) override;
+
+ virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override;
+
+private: //methods
+ static rtl::Reference< SvxShape >
+ createDataPoint3D_Bar(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D& rPosition
+ , const css::drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
+ , const css::uno::Reference< css::beans::XPropertySet >& xObjectProperties
+ , sal_Int32 nGeometry3D );
+
+ css::awt::Point getLabelScreenPositionAndAlignment(
+ LabelAlignment& rAlignment, sal_Int32 nLabelPlacement
+ , double fScaledX, double fScaledLowerYValue, double fScaledUpperYValue, double fScaledZ
+ , double fScaledLowerBarDepth, double fScaledUpperBarDepth, double fBaseValue
+ , BarPositionHelper const * pPosHelper ) const;
+
+ virtual PlottingPositionHelper& getPlottingPositionHelper( sal_Int32 nAxisIndex ) const override;//nAxisIndex indicates whether the position belongs to the main axis ( nAxisIndex==0 ) or secondary axis ( nAxisIndex==1 )
+
+ void adaptOverlapAndGapwidthForGroupBarsPerAxis();
+
+ //better performance for big data
+ struct FormerBarPoint
+ {
+ FormerBarPoint( double fX, double fUpperY, double fLowerY, double fZ )
+ : m_fX(fX), m_fUpperY(fUpperY), m_fLowerY(fLowerY), m_fZ(fZ)
+ {}
+ FormerBarPoint()
+ : m_fX(std::numeric_limits<double>::quiet_NaN())
+ , m_fUpperY(std::numeric_limits<double>::quiet_NaN())
+ , m_fLowerY(std::numeric_limits<double>::quiet_NaN())
+ , m_fZ(std::numeric_limits<double>::quiet_NaN())
+ {
+ }
+
+ double m_fX;
+ double m_fUpperY;
+ double m_fLowerY;
+ double m_fZ;
+ };
+
+ void doZSlot(
+ bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited, const std::vector< VDataSeriesGroup >& rZSlot,
+ sal_Int32 nZ, sal_Int32 nPointIndex, sal_Int32 nStartIndex,
+ const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget,
+ std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet,
+ std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap,
+ std::map< sal_Int32, double >& aLogicYSumMap);
+
+ void doXSlot(
+ const VDataSeriesGroup& rXSlot,
+ bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited,
+ sal_Int32 nZ, sal_Int32 nPointIndex, sal_Int32 nStartIndex,
+ const rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget,
+ std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet,
+ std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap,
+ std::map< sal_Int32, double >& aLogicYSumMap,
+ double fLogicBaseWidth, double fSlotX,
+ BarPositionHelper* const pPosHelper,
+ double fLogicPositiveYSum, double fLogicNegativeYSum,
+ sal_Int32 nAttachedAxisIndex);
+
+private: //member
+ std::unique_ptr<BarPositionHelper> m_pMainPosHelper;
+ css::uno::Sequence< sal_Int32 > m_aOverlapSequence;
+ css::uno::Sequence< sal_Int32 > m_aGapwidthSequence;
+};
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/BarPositionHelper.cxx b/chart2/source/view/charttypes/BarPositionHelper.cxx
new file mode 100644
index 0000000000..f8ac3e7d62
--- /dev/null
+++ b/chart2/source/view/charttypes/BarPositionHelper.cxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "BarPositionHelper.hxx"
+#include <DateHelper.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+BarPositionHelper::BarPositionHelper()
+ : CategoryPositionHelper( 1 )
+{
+ AllowShiftXAxisPos(true);
+ AllowShiftZAxisPos(true);
+}
+
+BarPositionHelper::BarPositionHelper( const BarPositionHelper& rSource )
+ : CategoryPositionHelper( rSource )
+ , PlottingPositionHelper( rSource )
+{
+}
+
+BarPositionHelper::~BarPositionHelper()
+{
+}
+
+std::unique_ptr<PlottingPositionHelper> BarPositionHelper::clone() const
+{
+ return std::make_unique<BarPositionHelper>(*this);
+}
+
+void BarPositionHelper::updateSeriesCount( double fSeriesCount )
+{
+ m_fSeriesCount = fSeriesCount;
+}
+
+double BarPositionHelper::getScaledSlotPos( double fUnscaledLogicX, double fSeriesNumber ) const
+{
+ if( m_bDateAxis )
+ fUnscaledLogicX = DateHelper::RasterizeDateValue( fUnscaledLogicX, m_aNullDate, m_nTimeResolution );
+ double fScaledLogicX(fUnscaledLogicX);
+ doLogicScaling(&fScaledLogicX,nullptr,nullptr);
+ fScaledLogicX = CategoryPositionHelper::getScaledSlotPos( fScaledLogicX, fSeriesNumber );
+ return fScaledLogicX;
+
+}
+
+void BarPositionHelper::setScaledCategoryWidth( double fScaledCategoryWidth )
+{
+ m_fScaledCategoryWidth = fScaledCategoryWidth;
+ CategoryPositionHelper::setCategoryWidth( m_fScaledCategoryWidth );
+}
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/BarPositionHelper.hxx b/chart2/source/view/charttypes/BarPositionHelper.hxx
new file mode 100644
index 0000000000..961ea988f6
--- /dev/null
+++ b/chart2/source/view/charttypes/BarPositionHelper.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <PlottingPositionHelper.hxx>
+#include "CategoryPositionHelper.hxx"
+
+namespace chart
+{
+class BarPositionHelper : public CategoryPositionHelper, public PlottingPositionHelper
+{
+public:
+ explicit BarPositionHelper();
+ BarPositionHelper(const BarPositionHelper& rSource);
+ virtual ~BarPositionHelper() override;
+
+ virtual std::unique_ptr<PlottingPositionHelper> clone() const override;
+
+ void updateSeriesCount(double fSeriesCount); /*only enter the size of x stacked series*/
+
+ virtual double getScaledSlotPos(double fCategoryX, double fSeriesNumber) const override;
+ virtual void setScaledCategoryWidth(double fScaledCategoryWidth) override;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/BubbleChart.cxx b/chart2/source/view/charttypes/BubbleChart.cxx
new file mode 100644
index 0000000000..803cf73b20
--- /dev/null
+++ b/chart2/source/view/charttypes/BubbleChart.cxx
@@ -0,0 +1,362 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "BubbleChart.hxx"
+#include <PlottingPositionHelper.hxx>
+#include <ShapeFactory.hxx>
+#include <ObjectIdentifier.hxx>
+#include <LabelPositionHelper.hxx>
+#include <ChartType.hxx>
+
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+
+#include <limits>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+BubbleChart::BubbleChart( const rtl::Reference<ChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount, false )
+ , m_fMaxLogicBubbleSize( 0.0 )
+ , m_fBubbleSizeFactorToScreen( 1.0 )
+{
+ // We only support 2 dimensional bubble charts
+ assert(nDimensionCount == 2);
+
+ if( !m_pMainPosHelper )
+ m_pMainPosHelper = new PlottingPositionHelper();
+ PlotterBase::m_pPosHelper = m_pMainPosHelper;
+}
+
+BubbleChart::~BubbleChart()
+{
+ delete m_pMainPosHelper;
+}
+
+void BubbleChart::calculateMaximumLogicBubbleSize()
+{
+ double fMaxSize = 0.0;
+
+ sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
+ for( sal_Int32 nIndex = 0; nIndex < nEndIndex; nIndex++ )
+ {
+ for( auto const& rZSlot : m_aZSlots )
+ {
+ for( auto const& rXSlot : rZSlot )
+ {
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ if(!pSeries)
+ continue;
+
+ double fSize = pSeries->getBubble_Size( nIndex );
+ if( fSize > fMaxSize )
+ fMaxSize = fSize;
+ }
+ }
+ }
+ }
+
+ m_fMaxLogicBubbleSize = fMaxSize;
+}
+
+void BubbleChart::calculateBubbleSizeScalingFactor()
+{
+ double fLogicZ=1.0;
+ drawing::Position3D aSceneMinPos( m_pMainPosHelper->transformLogicToScene( m_pMainPosHelper->getLogicMinX(),m_pMainPosHelper->getLogicMinY(),fLogicZ, false ) );
+ drawing::Position3D aSceneMaxPos( m_pMainPosHelper->transformLogicToScene( m_pMainPosHelper->getLogicMaxX(),m_pMainPosHelper->getLogicMaxY(),fLogicZ, false ) );
+
+ awt::Point aScreenMinPos( LabelPositionHelper(m_nDimension,m_xLogicTarget).transformSceneToScreenPosition( aSceneMinPos ) );
+ awt::Point aScreenMaxPos( LabelPositionHelper(m_nDimension,m_xLogicTarget).transformSceneToScreenPosition( aSceneMaxPos ) );
+
+ sal_Int32 nWidth = abs( aScreenMaxPos.X - aScreenMinPos.X );
+ sal_Int32 nHeight = abs( aScreenMaxPos.Y - aScreenMinPos.Y );
+
+ sal_Int32 nMinExtend = std::min( nWidth, nHeight );
+ m_fBubbleSizeFactorToScreen = nMinExtend * 0.25;//max bubble size is 25 percent of diagram size
+}
+
+drawing::Direction3D BubbleChart::transformToScreenBubbleSize( double fLogicSize )
+{
+ drawing::Direction3D aRet(0,0,0);
+
+ if( std::isnan(fLogicSize) || std::isinf(fLogicSize) )
+ return aRet;
+
+ double fMaxSize = m_fMaxLogicBubbleSize;
+
+ double fMaxRadius = sqrt( fMaxSize / M_PI );
+ double fRadius = sqrt( fLogicSize / M_PI );
+
+ aRet.DirectionX = m_fBubbleSizeFactorToScreen * fRadius / fMaxRadius;
+ aRet.DirectionY = aRet.DirectionX;
+
+ return aRet;
+}
+
+bool BubbleChart::isExpandIfValuesCloseToBorder( sal_Int32 /*nDimensionIndex*/ )
+{
+ return true;
+}
+
+bool BubbleChart::isSeparateStackingForDifferentSigns( sal_Int32 /*nDimensionIndex*/ )
+{
+ return false;
+}
+
+LegendSymbolStyle BubbleChart::getLegendSymbolStyle()
+{
+ return LegendSymbolStyle::Circle;
+}
+
+drawing::Direction3D BubbleChart::getPreferredDiagramAspectRatio() const
+{
+ return drawing::Direction3D(-1,-1,-1);
+}
+
+namespace {
+
+//better performance for big data
+struct FormerPoint
+{
+ FormerPoint( double fX, double fY, double fZ )
+ : m_fX(fX), m_fY(fY), m_fZ(fZ)
+ {}
+ FormerPoint()
+ : m_fX(std::numeric_limits<double>::quiet_NaN())
+ , m_fY(std::numeric_limits<double>::quiet_NaN())
+ , m_fZ(std::numeric_limits<double>::quiet_NaN())
+ {
+ }
+
+ double m_fX;
+ double m_fY;
+ double m_fZ;
+};
+
+}
+
+void BubbleChart::createShapes()
+{
+ if( m_aZSlots.empty() ) //no series
+ return;
+
+ OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"BubbleChart is not proper initialized");
+ if(!(m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+
+ //therefore create an own group for the texts and the error bars to move them to front
+ //(because the text group is created after the series group the texts are displayed on top)
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget = createGroupShape( m_xLogicTarget );
+ rtl::Reference< SvxShapeGroup > xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget );
+
+ //update/create information for current group
+ double fLogicZ = 1.0;//as defined
+
+ sal_Int32 const nStartIndex = 0; // inclusive ;..todo get somehow from x scale
+ sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
+ if(nEndIndex<=0)
+ nEndIndex=1;
+
+ //better performance for big data
+ std::map< VDataSeries*, FormerPoint > aSeriesFormerPointMap;
+ m_bPointsWereSkipped = false;
+ sal_Int32 nSkippedPoints = 0;
+ sal_Int32 nCreatedPoints = 0;
+
+ calculateMaximumLogicBubbleSize();
+ calculateBubbleSizeScalingFactor();
+ if( m_fMaxLogicBubbleSize <= 0 || m_fBubbleSizeFactorToScreen <= 0 )
+ return;
+
+ //iterate through all x values per indices
+ for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ )
+ {
+ for( auto const& rZSlot : m_aZSlots )
+ {
+ for( auto const& rXSlot : rZSlot )
+ {
+ //iterate through all series
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ if(!pSeries)
+ continue;
+
+ bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor");
+ bool bHasBorderColorMapping = pSeries->hasPropertyMapping("LineColor");
+
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShape(pSeries.get(), xSeriesTarget);
+
+ sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
+ PlottingPositionHelper& rPosHelper
+ = getPlottingPositionHelper(nAttachedAxisIndex);
+ m_pPosHelper = &rPosHelper;
+
+ //collect data point information (logic coordinates, style ):
+ double fLogicX = pSeries->getXValue(nIndex);
+ double fLogicY = pSeries->getYValue(nIndex);
+ double fBubbleSize = pSeries->getBubble_Size( nIndex );
+
+ if( fBubbleSize<0.0 )
+ continue;
+
+ if( fBubbleSize == 0.0 || std::isnan(fBubbleSize) )
+ continue;
+
+ if( std::isnan(fLogicX) || std::isinf(fLogicX)
+ || std::isnan(fLogicY) || std::isinf(fLogicY) )
+ continue;
+
+ bool bIsVisible = rPosHelper.isLogicVisible(fLogicX, fLogicY, fLogicZ);
+
+ drawing::Position3D aUnscaledLogicPosition( fLogicX, fLogicY, fLogicZ );
+ drawing::Position3D aScaledLogicPosition(aUnscaledLogicPosition);
+ rPosHelper.doLogicScaling(aScaledLogicPosition);
+
+ //transformation 3) -> 4)
+ drawing::Position3D aScenePosition(
+ rPosHelper.transformLogicToScene(fLogicX, fLogicY, fLogicZ, false));
+
+ //better performance for big data
+ FormerPoint aFormerPoint( aSeriesFormerPointMap[pSeries.get()] );
+ rPosHelper.setCoordinateSystemResolution(m_aCoordinateSystemResolution);
+ if (!pSeries->isAttributedDataPoint(nIndex)
+ && rPosHelper.isSameForGivenResolution(
+ aFormerPoint.m_fX, aFormerPoint.m_fY, aFormerPoint.m_fZ,
+ aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY,
+ aScaledLogicPosition.PositionZ))
+ {
+ nSkippedPoints++;
+ m_bPointsWereSkipped = true;
+ continue;
+ }
+ aSeriesFormerPointMap[pSeries.get()] = FormerPoint(aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ);
+
+ //create a single datapoint if point is visible
+ if( !bIsVisible )
+ continue;
+
+ //create a group shape for this point and add to the series shape:
+ OUString aPointCID = ObjectIdentifier::createPointCID(
+ pSeries->getPointCID_Stub(), nIndex );
+ rtl::Reference<SvxShapeGroupAnyD> xPointGroupShape_Shapes(
+ createGroupShape(xSeriesGroupShape_Shapes,aPointCID) );
+
+ {
+ nCreatedPoints++;
+
+ //create data point
+ drawing::Direction3D aSymbolSize = transformToScreenBubbleSize( fBubbleSize );
+ rtl::Reference<SvxShapeCircle> xShape = ShapeFactory::createCircle2D( xPointGroupShape_Shapes
+ , aScenePosition, aSymbolSize );
+
+ PropertyMapper::setMappedProperties( *xShape
+ , pSeries->getPropertiesOfPoint( nIndex )
+ , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+
+ if(bHasFillColorMapping)
+ {
+ double nPropVal = pSeries->getValueByProperty(nIndex, "FillColor");
+ if(!std::isnan(nPropVal))
+ {
+ xShape->SvxShape::setPropertyValue("FillColor", uno::Any(static_cast<sal_Int32>(nPropVal)));
+ }
+ }
+ if(bHasBorderColorMapping)
+ {
+ double nPropVal = pSeries->getValueByProperty(nIndex, "LineColor");
+ if(!std::isnan(nPropVal))
+ {
+ xShape->SvxShape::setPropertyValue("LineColor", uno::Any(static_cast<sal_Int32>(nPropVal)));
+ }
+ }
+
+ ::chart::ShapeFactory::setShapeName( xShape, "MarkHandles" );
+
+ //create data point label
+ if( pSeries->getDataPointLabelIfLabel(nIndex) )
+ {
+ LabelAlignment eAlignment = LABEL_ALIGN_TOP;
+ drawing::Position3D aScenePosition3D( aScenePosition.PositionX
+ , aScenePosition.PositionY
+ , aScenePosition.PositionZ+getTransformedDepth() );
+
+ sal_Int32 nLabelPlacement = pSeries->getLabelPlacement(
+ nIndex, m_xChartTypeModel, rPosHelper.isSwapXAndY());
+
+ switch(nLabelPlacement)
+ {
+ case css::chart::DataLabelPlacement::TOP:
+ aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_TOP;
+ break;
+ case css::chart::DataLabelPlacement::BOTTOM:
+ aScenePosition3D.PositionY += (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_BOTTOM;
+ break;
+ case css::chart::DataLabelPlacement::LEFT:
+ aScenePosition3D.PositionX -= (aSymbolSize.DirectionX/2+1);
+ eAlignment = LABEL_ALIGN_LEFT;
+ break;
+ case css::chart::DataLabelPlacement::RIGHT:
+ aScenePosition3D.PositionX += (aSymbolSize.DirectionX/2+1);
+ eAlignment = LABEL_ALIGN_RIGHT;
+ break;
+ case css::chart::DataLabelPlacement::CENTER:
+ eAlignment = LABEL_ALIGN_CENTER;
+ break;
+ default:
+ OSL_FAIL("this label alignment is not implemented yet");
+ aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_TOP;
+ break;
+ }
+
+ awt::Point aScreenPosition2D( LabelPositionHelper(m_nDimension,m_xLogicTarget)
+ .transformSceneToScreenPosition( aScenePosition3D ) );
+ sal_Int32 nOffset = 0;
+ if(eAlignment!=LABEL_ALIGN_CENTER)
+ nOffset = 100;//add some spacing //@todo maybe get more intelligent values
+ createDataLabel( xTextTarget, *pSeries, nIndex
+ , fBubbleSize, fBubbleSize, aScreenPosition2D, eAlignment, nOffset );
+ }
+ }
+
+ //remove PointGroupShape if empty
+ if(!xPointGroupShape_Shapes->getCount())
+ xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shapes);
+
+ }//next series in x slot (next y slot)
+ }//next x slot
+ }//next z slot
+ }//next category
+ SAL_INFO(
+ "chart2",
+ "skipped points: " << nSkippedPoints << " created points: "
+ << nCreatedPoints);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/BubbleChart.hxx b/chart2/source/view/charttypes/BubbleChart.hxx
new file mode 100644
index 0000000000..c25e5b6345
--- /dev/null
+++ b/chart2/source/view/charttypes/BubbleChart.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <VSeriesPlotter.hxx>
+#include <com/sun/star/drawing/Direction3D.hpp>
+
+namespace chart
+{
+
+class BubbleChart : public VSeriesPlotter
+{
+ // public methods
+public:
+ BubbleChart() = delete;
+
+ BubbleChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount );
+ virtual ~BubbleChart() override;
+
+ virtual void createShapes() override;
+
+ virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override;
+
+ // MinimumAndMaximumSupplier
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex ) override;
+ virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) override;
+
+ virtual LegendSymbolStyle getLegendSymbolStyle() override;
+
+private: //methods
+ void calculateMaximumLogicBubbleSize();
+ void calculateBubbleSizeScalingFactor();
+
+ css::drawing::Direction3D transformToScreenBubbleSize( double fLogicSize );
+
+private: //member
+
+ double m_fMaxLogicBubbleSize;//calculated values
+ double m_fBubbleSizeFactorToScreen;//calculated values
+};
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/CandleStickChart.cxx b/chart2/source/view/charttypes/CandleStickChart.cxx
new file mode 100644
index 0000000000..20c53461d1
--- /dev/null
+++ b/chart2/source/view/charttypes/CandleStickChart.cxx
@@ -0,0 +1,314 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "CandleStickChart.hxx"
+#include <ChartType.hxx>
+#include <ShapeFactory.hxx>
+#include <CommonConverters.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <ObjectIdentifier.hxx>
+#include "BarPositionHelper.hxx"
+#include <DateHelper.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <osl/diagnose.h>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+CandleStickChart::CandleStickChart( const rtl::Reference<ChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount )
+ , m_pMainPosHelper( new BarPositionHelper() )
+{
+ PlotterBase::m_pPosHelper = m_pMainPosHelper.get();
+ VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper.get();
+}
+
+CandleStickChart::~CandleStickChart()
+{
+}
+
+// MinimumAndMaximumSupplier
+
+bool CandleStickChart::isSeparateStackingForDifferentSigns( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+LegendSymbolStyle CandleStickChart::getLegendSymbolStyle()
+{
+ return LegendSymbolStyle::Line;
+}
+
+drawing::Direction3D CandleStickChart::getPreferredDiagramAspectRatio() const
+{
+ return drawing::Direction3D(-1,-1,-1);
+}
+
+void CandleStickChart::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 /* zSlot */, sal_Int32 xSlot, sal_Int32 ySlot )
+{
+ //ignore y stacking for candle stick chart
+ VSeriesPlotter::addSeries( std::move(pSeries), 0, xSlot, ySlot );
+}
+
+void CandleStickChart::createShapes()
+{
+ if( m_aZSlots.empty() ) //no series
+ return;
+
+ if( m_nDimension!=2 )
+ return;
+
+ OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"CandleStickChart is not proper initialized");
+ if(!(m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+
+ //the text labels should be always on top of the other series shapes
+ //therefore create an own group for the texts to move them to front
+ //(because the text group is created after the series group the texts are displayed on top)
+
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget =
+ createGroupShape( m_xLogicTarget );
+ rtl::Reference<SvxShapeGroupAnyD> xLossTarget =
+ createGroupShape( m_xLogicTarget, ObjectIdentifier::createClassifiedIdentifier(
+ OBJECTTYPE_DATA_STOCK_LOSS, u"" ));
+ rtl::Reference<SvxShapeGroupAnyD> xGainTarget =
+ createGroupShape( m_xLogicTarget, ObjectIdentifier::createClassifiedIdentifier(
+ OBJECTTYPE_DATA_STOCK_GAIN, u"" ));
+ rtl::Reference< SvxShapeGroup > xTextTarget =
+ ShapeFactory::createGroup2D( m_xFinalTarget );
+
+ //check necessary here that different Y axis can not be stacked in the same group? ... hm?
+
+ bool bJapaneseStyle=true;//@todo is this the correct default?
+ bool bShowFirst = true;//is only important if bJapaneseStyle == false
+ tNameSequence aWhiteBox_Names, aBlackBox_Names;
+ tAnySequence aWhiteBox_Values, aBlackBox_Values;
+ try
+ {
+ if( m_xChartTypeModel.is() )
+ {
+ m_xChartTypeModel->getPropertyValue( "ShowFirst" ) >>= bShowFirst;
+
+ uno::Reference< beans::XPropertySet > xWhiteDayProps;
+ uno::Reference< beans::XPropertySet > xBlackDayProps;
+ m_xChartTypeModel->getPropertyValue( "Japanese" ) >>= bJapaneseStyle;
+ m_xChartTypeModel->getPropertyValue( "WhiteDay" ) >>= xWhiteDayProps;
+ m_xChartTypeModel->getPropertyValue( "BlackDay" ) >>= xBlackDayProps;
+
+ tPropertyNameValueMap aWhiteBox_Map;
+ PropertyMapper::getValueMap( aWhiteBox_Map, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xWhiteDayProps );
+ PropertyMapper::getMultiPropertyListsFromValueMap( aWhiteBox_Names, aWhiteBox_Values, aWhiteBox_Map );
+
+ tPropertyNameValueMap aBlackBox_Map;
+ PropertyMapper::getValueMap( aBlackBox_Map, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xBlackDayProps );
+ PropertyMapper::getMultiPropertyListsFromValueMap( aBlackBox_Names, aBlackBox_Values, aBlackBox_Map );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ //(@todo maybe different iteration for breaks in axis ?)
+ sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
+ double fLogicZ = 1.5;//as defined
+ //iterate through all x values per indices
+ for( sal_Int32 nIndex = 0; nIndex < nEndIndex; nIndex++ )
+ {
+ for( auto const& rZSlot : m_aZSlots )
+ {
+ BarPositionHelper* pPosHelper = m_pMainPosHelper.get();
+ if( !rZSlot.empty() )
+ {
+ sal_Int32 nAttachedAxisIndex = rZSlot.front().getAttachedAxisIndexForFirstSeries();
+ //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
+ pPosHelper = dynamic_cast<BarPositionHelper*>(&( getPlottingPositionHelper( nAttachedAxisIndex ) ) );
+ if(!pPosHelper)
+ pPosHelper = m_pMainPosHelper.get();
+ }
+ PlotterBase::m_pPosHelper = pPosHelper;
+
+ //update/create information for current group
+ pPosHelper->updateSeriesCount( rZSlot.size() );
+ double fSlotX=0;
+ //iterate through all x slots in this category
+ for( auto const& rXSlot : rZSlot )
+ {
+ //iterate through all series in this x slot
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ //collect data point information (logic coordinates, style ):
+ double fUnscaledX = pSeries->getXValue( nIndex );
+ if( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() )
+ fUnscaledX = DateHelper::RasterizeDateValue( fUnscaledX, m_aNullDate, m_nTimeResolution );
+ if(fUnscaledX<pPosHelper->getLogicMinX() || fUnscaledX>pPosHelper->getLogicMaxX())
+ continue;//point not visible
+ double fScaledX = pPosHelper->getScaledSlotPos( fUnscaledX, fSlotX );
+
+ double fUnscaledY_First = pSeries->getY_First( nIndex );
+ double fUnscaledY_Last = pSeries->getY_Last( nIndex );
+ double fUnscaledY_Min = pSeries->getY_Min( nIndex );
+ double fUnscaledY_Max = pSeries->getY_Max( nIndex );
+
+ bool bBlack=false;
+ if(fUnscaledY_Last<=fUnscaledY_First)
+ {
+ std::swap(fUnscaledY_First,fUnscaledY_Last);
+ bBlack=true;
+ }
+ if(fUnscaledY_Max<fUnscaledY_Min)
+ std::swap(fUnscaledY_Min,fUnscaledY_Max);
+ //transformation 3) -> 4)
+ double fHalfScaledWidth = pPosHelper->getScaledSlotWidth()/2.0;
+
+ double fScaledY_First(fUnscaledY_First);
+ double fScaledY_Last(fUnscaledY_Last);
+ double fScaledY_Min(fUnscaledY_Min);
+ double fScaledY_Max(fUnscaledY_Max);
+ pPosHelper->clipLogicValues( nullptr,&fScaledY_First,nullptr );
+ pPosHelper->clipLogicValues( nullptr,&fScaledY_Last,nullptr );
+ pPosHelper->clipLogicValues( nullptr,&fScaledY_Min,nullptr );
+ pPosHelper->clipLogicValues( nullptr,&fScaledY_Max,nullptr );
+ pPosHelper->doLogicScaling( nullptr,&fScaledY_First,nullptr );
+ pPosHelper->doLogicScaling( nullptr,&fScaledY_Last,nullptr );
+ pPosHelper->doLogicScaling( nullptr,&fScaledY_Min,nullptr );
+ pPosHelper->doLogicScaling( nullptr,&fScaledY_Max,nullptr );
+
+ drawing::Position3D aPosLeftFirst( pPosHelper->transformScaledLogicToScene( fScaledX-fHalfScaledWidth, fScaledY_First ,0 ,true ) );
+ drawing::Position3D aPosRightLast( pPosHelper->transformScaledLogicToScene( fScaledX+fHalfScaledWidth, fScaledY_Last ,0 ,true ) );
+ drawing::Position3D aPosMiddleFirst( pPosHelper->transformScaledLogicToScene( fScaledX, fScaledY_First ,0 ,true ) );
+ drawing::Position3D aPosMiddleLast( pPosHelper->transformScaledLogicToScene( fScaledX, fScaledY_Last ,0 ,true ) );
+ drawing::Position3D aPosMiddleMinimum( pPosHelper->transformScaledLogicToScene( fScaledX, fScaledY_Min ,0 ,true ) );
+ drawing::Position3D aPosMiddleMaximum( pPosHelper->transformScaledLogicToScene( fScaledX, fScaledY_Max ,0 ,true ) );
+
+ rtl::Reference<SvxShapeGroupAnyD> xLossGainTarget( xGainTarget );
+ if(bBlack)
+ xLossGainTarget = xLossTarget;
+
+ uno::Reference< beans::XPropertySet > xPointProp( pSeries->getPropertiesOfPoint( nIndex ));
+ rtl::Reference<SvxShapeGroupAnyD> xPointGroupShape_Shapes;
+ {
+ OUString aPointCID = ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), nIndex );
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes( getSeriesGroupShape(pSeries.get(), xSeriesTarget) );
+ xPointGroupShape_Shapes = createGroupShape(xSeriesGroupShape_Shapes,aPointCID);
+ }
+
+ //create min-max line
+ if( isValidPosition(aPosMiddleMinimum) && isValidPosition(aPosMiddleMaximum) )
+ {
+ std::vector<std::vector<css::drawing::Position3D>> aPoly
+ {
+ { aPosMiddleMinimum, aPosMiddleMaximum }
+ };
+
+ rtl::Reference<SvxShapePolyPolygon> xShape =
+ ShapeFactory::createLine2D( xPointGroupShape_Shapes, aPoly);
+ PropertyMapper::setMappedProperties( *xShape, xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
+ }
+
+ //create first-last shape
+ if(bJapaneseStyle && isValidPosition(aPosLeftFirst) && isValidPosition(aPosRightLast) )
+ {
+ drawing::Direction3D aDiff = aPosRightLast-aPosLeftFirst;
+ awt::Size aAWTSize( Direction3DToAWTSize( aDiff ));
+ // workaround for bug in drawing: if height is 0 the box gets infinitely large
+ if( aAWTSize.Height == 0 )
+ aAWTSize.Height = 1;
+
+ tNameSequence aNames;
+ tAnySequence aValues;
+
+ rtl::Reference<SvxShapeRect> xShape =
+ ShapeFactory::createRectangle( xLossGainTarget,
+ aAWTSize, Position3DToAWTPoint( aPosLeftFirst ),
+ aNames, aValues);
+
+ if(bBlack)
+ PropertyMapper::setMultiProperties( aBlackBox_Names, aBlackBox_Values, *xShape );
+ else
+ PropertyMapper::setMultiProperties( aWhiteBox_Names, aWhiteBox_Values, *xShape );
+ }
+ else
+ {
+ std::vector<std::vector<css::drawing::Position3D>> aPoly;
+
+ sal_Int32 nLineIndex = 0;
+ if( bShowFirst && pPosHelper->isLogicVisible( fUnscaledX, fUnscaledY_First ,fLogicZ )
+ && isValidPosition(aPosLeftFirst) && isValidPosition(aPosMiddleFirst) )
+ {
+ AddPointToPoly( aPoly, aPosLeftFirst, nLineIndex );
+ AddPointToPoly( aPoly, aPosMiddleFirst, nLineIndex++ );
+ }
+ if( pPosHelper->isLogicVisible( fUnscaledX, fUnscaledY_Last ,fLogicZ )
+ && isValidPosition(aPosMiddleLast) && isValidPosition(aPosRightLast) )
+ {
+ AddPointToPoly( aPoly, aPosMiddleLast, nLineIndex );
+ AddPointToPoly( aPoly, aPosRightLast, nLineIndex );
+ }
+
+ if( !aPoly.empty() )
+ {
+ rtl::Reference<SvxShapePolyPolygon> xShape =
+ ShapeFactory::createLine2D( xPointGroupShape_Shapes, aPoly );
+ PropertyMapper::setMappedProperties( *xShape, xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
+ }
+ }
+
+ //create data point label
+ if( pSeries->getDataPointLabelIfLabel(nIndex) )
+ {
+ if(isValidPosition(aPosMiddleFirst))
+ createDataLabel( xTextTarget, *pSeries, nIndex
+ , fUnscaledY_First, 1.0, Position3DToAWTPoint(aPosMiddleFirst), LABEL_ALIGN_LEFT_BOTTOM );
+ if(isValidPosition(aPosMiddleLast))
+ createDataLabel( xTextTarget, *pSeries, nIndex
+ , fUnscaledY_Last, 1.0, Position3DToAWTPoint(aPosMiddleLast), LABEL_ALIGN_RIGHT_TOP );
+ if(isValidPosition(aPosMiddleMinimum))
+ createDataLabel( xTextTarget, *pSeries, nIndex
+ , fUnscaledY_Min, 1.0, Position3DToAWTPoint(aPosMiddleMinimum), LABEL_ALIGN_BOTTOM );
+ if(isValidPosition(aPosMiddleMaximum))
+ createDataLabel( xTextTarget, *pSeries, nIndex
+ , fUnscaledY_Max, 1.0, Position3DToAWTPoint(aPosMiddleMaximum), LABEL_ALIGN_TOP );
+ }
+ }//next series in x slot (next y slot)
+ fSlotX+=1.0;
+ }//next x slot
+ }//next z slot
+ }//next category
+ /* @todo remove series shapes if empty
+ //remove and delete point-group-shape if empty
+ if(!xSeriesGroupShape_Shapes->getCount())
+ {
+ pSeries->m_xShape.set(NULL);
+ m_xLogicTarget->remove(xSeriesGroupShape_Shape);
+ }
+ */
+
+ //remove and delete series-group-shape if empty
+
+ //... todo
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/CandleStickChart.hxx b/chart2/source/view/charttypes/CandleStickChart.hxx
new file mode 100644
index 0000000000..93571889ee
--- /dev/null
+++ b/chart2/source/view/charttypes/CandleStickChart.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <VSeriesPlotter.hxx>
+
+namespace chart
+{
+class BarPositionHelper;
+
+class CandleStickChart : public VSeriesPlotter
+{
+ // public methods
+public:
+ CandleStickChart() = delete;
+
+ CandleStickChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount );
+ virtual ~CandleStickChart() override;
+
+ virtual void createShapes() override;
+ virtual void addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot ) override;
+
+ virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override;
+
+ // MinimumAndMaximumSupplier
+ virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) override;
+
+ virtual LegendSymbolStyle getLegendSymbolStyle() override;
+
+private: //member
+ std::unique_ptr<BarPositionHelper> m_pMainPosHelper;
+};
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/CategoryPositionHelper.cxx b/chart2/source/view/charttypes/CategoryPositionHelper.cxx
new file mode 100644
index 0000000000..d7412d3cbe
--- /dev/null
+++ b/chart2/source/view/charttypes/CategoryPositionHelper.cxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "CategoryPositionHelper.hxx"
+
+namespace chart
+{
+
+CategoryPositionHelper::CategoryPositionHelper( double fSeriesCount, double fCategoryWidth )
+ : m_fSeriesCount(fSeriesCount)
+ , m_fCategoryWidth(fCategoryWidth)
+ , m_fInnerDistance(0.0)
+ , m_fOuterDistance(1.0)
+{
+}
+
+CategoryPositionHelper::~CategoryPositionHelper()
+{
+}
+
+double CategoryPositionHelper::getScaledSlotWidth() const
+{
+ double fWidth = m_fCategoryWidth /
+ ( m_fSeriesCount
+ + m_fOuterDistance
+ + m_fInnerDistance*( m_fSeriesCount - 1.0) );
+ return fWidth;
+}
+
+double CategoryPositionHelper::getScaledSlotPos( double fScaledXPos, double fSeriesNumber ) const
+{
+ //the returned position is in the middle of the rect
+ //fSeriesNumber 0...n-1
+ double fPos = fScaledXPos
+ - (m_fCategoryWidth/2.0)
+ + (m_fOuterDistance/2.0 + fSeriesNumber*(1.0+m_fInnerDistance)) * getScaledSlotWidth()
+ + getScaledSlotWidth()/2.0;
+ return fPos;
+}
+
+void CategoryPositionHelper::setInnerDistance( double fInnerDistance )
+{
+ if( fInnerDistance < -1.0 )
+ fInnerDistance = -1.0;
+ if( fInnerDistance > 1.0 )
+ fInnerDistance = 1.0;
+ m_fInnerDistance = fInnerDistance;
+}
+
+void CategoryPositionHelper::setOuterDistance( double fOuterDistance )
+{
+ if( fOuterDistance < 0.0 )
+ fOuterDistance = 0.0;
+ if( fOuterDistance > 6.0 )
+ fOuterDistance = 6.0;
+ m_fOuterDistance = fOuterDistance;
+}
+
+void CategoryPositionHelper::setCategoryWidth( double fCategoryWidth )
+{
+ m_fCategoryWidth = fCategoryWidth;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/CategoryPositionHelper.hxx b/chart2/source/view/charttypes/CategoryPositionHelper.hxx
new file mode 100644
index 0000000000..ebc784ef66
--- /dev/null
+++ b/chart2/source/view/charttypes/CategoryPositionHelper.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+namespace chart
+{
+class CategoryPositionHelper
+{
+public:
+ CategoryPositionHelper(double fSeriesCount, double CategoryWidth = 1.0);
+ virtual ~CategoryPositionHelper();
+
+ CategoryPositionHelper(CategoryPositionHelper const&) = default;
+ CategoryPositionHelper(CategoryPositionHelper&&) = default;
+ CategoryPositionHelper& operator=(CategoryPositionHelper const&) = default;
+ CategoryPositionHelper& operator=(CategoryPositionHelper&&) = default;
+
+ double getScaledSlotWidth() const;
+ virtual double getScaledSlotPos(double fCategoryX, double fSeriesNumber) const;
+ void setCategoryWidth(double fCategoryWidth);
+
+ //Distance between two neighboring bars in same category, seen relative to width of the bar
+ void setInnerDistance(double fInnerDistance);
+
+ //Distance between two neighboring bars in different category, seen relative to width of the bar:
+ void setOuterDistance(double fOuterDistance);
+
+protected:
+ double m_fSeriesCount;
+ double m_fCategoryWidth;
+ //Distance between two neighboring bars in same category, seen relative to width of the bar:
+ double
+ m_fInnerDistance; //[-1,1] m_fInnerDistance=1 --> distance == width; m_fInnerDistance=-1-->all rects are painted on the same position
+ //Distance between two neighboring bars in different category, seen relative to width of the bar:
+ double m_fOuterDistance; //>=0 m_fOuterDistance=1 --> distance == width
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/NetChart.cxx b/chart2/source/view/charttypes/NetChart.cxx
new file mode 100644
index 0000000000..5b8f1db34b
--- /dev/null
+++ b/chart2/source/view/charttypes/NetChart.cxx
@@ -0,0 +1,642 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "NetChart.hxx"
+#include <PlottingPositionHelper.hxx>
+#include <ShapeFactory.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <CommonConverters.hxx>
+#include <ObjectIdentifier.hxx>
+#include <LabelPositionHelper.hxx>
+#include <Clipping.hxx>
+#include <PolarLabelPositionHelper.hxx>
+#include <DateHelper.hxx>
+#include <ChartType.hxx>
+
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+
+#include <officecfg/Office/Compatibility.hxx>
+
+#include <limits>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+NetChart::NetChart( const rtl::Reference<ChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bNoArea
+ , std::unique_ptr<PlottingPositionHelper> pPlottingPositionHelper
+ )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount, true )
+ , m_pMainPosHelper(std::move(pPlottingPositionHelper))
+ , m_bArea(!bNoArea)
+ , m_bLine(bNoArea)
+{
+ // we only support 2D Net charts
+ assert(nDimensionCount == 2);
+
+ m_pMainPosHelper->AllowShiftXAxisPos(true);
+ m_pMainPosHelper->AllowShiftZAxisPos(true);
+
+ PlotterBase::m_pPosHelper = m_pMainPosHelper.get();
+ VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper.get();
+}
+
+NetChart::~NetChart()
+{
+}
+
+double NetChart::getMaximumX()
+{
+ double fMax = VSeriesPlotter::getMaximumX() + 1.0;
+ return fMax;
+}
+
+bool NetChart::isExpandIfValuesCloseToBorder( sal_Int32 )
+{
+ return false;
+}
+
+bool NetChart::isSeparateStackingForDifferentSigns( sal_Int32 /*nDimensionIndex*/ )
+{
+ // no separate stacking in all types of line/area charts
+ return false;
+}
+
+LegendSymbolStyle NetChart::getLegendSymbolStyle()
+{
+ if( m_bArea )
+ return LegendSymbolStyle::Box;
+ return LegendSymbolStyle::Line;
+}
+
+uno::Any NetChart::getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex )
+{
+ uno::Any aRet;
+
+ Symbol* pSymbolProperties = rSeries.getSymbolProperties( nPointIndex );
+ if( pSymbolProperties )
+ {
+ aRet <<= *pSymbolProperties;
+ }
+
+ return aRet;
+}
+
+drawing::Direction3D NetChart::getPreferredDiagramAspectRatio() const
+{
+ return drawing::Direction3D(1,1,1);
+}
+
+bool NetChart::impl_createLine( VDataSeries* pSeries
+ , const std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly
+ , PlottingPositionHelper const * pPosHelper )
+{
+ //return true if a line was created successfully
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
+
+ std::vector<std::vector<css::drawing::Position3D>> aPoly;
+ {
+ bool bIsClipped = false;
+ if( !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
+ {
+ // do NOT connect last and first point, if one is NAN, and NAN handling is NAN_AS_GAP
+ double fFirstY = pSeries->getYValue( 0 );
+ double fLastY = pSeries->getYValue( VSeriesPlotter::getPointCount() - 1 );
+ if( (pSeries->getMissingValueTreatment() != css::chart::MissingValueTreatment::LEAVE_GAP)
+ || (std::isfinite( fFirstY ) && std::isfinite( fLastY )) )
+ {
+ // connect last point in last polygon with first point in first polygon
+ ::basegfx::B2DRectangle aScaledLogicClipDoubleRect( pPosHelper->getScaledLogicClipDoubleRect() );
+ std::vector<std::vector<css::drawing::Position3D>> aTmpPoly(*pSeriesPoly);
+ drawing::Position3D aLast(aScaledLogicClipDoubleRect.getMaxX(),aTmpPoly[0][0].PositionY,aTmpPoly[0][0].PositionZ);
+ // add connector line to last polygon
+ AddPointToPoly( aTmpPoly, aLast, pSeriesPoly->size() - 1 );
+ Clipping::clipPolygonAtRectangle( aTmpPoly, aScaledLogicClipDoubleRect, aPoly );
+ bIsClipped = true;
+ }
+ }
+
+ if( !bIsClipped )
+ Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+ }
+
+ if(!ShapeFactory::hasPolygonAnyLines(aPoly))
+ return false;
+
+ //transformation 3) -> 4)
+ pPosHelper->transformScaledLogicToScene( aPoly );
+
+ //create line:
+ rtl::Reference<SvxShapePolyPolygon> xShape;
+ {
+ xShape = ShapeFactory::createLine2D( xSeriesGroupShape_Shapes, aPoly );
+ PropertyMapper::setMappedProperties( *xShape
+ , pSeries->getPropertiesOfSeries()
+ , PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
+ //because of this name this line will be used for marking
+ ::chart::ShapeFactory::setShapeName(xShape, "MarkHandles");
+ }
+ return true;
+}
+
+bool NetChart::impl_createArea( VDataSeries* pSeries
+ , const std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly
+ , std::vector<std::vector<css::drawing::Position3D>> const * pPreviousSeriesPoly
+ , PlottingPositionHelper const * pPosHelper )
+{
+ //return true if an area was created successfully
+
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
+ double zValue = pSeries->m_fLogicZPos;
+
+ std::vector<std::vector<css::drawing::Position3D>> aPoly( *pSeriesPoly );
+ //add second part to the polygon (grounding points or previous series points)
+ if( !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
+ {
+ if( pPreviousSeriesPoly )
+ addPolygon( aPoly, *pPreviousSeriesPoly );
+ }
+ else if(!pPreviousSeriesPoly)
+ {
+ double fMinX = pSeries->m_fLogicMinX;
+ double fMaxX = pSeries->m_fLogicMaxX;
+ double fY = pPosHelper->getBaseValueY();//logic grounding
+
+ //clip to scale
+ if(fMaxX<pPosHelper->getLogicMinX() || fMinX>pPosHelper->getLogicMaxX())
+ return false;//no visible shape needed
+ pPosHelper->clipLogicValues( &fMinX, &fY, nullptr );
+ pPosHelper->clipLogicValues( &fMaxX, nullptr, nullptr );
+
+ //apply scaling
+ {
+ pPosHelper->doLogicScaling( &fMinX, &fY, &zValue );
+ pPosHelper->doLogicScaling( &fMaxX, nullptr, nullptr );
+ }
+
+ AddPointToPoly( aPoly, drawing::Position3D( fMaxX,fY,zValue) );
+ AddPointToPoly( aPoly, drawing::Position3D( fMinX,fY,zValue) );
+ }
+ else
+ {
+ appendPoly( aPoly, *pPreviousSeriesPoly );
+ }
+ ShapeFactory::closePolygon(aPoly);
+
+ //apply clipping
+ {
+ std::vector<std::vector<css::drawing::Position3D>> aClippedPoly;
+ Clipping::clipPolygonAtRectangle( aPoly, pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly, false );
+ ShapeFactory::closePolygon(aClippedPoly); //again necessary after clipping
+ aPoly = aClippedPoly;
+ }
+
+ if(!ShapeFactory::hasPolygonAnyLines(aPoly))
+ return false;
+
+ //transformation 3) -> 4)
+ pPosHelper->transformScaledLogicToScene( aPoly );
+
+ //create area:
+ rtl::Reference<SvxShapePolyPolygon>
+ xShape = ShapeFactory::createArea2D( xSeriesGroupShape_Shapes
+ , aPoly );
+ PropertyMapper::setMappedProperties( *xShape
+ , pSeries->getPropertiesOfSeries()
+ , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ //because of this name this line will be used for marking
+ ::chart::ShapeFactory::setShapeName(xShape, "MarkHandles");
+ return true;
+}
+
+void NetChart::impl_createSeriesShapes()
+{
+ //the polygon shapes for each series need to be created before
+
+ //iterate through all series again to create the series shapes
+ for( auto const& rZSlot : m_aZSlots )
+ {
+ for( auto const& rXSlot : rZSlot )
+ {
+ std::map< sal_Int32, std::vector<std::vector<css::drawing::Position3D>>* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex
+ std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly = nullptr;
+
+ //iterate through all series
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
+ m_pPosHelper = &getPlottingPositionHelper(nAttachedAxisIndex);
+
+ pSeriesPoly = &pSeries->m_aPolyPolygonShape3D;
+ if( m_bArea )
+ {
+ if (!impl_createArea(pSeries.get(), pSeriesPoly,
+ aPreviousSeriesPolyMap[nAttachedAxisIndex], m_pPosHelper))
+ continue;
+ }
+ if( m_bLine )
+ {
+ if (!impl_createLine(pSeries.get(), pSeriesPoly, m_pPosHelper))
+ continue;
+ }
+ aPreviousSeriesPolyMap[nAttachedAxisIndex] = pSeriesPoly;
+ }//next series in x slot (next y slot)
+ }//next x slot
+ }//next z slot
+}
+
+namespace
+{
+
+void lcl_reorderSeries( std::vector< std::vector< VDataSeriesGroup > >& rZSlots )
+{
+ std::vector< std::vector< VDataSeriesGroup > > aRet;
+ aRet.reserve( rZSlots.size() );
+
+ std::vector< std::vector< VDataSeriesGroup > >::reverse_iterator aZIt( rZSlots.rbegin() );
+ std::vector< std::vector< VDataSeriesGroup > >::reverse_iterator aZEnd( rZSlots.rend() );
+ for( ; aZIt != aZEnd; ++aZIt )
+ {
+ std::vector< VDataSeriesGroup > aXSlot;
+
+ std::vector< VDataSeriesGroup >::reverse_iterator aXIt( aZIt->rbegin() );
+ std::vector< VDataSeriesGroup >::reverse_iterator aXEnd( aZIt->rend() );
+ for( ; aXIt != aXEnd; ++aXIt )
+ aXSlot.push_back(std::move(*aXIt));
+
+ aRet.push_back(std::move(aXSlot));
+ }
+
+ rZSlots = std::move(aRet);
+}
+
+//better performance for big data
+struct FormerPoint
+{
+ FormerPoint( double fX, double fY, double fZ )
+ : m_fX(fX), m_fY(fY), m_fZ(fZ)
+ {}
+ FormerPoint()
+ : m_fX(std::numeric_limits<double>::quiet_NaN())
+ , m_fY(std::numeric_limits<double>::quiet_NaN())
+ , m_fZ(std::numeric_limits<double>::quiet_NaN())
+
+ {
+ }
+
+ double m_fX;
+ double m_fY;
+ double m_fZ;
+};
+
+}//anonymous namespace
+
+void NetChart::createShapes()
+{
+ if( m_aZSlots.empty() ) //no series
+ return;
+
+ //tdf#127813 Don't reverse the series in OOXML-heavy environments
+ if (officecfg::Office::Compatibility::View::ReverseSeriesOrderAreaAndNetChart::get() && m_bArea)
+ lcl_reorderSeries( m_aZSlots );
+
+ OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),"NetChart is not proper initialized");
+ if(!(m_xLogicTarget.is()&&m_xFinalTarget.is()))
+ return;
+
+ //the text labels should be always on top of the other series shapes
+ //for area chart the error bars should be always on top of the other series shapes
+
+ //therefore create an own group for the texts and the error bars to move them to front
+ //(because the text group is created after the series group the texts are displayed on top)
+ m_xSeriesTarget = createGroupShape( m_xLogicTarget );
+ m_xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget );
+
+ //check necessary here that different Y axis can not be stacked in the same group? ... hm?
+
+ //update/create information for current group
+ double fLogicZ = 1.0;//as defined
+
+ sal_Int32 const nStartIndex = 0; // inclusive ;..todo get somehow from x scale
+ sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
+ if(nEndIndex<=0)
+ nEndIndex=1;
+
+ //better performance for big data
+ std::map< VDataSeries*, FormerPoint > aSeriesFormerPointMap;
+ m_bPointsWereSkipped = false;
+
+ bool bDateCategory = (m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis());
+
+ //iterate through all x values per indices
+ for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ )
+ {
+ std::map< sal_Int32, double > aLogicYSumMap;//one for each different nAttachedAxisIndex
+ for( auto const& rZSlot : m_aZSlots )
+ {
+ //iterate through all x slots in this category to get 100percent sum
+ for( auto const& rXSlot : rZSlot )
+ {
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ if(!pSeries)
+ continue;
+
+ if (bDateCategory)
+ pSeries->doSortByXValues();
+
+ sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
+ aLogicYSumMap.insert({nAttachedAxisIndex, 0.0});
+
+ m_pPosHelper = &getPlottingPositionHelper(nAttachedAxisIndex);
+
+ double fAdd = pSeries->getYValue( nIndex );
+ if( !std::isnan(fAdd) && !std::isinf(fAdd) )
+ aLogicYSumMap[nAttachedAxisIndex] += fabs( fAdd );
+ }
+ }
+ }
+
+ for( auto const& rZSlot : m_aZSlots )
+ {
+ //for the area chart there should be at most one x slot (no side by side stacking available)
+ //attention different: xSlots are always interpreted as independent areas one behind the other: @todo this doesn't work why not???
+ for( auto const& rXSlot : rZSlot )
+ {
+ std::map< sal_Int32, double > aLogicYForNextSeriesMap;//one for each different nAttachedAxisIndex
+ //iterate through all series
+ for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector )
+ {
+ if(!pSeries)
+ continue;
+
+ /* #i70133# ignore points outside of series length in standard area
+ charts. Stacked area charts will use missing points as zeros. In
+ standard charts, pSeriesList contains only one series. */
+ if( m_bArea && (rXSlot.m_aSeriesVector.size() == 1) && (nIndex >= pSeries->getTotalPointCount()) )
+ continue;
+
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShapeFrontChild(pSeries.get(), m_xSeriesTarget);
+
+ sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
+ m_pPosHelper = &getPlottingPositionHelper(nAttachedAxisIndex);
+
+ pSeries->m_fLogicZPos = fLogicZ;
+
+ //collect data point information (logic coordinates, style ):
+ double fLogicX = pSeries->getXValue(nIndex);
+ if (bDateCategory)
+ fLogicX = DateHelper::RasterizeDateValue( fLogicX, m_aNullDate, m_nTimeResolution );
+ double fLogicY = pSeries->getYValue(nIndex);
+
+ if( m_bArea && ( std::isnan(fLogicY) || std::isinf(fLogicY) ) )
+ {
+ if( pSeries->getMissingValueTreatment() == css::chart::MissingValueTreatment::LEAVE_GAP )
+ {
+ if( rXSlot.m_aSeriesVector.size() == 1 || pSeries == rXSlot.m_aSeriesVector.front() )
+ {
+ fLogicY = m_pPosHelper->getLogicMinY();
+ if (!m_pPosHelper->isMathematicalOrientationY())
+ fLogicY = m_pPosHelper->getLogicMaxY();
+ }
+ else
+ fLogicY = 0.0;
+ }
+ }
+
+ if (m_pPosHelper->isPercentY() && aLogicYSumMap[nAttachedAxisIndex] != 0.0)
+ {
+ fLogicY = fabs( fLogicY )/aLogicYSumMap[nAttachedAxisIndex];
+ }
+
+ if( std::isnan(fLogicX) || std::isinf(fLogicX)
+ || std::isnan(fLogicY) || std::isinf(fLogicY)
+ || std::isnan(fLogicZ) || std::isinf(fLogicZ) )
+ {
+ if( pSeries->getMissingValueTreatment() == css::chart::MissingValueTreatment::LEAVE_GAP )
+ {
+ std::vector<std::vector<css::drawing::Position3D>>& rPolygon = pSeries->m_aPolyPolygonShape3D;
+ sal_Int32& rIndex = pSeries->m_nPolygonIndex;
+ if( 0<= rIndex && o3tl::make_unsigned(rIndex) < rPolygon.size() )
+ {
+ if( !rPolygon[ rIndex ].empty() )
+ rIndex++; //start a new polygon for the next point if the current poly is not empty
+ }
+ }
+ continue;
+ }
+
+ aLogicYForNextSeriesMap.try_emplace(nAttachedAxisIndex, 0.0);
+
+ double fLogicValueForLabeDisplay = fLogicY;
+
+ fLogicY += aLogicYForNextSeriesMap[nAttachedAxisIndex];
+ aLogicYForNextSeriesMap[nAttachedAxisIndex] = fLogicY;
+
+ bool bIsVisible = m_pPosHelper->isLogicVisible(fLogicX, fLogicY, fLogicZ);
+
+ //remind minimal and maximal x values for area 'grounding' points
+ //only for filled area
+ {
+ double& rfMinX = pSeries->m_fLogicMinX;
+ if(!nIndex||fLogicX<rfMinX)
+ rfMinX=fLogicX;
+ double& rfMaxX = pSeries->m_fLogicMaxX;
+ if(!nIndex||fLogicX>rfMaxX)
+ rfMaxX=fLogicX;
+ }
+
+ drawing::Position3D aUnscaledLogicPosition( fLogicX, fLogicY, fLogicZ );
+ drawing::Position3D aScaledLogicPosition(aUnscaledLogicPosition);
+ m_pPosHelper->doLogicScaling(aScaledLogicPosition);
+
+ //transformation 3) -> 4)
+ drawing::Position3D aScenePosition(
+ m_pPosHelper->transformLogicToScene(fLogicX, fLogicY, fLogicZ, false));
+
+ //better performance for big data
+ FormerPoint aFormerPoint( aSeriesFormerPointMap[pSeries.get()] );
+ m_pPosHelper->setCoordinateSystemResolution(m_aCoordinateSystemResolution);
+ if( !pSeries->isAttributedDataPoint(nIndex)
+ && m_pPosHelper->isSameForGivenResolution(
+ aFormerPoint.m_fX, aFormerPoint.m_fY, aFormerPoint.m_fZ
+ , aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ ) )
+ {
+ m_bPointsWereSkipped = true;
+ continue;
+ }
+ aSeriesFormerPointMap[pSeries.get()] = FormerPoint(aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ);
+
+ //store point information for series polygon
+ //for area and/or line (symbols only do not need this)
+ if( isValidPosition(aScaledLogicPosition) )
+ {
+ AddPointToPoly( pSeries->m_aPolyPolygonShape3D, aScaledLogicPosition, pSeries->m_nPolygonIndex );
+
+ //prepare clipping for filled net charts
+ if( !bIsVisible && m_bArea )
+ {
+ drawing::Position3D aClippedPos(aScaledLogicPosition);
+ m_pPosHelper->clipScaledLogicValues(nullptr, &aClippedPos.PositionY,
+ nullptr);
+ if (m_pPosHelper->isLogicVisible(aClippedPos.PositionX,
+ aClippedPos.PositionY,
+ aClippedPos.PositionZ))
+ {
+ AddPointToPoly( pSeries->m_aPolyPolygonShape3D, aClippedPos, pSeries->m_nPolygonIndex );
+ AddPointToPoly( pSeries->m_aPolyPolygonShape3D, aScaledLogicPosition, pSeries->m_nPolygonIndex );
+ }
+ }
+ }
+
+ //create a single datapoint if point is visible
+ //apply clipping:
+ if( !bIsVisible )
+ continue;
+
+ Symbol* pSymbolProperties = pSeries->getSymbolProperties( nIndex );
+ bool bCreateSymbol = pSymbolProperties && (pSymbolProperties->Style != SymbolStyle_NONE);
+
+ if( !bCreateSymbol && !pSeries->getDataPointLabelIfLabel(nIndex) )
+ continue;
+
+ //create a group shape for this point and add to the series shape:
+ OUString aPointCID = ObjectIdentifier::createPointCID(
+ pSeries->getPointCID_Stub(), nIndex );
+ rtl::Reference<SvxShapeGroupAnyD> xPointGroupShape_Shapes(
+ createGroupShape(xSeriesGroupShape_Shapes,aPointCID) );
+
+ {
+ //create data point
+ drawing::Direction3D aSymbolSize(0,0,0);
+ if (bCreateSymbol) // implies pSymbolProperties
+ {
+ if (pSymbolProperties->Style != SymbolStyle_NONE)
+ {
+ aSymbolSize.DirectionX = pSymbolProperties->Size.Width;
+ aSymbolSize.DirectionY = pSymbolProperties->Size.Height;
+ }
+
+ if (pSymbolProperties->Style == SymbolStyle_STANDARD)
+ {
+ sal_Int32 nSymbol = pSymbolProperties->StandardSymbol;
+ ShapeFactory::createSymbol2D(
+ xPointGroupShape_Shapes, aScenePosition, aSymbolSize, nSymbol,
+ pSymbolProperties->BorderColor, pSymbolProperties->FillColor);
+ }
+ else if (pSymbolProperties->Style == SymbolStyle_GRAPHIC)
+ {
+ ShapeFactory::createGraphic2D(xPointGroupShape_Shapes,
+ aScenePosition, aSymbolSize,
+ pSymbolProperties->Graphic);
+ }
+ //@todo other symbol styles
+ }
+
+ //create data point label
+ if( pSeries->getDataPointLabelIfLabel(nIndex) )
+ {
+ LabelAlignment eAlignment = LABEL_ALIGN_TOP;
+ drawing::Position3D aScenePosition3D( aScenePosition.PositionX
+ , aScenePosition.PositionY
+ , aScenePosition.PositionZ+getTransformedDepth() );
+
+ sal_Int32 nLabelPlacement = pSeries->getLabelPlacement(
+ nIndex, m_xChartTypeModel, m_pPosHelper->isSwapXAndY());
+
+ switch(nLabelPlacement)
+ {
+ case css::chart::DataLabelPlacement::TOP:
+ aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_TOP;
+ break;
+ case css::chart::DataLabelPlacement::BOTTOM:
+ aScenePosition3D.PositionY += (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_BOTTOM;
+ break;
+ case css::chart::DataLabelPlacement::LEFT:
+ aScenePosition3D.PositionX -= (aSymbolSize.DirectionX/2+1);
+ eAlignment = LABEL_ALIGN_LEFT;
+ break;
+ case css::chart::DataLabelPlacement::RIGHT:
+ aScenePosition3D.PositionX += (aSymbolSize.DirectionX/2+1);
+ eAlignment = LABEL_ALIGN_RIGHT;
+ break;
+ case css::chart::DataLabelPlacement::CENTER:
+ eAlignment = LABEL_ALIGN_CENTER;
+ //todo implement this different for area charts
+ break;
+ default:
+ OSL_FAIL("this label alignment is not implemented yet");
+ aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
+ eAlignment = LABEL_ALIGN_TOP;
+ break;
+ }
+
+ awt::Point aScreenPosition2D;//get the screen position for the labels
+ sal_Int32 nOffset = 100; //todo maybe calculate this font height dependent
+ if( nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE )
+ {
+ PolarPlottingPositionHelper* pPolarPosHelper
+ = dynamic_cast<PolarPlottingPositionHelper*>(m_pPosHelper);
+ if( pPolarPosHelper )
+ {
+ PolarLabelPositionHelper aPolarLabelPositionHelper(pPolarPosHelper,m_nDimension,m_xLogicTarget);
+ aScreenPosition2D = aPolarLabelPositionHelper.getLabelScreenPositionAndAlignmentForLogicValues(
+ eAlignment, fLogicX, fLogicY, fLogicZ, nOffset );
+ }
+ }
+ else
+ {
+ if(eAlignment==LABEL_ALIGN_CENTER )
+ nOffset = 0;
+ aScreenPosition2D = LabelPositionHelper(m_nDimension,m_xLogicTarget)
+ .transformSceneToScreenPosition( aScenePosition3D );
+ }
+
+ createDataLabel( m_xTextTarget, *pSeries, nIndex
+ , fLogicValueForLabeDisplay
+ , aLogicYSumMap[nAttachedAxisIndex], aScreenPosition2D, eAlignment, nOffset );
+ }
+ }
+
+ //remove PointGroupShape if empty
+ if(!xPointGroupShape_Shapes->getCount())
+ xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shapes);
+
+ }//next series in x slot (next y slot)
+ }//next x slot
+ }//next z slot
+ }//next category
+
+ impl_createSeriesShapes();
+
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/NetChart.hxx b/chart2/source/view/charttypes/NetChart.hxx
new file mode 100644
index 0000000000..a536daf15f
--- /dev/null
+++ b/chart2/source/view/charttypes/NetChart.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <VSeriesPlotter.hxx>
+
+namespace chart
+{
+
+class NetChart : public VSeriesPlotter
+{
+ // public methods
+public:
+ NetChart() = delete;
+
+ NetChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bNoArea
+ , std::unique_ptr<PlottingPositionHelper> pPlottingPositionHelper //takes ownership
+ );
+ virtual ~NetChart() override;
+
+ virtual void createShapes() override;
+
+ virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override;
+
+ // MinimumAndMaximumSupplier
+ virtual double getMaximumX() override;
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex ) override;
+ virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) override;
+
+ virtual LegendSymbolStyle getLegendSymbolStyle() override;
+ virtual css::uno::Any getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex/*-1 for series symbol*/ ) override;
+
+private: //methods
+ void impl_createSeriesShapes();
+ bool impl_createArea( VDataSeries* pSeries
+ , const std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly
+ , std::vector<std::vector<css::drawing::Position3D>> const * pPreviousSeriesPoly
+ , PlottingPositionHelper const * pPosHelper );
+ bool impl_createLine( VDataSeries* pSeries
+ , const std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly
+ , PlottingPositionHelper const * pPosHelper );
+
+private: //member
+ std::unique_ptr<PlottingPositionHelper> m_pMainPosHelper;
+
+ bool m_bArea;//false -> line or symbol only
+ bool m_bLine;
+
+ rtl::Reference<SvxShapeGroupAnyD> m_xSeriesTarget;
+ rtl::Reference<SvxShapeGroupAnyD> m_xTextTarget;
+};
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx
new file mode 100644
index 0000000000..1c5f15d7ec
--- /dev/null
+++ b/chart2/source/view/charttypes/PieChart.cxx
@@ -0,0 +1,1723 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <BaseGFXHelper.hxx>
+#include <VLineProperties.hxx>
+#include "PieChart.hxx"
+#include <PlottingPositionHelper.hxx>
+#include <ShapeFactory.hxx>
+#include <PolarLabelPositionHelper.hxx>
+#include <CommonConverters.hxx>
+#include <ObjectIdentifier.hxx>
+#include <ChartType.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesProperties.hxx>
+
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart2/XColorScheme.hpp>
+
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/helpers.hxx>
+
+#include <limits>
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart::DataSeriesProperties;
+
+namespace chart {
+
+struct PieChart::ShapeParam
+{
+ /** the start angle of the slice
+ */
+ double mfUnitCircleStartAngleDegree;
+
+ /** the angle width of the slice
+ */
+ double mfUnitCircleWidthAngleDegree;
+
+ /** the normalized outer radius of the ring the slice belongs to.
+ */
+ double mfUnitCircleOuterRadius;
+
+ /** the normalized inner radius of the ring the slice belongs to
+ */
+ double mfUnitCircleInnerRadius;
+
+ /** relative distance offset of a slice from the pie center;
+ * this parameter is used for instance when the user performs manual
+ * dragging of a slice (the drag operation is possible only for slices that
+ * belong to the outer ring and only along the ray bisecting the slice);
+ * the value for the given entry in the data series is obtained by the
+ * `Offset` property attached to each entry; note that the value
+ * provided by the `Offset` property is used both as a logical value in
+ * `PiePositionHelper::getInnerAndOuterRadius` and as a percentage value in
+ * the `PieChart::createDataPoint` and `PieChart::createTextLabelShape`
+ * methods; since the logical height of a ring is always 1, this duality
+ * does not cause any incorrect behavior;
+ */
+ double mfExplodePercentage;
+
+ /** sum of all Y values in a single series
+ */
+ double mfLogicYSum;
+
+ /** for 3D pie chart: label z coordinate
+ */
+ double mfLogicZ;
+
+ /** for 3D pie chart: height
+ */
+ double mfDepth;
+
+ ShapeParam() :
+ mfUnitCircleStartAngleDegree(0.0),
+ mfUnitCircleWidthAngleDegree(0.0),
+ mfUnitCircleOuterRadius(0.0),
+ mfUnitCircleInnerRadius(0.0),
+ mfExplodePercentage(0.0),
+ mfLogicYSum(0.0),
+ mfLogicZ(0.0),
+ mfDepth(0.0) {}
+};
+
+namespace
+{
+::basegfx::B2IRectangle lcl_getRect(const rtl::Reference<SvxShape>& xShape)
+{
+ ::basegfx::B2IRectangle aRect;
+ if (xShape.is())
+ aRect = BaseGFXHelper::makeRectangle(xShape->getPosition(), xShape->getSize());
+ return aRect;
+}
+
+bool lcl_isInsidePage(const awt::Point& rPos, const awt::Size& rSize, const awt::Size& rPageSize)
+{
+ if (rPos.X < 0 || rPos.Y < 0)
+ return false;
+ if ((rPos.X + rSize.Width) > rPageSize.Width)
+ return false;
+ if ((rPos.Y + rSize.Height) > rPageSize.Height)
+ return false;
+ return true;
+}
+
+} //end anonymous namespace
+
+class PiePositionHelper : public PolarPlottingPositionHelper
+{
+public:
+ PiePositionHelper( double fAngleDegreeOffset );
+
+ bool getInnerAndOuterRadius( double fCategoryX, double& fLogicInnerRadius, double& fLogicOuterRadius, bool bUseRings, double fMaxOffset ) const;
+
+public:
+ //Distance between different category rings, seen relative to width of a ring:
+ double m_fRingDistance; //>=0 m_fRingDistance=1 --> distance == width
+};
+
+PiePositionHelper::PiePositionHelper( double fAngleDegreeOffset )
+ : m_fRingDistance(0.0)
+{
+ m_fRadiusOffset = 0.0;
+ m_fAngleDegreeOffset = fAngleDegreeOffset;
+}
+
+/** Compute the outer and the inner radius for the current ring (not for the
+ * whole donut!), in general it is:
+ * inner_radius = (ring_index + 1) - 0.5 + max_offset,
+ * outer_radius = (ring_index + 1) + 0.5 + max_offset.
+ * When orientation for the radius axis is reversed these values are swapped.
+ * (Indeed the orientation for the radius axis is always reversed!
+ * See `PieChartTypeTemplate::adaptScales`.)
+ * The maximum relative offset (see notes for `PieChart::getMaxOffset`) is
+ * added to both the inner and the outer radius.
+ * It returns true if the ring is visible (that is not out of the radius
+ * axis scale range).
+ */
+bool PiePositionHelper::getInnerAndOuterRadius( double fCategoryX
+ , double& fLogicInnerRadius, double& fLogicOuterRadius
+ , bool bUseRings, double fMaxOffset ) const
+{
+ if( !bUseRings )
+ fCategoryX = 1.0;
+
+ double fLogicInner = fCategoryX -0.5+m_fRingDistance/2.0;
+ double fLogicOuter = fCategoryX +0.5-m_fRingDistance/2.0;
+
+ if( !isMathematicalOrientationRadius() )
+ {
+ //in this case the given getMaximumX() was not correct instead the minimum should have been smaller by fMaxOffset
+ //but during getMaximumX and getMimumX we do not know the axis orientation
+ fLogicInner += fMaxOffset;
+ fLogicOuter += fMaxOffset;
+ }
+
+ if( fLogicInner >= getLogicMaxX() )
+ return false;
+ if( fLogicOuter <= getLogicMinX() )
+ return false;
+
+ if( fLogicInner < getLogicMinX() )
+ fLogicInner = getLogicMinX();
+ if( fLogicOuter > getLogicMaxX() )
+ fLogicOuter = getLogicMaxX();
+
+ fLogicInnerRadius = fLogicInner;
+ fLogicOuterRadius = fLogicOuter;
+ if( !isMathematicalOrientationRadius() )
+ std::swap(fLogicInnerRadius,fLogicOuterRadius);
+ return true;
+}
+
+PieChart::PieChart( const rtl::Reference<ChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bExcludingPositioning )
+ : VSeriesPlotter( xChartTypeModel, nDimensionCount )
+ , m_pPosHelper( new PiePositionHelper( (m_nDimension==3) ? 0.0 : 90.0 ) )
+ , m_bUseRings(false)
+ , m_bSizeExcludesLabelsAndExplodedSegments(bExcludingPositioning)
+ , m_fMaxOffset(std::numeric_limits<double>::quiet_NaN())
+{
+ PlotterBase::m_pPosHelper = m_pPosHelper.get();
+ VSeriesPlotter::m_pMainPosHelper = m_pPosHelper.get();
+ m_pPosHelper->m_fRadiusOffset = 0.0;
+ m_pPosHelper->m_fRingDistance = 0.0;
+
+ if( !xChartTypeModel.is() )
+ return;
+
+ try
+ {
+ xChartTypeModel->getFastPropertyValue(PROP_PIECHARTTYPE_USE_RINGS) >>= m_bUseRings; // "UseRings"
+ if( m_bUseRings )
+ {
+ m_pPosHelper->m_fRadiusOffset = 1.0;
+ if( nDimensionCount==3 )
+ m_pPosHelper->m_fRingDistance = 0.1;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+PieChart::~PieChart()
+{
+}
+
+void PieChart::setScales( std::vector< ExplicitScaleData >&& rScales, bool /* bSwapXAndYAxis */ )
+{
+ OSL_ENSURE(m_nDimension<=static_cast<sal_Int32>(rScales.size()),"Dimension of Plotter does not fit two dimension of given scale sequence");
+ m_pPosHelper->setScales( std::move(rScales), true );
+}
+
+drawing::Direction3D PieChart::getPreferredDiagramAspectRatio() const
+{
+ if( m_nDimension == 3 )
+ return drawing::Direction3D(1,1,0.10);
+ return drawing::Direction3D(1,1,1);
+}
+
+bool PieChart::shouldSnapRectToUsedArea()
+{
+ return true;
+}
+
+rtl::Reference<SvxShape> PieChart::createDataPoint(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const uno::Reference<beans::XPropertySet>& xObjectProperties,
+ const ShapeParam& rParam,
+ const sal_Int32 nPointCount,
+ const bool bConcentricExplosion)
+{
+ //transform position:
+ drawing::Direction3D aOffset;
+ double fExplodedInnerRadius = rParam.mfUnitCircleInnerRadius;
+ double fExplodedOuterRadius = rParam.mfUnitCircleOuterRadius;
+ double fStartAngle = rParam.mfUnitCircleStartAngleDegree;
+ double fWidthAngle = rParam.mfUnitCircleWidthAngleDegree;
+
+ if (rParam.mfExplodePercentage != 0.0) {
+ double fRadius = (fExplodedOuterRadius-fExplodedInnerRadius)*rParam.mfExplodePercentage;
+
+ if (bConcentricExplosion) {
+
+ // For concentric explosion, increase the radius but retain the original
+ // arc length of all ring segments together. This results in a gap
+ // that's evenly divided among all segments, assuming they all have
+ // the same explosion percentage
+ assert(fExplodedInnerRadius >= 0 && fExplodedOuterRadius > 0);
+ double fAngleRatio = (fExplodedInnerRadius + fExplodedOuterRadius) /
+ (fExplodedInnerRadius + fExplodedOuterRadius + 2 * fRadius);
+
+ assert(nPointCount > 0);
+ double fAngleGap = 360 * (1.0 - fAngleRatio) / nPointCount;
+ fStartAngle += fAngleGap / 2;
+ fWidthAngle -= fAngleGap;
+
+ fExplodedInnerRadius += fRadius;
+ fExplodedOuterRadius += fRadius;
+
+ } else {
+ // For the non-concentric explosion case, keep the original radius
+ // but shift the circle origin
+ double fAngle = fStartAngle + fWidthAngle/2.0;
+
+ drawing::Position3D aOrigin = m_pPosHelper->transformUnitCircleToScene(0, 0, rParam.mfLogicZ);
+ drawing::Position3D aNewOrigin = m_pPosHelper->transformUnitCircleToScene(fAngle, fRadius, rParam.mfLogicZ);
+ aOffset = aNewOrigin - aOrigin;
+ }
+ }
+
+ //create point
+ rtl::Reference<SvxShape> xShape;
+ if(m_nDimension==3)
+ {
+ xShape = ShapeFactory::createPieSegment( xTarget
+ , fStartAngle, fWidthAngle
+ , fExplodedInnerRadius, fExplodedOuterRadius
+ , aOffset, B3DHomMatrixToHomogenMatrix( m_pPosHelper->getUnitCartesianToScene() )
+ , rParam.mfDepth );
+ }
+ else
+ {
+ xShape = ShapeFactory::createPieSegment2D( xTarget
+ , fStartAngle, fWidthAngle
+ , fExplodedInnerRadius, fExplodedOuterRadius
+ , aOffset, B3DHomMatrixToHomogenMatrix( m_pPosHelper->getUnitCartesianToScene() ) );
+ }
+ PropertyMapper::setMappedProperties( *xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
+ return xShape;
+}
+
+void PieChart::createTextLabelShape(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget,
+ VDataSeries& rSeries, sal_Int32 nPointIndex, ShapeParam& rParam )
+{
+ if (!rSeries.getDataPointLabelIfLabel(nPointIndex))
+ // There is no text label for this data point. Nothing to do.
+ return;
+
+ ///by using the `mfExplodePercentage` parameter a normalized offset is added
+ ///to both normalized radii. (See notes for
+ ///`PolarPlottingPositionHelper::transformToRadius`, especially example 3,
+ ///and related comments).
+ if (rParam.mfExplodePercentage != 0.0)
+ {
+ double fExplodeOffset = (rParam.mfUnitCircleOuterRadius-rParam.mfUnitCircleInnerRadius)*rParam.mfExplodePercentage;
+ rParam.mfUnitCircleInnerRadius += fExplodeOffset;
+ rParam.mfUnitCircleOuterRadius += fExplodeOffset;
+ }
+
+ ///get the required label placement type. Available placements are
+ ///`AVOID_OVERLAP`, `CENTER`, `OUTSIDE` and `INSIDE`;
+ sal_Int32 nLabelPlacement = rSeries.getLabelPlacement(
+ nPointIndex, m_xChartTypeModel, m_pPosHelper->isSwapXAndY());
+
+ ///when the placement is of `AVOID_OVERLAP` type a later rearrangement of
+ ///the label position is allowed; the `createTextLabelShape` treats the
+ ///`AVOID_OVERLAP` as if it was of `CENTER` type;
+
+ double nVal = rSeries.getYValue(nPointIndex);
+ //AVOID_OVERLAP is in fact "Best fit" in the UI.
+ bool bMovementAllowed = nLabelPlacement == css::chart::DataLabelPlacement::AVOID_OVERLAP
+ || nLabelPlacement == css::chart::DataLabelPlacement::CUSTOM;
+ if( bMovementAllowed )
+ nLabelPlacement = css::chart::DataLabelPlacement::CENTER;
+
+ ///for `OUTSIDE` (`INSIDE`) label placements an offset of 150 (-150), in the
+ ///radius direction, is added to the final screen position of the label
+ ///anchor point. This is required in order to ensure that the label is
+ ///completely outside (inside) the related slice. Indeed this value should
+ ///depend on the font height;
+ ///pay attention: 150 is not a big offset, in fact the screen position
+ ///coordinates for label anchor points are in the 10000-20000 range, hence
+ ///these are coordinates of a virtual screen and 150 is a small value;
+ LabelAlignment eAlignment(LABEL_ALIGN_CENTER);
+ sal_Int32 nScreenValueOffsetInRadiusDirection = 0 ;
+ if( nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE )
+ nScreenValueOffsetInRadiusDirection = (m_nDimension!=3) ? 150 : 0;//todo maybe calculate this font height dependent
+ else if( nLabelPlacement == css::chart::DataLabelPlacement::INSIDE )
+ nScreenValueOffsetInRadiusDirection = (m_nDimension!=3) ? -150 : 0;//todo maybe calculate this font height dependent
+
+ ///the scene position of the label anchor point is calculated (see notes for
+ ///`PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCircleValues`),
+ ///and immediately transformed into the screen position.
+ PolarLabelPositionHelper aPolarPosHelper(m_pPosHelper.get(),m_nDimension,m_xLogicTarget);
+ awt::Point aScreenPosition2D(
+ aPolarPosHelper.getLabelScreenPositionAndAlignmentForUnitCircleValues(eAlignment, nLabelPlacement
+ , rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree
+ , rParam.mfUnitCircleInnerRadius, rParam.mfUnitCircleOuterRadius, rParam.mfLogicZ+0.5, 0 ));
+
+ ///the screen position of the pie/donut center is calculated.
+ PieLabelInfo aPieLabelInfo;
+ aPieLabelInfo.aFirstPosition = basegfx::B2IVector( aScreenPosition2D.X, aScreenPosition2D.Y );
+ awt::Point aOrigin( aPolarPosHelper.transformSceneToScreenPosition( m_pPosHelper->transformUnitCircleToScene( 0.0, 0.0, rParam.mfLogicZ+1.0 ) ) );
+ aPieLabelInfo.aOrigin = basegfx::B2IVector( aOrigin.X, aOrigin.Y );
+
+ ///add a scaling independent Offset if requested
+ if( nScreenValueOffsetInRadiusDirection != 0)
+ {
+ basegfx::B2IVector aDirection( aScreenPosition2D.X- aOrigin.X, aScreenPosition2D.Y- aOrigin.Y );
+ aDirection.setLength(nScreenValueOffsetInRadiusDirection);
+ aScreenPosition2D.X += aDirection.getX();
+ aScreenPosition2D.Y += aDirection.getY();
+ }
+
+ // compute outer pie radius
+ awt::Point aOuterCirclePoint = PlottingPositionHelper::transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene(
+ 0,
+ rParam.mfUnitCircleOuterRadius,
+ 0 ),
+ m_xLogicTarget, m_nDimension );
+ basegfx::B2IVector aRadiusVector(
+ aOuterCirclePoint.X - aPieLabelInfo.aOrigin.getX(),
+ aOuterCirclePoint.Y - aPieLabelInfo.aOrigin.getY() );
+ double fSquaredPieRadius = aRadiusVector.scalar(aRadiusVector);
+ double fPieRadius = sqrt( fSquaredPieRadius );
+ double fAngleDegree
+ = rParam.mfUnitCircleStartAngleDegree + rParam.mfUnitCircleWidthAngleDegree / 2.0;
+ while (fAngleDegree > 360.0)
+ fAngleDegree -= 360.0;
+ while (fAngleDegree < 0.0)
+ fAngleDegree += 360.0;
+
+ awt::Point aOuterPosition = PlottingPositionHelper::transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene(fAngleDegree, rParam.mfUnitCircleOuterRadius, 0),
+ m_xLogicTarget, m_nDimension);
+ aPieLabelInfo.aOuterPosition = basegfx::B2IVector(aOuterPosition.X, aOuterPosition.Y);
+
+ // set the maximum text width to be used when text wrapping is enabled
+ double fTextMaximumFrameWidth = 0.8 * fPieRadius;
+ if (nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE
+ && m_aAvailableOuterRect.getWidth())
+ {
+ if ((fAngleDegree >= 67.5 && fAngleDegree <= 112.5)
+ || (fAngleDegree >= 247.5 && fAngleDegree <= 292.5))
+ fTextMaximumFrameWidth = m_aAvailableOuterRect.getWidth() / 3.0;
+ else
+ fTextMaximumFrameWidth = 0.85 * (m_aAvailableOuterRect.getWidth() / 2.0 - fPieRadius);
+ }
+ sal_Int32 nTextMaximumFrameWidth = ceil(fTextMaximumFrameWidth);
+
+ ///the text shape for the label is created
+ aPieLabelInfo.xTextShape = createDataLabel(
+ xTextTarget, rSeries, nPointIndex, nVal, rParam.mfLogicYSum,
+ aScreenPosition2D, eAlignment, 0, nTextMaximumFrameWidth);
+
+ ///a new `PieLabelInfo` instance is initialized with all the info related to
+ ///the current label in order to simplify later label position rearrangement;
+ rtl::Reference< SvxShape > xChild = aPieLabelInfo.xTextShape;
+
+ ///text shape could be empty; in that case there is no need to add label info
+ if( !xChild.is() )
+ return;
+
+ aPieLabelInfo.xLabelGroupShape = dynamic_cast<SvxShapeGroupAnyD*>(xChild->getParent().get());
+
+ if (bMovementAllowed && !m_bUseRings)
+ {
+ /** Handle the placement of the label in the best fit case.
+ * First off the routine try to place the label inside the related pie slice,
+ * if this is not possible the label is placed outside.
+ */
+ if (rSeries.getLabelPlacement(nPointIndex, m_xChartTypeModel, m_pPosHelper->isSwapXAndY())
+ == css::chart::DataLabelPlacement::CUSTOM
+ || !performLabelBestFitInnerPlacement(rParam, aPieLabelInfo))
+ {
+ if (m_aAvailableOuterRect.getWidth())
+ {
+ if ((fAngleDegree >= 67.5 && fAngleDegree <= 112.5)
+ || (fAngleDegree >= 247.5 && fAngleDegree <= 292.5))
+ fTextMaximumFrameWidth = m_aAvailableOuterRect.getWidth() / 3.0;
+ else
+ fTextMaximumFrameWidth
+ = 0.85 * (m_aAvailableOuterRect.getWidth() / 2.0 - fPieRadius);
+ nTextMaximumFrameWidth = ceil(fTextMaximumFrameWidth);
+ }
+
+ nScreenValueOffsetInRadiusDirection = (m_nDimension != 3) ? 150 : 0;
+ aScreenPosition2D
+ = aPolarPosHelper.getLabelScreenPositionAndAlignmentForUnitCircleValues(
+ eAlignment, css::chart::DataLabelPlacement::OUTSIDE,
+ rParam.mfUnitCircleStartAngleDegree,
+ rParam.mfUnitCircleWidthAngleDegree, rParam.mfUnitCircleInnerRadius,
+ rParam.mfUnitCircleOuterRadius, rParam.mfLogicZ + 0.5, 0);
+ aPieLabelInfo.aFirstPosition
+ = basegfx::B2IVector(aScreenPosition2D.X, aScreenPosition2D.Y);
+
+ //add a scaling independent Offset if requested
+ if (nScreenValueOffsetInRadiusDirection != 0)
+ {
+ basegfx::B2IVector aDirection(aScreenPosition2D.X - aOrigin.X,
+ aScreenPosition2D.Y - aOrigin.Y);
+ aDirection.setLength(nScreenValueOffsetInRadiusDirection);
+ aScreenPosition2D.X += aDirection.getX();
+ aScreenPosition2D.Y += aDirection.getY();
+ }
+
+ uno::Reference<drawing::XShapes> xShapes(xChild->getParent(), uno::UNO_QUERY);
+ xShapes->remove(aPieLabelInfo.xTextShape);
+ aPieLabelInfo.xTextShape
+ = createDataLabel(xTextTarget, rSeries, nPointIndex, nVal, rParam.mfLogicYSum,
+ aScreenPosition2D, eAlignment, 0, nTextMaximumFrameWidth);
+ xChild = aPieLabelInfo.xTextShape;
+ if (!xChild.is())
+ return;
+
+ aPieLabelInfo.xLabelGroupShape = dynamic_cast<SvxShapeGroupAnyD*>(xChild->getParent().get());
+ }
+ }
+
+ bool bShowLeaderLine = rSeries.getModel()
+ ->getFastPropertyValue(PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES) // "ShowCustomLeaderLines"
+ .get<sal_Bool>();
+ if (m_bPieLabelsAllowToMove)
+ {
+ ::basegfx::B2IRectangle aRect(lcl_getRect(aPieLabelInfo.xLabelGroupShape));
+ sal_Int32 nPageWidth = m_aPageReferenceSize.Width;
+ sal_Int32 nPageHeight = m_aPageReferenceSize.Height;
+
+ // the data label should be inside the chart area
+ awt::Point aShapePos = aPieLabelInfo.xLabelGroupShape->getPosition();
+ if (aRect.getMinX() < 0)
+ aPieLabelInfo.xLabelGroupShape->setPosition(
+ awt::Point(aShapePos.X - aRect.getMinX(), aShapePos.Y));
+ if (aRect.getMinY() < 0)
+ aPieLabelInfo.xLabelGroupShape->setPosition(
+ awt::Point(aShapePos.X, aShapePos.Y - aRect.getMinY()));
+ if (aRect.getMaxX() > nPageWidth)
+ aPieLabelInfo.xLabelGroupShape->setPosition(
+ awt::Point(aShapePos.X - (aRect.getMaxX() - nPageWidth), aShapePos.Y));
+ if (aRect.getMaxY() > nPageHeight)
+ aPieLabelInfo.xLabelGroupShape->setPosition(
+ awt::Point(aShapePos.X, aShapePos.Y - (aRect.getMaxY() - nPageHeight)));
+
+ if (rSeries.isLabelCustomPos(nPointIndex) && bShowLeaderLine)
+ {
+ sal_Int32 nX1 = aPieLabelInfo.aOuterPosition.getX();
+ sal_Int32 nY1 = aPieLabelInfo.aOuterPosition.getY();
+ sal_Int32 nX2 = nX1;
+ sal_Int32 nY2 = nY1;
+ if (nX1 < aRect.getMinX())
+ nX2 = aRect.getMinX();
+ else if (nX1 > aRect.getMaxX())
+ nX2 = aRect.getMaxX();
+
+ if (nY1 < aRect.getMinY())
+ nY2 = aRect.getMinY();
+ else if (nY1 > aRect.getMaxY())
+ nY2 = aRect.getMaxY();
+
+ sal_Int32 nSquaredDistanceFromOrigin
+ = (nX2 - aOrigin.X) * (nX2 - aOrigin.X) + (nY2 - aOrigin.Y) * (nY2 - aOrigin.Y);
+
+ // tdf#138018 Don't show leader line when custom positioned data label is inside pie chart
+ if (nSquaredDistanceFromOrigin > fSquaredPieRadius)
+ {
+ //when the line is very short compared to the page size don't create one
+ ::basegfx::B2DVector aLength(nX1 - nX2, nY1 - nY2);
+ double fPageDiagonaleLength = std::hypot(nPageWidth, nPageHeight);
+ if ((aLength.getLength() / fPageDiagonaleLength) >= 0.01)
+ {
+ drawing::PointSequenceSequence aPoints{ { {nX1, nY1}, {nX2, nY2} } };
+
+ VLineProperties aVLineProperties;
+ if (aPieLabelInfo.xTextShape.is())
+ {
+ sal_Int32 nColor = 0;
+ aPieLabelInfo.xTextShape->SvxShape::getPropertyValue("CharColor") >>= nColor;
+ //automatic font color does not work for lines -> fallback to black
+ if (nColor != -1)
+ aVLineProperties.Color <<= nColor;
+ }
+ ShapeFactory::createLine2D(xTextTarget, aPoints, &aVLineProperties);
+ }
+ }
+ }
+ }
+
+ aPieLabelInfo.fValue = nVal;
+ aPieLabelInfo.bMovementAllowed = bMovementAllowed;
+ aPieLabelInfo.bMoved = false;
+ aPieLabelInfo.xTextTarget = xTextTarget;
+ aPieLabelInfo.bShowLeaderLine = bShowLeaderLine && !rSeries.isLabelCustomPos(nPointIndex);
+
+ m_aLabelInfoList.push_back(aPieLabelInfo);
+}
+
+void PieChart::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 /* zSlot */, sal_Int32 /* xSlot */, sal_Int32 /* ySlot */ )
+{
+ VSeriesPlotter::addSeries( std::move(pSeries), 0, -1, 0 );
+}
+
+double PieChart::getMinimumX()
+{
+ return 0.5;
+}
+double PieChart::getMaxOffset()
+{
+ if (!std::isnan(m_fMaxOffset))
+ // Value already cached. Use it.
+ return m_fMaxOffset;
+
+ m_fMaxOffset = 0.0;
+ if( m_aZSlots.empty() )
+ return m_fMaxOffset;
+ if( m_aZSlots.front().empty() )
+ return m_fMaxOffset;
+
+ const std::vector< std::unique_ptr<VDataSeries> >& rSeriesList( m_aZSlots.front().front().m_aSeriesVector );
+ if(rSeriesList.empty())
+ return m_fMaxOffset;
+
+ VDataSeries* pSeries = rSeriesList.front().get();
+ rtl::Reference< DataSeries > xSeries( pSeries->getModel() );
+ if( !xSeries.is() )
+ return m_fMaxOffset;
+
+ double fExplodePercentage=0.0;
+ xSeries->getPropertyValue( "Offset") >>= fExplodePercentage;
+ if(fExplodePercentage>m_fMaxOffset)
+ m_fMaxOffset=fExplodePercentage;
+
+ if(!m_bSizeExcludesLabelsAndExplodedSegments)
+ {
+ uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
+ // "AttributedDataPoints"
+ if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
+ {
+ for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
+ {
+ uno::Reference< beans::XPropertySet > xPointProp( pSeries->getPropertiesOfPoint(aAttributedDataPointIndexList[nN]) );
+ if(xPointProp.is())
+ {
+ fExplodePercentage=0.0;
+ xPointProp->getPropertyValue( "Offset") >>= fExplodePercentage;
+ if(fExplodePercentage>m_fMaxOffset)
+ m_fMaxOffset=fExplodePercentage;
+ }
+ }
+ }
+ }
+ return m_fMaxOffset;
+}
+double PieChart::getMaximumX()
+{
+ double fMaxOffset = getMaxOffset();
+ if( !m_aZSlots.empty() && m_bUseRings)
+ return m_aZSlots.front().size()+0.5+fMaxOffset;
+ return 1.5+fMaxOffset;
+}
+double PieChart::getMinimumYInRange( double /* fMinimumX */, double /* fMaximumX */, sal_Int32 /* nAxisIndex */ )
+{
+ return 0.0;
+}
+
+double PieChart::getMaximumYInRange( double /* fMinimumX */, double /* fMaximumX */, sal_Int32 /* nAxisIndex */ )
+{
+ return 1.0;
+}
+
+bool PieChart::isExpandBorderToIncrementRhythm( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+bool PieChart::isExpandIfValuesCloseToBorder( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+bool PieChart::isExpandWideValuesToZero( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+bool PieChart::isExpandNarrowValuesTowardZero( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+bool PieChart::isSeparateStackingForDifferentSigns( sal_Int32 /* nDimensionIndex */ )
+{
+ return false;
+}
+
+void PieChart::createShapes()
+{
+ ///a ZSlot is a vector< vector< VDataSeriesGroup > >. There is only one
+ ///ZSlot: m_aZSlots[0] which has a number of elements equal to the total
+ ///number of data series (in fact, even if m_aZSlots[0][i] is an object of
+ ///type `VDataSeriesGroup`, in the current implementation, there is only one
+ ///data series in each data series group).
+ if (m_aZSlots.empty())
+ // No series to plot.
+ return;
+
+ ///m_xLogicTarget is where the group of all data series shapes (e.g. a pie
+ ///slice) is added (xSeriesTarget);
+
+ ///m_xFinalTarget is where the group of all text shapes (labels) is added
+ ///(xTextTarget).
+
+ ///both have been already created and added to the same root shape
+ ///( a member of a VDiagram object); this initialization occurs in
+ ///`ChartView::impl_createDiagramAndContent`.
+
+ OSL_ENSURE(m_xLogicTarget.is() && m_xFinalTarget.is(), "PieChart is not properly initialized.");
+ if (!m_xLogicTarget.is() || !m_xFinalTarget.is())
+ return;
+
+ ///the text labels should be always on top of the other series shapes
+ ///therefore create an own group for the texts to move them to front
+ ///(because the text group is created after the series group the texts are
+ ///displayed on top)
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget = createGroupShape( m_xLogicTarget );
+ rtl::Reference<SvxShapeGroup> xTextTarget = ShapeFactory::createGroup2D( m_xFinalTarget );
+ //check necessary here that different Y axis can not be stacked in the same group? ... hm?
+
+ ///pay attention that the `m_bSwapXAndY` parameter used by the polar
+ ///plotting position helper is always set to true for pie/donut charts
+ ///(see PieChart::setScales). This fact causes that `createShapes` expects
+ ///that the radius axis scale is the one with index 0 and the angle axis
+ ///scale is the one with index 1.
+
+ std::vector< VDataSeriesGroup >::iterator aXSlotIter = m_aZSlots.front().begin();
+ const std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = m_aZSlots.front().end();
+
+ ///m_bUseRings == true if chart type is `donut`, == false if chart type is
+ ///`pie`; if the chart is of `donut` type we have as many rings as many data
+ ///series, else we have a single ring (a pie) representing the first data
+ ///series;
+ ///for what I can see the radius axis orientation is always reversed and
+ ///the angle axis orientation is always non-reversed;
+ ///the radius axis scale range is [0.5, number of rings + 0.5 + max_offset],
+ ///the angle axis scale range is [0, 1]. The max_offset parameter is used
+ ///for exploded pie chart and its value is 0.5.
+
+ ///the `explodeable` ring is the first one except when the radius axis
+ ///orientation is reversed (always!?) and we are dealing with a donut: in
+ ///such a case the `explodeable` ring is the last one.
+ std::vector< VDataSeriesGroup >::size_type nExplodeableSlot = 0;
+ if( m_pPosHelper->isMathematicalOrientationRadius() && m_bUseRings )
+ nExplodeableSlot = m_aZSlots.front().size()-1;
+
+ m_aLabelInfoList.clear();
+ m_fMaxOffset = std::numeric_limits<double>::quiet_NaN();
+ sal_Int32 n3DRelativeHeight = 100;
+ if ( (m_nDimension==3) && m_xChartTypeModel.is())
+ {
+ try
+ {
+ uno::Any aAny = m_xChartTypeModel->getFastPropertyValue( PROP_PIECHARTTYPE_3DRELATIVEHEIGHT ); // "3DRelativeHeight"
+ aAny >>= n3DRelativeHeight;
+ }
+ catch (const uno::Exception&) { }
+ }
+ ///iterate over each xslot, that is on each data series (there is
+ ///only one data series in each data series group!); note that if the chart
+ ///type is a pie the loop iterates only over the first data series
+ ///(m_bUseRings||fSlotX<0.5)
+ for( double fSlotX=0; aXSlotIter != aXSlotEnd && (m_bUseRings||fSlotX<0.5 ); ++aXSlotIter, fSlotX+=1.0 )
+ {
+ ShapeParam aParam;
+
+ std::vector< std::unique_ptr<VDataSeries> >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
+ if(pSeriesList->empty())//there should be only one series in each x slot
+ continue;
+ VDataSeries* pSeries = pSeriesList->front().get();
+ if(!pSeries)
+ continue;
+
+ bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor");
+
+ /// The angle degree offset is set by the same property of the
+ /// data series.
+ /// Counter-clockwise offset from the 3 o'clock position.
+ m_pPosHelper->m_fAngleDegreeOffset = pSeries->getStartingAngle();
+
+ ///iterate through all points to get the sum of all entries of
+ ///the current data series
+ sal_Int32 nPointIndex=0;
+ sal_Int32 nPointCount=pSeries->getTotalPointCount();
+ for( nPointIndex = 0; nPointIndex < nPointCount; nPointIndex++ )
+ {
+ double fY = pSeries->getYValue( nPointIndex );
+ if(fY<0.0)
+ {
+ //@todo warn somehow that negative values are treated as positive
+ }
+ if( std::isnan(fY) )
+ continue;
+ aParam.mfLogicYSum += fabs(fY);
+ }
+
+ if (aParam.mfLogicYSum == 0.0)
+ // Total sum of all Y values in this series is zero. Skip the whole series.
+ continue;
+
+ double fLogicYForNextPoint = 0.0;
+ ///iterate through all points to create shapes
+ for( nPointIndex = 0; nPointIndex < nPointCount; nPointIndex++ )
+ {
+ double fLogicInnerRadius, fLogicOuterRadius;
+
+ ///compute the maximum relative distance offset of the current slice
+ ///from the pie center
+ ///it is worth noting that after the first invocation the maximum
+ ///offset value is cached, so it is evaluated only once per each
+ ///call to `createShapes`
+ double fOffset = getMaxOffset();
+
+ ///compute the outer and the inner radius for the current ring slice
+ bool bIsVisible = m_pPosHelper->getInnerAndOuterRadius( fSlotX+1.0, fLogicInnerRadius, fLogicOuterRadius, m_bUseRings, fOffset );
+ if( !bIsVisible )
+ continue;
+
+ aParam.mfDepth = getTransformedDepth() * (n3DRelativeHeight / 100.0);
+
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = getSeriesGroupShape(pSeries, xSeriesTarget);
+ ///collect data point information (logic coordinates, style ):
+ double fLogicYValue = fabs(pSeries->getYValue( nPointIndex ));
+ if( std::isnan(fLogicYValue) )
+ continue;
+ if(fLogicYValue==0.0)//@todo: continue also if the resolution is too small
+ continue;
+ double fLogicYPos = fLogicYForNextPoint;
+ fLogicYForNextPoint += fLogicYValue;
+
+ uno::Reference< beans::XPropertySet > xPointProperties = pSeries->getPropertiesOfPoint( nPointIndex );
+
+ //iterate through all subsystems to create partial points
+ {
+ //logic values on angle axis:
+ double fLogicStartAngleValue = fLogicYPos / aParam.mfLogicYSum;
+ double fLogicEndAngleValue = (fLogicYPos+fLogicYValue) / aParam.mfLogicYSum;
+
+ ///note that the explode percentage is set to the `Offset`
+ ///property of the current data series entry only for slices
+ ///belonging to the outer ring
+ aParam.mfExplodePercentage = 0.0;
+ bool bDoExplode = ( nExplodeableSlot == static_cast< std::vector< VDataSeriesGroup >::size_type >(fSlotX) );
+ if(bDoExplode) try
+ {
+ xPointProperties->getPropertyValue( "Offset") >>= aParam.mfExplodePercentage;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ ///see notes for `PolarPlottingPositionHelper` methods
+ ///transform to unit circle:
+ aParam.mfUnitCircleWidthAngleDegree = m_pPosHelper->getWidthAngleDegree( fLogicStartAngleValue, fLogicEndAngleValue );
+ aParam.mfUnitCircleStartAngleDegree = m_pPosHelper->transformToAngleDegree( fLogicStartAngleValue );
+ aParam.mfUnitCircleInnerRadius = m_pPosHelper->transformToRadius( fLogicInnerRadius );
+ aParam.mfUnitCircleOuterRadius = m_pPosHelper->transformToRadius( fLogicOuterRadius );
+
+ ///create data point
+ aParam.mfLogicZ = -1.0; // For 3D pie chart label position
+
+ // Do concentric explosion if it's a donut chart with more than one series
+ const bool bConcentricExplosion = m_bUseRings && (m_aZSlots.front().size() > 1);
+ rtl::Reference<SvxShape> xPointShape =
+ createDataPoint(
+ xSeriesGroupShape_Shapes, xPointProperties, aParam, nPointCount,
+ bConcentricExplosion);
+
+ ///point color:
+ if (!pSeries->hasPointOwnColor(nPointIndex) && m_xColorScheme.is())
+ {
+ xPointShape->setPropertyValue("FillColor",
+ uno::Any(m_xColorScheme->getColorByIndex( nPointIndex )));
+ }
+
+
+ if(bHasFillColorMapping)
+ {
+ double nPropVal = pSeries->getValueByProperty(nPointIndex, "FillColor");
+ if(!std::isnan(nPropVal))
+ {
+ xPointShape->setPropertyValue("FillColor", uno::Any(static_cast<sal_Int32>( nPropVal)));
+ }
+ }
+
+ ///create label
+ createTextLabelShape(xTextTarget, *pSeries, nPointIndex, aParam);
+
+ if(!bDoExplode)
+ {
+ ShapeFactory::setShapeName( xPointShape
+ , ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), nPointIndex ) );
+ }
+ else try
+ {
+ ///enable dragging of outer segments
+
+ double fAngle = aParam.mfUnitCircleStartAngleDegree + aParam.mfUnitCircleWidthAngleDegree/2.0;
+ double fMaxDeltaRadius = aParam.mfUnitCircleOuterRadius-aParam.mfUnitCircleInnerRadius;
+ drawing::Position3D aOrigin = m_pPosHelper->transformUnitCircleToScene( fAngle, aParam.mfUnitCircleOuterRadius, aParam.mfLogicZ );
+ drawing::Position3D aNewOrigin = m_pPosHelper->transformUnitCircleToScene( fAngle, aParam.mfUnitCircleOuterRadius + fMaxDeltaRadius, aParam.mfLogicZ );
+
+ sal_Int32 nOffsetPercent( static_cast<sal_Int32>(aParam.mfExplodePercentage * 100.0) );
+
+ awt::Point aMinimumPosition( PlottingPositionHelper::transformSceneToScreenPosition(
+ aOrigin, m_xLogicTarget, m_nDimension ) );
+ awt::Point aMaximumPosition( PlottingPositionHelper::transformSceneToScreenPosition(
+ aNewOrigin, m_xLogicTarget, m_nDimension ) );
+
+ //enable dragging of piesegments
+ OUString aPointCIDStub( ObjectIdentifier::createSeriesSubObjectStub( OBJECTTYPE_DATA_POINT
+ , pSeries->getSeriesParticle()
+ , ObjectIdentifier::getPieSegmentDragMethodServiceName()
+ , ObjectIdentifier::createPieSegmentDragParameterString(
+ nOffsetPercent, aMinimumPosition, aMaximumPosition )
+ ) );
+
+ ShapeFactory::setShapeName( xPointShape
+ , ObjectIdentifier::createPointCID( aPointCIDStub, nPointIndex ) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }//next series in x slot (next y slot)
+ }//next category
+ }//next x slot
+}
+
+PieChart::PieLabelInfo::PieLabelInfo()
+ : fValue(0.0)
+ , bMovementAllowed(false), bMoved(false)
+ , bShowLeaderLine(false), pPrevious(nullptr)
+ , pNext(nullptr)
+{
+}
+
+/** In case this label and the passed label overlap the routine moves this
+ * label in order to fix the issue. After the label position has been
+ * rearranged it is checked that the moved label is still inside the page
+ * document, if the test is positive the routine returns true else returns
+ * false.
+ */
+bool PieChart::PieLabelInfo::moveAwayFrom( const PieChart::PieLabelInfo* pFix, const awt::Size& rPageSize, bool bMoveHalfWay, bool bMoveClockwise )
+{
+ //return true if the move was successful
+ if(!bMovementAllowed)
+ return false;
+
+ const sal_Int32 nLabelDistanceX = rPageSize.Width/50;
+ const sal_Int32 nLabelDistanceY = rPageSize.Height/50;
+
+ ///compute the rectangle representing the intersection of the label bounding
+ ///boxes (`aOverlap`).
+ ::basegfx::B2IRectangle aOverlap( lcl_getRect( xLabelGroupShape ) );
+ aOverlap.intersect( lcl_getRect( pFix->xLabelGroupShape ) );
+ if( aOverlap.isEmpty() )
+ return true;
+
+ //TODO: alternative move direction
+
+ ///the label is shifted along the direction orthogonal to the vector
+ ///starting at the pie/donut center and ending at this label anchor
+ ///point;
+
+ ///named `aTangentialDirection` the unit vector related to such a
+ ///direction, the magnitude of the shift along such a direction is
+ ///calculated in this way: if the horizontal component of
+ ///`aTangentialDirection` is greater than the vertical component,
+ ///the magnitude of the shift is equal to `aOverlap.Width` else to
+ ///`aOverlap.Height`;
+ basegfx::B2IVector aRadiusDirection = aFirstPosition - aOrigin;
+ aRadiusDirection.setLength(1.0);
+ basegfx::B2IVector aTangentialDirection( -aRadiusDirection.getY(), aRadiusDirection.getX() );
+ bool bShiftHorizontal = abs(aTangentialDirection.getX()) > abs(aTangentialDirection.getY());
+ sal_Int32 nShift = bShiftHorizontal ? static_cast<sal_Int32>(aOverlap.getWidth()) : static_cast<sal_Int32>(aOverlap.getHeight());
+ ///the magnitude of the shift is also increased by 1/50-th of the width
+ ///or the height of the document page;
+ nShift += (bShiftHorizontal ? nLabelDistanceX : nLabelDistanceY);
+ ///in case the `bMoveHalfWay` parameter is true the magnitude of
+ ///the shift is halved.
+ if( bMoveHalfWay )
+ nShift/=2;
+ ///in case the `bMoveClockwise` parameter is false the direction of
+ ///`aTangentialDirection` is reversed;
+ if(!bMoveClockwise)
+ nShift*=-1;
+ awt::Point aOldPos( xLabelGroupShape->getPosition() );
+ basegfx::B2IVector aNewPos = basegfx::B2IVector( aOldPos.X, aOldPos.Y ) + nShift*aTangentialDirection;
+
+ ///a final check is performed in order to be sure that the moved label
+ ///is still inside the page document;
+ awt::Point aNewAWTPos( aNewPos.getX(), aNewPos.getY() );
+ if( !lcl_isInsidePage( aNewAWTPos, xLabelGroupShape->getSize(), rPageSize ) )
+ return false;
+
+ xLabelGroupShape->setPosition( aNewAWTPos );
+ bMoved = true;
+
+ return true;
+
+ ///note that no further test is performed in order to check that the
+ ///overlap is really fixed: this result is surely achieved if the shift
+ ///would occur in the horizontal or vertical direction (since, in such a
+ ///direction, the magnitude of the shift would be greater than the length
+ ///of the overlap), but in general this is not true;
+ ///adding a constant term equal to 1/50-th of the width or the height of
+ ///the document page increases the probability of success, anyway it is
+ ///worth noting that the method can return true even if the overlap issue
+ ///is not (completely) fixed;
+}
+
+void PieChart::resetLabelPositionsToPreviousState()
+{
+ for (auto const& labelInfo : m_aLabelInfoList)
+ labelInfo.xLabelGroupShape->setPosition(labelInfo.aPreviousPosition);
+}
+
+bool PieChart::detectLabelOverlapsAndMove( const awt::Size& rPageSize )
+{
+ ///the routine tries to individuate a chain of overlapping labels and
+ ///assigns the first and the last of them to `pFirstBorder` and
+ ///`pSecondBorder`;
+ ///this result is achieved by performing two consecutive while loop.
+
+ ///find borders of a group of overlapping labels
+
+ ///a first while loop is started on the collection of `PieLabelInfo` objects;
+ ///the bounding box of each label is checked for overlap against the bounding
+ ///box of the previous and of the next label;
+ ///when an overlap is found `bOverlapFound` is set to true, however the
+ ///iteration is break only if the overlap occurs against only the next label
+ ///and not against the previous label: so we exit from the loop whenever an
+ ///overlap occurs except when the loop initial label overlaps with the
+ ///previous one;
+ bool bOverlapFound = false;
+ PieLabelInfo* pStart = &(*(m_aLabelInfoList.rbegin()));
+ PieLabelInfo* pFirstBorder = nullptr;
+ PieLabelInfo* pSecondBorder = nullptr;
+ PieLabelInfo* pCurrent = pStart;
+ do
+ {
+ ::basegfx::B2IRectangle aPreviousOverlap( lcl_getRect( pCurrent->xLabelGroupShape ) );
+ ::basegfx::B2IRectangle aNextOverlap( aPreviousOverlap );
+ aPreviousOverlap.intersect( lcl_getRect( pCurrent->pPrevious->xLabelGroupShape ) );
+ aNextOverlap.intersect( lcl_getRect( pCurrent->pNext->xLabelGroupShape ) );
+
+ bool bPreviousOverlap = !aPreviousOverlap.isEmpty();
+ bool bNextOverlap = !aNextOverlap.isEmpty();
+ if( bPreviousOverlap || bNextOverlap )
+ bOverlapFound = true;
+ if( !bPreviousOverlap && bNextOverlap )
+ {
+ pFirstBorder = pCurrent;
+ break;
+ }
+ pCurrent = pCurrent->pNext;
+ }
+ while( pCurrent != pStart );
+
+ if( !bOverlapFound )
+ return false;
+
+ ///in case we found a label (`pFirstBorder`) which overlaps with the next
+ ///label and not with the previous label a second while loop is started with
+ ///`pFirstBorder` as initial label; one more time the bounding box of each
+ ///label is checked for overlap against the bounding box of the previous and
+ ///of the next label, however this time we exit from the loop only if the
+ ///current label overlaps with the previous one but does not with the next
+ ///one (the opposite of what is required in the former loop);
+ ///in case such a label is found it is assigned to `pSecondBorder` and the
+ ///iteration is stopped; so in case there is a chain of overlapping labels
+ ///we end up having the first label of the chain pointed by `pFirstBorder`
+ ///and the last label of the chain pointed by `pSecondBorder`;
+ if( pFirstBorder )
+ {
+ pCurrent = pFirstBorder;
+ do
+ {
+ ::basegfx::B2IRectangle aPreviousOverlap( lcl_getRect( pCurrent->xLabelGroupShape ) );
+ ::basegfx::B2IRectangle aNextOverlap( aPreviousOverlap );
+ aPreviousOverlap.intersect( lcl_getRect( pCurrent->pPrevious->xLabelGroupShape ) );
+ aNextOverlap.intersect( lcl_getRect( pCurrent->pNext->xLabelGroupShape ) );
+
+ if( !aPreviousOverlap.isEmpty() && aNextOverlap.isEmpty() )
+ {
+ pSecondBorder = pCurrent;
+ break;
+ }
+ pCurrent = pCurrent->pNext;
+ }
+ while( pCurrent != pFirstBorder );
+ }
+
+ ///when two labels satisfying the required conditions are not found
+ ///(`pFirstBorder == 0 || pSecondBorder == 0`) but still an overlap occurs
+ ///(`bOverlapFound == true`) we are in the situation where each label
+ ///overlaps with both the previous and the next one; so `pFirstBorder` is
+ ///set to point to the last `PieLabelInfo` object in the collection and
+ ///`pSecondBorder` is set to point to the first one;
+ if( !pFirstBorder || !pSecondBorder )
+ {
+ pFirstBorder = &(*(m_aLabelInfoList.rbegin()));
+ pSecondBorder = &(*(m_aLabelInfoList.begin()));
+ }
+
+ ///the total number of labels that made up the chain is calculated and used
+ ///for getting a pointer to the central label (`pCenter`);
+ PieLabelInfo* pCenter = pFirstBorder;
+ sal_Int32 nOverlapGroupCount = 1;
+ for( pCurrent = pFirstBorder ;pCurrent != pSecondBorder; pCurrent = pCurrent->pNext )
+ nOverlapGroupCount++;
+ sal_Int32 nCenterPos = nOverlapGroupCount/2;
+ bool bSingleCenter = nOverlapGroupCount%2 != 0;
+ if( bSingleCenter )
+ nCenterPos++;
+ if(nCenterPos>1)
+ {
+ pCurrent = pFirstBorder;
+ while( --nCenterPos )
+ pCurrent = pCurrent->pNext;
+ pCenter = pCurrent;
+ }
+
+ ///the current position of each label in the collection is saved in
+ ///`PieLabelInfo.aPreviousPosition`, so that it is possible to undo the label
+ ///move action if it is needed; the undo action is provided by the
+ ///`PieChart::resetLabelPositionsToPreviousState` method.
+ pCurrent = pStart;
+ do
+ {
+ pCurrent->aPreviousPosition = pCurrent->xLabelGroupShape->getPosition();
+ pCurrent = pCurrent->pNext;
+ }
+ while( pCurrent != pStart );
+
+ ///the `PieChart::tryMoveLabels` method is invoked with
+ ///`rbAlternativeMoveDirection` boolean parameter set to false, such a method
+ ///tries to remove all overlaps that occur in the list of labels going from
+ ///`pFirstBorder` to `pSecondBorder`;
+ ///if the `PieChart::tryMoveLabels` returns true no further action is
+ ///performed, however it is worth noting that it does not mean that all
+ ///overlap issues have been surely fixed, but only that all moved labels are
+ ///at least completely inside the page document;
+ ///when `PieChart::tryMoveLabels` returns false, it means that the attempt
+ ///to fix one of the overlap issues caused that a label has been moved
+ ///(partially) outside the page document (anyway the `PieChart::tryMoveLabels`
+ ///method takes care to restore the position of all labels to their initial
+ ///position, and to set the `rbAlternativeMoveDirection` in/out parameter to
+ ///true); in such a case a second invocation of `PieChart::tryMoveLabels` is
+ ///performed (and this time the `rbAlternativeMoveDirection` boolean
+ ///parameter is true) and independently by what the `PieChart::tryMoveLabels`
+ ///method returns no further action is performed;
+ ///(see notes for `PieChart::tryMoveLabels`);
+ bool bAlternativeMoveDirection = false;
+ if( !tryMoveLabels( pFirstBorder, pSecondBorder, pCenter, bSingleCenter, bAlternativeMoveDirection, rPageSize ) )
+ tryMoveLabels( pFirstBorder, pSecondBorder, pCenter, bSingleCenter, bAlternativeMoveDirection, rPageSize );
+
+ ///in both cases (one or two invocations of `PieChart::tryMoveLabels`) the
+ ///`detectLabelOverlapsAndMove` method ends returning true.
+ return true;
+}
+
+
+/** Try to remove all overlaps that occur in the list of labels going from
+ * `pFirstBorder` to `pSecondBorder`
+ */
+bool PieChart::tryMoveLabels( PieLabelInfo const * pFirstBorder, PieLabelInfo const * pSecondBorder
+ , PieLabelInfo* pCenter
+ , bool bSingleCenter, bool& rbAlternativeMoveDirection, const awt::Size& rPageSize )
+{
+
+ PieLabelInfo* p1 = bSingleCenter ? pCenter->pPrevious : pCenter;
+ PieLabelInfo* p2 = pCenter->pNext;
+ //return true when successful
+
+ bool bLabelOrderIsAntiClockWise = m_pPosHelper->isMathematicalOrientationAngle();
+
+ ///two loops are performed simultaneously: the outer loop iterates on
+ ///`PieLabelInfo` objects in the list starting from the central element
+ ///(`pCenter`) and moving forward until the last element (`pSecondBorder`);
+ ///the inner loop starts from the previous element of `pCenter` and moves
+ ///forward until the current `PieLabelInfo` object of the outer loop is
+ ///reached
+ PieLabelInfo* pCurrent = nullptr;
+ for( pCurrent = p2 ;pCurrent->pPrevious != pSecondBorder; pCurrent = pCurrent->pNext )
+ {
+ PieLabelInfo* pFix = nullptr;
+ for( pFix = p2->pPrevious ;pFix != pCurrent; pFix = pFix->pNext )
+ {
+ ///on the current `PieLabelInfo` object of the outer loop the
+ ///`moveAwayFrom` method is invoked by passing the current
+ ///`PieLabelInfo` object of the inner loop as argument.
+
+ ///so each label going from the central one to the last one is
+ ///checked for overlapping against all previous labels (that comes
+ ///after the central label) and in case the overlap occurs the
+ ///`moveAwayFrom` method tries to fix the issue;
+ ///if `moveAwayFrom` returns true (pay attention: that does not
+ ///mean that the overlap issue has been surely fixed but only that
+ ///the moved label is at least completely inside the page document:
+ ///see notes on `PieChart::PieLabelInfo::moveAwayFrom`), the inner
+ ///loop starts a new iteration else the `rbAlternativeMoveDirection`
+ ///boolean parameter is tested: if it is false the parameter is set
+ ///to true, the position of all labels is restored to the initial
+ ///one (through the `PieChart::resetLabelPositionsToPreviousState`
+ ///method) and the method ends by returning false, else the inner
+ ///loop starts a new iteration step;
+ ///so when `rbAlternativeMoveDirection` is true the method goes on
+ ///trying to fix left overlap issues even if the last `moveAwayFrom`
+ ///invocation has moved a label in a position that it is not
+ ///completely inside the page document
+
+ if( !pCurrent->moveAwayFrom( pFix, rPageSize, !bSingleCenter && pCurrent == p2, !bLabelOrderIsAntiClockWise ) )
+ {
+ if( !rbAlternativeMoveDirection )
+ {
+ rbAlternativeMoveDirection = true;
+ resetLabelPositionsToPreviousState();
+ return false;
+ }
+ }
+ }
+ }
+
+ ///if the method does not return before ending the first pair of loops,
+ ///a second pair of simultaneous loops is performed in the opposite
+ ///direction (respect with the previous case): the outer loop iterates on
+ ///`PieLabelInfo` objects in the list starting from the central element
+ ///(`pCenter`) and moving backward until the first element (`pFirstBorder`);
+ ///the inner loop starts from the next element of `pCenter` and moves
+ ///backward until the current `PieLabelInfo` object of the outer loop is
+ ///reached
+
+ ///like in the previous case on the current `PieLabelInfo` object of
+ ///the outer loop the `moveAwayFrom` method is invoked by passing
+ ///the current `PieLabelInfo` object of the inner loop as argument
+
+ ///so each label going from the central one to the first one is checked for
+ ///overlapping on all subsequent labels (that come before the central label)
+ ///and in case the overlap occurs the `moveAwayFrom` method tries to fix
+ ///the issue. The subsequent actions performed after the invocation
+ ///`moveAwayFrom` are the same detailed above for the first pair of loops
+
+ for( pCurrent = p1 ;pCurrent->pNext != pFirstBorder; pCurrent = pCurrent->pPrevious )
+ {
+ PieLabelInfo* pFix = nullptr;
+ for( pFix = p2->pNext ;pFix != pCurrent; pFix = pFix->pPrevious )
+ {
+ if( !pCurrent->moveAwayFrom( pFix, rPageSize, false, bLabelOrderIsAntiClockWise ) )
+ {
+ if( !rbAlternativeMoveDirection )
+ {
+ rbAlternativeMoveDirection = true;
+ resetLabelPositionsToPreviousState();
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void PieChart::rearrangeLabelToAvoidOverlapIfRequested( const awt::Size& rPageSize )
+{
+ ///this method is invoked by `ChartView::impl_createDiagramAndContent` for
+ ///pie and donut charts after text label creation;
+ ///it tries to rearrange labels only when the label placement type is
+ ///`AVOID_OVERLAP`.
+ // no need to do anything when we only have one label
+ if (m_aLabelInfoList.size() < 2)
+ return;
+
+ ///check whether there are any labels that should be moved
+ bool bMoveableFound = false;
+ for (auto const& labelInfo : m_aLabelInfoList)
+ {
+ if(labelInfo.bMovementAllowed)
+ {
+ bMoveableFound = true;
+ break;
+ }
+ }
+ if(!bMoveableFound)
+ return;
+
+ double fPageDiagonaleLength = std::hypot(rPageSize.Width, rPageSize.Height);
+ if( fPageDiagonaleLength == 0.0 )
+ return;
+
+ ///initialize next and previous member of `PieLabelInfo` objects
+ auto aIt1 = m_aLabelInfoList.begin();
+ auto aEnd = m_aLabelInfoList.end();
+ std::vector< PieLabelInfo >::iterator aIt2 = aIt1;
+ aIt1->pPrevious = &(*(m_aLabelInfoList.rbegin()));
+ ++aIt2;
+ for( ;aIt2!=aEnd; ++aIt1, ++aIt2 )
+ {
+ PieLabelInfo& rInfo1( *aIt1 );
+ PieLabelInfo& rInfo2( *aIt2 );
+ rInfo1.pNext = &rInfo2;
+ rInfo2.pPrevious = &rInfo1;
+ }
+ aIt1->pNext = &(*(m_aLabelInfoList.begin()));
+
+ ///detect overlaps and move
+ sal_Int32 nMaxIterations = 50;
+ while( detectLabelOverlapsAndMove( rPageSize ) && nMaxIterations > 0 )
+ nMaxIterations--;
+
+ ///create connection lines for the moved labels
+ VLineProperties aVLineProperties;
+ for (auto const& labelInfo : m_aLabelInfoList)
+ {
+ if( labelInfo.bMoved && labelInfo.bShowLeaderLine )
+ {
+ sal_Int32 nX1 = labelInfo.aOuterPosition.getX();
+ sal_Int32 nY1 = labelInfo.aOuterPosition.getY();
+ sal_Int32 nX2 = nX1;
+ sal_Int32 nY2 = nY1;
+ ::basegfx::B2IRectangle aRect( lcl_getRect( labelInfo.xLabelGroupShape ) );
+ if( nX1 < aRect.getMinX() )
+ nX2 = aRect.getMinX();
+ else if( nX1 > aRect.getMaxX() )
+ nX2 = aRect.getMaxX();
+
+ if( nY1 < aRect.getMinY() )
+ nY2 = aRect.getMinY();
+ else if( nY1 > aRect.getMaxY() )
+ nY2 = aRect.getMaxY();
+
+ //when the line is very short compared to the page size don't create one
+ ::basegfx::B2DVector aLength(nX1-nX2, nY1-nY2);
+ if( (aLength.getLength()/fPageDiagonaleLength) < 0.01 )
+ continue;
+
+ drawing::PointSequenceSequence aPoints{ { {nX1, nY1}, {nX2, nY2} } };
+
+ if( labelInfo.xTextShape.is() )
+ {
+ sal_Int32 nColor = 0;
+ labelInfo.xTextShape->SvxShape::getPropertyValue("CharColor") >>= nColor;
+ if( nColor != -1 )//automatic font color does not work for lines -> fallback to black
+ aVLineProperties.Color <<= nColor;
+ }
+ ShapeFactory::createLine2D( labelInfo.xTextTarget, aPoints, &aVLineProperties );
+ }
+ }
+}
+
+
+/** Handle the placement of the label in the best fit case:
+ * the routine try to place the label inside the related pie slice,
+ * in case of success it returns true else returns false.
+ *
+ * Notation:
+ * C: the pie center
+ * s: the bisector ray of the current pie slice
+ * alpha: the angle between the horizontal axis and the bisector ray s
+ * N: the vertex of the label b.b. which is nearest to C
+ * F: the vertex of the label b.b. not adjacent to N; F lies on the pie border
+ * P, Q: the intersection points between the label b.b. and the bisector ray s;
+ * P is the one at minimum distance respect with C
+ * e: the edge of the label b.b. where P lies (the nearest edge to C)
+ * M: the vertex of e that is not N
+ * G: the vertex of the label b.b. which is adjacent to N and that is not M
+ * beta: the angle MPF
+ * theta: the angle CPF
+ *
+ *
+ * |
+ * | /s
+ * | /
+ * | /
+ * | G _________________________/____________________________ F
+ * | | /Q ..|
+ * | | / . . |
+ * | | / . . |
+ * | | / . . |
+ * | | / . . |
+ * | | / . . |
+ * | | / d. . |
+ * | | / . . |
+ * | | / . . |
+ * | | / . . |
+ * | | / . . |
+ * | | / . . |
+ * | | / . . |
+ * | | / . \ beta . |
+ * | |__________/._\___|_______.____________________________|
+ * | N /P / . M
+ * | /___/theta .
+ * | / .
+ * | / . r
+ * | / .
+ * | / .
+ * | / .
+ * | / .
+ * | / .
+ * | / .
+ * | / .
+ * | / .
+ * | /\. alpha
+ * __|/__|_____________________________________________________________
+ * |C
+ * |
+ *
+ *
+ * When alpha = 45k (k integer) s crosses the label b.b. at N exactly.
+ * In such a case the nearest edge e is defined as the edge having N as the
+ * start vertex and that is covered in the counterclockwise direction when
+ * we move from N to the adjacent vertex.
+ *
+ * The nearest vertex N is:
+ * 1. the bottom left vertex when 0 < alpha < 90
+ * 2. the bottom right vertex when 90 < alpha < 180
+ * 3. the top right vertex when 180 < alpha < 270
+ * 4. the top left vertex when 270 < alpha < 360.
+ *
+ * The nearest edge e is:
+ * 1. the left edge when −45 < alpha < 45
+ * 2. the bottom edge when 45 < alpha <135
+ * 3. the right edge when 135 < alpha < 225
+ * 4. the top edge when 225 < alpha < 315.
+ *
+ **/
+bool PieChart::performLabelBestFitInnerPlacement(ShapeParam& rShapeParam, PieLabelInfo const & rPieLabelInfo)
+{
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ "** PieChart::performLabelBestFitInnerPlacement invoked **" );
+
+ // get pie slice properties
+ double fStartAngleDeg = NormAngle360(rShapeParam.mfUnitCircleStartAngleDegree);
+ double fWidthAngleDeg = rShapeParam.mfUnitCircleWidthAngleDegree;
+ double fHalfWidthAngleDeg = fWidthAngleDeg / 2.0;
+ double fBisectingRayAngleDeg = NormAngle360(fStartAngleDeg + fHalfWidthAngleDeg);
+
+ // get the middle point of the arc representing the pie slice border
+ double fLogicZ = rShapeParam.mfLogicZ + 1.0;
+ awt::Point aMiddleArcPoint = PlottingPositionHelper::transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene(
+ fBisectingRayAngleDeg,
+ rShapeParam.mfUnitCircleOuterRadius,
+ fLogicZ ),
+ m_xLogicTarget, m_nDimension );
+
+ // compute the pie radius
+ basegfx::B2IVector aPieCenter = rPieLabelInfo.aOrigin;
+ basegfx::B2IVector aRadiusVector(
+ aMiddleArcPoint.X - aPieCenter.getX(),
+ aMiddleArcPoint.Y - aPieCenter.getY() );
+ double fSquaredPieRadius = aRadiusVector.scalar(aRadiusVector);
+ double fPieRadius = sqrt( fSquaredPieRadius );
+
+ // the bb is moved as much as possible near to the border of the pie,
+ // anyway a small offset from the border is present (0.025 * pie radius)
+ const double fPieBorderOffset = 0.025;
+ fPieRadius = fPieRadius - fPieRadius * fPieBorderOffset;
+
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " pie sector:" );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " start angle = " << fStartAngleDeg );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " angle width = " << fWidthAngleDeg );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " bisecting ray angle = " << fBisectingRayAngleDeg );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " pie radius = " << fPieRadius );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " pie center = " << rPieLabelInfo.aOrigin );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " middle arc point = (" << aMiddleArcPoint.X << ","
+ << aMiddleArcPoint.Y << ")" );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " label bounding box:" );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " old anchor point = " << rPieLabelInfo.aFirstPosition );
+
+
+ if( fPieRadius == 0.0 )
+ return false;
+
+ // get label b.b. width and height
+ ::basegfx::B2IRectangle aBb( lcl_getRect( rPieLabelInfo.xLabelGroupShape ) );
+ double fLabelWidth = aBb.getWidth();
+ double fLabelHeight = aBb.getHeight();
+
+ // -45 <= fAlphaDeg < 315
+ double fAlphaDeg = NormAngle360(fBisectingRayAngleDeg + 45) - 45;
+ double fAlphaRad = basegfx::deg2rad(fAlphaDeg);
+
+ // compute nearest edge index
+ // 0 left
+ // 1 bottom
+ // 2 right
+ // 3 top
+ int nSectorIndex = floor( (fAlphaDeg + 45) / 45.0 );
+ int nNearestEdgeIndex = nSectorIndex / 2;
+
+ // compute lengths of the nearest edge and of the orthogonal edges
+ double fNearestEdgeLength = fLabelWidth;
+ double fOrthogonalEdgeLength = fLabelHeight;
+ basegfx::Axis2D eAxis = basegfx::Axis2D::X;
+ basegfx::Axis2D eOrthogonalAxis = basegfx::Axis2D::Y;
+ if( nNearestEdgeIndex % 2 == 0 ) // nearest edge is vertical
+ {
+ fNearestEdgeLength = fLabelHeight;
+ fOrthogonalEdgeLength = fLabelWidth;
+ eAxis = basegfx::Axis2D::Y;
+ eOrthogonalAxis = basegfx::Axis2D::X;
+ }
+
+ // compute the distance between N and P
+ // such a distance is piece wise linear respect with alpha:
+ // given 45k <= alpha < 45(k+1) we have
+ // when k is even: d(N,P) = (length(e) / 2) * (1 - (alpha - 45k)/45)
+ // when k is odd: d(N,P) = (length(e) / 2) * (1 - (45(k+1) - alpha)/45)
+ int nIndex = nSectorIndex -1; // nIndex = -1...6
+ double fIndexMod2 = (nIndex + 8) % 2; // fIndexMod2 must be non negative
+ double fSgn = 2.0 * (fIndexMod2 - 0.5); // 0 -> -1, 1 -> 1
+ double fDistanceNP = (fNearestEdgeLength / 2.0) * (1 + fSgn * ((fAlphaDeg - 45 * (nIndex + fIndexMod2)) / 45.0));
+ double fDistancePM = fNearestEdgeLength - fDistanceNP;
+
+ // compute the length of the diagonal vector d,
+ // that is the distance between P and F
+ double fDistancePF = std::hypot(fDistancePM, fOrthogonalEdgeLength);
+
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " width = " << fLabelWidth );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " height = " << fLabelHeight );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " nearest edge index = " << nNearestEdgeIndex );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " alpha = " << fAlphaDeg );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " distance(N,P) = " << fDistanceNP );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " nIndex = " << nIndex );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " fIndexMod2 = " << fIndexMod2 );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " fSgn = " << fSgn );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " distance(P,F) = " << fDistancePF );
+
+
+ // we check that the condition length(d) <= pie radius holds
+ if (fDistancePF > fPieRadius)
+ {
+ return false;
+ }
+
+ // compute beta: the angle of the diagonal vector d,
+ // that is, the angle in P respect with the triangle PMF;
+ // since both arguments are non negative the returned value is in [0, PI/2]
+ double fBetaRad = atan2( fOrthogonalEdgeLength, fDistancePM );
+
+ // compute the theta angle, that is the angle in P
+ // respect with the triangle CFP;
+ // when the second intersection edge is opposite to the nearest edge,
+ // theta depends on alpha and beta according to the following relation:
+ // theta = f(alpha, beta) = s * alpha + 90 * (1 - s * i) + beta
+ // where i is the nearest edge index and s is the sign of (alpha' - 45),
+ // with alpha' = (alpha + 45) mod 90;
+ // when the second intersection edge is adjacent to the nearest edge,
+ // we have theta = 360 - f(alpha, beta);
+ // note that in the former case 0 <= f(alpha, beta) <= 180,
+ // whilst in the latter case 180 <= f(alpha, beta) <= 360;
+ double fAlphaMod90 = fmod( fAlphaDeg + 45, 90.0 ) - 45;
+ double fSign = fAlphaMod90 == 0.0
+ ? 0.0
+ : ( fAlphaMod90 < 0 ) ? -1.0 : 1.0;
+ double fThetaRad = fSign * fAlphaRad + M_PI_2 * (1 - fSign * nNearestEdgeIndex) + fBetaRad;
+ if( fThetaRad > M_PI )
+ {
+ fThetaRad = 2 * M_PI - fThetaRad;
+ }
+
+ // compute the length of the positional vector,
+ // that is the distance between C and P
+ double fDistanceCP;
+ // when the bisector ray intersects the b.b. in F we have theta mod 180 == 0
+ if( fmod(fThetaRad, M_PI) == 0.0 )
+ {
+ fDistanceCP = fPieRadius - fDistancePF;
+ }
+ else // general case
+ {
+ // we can compute d(C,P) by applying some trigonometric formula to
+ // the triangle CFP : we know length(d) and length(r) = r and we have
+ // computed the angle in P (theta); so named delta the angle in C and
+ // gamma the angle in F, by the relation:
+ //
+ // r d(P,F) d(C,P)
+ // --------- = --------- = ---------
+ // sin theta sin delta sin gamma
+ //
+ // we get the wanted distance
+ double fSinTheta = sin( fThetaRad );
+ double fSinDelta = fDistancePF * fSinTheta / fPieRadius;
+ double fDeltaRad = asin( fSinDelta );
+ double fGammaRad = M_PI - (fThetaRad + fDeltaRad);
+ double fSinGamma = sin( fGammaRad );
+ fDistanceCP = fPieRadius * fSinGamma / fSinTheta;
+ }
+
+ // define the positional vector
+ basegfx::B2DVector aPositionalVector( cos(fAlphaRad), sin(fAlphaRad) );
+ aPositionalVector.setLength(fDistanceCP);
+
+ // we define a direction vector in order to know
+ // in which quadrant we are working
+ basegfx::B2DVector aDirection(1.0, 1.0);
+ if( 90 <= fBisectingRayAngleDeg && fBisectingRayAngleDeg < 270 )
+ {
+ aDirection.setX(-1.0);
+ }
+ if( fBisectingRayAngleDeg >= 180 )
+ {
+ aDirection.setY(-1.0);
+ }
+
+ // compute vertices N, M and G respect with pie center C
+ basegfx::B2DVector aNearestVertex(aPositionalVector);
+ aNearestVertex.set(eAxis, aNearestVertex.get(eAxis) - aDirection.get(eAxis) * fDistanceNP);
+ basegfx::B2DVector aVertexM(aNearestVertex);
+ aVertexM.set(eAxis, aVertexM.get(eAxis) + aDirection.get(eAxis) * fNearestEdgeLength);
+ basegfx::B2DVector aVertexG(aNearestVertex);
+ aVertexG.set(eOrthogonalAxis, aVertexG.get(eOrthogonalAxis) + aDirection.get(eOrthogonalAxis) * fOrthogonalEdgeLength);
+
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " beta = " << basegfx::rad2deg(fBetaRad) );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " theta = " << basegfx::rad2deg(fThetaRad) );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " fAlphaMod90 = " << fAlphaMod90 );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " fSign = " << fSign );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " distance(C,P) = " << fDistanceCP );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " direction vector = " << aDirection );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " N = " << aNearestVertex );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " M = " << aVertexM );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " G = " << aVertexG );
+
+ // in order to be able to place the label inside the pie slice we need
+ // to check that each angle between s and the ray starting from C and
+ // passing through a b.b. vertex is less than half width of the pie slice;
+ // when the nearest edge e crosses a Cartesian axis it is sufficient
+ // to test only the vertices belonging to e, else we need to test
+ // the 2 vertices that aren't either N or F. Note that if a b.b. edge
+ // crosses a Cartesian axis then it is the nearest edge to C
+
+ // check the angle between CP and CM
+ double fAngleRad = aPositionalVector.angle(aVertexM);
+ double fAngleDeg = NormAngle360(basegfx::rad2deg(fAngleRad));
+ if( fAngleDeg > 180 ) // in case the wrong angle has been computed
+ fAngleDeg = 360 - fAngleDeg;
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " angle between CP and CM: " << fAngleDeg );
+ if( fAngleDeg > fHalfWidthAngleDeg )
+ {
+ return false;
+ }
+
+ if( ( aNearestVertex.get(eAxis) >= 0 && aVertexM.get(eAxis) <= 0 )
+ || ( aNearestVertex.get(eAxis) <= 0 && aVertexM.get(eAxis) >= 0 ) )
+ {
+ // check the angle between CP and CN
+ fAngleRad = aPositionalVector.angle(aNearestVertex);
+ fAngleDeg = NormAngle360(basegfx::rad2deg(fAngleRad));
+ if( fAngleDeg > 180 ) // in case the wrong angle has been computed
+ fAngleDeg = 360 - fAngleDeg;
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " angle between CP and CN: " << fAngleDeg );
+ if( fAngleDeg > fHalfWidthAngleDeg )
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // check the angle between CP and CG
+ fAngleRad = aPositionalVector.angle(aVertexG);
+ fAngleDeg = NormAngle360(basegfx::rad2deg(fAngleRad));
+ if( fAngleDeg > 180 ) // in case the wrong angle has been computed
+ fAngleDeg = 360 - fAngleDeg;
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " angle between CP and CG: " << fAngleDeg );
+ if( fAngleDeg > fHalfWidthAngleDeg )
+ {
+ return false;
+ }
+ }
+
+ // compute the b.b. center respect with the pie center
+ basegfx::B2DVector aBBCenter(aNearestVertex);
+ aBBCenter.set(eAxis, aBBCenter.get(eAxis) + aDirection.get(eAxis) * fNearestEdgeLength / 2);
+ aBBCenter.set(eOrthogonalAxis, aBBCenter.get(eOrthogonalAxis) + aDirection.get(eOrthogonalAxis) * fOrthogonalEdgeLength / 2);
+
+ // compute the b.b. anchor point
+ basegfx::B2IVector aNewAnchorPoint = aPieCenter;
+ aNewAnchorPoint.setX(aNewAnchorPoint.getX() + floor(aBBCenter.getX()));
+ aNewAnchorPoint.setY(aNewAnchorPoint.getY() - floor(aBBCenter.getY())); // the Y axis on the screen points downward
+
+ // compute the translation vector for moving the label from the current
+ // screen position to the new one
+ basegfx::B2IVector aTranslationVector = aNewAnchorPoint - rPieLabelInfo.aFirstPosition;
+
+ // compute the new screen position and move the label
+ // XShape::getPosition returns the top left vertex of the b.b. of the shape
+ awt::Point aOldPos( rPieLabelInfo.xLabelGroupShape->getPosition() );
+ awt::Point aNewPos( aOldPos.X + aTranslationVector.getX(),
+ aOldPos.Y + aTranslationVector.getY() );
+ rPieLabelInfo.xLabelGroupShape->setPosition(aNewPos);
+
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " center = " << aBBCenter );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " new anchor point = " << aNewAnchorPoint );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " translation vector = " << aTranslationVector );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " old position = (" << aOldPos.X << "," << aOldPos.Y << ")" );
+ SAL_INFO( "chart2.pie.label.bestfit.inside",
+ " new position = (" << aNewPos.X << "," << aNewPos.Y << ")" );
+
+ return true;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/PieChart.hxx b/chart2/source/view/charttypes/PieChart.hxx
new file mode 100644
index 0000000000..9a5b7fb4c9
--- /dev/null
+++ b/chart2/source/view/charttypes/PieChart.hxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <VSeriesPlotter.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+#include <com/sun/star/awt/Point.hpp>
+
+namespace chart
+{
+class PiePositionHelper;
+
+class PieChart : public VSeriesPlotter
+{
+ struct ShapeParam;
+
+public:
+ PieChart() = delete;
+
+ PieChart( const rtl::Reference< ::chart::ChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount, bool bExcludingPositioning );
+ virtual ~PieChart() override;
+
+ /** This method creates all shapes needed for representing the pie chart.
+ */
+ virtual void createShapes() override;
+ virtual void rearrangeLabelToAvoidOverlapIfRequested( const css::awt::Size& rPageSize ) override;
+
+ virtual void setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ) override;
+ virtual void addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot ) override;
+
+ virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override;
+ virtual bool shouldSnapRectToUsedArea() override;
+
+ //MinimumAndMaximumSupplier
+ virtual double getMinimumX() override;
+ virtual double getMaximumX() override;
+ virtual double getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) override;
+ virtual double getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) override;
+
+ virtual bool isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex ) override;
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex ) override;
+ virtual bool isExpandWideValuesToZero( sal_Int32 nDimensionIndex ) override;
+ virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex ) override;
+ virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) override;
+
+private: //methods
+ rtl::Reference<SvxShape>
+ createDataPoint(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const css::uno::Reference<css::beans::XPropertySet>& xObjectProperties,
+ const ShapeParam& rParam,
+ const sal_Int32 nPointCount,
+ const bool bConcentricExplosion);
+
+ /** This method creates a text shape for a label of a data point.
+ *
+ * @param xTextTarget
+ * where to append the new created text shape.
+ * @param rSeries
+ * the data series, the data point belongs to.
+ * @param nPointIndex
+ * the index of the data point the label is related to.
+ * @param rParam
+ * ShapeParam object.
+ */
+ void createTextLabelShape(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget,
+ VDataSeries& rSeries, sal_Int32 nPointIndex, ShapeParam& rParam );
+
+ /** This method sets `m_fMaxOffset` to the maximum `Offset` property and
+ * returns it. There is a `Offset` property for each entry in a data
+ * series, moreover there exists a shared `Offset` property attached to
+ * the whole data series. The `Offset` property represents the
+ * relative distance offset of a slice from the pie center.
+ * The shared property is used for exploded pie chart, while the property
+ * attached to single data series entries is used for manual dragging of
+ * a slice.
+ * `m_fMaxOffset` is used by `PiePositionHelper::getInnerAndOuterRadius`.
+ * Note that only the `Offset` properties of the first (x slot) data series
+ * and its entries are utilized for computing the maximum offset.
+ */
+ double getMaxOffset();
+ bool detectLabelOverlapsAndMove(const css::awt::Size& rPageSize);//returns true when there might be more to do
+ void resetLabelPositionsToPreviousState();
+struct PieLabelInfo;
+ bool tryMoveLabels( PieLabelInfo const * pFirstBorder, PieLabelInfo const * pSecondBorder
+ , PieLabelInfo* pCenter, bool bSingleCenter, bool& rbAlternativeMoveDirection
+ , const css::awt::Size& rPageSize );
+
+ bool performLabelBestFitInnerPlacement( ShapeParam& rShapeParam
+ , PieLabelInfo const & rPieLabelInfo );
+
+private: //member
+ std::unique_ptr<PiePositionHelper>
+ m_pPosHelper;
+ bool m_bUseRings;
+ bool m_bSizeExcludesLabelsAndExplodedSegments;
+
+ struct PieLabelInfo
+ {
+ PieLabelInfo();
+ bool moveAwayFrom( const PieLabelInfo* pFix, const css::awt::Size& rPageSize
+ , bool bMoveHalfWay, bool bMoveClockwise );
+
+ rtl::Reference< SvxShapeText > xTextShape;
+ rtl::Reference< SvxShapeGroupAnyD > xLabelGroupShape;
+ ::basegfx::B2IVector aFirstPosition;
+ ::basegfx::B2IVector aOuterPosition;
+ ::basegfx::B2IVector aOrigin;
+ double fValue;
+ bool bMovementAllowed;
+ bool bMoved;
+ bool bShowLeaderLine;
+ rtl::Reference<SvxShapeGroupAnyD> xTextTarget;
+ PieLabelInfo* pPrevious;
+ PieLabelInfo* pNext;
+ css::awt::Point aPreviousPosition;
+ };
+
+ std::vector< PieLabelInfo > m_aLabelInfoList;
+
+ double m_fMaxOffset; /// cached max offset value (init'ed to NaN)
+};
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/Splines.cxx b/chart2/source/view/charttypes/Splines.cxx
new file mode 100644
index 0000000000..2aac969291
--- /dev/null
+++ b/chart2/source/view/charttypes/Splines.cxx
@@ -0,0 +1,872 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "Splines.hxx"
+#include <osl/diagnose.h>
+#include <com/sun/star/drawing/Position3D.hpp>
+
+#include <vector>
+#include <algorithm>
+#include <memory>
+#include <cmath>
+#include <limits>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+namespace
+{
+
+typedef std::pair< double, double > tPointType;
+typedef std::vector< tPointType > tPointVecType;
+typedef tPointVecType::size_type lcl_tSizeType;
+
+class lcl_SplineCalculation
+{
+public:
+ /** @descr creates an object that calculates cubic splines on construction
+
+ @param rSortedPoints the points for which splines shall be calculated, they need to be sorted in x values
+ @param fY1FirstDerivation the resulting spline should have the first
+ derivation equal to this value at the x-value of the first point
+ of rSortedPoints. If fY1FirstDerivation is set to infinity, a natural
+ spline is calculated.
+ @param fYnFirstDerivation the resulting spline should have the first
+ derivation equal to this value at the x-value of the last point
+ of rSortedPoints
+ */
+ lcl_SplineCalculation( tPointVecType && rSortedPoints,
+ double fY1FirstDerivation,
+ double fYnFirstDerivation );
+
+ /** @descr creates an object that calculates cubic splines on construction
+ for the special case of periodic cubic spline
+
+ @param rSortedPoints the points for which splines shall be calculated,
+ they need to be sorted in x values. First and last y value must be equal
+ */
+ explicit lcl_SplineCalculation( tPointVecType && rSortedPoints);
+
+ /** @descr this function corresponds to the function splint in [1].
+
+ [1] Numerical Recipes in C, 2nd edition
+ William H. Press, et al.,
+ Section 3.3, page 116
+ */
+ double GetInterpolatedValue( double x );
+
+private:
+ /// a copy of the points given in the CTOR
+ tPointVecType m_aPoints;
+
+ /// the result of the Calculate() method
+ std::vector< double > m_aSecDerivY;
+
+ double m_fYp1;
+ double m_fYpN;
+
+ // these values are cached for performance reasons
+ lcl_tSizeType m_nKLow;
+ lcl_tSizeType m_nKHigh;
+ double m_fLastInterpolatedValue;
+
+ /** @descr this function corresponds to the function spline in [1].
+
+ [1] Numerical Recipes in C, 2nd edition
+ William H. Press, et al.,
+ Section 3.3, page 115
+ */
+ void Calculate();
+
+ /** @descr this function corresponds to the algorithm 4.76 in [2] and
+ theorem 5.3.7 in [3]
+
+ [2] Engeln-Müllges, Gisela: Numerik-Algorithmen: Verfahren, Beispiele, Anwendungen
+ Springer, Berlin; Auflage: 9., überarb. und erw. A. (8. Dezember 2004)
+ Section 4.10.2, page 175
+
+ [3] Hanrath, Wilhelm: Mathematik III / Numerik, Vorlesungsskript zur
+ Veranstaltung im WS 2007/2008
+ Fachhochschule Aachen, 2009-09-19
+ Numerik_01.pdf, downloaded 2011-04-19 via
+ http://www.fh-aachen.de/index.php?id=11424&no_cache=1&file=5016&uid=44191
+ Section 5.3, page 129
+ */
+ void CalculatePeriodic();
+};
+
+lcl_SplineCalculation::lcl_SplineCalculation(
+ tPointVecType && rSortedPoints,
+ double fY1FirstDerivation,
+ double fYnFirstDerivation )
+ : m_aPoints( std::move(rSortedPoints) ),
+ m_fYp1( fY1FirstDerivation ),
+ m_fYpN( fYnFirstDerivation ),
+ m_nKLow( 0 ),
+ m_nKHigh( m_aPoints.size() - 1 ),
+ m_fLastInterpolatedValue(std::numeric_limits<double>::infinity())
+{
+ Calculate();
+}
+
+lcl_SplineCalculation::lcl_SplineCalculation(
+ tPointVecType && rSortedPoints)
+ : m_aPoints( std::move(rSortedPoints) ),
+ m_fYp1( 0.0 ), /*dummy*/
+ m_fYpN( 0.0 ), /*dummy*/
+ m_nKLow( 0 ),
+ m_nKHigh( m_aPoints.size() - 1 ),
+ m_fLastInterpolatedValue(std::numeric_limits<double>::infinity())
+{
+ CalculatePeriodic();
+}
+
+void lcl_SplineCalculation::Calculate()
+{
+ if( m_aPoints.size() <= 1 )
+ return;
+
+ // n is the last valid index to m_aPoints
+ const lcl_tSizeType n = m_aPoints.size() - 1;
+ std::vector< double > u( n );
+ m_aSecDerivY.resize( n + 1, 0.0 );
+
+ if( std::isinf( m_fYp1 ) )
+ {
+ // natural spline
+ m_aSecDerivY[ 0 ] = 0.0;
+ u[ 0 ] = 0.0;
+ }
+ else
+ {
+ m_aSecDerivY[ 0 ] = -0.5;
+ double xDiff = m_aPoints[ 1 ].first - m_aPoints[ 0 ].first;
+ u[ 0 ] = ( 3.0 / xDiff ) *
+ ((( m_aPoints[ 1 ].second - m_aPoints[ 0 ].second ) / xDiff ) - m_fYp1 );
+ }
+
+ for( lcl_tSizeType i = 1; i < n; ++i )
+ {
+ tPointType
+ p_i = m_aPoints[ i ],
+ p_im1 = m_aPoints[ i - 1 ],
+ p_ip1 = m_aPoints[ i + 1 ];
+
+ double sig = ( p_i.first - p_im1.first ) /
+ ( p_ip1.first - p_im1.first );
+ double p = sig * m_aSecDerivY[ i - 1 ] + 2.0;
+
+ m_aSecDerivY[ i ] = ( sig - 1.0 ) / p;
+ u[ i ] =
+ ( ( p_ip1.second - p_i.second ) /
+ ( p_ip1.first - p_i.first ) ) -
+ ( ( p_i.second - p_im1.second ) /
+ ( p_i.first - p_im1.first ) );
+ u[ i ] =
+ ( 6.0 * u[ i ] / ( p_ip1.first - p_im1.first )
+ - sig * u[ i - 1 ] ) / p;
+ }
+
+ // initialize to values for natural splines (used for m_fYpN equal to
+ // infinity)
+ double qn = 0.0;
+ double un = 0.0;
+
+ if( ! std::isinf( m_fYpN ) )
+ {
+ qn = 0.5;
+ double xDiff = m_aPoints[ n ].first - m_aPoints[ n - 1 ].first;
+ un = ( 3.0 / xDiff ) *
+ ( m_fYpN - ( m_aPoints[ n ].second - m_aPoints[ n - 1 ].second ) / xDiff );
+ }
+
+ m_aSecDerivY[ n ] = ( un - qn * u[ n - 1 ] ) / ( qn * m_aSecDerivY[ n - 1 ] + 1.0 );
+
+ // note: the algorithm in [1] iterates from n-1 to 0, but as size_type
+ // may be (usually is) an unsigned type, we can not write k >= 0, as this
+ // is always true.
+ for( lcl_tSizeType k = n; k > 0; --k )
+ {
+ m_aSecDerivY[ k - 1 ] = (m_aSecDerivY[ k - 1 ] * m_aSecDerivY[ k ] ) + u[ k - 1 ];
+ }
+}
+
+void lcl_SplineCalculation::CalculatePeriodic()
+{
+ if( m_aPoints.size() <= 1 )
+ return;
+
+ // n is the last valid index to m_aPoints
+ const lcl_tSizeType n = m_aPoints.size() - 1;
+
+ // u is used for vector f in A*c=f in [3], vector a in Ax=a in [2],
+ // vector z in Rtranspose z = a and Dr=z in [2]
+ std::vector< double > u( n + 1, 0.0 );
+
+ // used for vector c in A*c=f and vector x in Ax=a in [2]
+ m_aSecDerivY.resize( n + 1, 0.0 );
+
+ // diagonal of matrix A, used index 1 to n
+ std::vector< double > Adiag( n + 1, 0.0 );
+
+ // secondary diagonal of matrix A with index 1 to n-1 and upper right element in A[n]
+ std::vector< double > Aupper( n + 1, 0.0 );
+
+ // diagonal of matrix D in A=(R transpose)*D*R in [2], used index 1 to n
+ std::vector< double > Ddiag( n+1, 0.0 );
+
+ // right column of matrix R, used index 1 to n-2
+ std::vector< double > Rright( n-1, 0.0 );
+
+ // secondary diagonal of matrix R, used index 1 to n-1
+ std::vector< double > Rupper( n, 0.0 );
+
+ if (n<4)
+ {
+ if (n==3)
+ { // special handling of three polynomials, that are four points
+ double xDiff0 = m_aPoints[ 1 ].first - m_aPoints[ 0 ].first ;
+ double xDiff1 = m_aPoints[ 2 ].first - m_aPoints[ 1 ].first ;
+ double xDiff2 = m_aPoints[ 3 ].first - m_aPoints[ 2 ].first ;
+ double xDiff2p1 = xDiff2 + xDiff1;
+ double xDiff0p2 = xDiff0 + xDiff2;
+ double xDiff1p0 = xDiff1 + xDiff0;
+ double fFactor = 1.5 / (xDiff0*xDiff1 + xDiff1*xDiff2 + xDiff2*xDiff0);
+ double yDiff0 = (m_aPoints[ 1 ].second - m_aPoints[ 0 ].second) / xDiff0;
+ double yDiff1 = (m_aPoints[ 2 ].second - m_aPoints[ 1 ].second) / xDiff1;
+ double yDiff2 = (m_aPoints[ 0 ].second - m_aPoints[ 2 ].second) / xDiff2;
+ m_aSecDerivY[ 1 ] = fFactor * (yDiff1*xDiff2p1 - yDiff0*xDiff0p2);
+ m_aSecDerivY[ 2 ] = fFactor * (yDiff2*xDiff0p2 - yDiff1*xDiff1p0);
+ m_aSecDerivY[ 3 ] = fFactor * (yDiff0*xDiff1p0 - yDiff2*xDiff2p1);
+ m_aSecDerivY[ 0 ] = m_aSecDerivY[ 3 ];
+ }
+ else if (n==2)
+ {
+ // special handling of two polynomials, that are three points
+ double xDiff0 = m_aPoints[ 1 ].first - m_aPoints[ 0 ].first;
+ double xDiff1 = m_aPoints[ 2 ].first - m_aPoints[ 1 ].first;
+ double fHelp = 3.0 * (m_aPoints[ 0 ].second - m_aPoints[ 1 ].second) / (xDiff0*xDiff1);
+ m_aSecDerivY[ 1 ] = fHelp ;
+ m_aSecDerivY[ 2 ] = -fHelp ;
+ m_aSecDerivY[ 0 ] = m_aSecDerivY[ 2 ] ;
+ }
+ else
+ {
+ // should be handled with natural spline, periodic not possible.
+ }
+ }
+ else
+ {
+ double xDiff_i =1.0; // values are dummy;
+ double xDiff_im1 =1.0;
+ double yDiff_i = 1.0;
+ double yDiff_im1 = 1.0;
+ // fill matrix A and fill right side vector u
+ for( lcl_tSizeType i=1; i<n; ++i )
+ {
+ xDiff_im1 = m_aPoints[ i ].first - m_aPoints[ i-1 ].first;
+ xDiff_i = m_aPoints[ i+1 ].first - m_aPoints[ i ].first;
+ yDiff_im1 = (m_aPoints[ i ].second - m_aPoints[ i-1 ].second) / xDiff_im1;
+ yDiff_i = (m_aPoints[ i+1 ].second - m_aPoints[ i ].second) / xDiff_i;
+ Adiag[ i ] = 2 * (xDiff_im1 + xDiff_i);
+ Aupper[ i ] = xDiff_i;
+ u [ i ] = 3 * (yDiff_i - yDiff_im1);
+ }
+ xDiff_im1 = m_aPoints[ n ].first - m_aPoints[ n-1 ].first;
+ xDiff_i = m_aPoints[ 1 ].first - m_aPoints[ 0 ].first;
+ yDiff_im1 = (m_aPoints[ n ].second - m_aPoints[ n-1 ].second) / xDiff_im1;
+ yDiff_i = (m_aPoints[ 1 ].second - m_aPoints[ 0 ].second) / xDiff_i;
+ Adiag[ n ] = 2 * (xDiff_im1 + xDiff_i);
+ Aupper[ n ] = xDiff_i;
+ u [ n ] = 3 * (yDiff_i - yDiff_im1);
+
+ // decomposite A=(R transpose)*D*R
+ Ddiag[1] = Adiag[1];
+ Rupper[1] = Aupper[1] / Ddiag[1];
+ Rright[1] = Aupper[n] / Ddiag[1];
+ for( lcl_tSizeType i=2; i<=n-2; ++i )
+ {
+ Ddiag[i] = Adiag[i] - Aupper[ i-1 ] * Rupper[ i-1 ];
+ Rupper[ i ] = Aupper[ i ] / Ddiag[ i ];
+ Rright[ i ] = - Rright[ i-1 ] * Aupper[ i-1 ] / Ddiag[ i ];
+ }
+ Ddiag[ n-1 ] = Adiag[ n-1 ] - Aupper[ n-2 ] * Rupper[ n-2 ];
+ Rupper[ n-1 ] = ( Aupper[ n-1 ] - Aupper[ n-2 ] * Rright[ n-2] ) / Ddiag[ n-1 ];
+ double fSum = 0.0;
+ for ( lcl_tSizeType i=1; i<=n-2; ++i )
+ {
+ fSum += Ddiag[ i ] * Rright[ i ] * Rright[ i ];
+ }
+ Ddiag[ n ] = Adiag[ n ] - fSum - Ddiag[ n-1 ] * Rupper[ n-1 ] * Rupper[ n-1 ]; // bug in [2]!
+
+ // solve forward (R transpose)*z=u, overwrite u with z
+ for ( lcl_tSizeType i=2; i<=n-1; ++i )
+ {
+ u[ i ] -= u[ i-1 ]* Rupper[ i-1 ];
+ }
+ fSum = 0.0;
+ for ( lcl_tSizeType i=1; i<=n-2; ++i )
+ {
+ fSum += Rright[ i ] * u[ i ];
+ }
+ u[ n ] = u[ n ] - fSum - Rupper[ n - 1] * u[ n-1 ];
+
+ // solve forward D*r=z, z is in u, overwrite u with r
+ for ( lcl_tSizeType i=1; i<=n; ++i )
+ {
+ u[ i ] = u[i] / Ddiag[ i ];
+ }
+
+ // solve backward R*x= r, r is in u
+ m_aSecDerivY[ n ] = u[ n ];
+ m_aSecDerivY[ n-1 ] = u[ n-1 ] - Rupper[ n-1 ] * m_aSecDerivY[ n ];
+ for ( lcl_tSizeType i=n-2; i>=1; --i)
+ {
+ m_aSecDerivY[ i ] = u[ i ] - Rupper[ i ] * m_aSecDerivY[ i+1 ] - Rright[ i ] * m_aSecDerivY[ n ];
+ }
+ // periodic
+ m_aSecDerivY[ 0 ] = m_aSecDerivY[ n ];
+ }
+
+ // adapt m_aSecDerivY for usage in GetInterpolatedValue()
+ for( lcl_tSizeType i = 0; i <= n ; ++i )
+ {
+ m_aSecDerivY[ i ] *= 2.0;
+ }
+
+}
+
+double lcl_SplineCalculation::GetInterpolatedValue( double x )
+{
+ OSL_PRECOND( ( m_aPoints[ 0 ].first <= x ) &&
+ ( x <= m_aPoints[ m_aPoints.size() - 1 ].first ),
+ "Trying to extrapolate" );
+
+ const lcl_tSizeType n = m_aPoints.size() - 1;
+ if( x < m_fLastInterpolatedValue )
+ {
+ m_nKLow = 0;
+ m_nKHigh = n;
+
+ // calculate m_nKLow and m_nKHigh
+ // first initialization is done in CTOR
+ while( m_nKHigh - m_nKLow > 1 )
+ {
+ lcl_tSizeType k = ( m_nKHigh + m_nKLow ) / 2;
+ if( m_aPoints[ k ].first > x )
+ m_nKHigh = k;
+ else
+ m_nKLow = k;
+ }
+ }
+ else
+ {
+ while( ( m_nKHigh <= n ) &&
+ ( m_aPoints[ m_nKHigh ].first < x ) )
+ {
+ ++m_nKHigh;
+ ++m_nKLow;
+ }
+ OSL_ENSURE( m_nKHigh <= n, "Out of Bounds" );
+ }
+ m_fLastInterpolatedValue = x;
+
+ double h = m_aPoints[ m_nKHigh ].first - m_aPoints[ m_nKLow ].first;
+ OSL_ENSURE( h != 0, "Bad input to GetInterpolatedValue()" );
+
+ double a = ( m_aPoints[ m_nKHigh ].first - x ) / h;
+ double b = ( x - m_aPoints[ m_nKLow ].first ) / h;
+
+ return ( a * m_aPoints[ m_nKLow ].second +
+ b * m_aPoints[ m_nKHigh ].second +
+ (( a*a*a - a ) * m_aSecDerivY[ m_nKLow ] +
+ ( b*b*b - b ) * m_aSecDerivY[ m_nKHigh ] ) *
+ ( h*h ) / 6.0 );
+}
+
+// helper methods for B-spline
+
+// Create parameter t_0 to t_n using the centripetal method with a power of 0.5
+bool createParameterT(const tPointVecType& rUniquePoints, double* t)
+{ // precondition: no adjacent identical points
+ // postcondition: 0 = t_0 < t_1 < ... < t_n = 1
+ bool bIsSuccessful = true;
+ const lcl_tSizeType n = rUniquePoints.size() - 1;
+ t[0]=0.0;
+ double fDenominator = 0.0; // initialized for summing up
+ for (lcl_tSizeType i=1; i<=n ; ++i)
+ { // 4th root(dx^2+dy^2)
+ double dx = rUniquePoints[i].first - rUniquePoints[i-1].first;
+ double dy = rUniquePoints[i].second - rUniquePoints[i-1].second;
+ if (dx == 0 && dy == 0)
+ {
+ bIsSuccessful = false;
+ break;
+ }
+ else
+ {
+ fDenominator += sqrt(std::hypot(dx, dy));
+ }
+ }
+ if (fDenominator == 0.0)
+ {
+ bIsSuccessful = false;
+ }
+ if (bIsSuccessful)
+ {
+ for (lcl_tSizeType j=1; j<=n ; ++j)
+ {
+ double fNumerator = 0.0;
+ for (lcl_tSizeType i=1; i<=j ; ++i)
+ {
+ double dx = rUniquePoints[i].first - rUniquePoints[i-1].first;
+ double dy = rUniquePoints[i].second - rUniquePoints[i-1].second;
+ fNumerator += sqrt(std::hypot(dx, dy));
+ }
+ t[j] = fNumerator / fDenominator;
+
+ }
+ // postcondition check
+ t[n] = 1.0;
+ double fPrevious = 0.0;
+ for (lcl_tSizeType i=1; i <= n && bIsSuccessful ; ++i)
+ {
+ if (fPrevious >= t[i])
+ {
+ bIsSuccessful = false;
+ }
+ else
+ {
+ fPrevious = t[i];
+ }
+ }
+ }
+ return bIsSuccessful;
+}
+
+void createKnotVector(const lcl_tSizeType n, const sal_uInt32 p, const double* t, double* u)
+{ // precondition: 0 = t_0 < t_1 < ... < t_n = 1
+ for (lcl_tSizeType j = 0; j <= p; ++j)
+ {
+ u[j] = 0.0;
+ }
+ for (lcl_tSizeType j = 1; j <= n-p; ++j )
+ {
+ double fSum = 0.0;
+ for (lcl_tSizeType i = j; i <= j+p-1; ++i)
+ {
+ fSum += t[i];
+ }
+ assert(p != 0);
+ u[j+p] = fSum / p ;
+ }
+ for (lcl_tSizeType j = n+1; j <= n+1+p; ++j)
+ {
+ u[j] = 1.0;
+ }
+}
+
+void applyNtoParameterT(const lcl_tSizeType i,const double tk,const sal_uInt32 p,const double* u, double* rowN)
+{
+ // get N_p(t_k) recursively, only N_(i-p) till N_(i) are relevant, all other N_# are zero
+
+ // initialize with indicator function degree 0
+ rowN[p] = 1.0; // all others are zero
+
+ // calculate up to degree p
+ for (sal_uInt32 s = 1; s <= p; ++s)
+ {
+ // first element
+ double fLeftFactor = 0.0;
+ double fRightFactor = ( u[i+1] - tk ) / ( u[i+1]- u[i-s+1] );
+ // i-s "true index" - (i-p)"shift" = p-s
+ rowN[p-s] = fRightFactor * rowN[p-s+1];
+
+ // middle elements
+ for (sal_uInt32 j = s-1; j>=1 ; --j)
+ {
+ fLeftFactor = ( tk - u[i-j] ) / ( u[i-j+s] - u[i-j] ) ;
+ fRightFactor = ( u[i-j+s+1] - tk ) / ( u[i-j+s+1] - u[i-j+1] );
+ // i-j "true index" - (i-p)"shift" = p-j
+ rowN[p-j] = fLeftFactor * rowN[p-j] + fRightFactor * rowN[p-j+1];
+ }
+
+ // last element
+ fLeftFactor = ( tk - u[i] ) / ( u[i+s] - u[i] );
+ // i "true index" - (i-p)"shift" = p
+ rowN[p] = fLeftFactor * rowN[p];
+ }
+}
+
+} // anonymous namespace
+
+// Calculates uniform parametric splines with subinterval length 1,
+// according ODF1.2 part 1, chapter 'chart interpolation'.
+void SplineCalculater::CalculateCubicSplines(
+ const std::vector<std::vector<css::drawing::Position3D>>& rInput
+ , std::vector<std::vector<css::drawing::Position3D>>& rResult
+ , sal_uInt32 nGranularity )
+{
+ OSL_PRECOND( nGranularity > 0, "Granularity is invalid" );
+
+ sal_uInt32 nOuterCount = rInput.size();
+
+ rResult.resize(nOuterCount);
+
+ auto pSequence = rResult.data();
+
+ if( !nOuterCount )
+ return;
+
+ for( sal_uInt32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+ {
+ if( rInput[nOuter].size() <= 1 )
+ continue; //we need at least two points
+
+ sal_uInt32 nMaxIndexPoints = rInput[nOuter].size()-1; // is >=1
+ const css::drawing::Position3D* pOld = rInput[nOuter].data();
+
+ std::vector < double > aParameter(nMaxIndexPoints+1);
+ aParameter[0]=0.0;
+ for( sal_uInt32 nIndex=1; nIndex<=nMaxIndexPoints; nIndex++ )
+ {
+ aParameter[nIndex]=aParameter[nIndex-1]+1;
+ }
+
+ // Split the calculation to X, Y and Z coordinate
+ tPointVecType aInputX;
+ aInputX.resize(nMaxIndexPoints+1);
+ tPointVecType aInputY;
+ aInputY.resize(nMaxIndexPoints+1);
+ tPointVecType aInputZ;
+ aInputZ.resize(nMaxIndexPoints+1);
+ for (sal_uInt32 nN=0;nN<=nMaxIndexPoints; nN++ )
+ {
+ aInputX[ nN ].first=aParameter[nN];
+ aInputX[ nN ].second=pOld[ nN ].PositionX;
+ aInputY[ nN ].first=aParameter[nN];
+ aInputY[ nN ].second=pOld[ nN ].PositionY;
+ aInputZ[ nN ].first=aParameter[nN];
+ aInputZ[ nN ].second=pOld[ nN ].PositionZ;
+ }
+
+ // generate a spline for each coordinate. It holds the complete
+ // information to calculate each point of the curve
+ std::unique_ptr<lcl_SplineCalculation> aSplineX;
+ std::unique_ptr<lcl_SplineCalculation> aSplineY;
+ // lcl_SplineCalculation* aSplineZ; the z-coordinates of all points in
+ // a data series are equal. No spline calculation needed, but copy
+ // coordinate to output
+
+ if( pOld[ 0 ].PositionX == pOld[nMaxIndexPoints].PositionX &&
+ pOld[ 0 ].PositionY == pOld[nMaxIndexPoints].PositionY &&
+ pOld[ 0 ].PositionZ == pOld[nMaxIndexPoints].PositionZ &&
+ nMaxIndexPoints >=2 )
+ { // periodic spline
+ aSplineX = std::make_unique<lcl_SplineCalculation>(std::move(aInputX));
+ aSplineY = std::make_unique<lcl_SplineCalculation>(std::move(aInputY));
+ }
+ else // generate the kind "natural spline"
+ {
+ double fXDerivation = std::numeric_limits<double>::infinity();
+ double fYDerivation = std::numeric_limits<double>::infinity();
+ aSplineX = std::make_unique<lcl_SplineCalculation>(std::move(aInputX), fXDerivation, fXDerivation);
+ aSplineY = std::make_unique<lcl_SplineCalculation>(std::move(aInputY), fYDerivation, fYDerivation);
+ }
+
+ // fill result polygon with calculated values
+ pSequence[nOuter].resize( nMaxIndexPoints*nGranularity + 1);
+
+ css::drawing::Position3D* pNew = pSequence[nOuter].data();
+
+ sal_uInt32 nNewPointIndex = 0; // Index in result points
+
+ for( sal_uInt32 ni = 0; ni < nMaxIndexPoints; ni++ )
+ {
+ // given point is surely a curve point
+ pNew[nNewPointIndex].PositionX = pOld[ni].PositionX;
+ pNew[nNewPointIndex].PositionY = pOld[ni].PositionY;
+ pNew[nNewPointIndex].PositionZ = pOld[ni].PositionZ;
+ nNewPointIndex++;
+
+ // calculate intermediate points
+ double fInc = ( aParameter[ ni+1 ] - aParameter[ni] ) / static_cast< double >( nGranularity );
+ for(sal_uInt32 nj = 1; nj < nGranularity; nj++)
+ {
+ double fParam = aParameter[ni] + ( fInc * static_cast< double >( nj ) );
+
+ pNew[nNewPointIndex].PositionX = aSplineX->GetInterpolatedValue( fParam );
+ pNew[nNewPointIndex].PositionY = aSplineY->GetInterpolatedValue( fParam );
+ // pNewZ[nNewPointIndex]=aSplineZ->GetInterpolatedValue( fParam );
+ pNew[nNewPointIndex].PositionZ = pOld[ni].PositionZ;
+ nNewPointIndex++;
+ }
+ }
+ // add last point
+ pNew[nNewPointIndex] = pOld[nMaxIndexPoints];
+ }
+}
+
+void SplineCalculater::CalculateBSplines(
+ const std::vector<std::vector<css::drawing::Position3D>>& rInput
+ , std::vector<std::vector<css::drawing::Position3D>>& rResult
+ , sal_uInt32 nResolution
+ , sal_uInt32 nDegree )
+{
+ // nResolution is ODF1.2 file format attribute chart:spline-resolution and
+ // ODF1.2 spec variable k. Causion, k is used as index in the spec in addition.
+ // nDegree is ODF1.2 file format attribute chart:spline-order and
+ // ODF1.2 spec variable p
+ OSL_ASSERT( nResolution > 1 );
+ OSL_ASSERT( nDegree >= 1 );
+
+ // limit the b-spline degree at 15 to prevent insanely large sets of points
+ sal_uInt32 p = std::min<sal_uInt32>(nDegree, 15);
+
+ sal_Int32 nOuterCount = rInput.size();
+
+ rResult.resize(nOuterCount);
+
+ auto pSequence = rResult.data();
+
+ if( !nOuterCount )
+ return; // no input
+
+ for( sal_Int32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+ {
+ if( rInput[nOuter].size() <= 1 )
+ continue; // need at least 2 points, next piece of the series
+
+ // Copy input to vector of points and remove adjacent double points. The
+ // Z-coordinate is equal for all points in a series and holds the depth
+ // in 3D mode, simple copying is enough.
+ lcl_tSizeType nMaxIndexPoints = rInput[nOuter].size()-1; // is >=1
+ const css::drawing::Position3D* pOld = rInput[nOuter].data();
+ double fZCoordinate = pOld[0].PositionZ;
+ tPointVecType aPointsIn;
+ aPointsIn.resize(nMaxIndexPoints+1);
+ for (lcl_tSizeType i = 0; i <= nMaxIndexPoints; ++i )
+ {
+ aPointsIn[ i ].first = pOld[i].PositionX;
+ aPointsIn[ i ].second = pOld[i].PositionY;
+ }
+ aPointsIn.erase( std::unique( aPointsIn.begin(), aPointsIn.end()),
+ aPointsIn.end() );
+
+ // n is the last valid index to the reduced aPointsIn
+ // There are n+1 valid data points.
+ const lcl_tSizeType n = aPointsIn.size() - 1;
+ if (n < 1 || p > n)
+ continue; // need at least 2 points, degree p needs at least n+1 points
+ // next piece of series
+
+ std::vector<double> t(n + 1);
+ if (!createParameterT(aPointsIn, t.data()))
+ {
+ continue; // next piece of series
+ }
+
+ lcl_tSizeType m = n + p + 1;
+ std::vector<double> u(m + 1);
+ createKnotVector(n, p, t.data(), u.data());
+
+ // The matrix N contains the B-spline basis functions applied to parameters.
+ // In each row only p+1 adjacent elements are non-zero. The starting
+ // column in a higher row is equal or greater than in the lower row.
+ // To store this matrix the non-zero elements are shifted to column 0
+ // and the amount of shifting is remembered in an array.
+ std::vector<std::vector<double>> aMatN(n + 1, std::vector<double>(p + 1));
+ std::vector<lcl_tSizeType> aShift(n + 1);
+ aMatN[0][0] = 1.0; //all others are zero
+ aShift[0] = 0;
+ aMatN[n][0] = 1.0;
+ aShift[n] = n;
+ for (lcl_tSizeType k = 1; k<=n-1; ++k)
+ { // all basis functions are applied to t_k,
+ // results are elements in row k in matrix N
+
+ // find the one interval with u_i <= t_k < u_(i+1)
+ // remember u_0 = ... = u_p = 0.0 and u_(m-p) = ... u_m = 1.0 and 0<t_k<1
+ lcl_tSizeType i = p;
+ while (u[i] > t[k] || t[k] >= u[i+1])
+ {
+ ++i;
+ }
+
+ // index in reduced matrix aMatN = (index in full matrix N) - (i-p)
+ aShift[k] = i - p;
+
+ applyNtoParameterT(i, t[k], p, u.data(), aMatN[k].data());
+ } // next row k
+
+ // Get matrix C of control points from the matrix equation aMatN * C = aPointsIn
+ // aPointsIn is overwritten with C.
+ // Gaussian elimination is possible without pivoting, see reference
+ lcl_tSizeType r = 0; // true row index
+ lcl_tSizeType c = 0; // true column index
+ double fDivisor = 1.0; // used for diagonal element
+ double fEliminate = 1.0; // used for the element, that will become zero
+ bool bIsSuccessful = true;
+ for (c = 0 ; c <= n && bIsSuccessful; ++c)
+ {
+ // search for first non-zero downwards
+ r = c;
+ while ( r < n && aMatN[r][c-aShift[r]] == 0 )
+ {
+ ++r;
+ }
+ if (aMatN[r][c-aShift[r]] == 0.0)
+ {
+ // Matrix N is singular, although this is mathematically impossible
+ bIsSuccessful = false;
+ }
+ else
+ {
+ // exchange total row r with total row c if necessary
+ if (r != c)
+ {
+ std::swap( aMatN[r], aMatN[c] );
+ std::swap( aPointsIn[r], aPointsIn[c] );
+ std::swap( aShift[r], aShift[c] );
+ }
+
+ // divide row c, so that element(c,c) becomes 1
+ fDivisor = aMatN[c][c-aShift[c]]; // not zero, see above
+ for (sal_uInt32 i = 0; i <= p; ++i)
+ {
+ aMatN[c][i] /= fDivisor;
+ }
+ aPointsIn[c].first /= fDivisor;
+ aPointsIn[c].second /= fDivisor;
+
+ // eliminate forward, examine row c+1 to n-1 (worst case)
+ // stop if first non-zero element in row has an higher column as c
+ // look at nShift for that, elements in nShift are equal or increasing
+ for ( r = c+1; r < n && aShift[r]<=c ; ++r)
+ {
+ fEliminate = aMatN[r][0];
+ if (fEliminate != 0.0) // else accidentally zero, nothing to do
+ {
+ for (sal_uInt32 i = 1; i <= p; ++i)
+ {
+ aMatN[r][i-1] = aMatN[r][i] - fEliminate * aMatN[c][i];
+ }
+ aMatN[r][p]=0;
+ aPointsIn[r].first -= fEliminate * aPointsIn[c].first;
+ aPointsIn[r].second -= fEliminate * aPointsIn[c].second;
+ ++aShift[r];
+ }
+ }
+ }
+ }// upper triangle form is reached
+ if( bIsSuccessful)
+ {
+ // eliminate backwards, begin with last column
+ for (lcl_tSizeType cc = n; cc >= 1; --cc )
+ {
+ // In row cc the diagonal element(cc,cc) == 1 and all elements left from
+ // diagonal are zero and do not influence other rows.
+ // Full matrix N has semibandwidth < p, therefore element(r,c) is
+ // zero, if abs(r-cc)>=p. abs(r-cc)=cc-r, because r<cc.
+ r = cc - 1;
+ while ( r !=0 && cc-r < p )
+ {
+ fEliminate = aMatN[r][ cc - aShift[r] ];
+ if ( fEliminate != 0.0) // else element is accidentally zero, no action needed
+ {
+ // row r -= fEliminate * row cc only relevant for right side
+ aMatN[r][cc - aShift[r]] = 0.0;
+ aPointsIn[r].first -= fEliminate * aPointsIn[cc].first;
+ aPointsIn[r].second -= fEliminate * aPointsIn[cc].second;
+ }
+ --r;
+ }
+ }
+ // aPointsIn contains the control points now.
+
+ // calculate the intermediate points according given resolution
+ // using deBoor-Cox algorithm
+ lcl_tSizeType nNewSize = nResolution * n + 1;
+ pSequence[nOuter].resize(nNewSize);
+ css::drawing::Position3D* pNew = pSequence[nOuter].data();
+ pNew[0].PositionX = aPointsIn[0].first;
+ pNew[0].PositionY = aPointsIn[0].second;
+ pNew[0].PositionZ = fZCoordinate; // Precondition: z-coordinates of all points of a series are equal
+ pNew[nNewSize -1 ].PositionX = aPointsIn[n].first;
+ pNew[nNewSize -1 ].PositionY = aPointsIn[n].second;
+ pNew[nNewSize -1 ].PositionZ = fZCoordinate;
+ std::vector<double> aP(m + 1);
+ lcl_tSizeType nLow = 0;
+ for ( lcl_tSizeType nTIndex = 0; nTIndex <= n-1; ++nTIndex)
+ {
+ for (sal_uInt32 nResolutionStep = 1;
+ nResolutionStep <= nResolution && ( nTIndex != n-1 || nResolutionStep != nResolution);
+ ++nResolutionStep)
+ {
+ lcl_tSizeType nNewIndex = nTIndex * nResolution + nResolutionStep;
+ double ux = t[nTIndex] + nResolutionStep * ( t[nTIndex+1] - t[nTIndex]) /nResolution;
+
+ // get index nLow, so that u[nLow]<= ux < u[nLow +1]
+ // continue from previous nLow
+ while ( u[nLow] <= ux)
+ {
+ ++nLow;
+ }
+ --nLow;
+
+ // x-coordinate
+ for (lcl_tSizeType i = nLow-p; i <= nLow; ++i)
+ {
+ aP[i] = aPointsIn[i].first;
+ }
+ for (sal_uInt32 lcl_Degree = 1; lcl_Degree <= p; ++lcl_Degree)
+ {
+ for (lcl_tSizeType i = nLow; i >= nLow + lcl_Degree - p; --i)
+ {
+ double fFactor = ( ux - u[i] ) / ( u[i+p+1-lcl_Degree] - u[i]);
+ aP[i] = (1 - fFactor)* aP[i-1] + fFactor * aP[i];
+ }
+ }
+ pNew[nNewIndex].PositionX = aP[nLow];
+
+ // y-coordinate
+ for (lcl_tSizeType i = nLow - p; i <= nLow; ++i)
+ {
+ aP[i] = aPointsIn[i].second;
+ }
+ for (sal_uInt32 lcl_Degree = 1; lcl_Degree <= p; ++lcl_Degree)
+ {
+ for (lcl_tSizeType i = nLow; i >= nLow +lcl_Degree - p; --i)
+ {
+ double fFactor = ( ux - u[i] ) / ( u[i+p+1-lcl_Degree] - u[i]);
+ aP[i] = (1 - fFactor)* aP[i-1] + fFactor * aP[i];
+ }
+ }
+ pNew[nNewIndex].PositionY = aP[nLow];
+ pNew[nNewIndex].PositionZ = fZCoordinate;
+ }
+ }
+ }
+ } // next piece of the series
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/Splines.hxx b/chart2/source/view/charttypes/Splines.hxx
new file mode 100644
index 0000000000..b83c13931b
--- /dev/null
+++ b/chart2/source/view/charttypes/Splines.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <vector>
+
+namespace com::sun::star::drawing { struct PolyPolygonShape3D; }
+namespace com::sun::star::drawing { struct Position3D; }
+
+namespace chart
+{
+
+class SplineCalculater
+{
+public:
+ static void CalculateCubicSplines(
+ const std::vector<std::vector<css::drawing::Position3D>>& rPoints
+ , std::vector<std::vector<css::drawing::Position3D>>& rResult
+ , sal_uInt32 nGranularity );
+
+ static void CalculateBSplines(
+ const std::vector<std::vector<css::drawing::Position3D>>& rPoints
+ , std::vector<std::vector<css::drawing::Position3D>>& rResult
+ , sal_uInt32 nGranularity
+ , sal_uInt32 nSplineDepth );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx
new file mode 100644
index 0000000000..f9fa8fe0fe
--- /dev/null
+++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx
@@ -0,0 +1,2950 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cstddef>
+#include <limits>
+#include <memory>
+#include <VSeriesPlotter.hxx>
+#include <BaseGFXHelper.hxx>
+#include <VLineProperties.hxx>
+#include <ShapeFactory.hxx>
+#include <Diagram.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesProperties.hxx>
+
+#include <CommonConverters.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <FormattedString.hxx>
+#include <ObjectIdentifier.hxx>
+#include <StatisticsHelper.hxx>
+#include <PlottingPositionHelper.hxx>
+#include <LabelPositionHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <Clipping.hxx>
+#include <servicenames_charttypes.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <DataSeriesHelper.hxx>
+#include <RegressionCurveModel.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <VLegendSymbolFactory.hxx>
+#include <FormattedStringHelper.hxx>
+#include <RelativePositionHelper.hxx>
+#include <DateHelper.hxx>
+#include <DiagramHelper.hxx>
+#include <defines.hxx>
+#include <ChartModel.hxx>
+
+//only for creation: @todo remove if all plotter are uno components and instantiated via servicefactory
+#include "BarChart.hxx"
+#include "PieChart.hxx"
+#include "AreaChart.hxx"
+#include "CandleStickChart.hxx"
+#include "BubbleChart.hxx"
+#include "NetChart.hxx"
+#include <unonames.hxx>
+#include <SpecialCharacters.hxx>
+
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/chart/TimeUnit.hpp>
+#include <com/sun/star/chart2/MovingAverageType.hpp>
+#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <o3tl/safeint.hxx>
+#include <tools/color.hxx>
+#include <tools/UnitConversion.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/math.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+
+#include <unotools/localedatawrapper.hxx>
+#include <comphelper/sequence.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+
+#include <functional>
+#include <map>
+#include <unordered_map>
+
+
+namespace chart {
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart;
+using namespace ::com::sun::star::chart2;
+using namespace ::chart::DataSeriesProperties;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+VDataSeriesGroup::CachedYValues::CachedYValues()
+ : m_bValuesDirty(true)
+ , m_fMinimumY(0.0)
+ , m_fMaximumY(0.0)
+{
+}
+
+VDataSeriesGroup::VDataSeriesGroup( std::unique_ptr<VDataSeries> pSeries )
+ : m_aSeriesVector(1)
+ , m_bMaxPointCountDirty(true)
+ , m_nMaxPointCount(0)
+{
+ m_aSeriesVector[0] = std::move(pSeries);
+}
+
+VDataSeriesGroup::VDataSeriesGroup(VDataSeriesGroup&& other) noexcept
+ : m_aSeriesVector( std::move(other.m_aSeriesVector) )
+ , m_bMaxPointCountDirty( other.m_bMaxPointCountDirty )
+ , m_nMaxPointCount( other.m_nMaxPointCount )
+ , m_aListOfCachedYValues( std::move(other.m_aListOfCachedYValues) )
+{
+}
+
+VDataSeriesGroup::~VDataSeriesGroup()
+{
+}
+
+void VDataSeriesGroup::deleteSeries()
+{
+ //delete all data series help objects:
+ m_aSeriesVector.clear();
+}
+
+void VDataSeriesGroup::addSeries( std::unique_ptr<VDataSeries> pSeries )
+{
+ m_aSeriesVector.push_back(std::move(pSeries));
+ m_bMaxPointCountDirty=true;
+}
+
+sal_Int32 VDataSeriesGroup::getSeriesCount() const
+{
+ return m_aSeriesVector.size();
+}
+
+VSeriesPlotter::VSeriesPlotter( rtl::Reference<ChartType> xChartTypeModel
+ , sal_Int32 nDimensionCount, bool bCategoryXAxis )
+ : PlotterBase( nDimensionCount )
+ , m_pMainPosHelper( nullptr )
+ , m_xChartTypeModel(std::move(xChartTypeModel))
+ , m_bCategoryXAxis(bCategoryXAxis)
+ , m_nTimeResolution(css::chart::TimeUnit::DAY)
+ , m_aNullDate(30,12,1899)
+ , m_pExplicitCategoriesProvider(nullptr)
+ , m_bPointsWereSkipped(false)
+ , m_bPieLabelsAllowToMove(false)
+ , m_aAvailableOuterRect(0, 0, 0, 0)
+{
+ SAL_WARN_IF(!m_xChartTypeModel.is(),"chart2","no XChartType available in view, fallback to default values may be wrong");
+}
+
+VSeriesPlotter::~VSeriesPlotter()
+{
+ //delete all data series help objects:
+ for (std::vector<VDataSeriesGroup> & rGroupVector : m_aZSlots)
+ {
+ for (VDataSeriesGroup & rGroup : rGroupVector)
+ {
+ rGroup.deleteSeries();
+ }
+ rGroupVector.clear();
+ }
+ m_aZSlots.clear();
+
+ m_aSecondaryPosHelperMap.clear();
+
+ m_aSecondaryValueScales.clear();
+}
+
+void VSeriesPlotter::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
+{
+ //take ownership of pSeries
+
+ OSL_PRECOND( pSeries, "series to add is NULL" );
+ if(!pSeries)
+ return;
+
+ if(m_bCategoryXAxis)
+ {
+ if( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() )
+ pSeries->setXValues( m_pExplicitCategoriesProvider->getOriginalCategories() );
+ else
+ pSeries->setCategoryXAxis();
+ }
+ else
+ {
+ if( m_pExplicitCategoriesProvider )
+ pSeries->setXValuesIfNone( m_pExplicitCategoriesProvider->getOriginalCategories() );
+ }
+
+ if(zSlot<0 || o3tl::make_unsigned(zSlot)>=m_aZSlots.size())
+ {
+ //new z slot
+ std::vector< VDataSeriesGroup > aZSlot;
+ aZSlot.emplace_back( std::move(pSeries) );
+ m_aZSlots.push_back( std::move(aZSlot) );
+ }
+ else
+ {
+ //existing zslot
+ std::vector< VDataSeriesGroup >& rXSlots = m_aZSlots[zSlot];
+
+ if(xSlot<0 || o3tl::make_unsigned(xSlot)>=rXSlots.size())
+ {
+ //append the series to already existing x series
+ rXSlots.emplace_back( std::move(pSeries) );
+ }
+ else
+ {
+ //x slot is already occupied
+ //y slot decides what to do:
+
+ VDataSeriesGroup& rYSlots = rXSlots[xSlot];
+ sal_Int32 nYSlotCount = rYSlots.getSeriesCount();
+
+ if( ySlot < -1 )
+ {
+ //move all existing series in the xSlot to next slot
+ //@todo
+ OSL_FAIL( "Not implemented yet");
+ }
+ else if( ySlot == -1 || ySlot >= nYSlotCount)
+ {
+ //append the series to already existing y series
+ rYSlots.addSeries( std::move(pSeries) );
+ }
+ else
+ {
+ //y slot is already occupied
+ //insert at given y and x position
+
+ //@todo
+ OSL_FAIL( "Not implemented yet");
+ }
+ }
+ }
+}
+
+drawing::Direction3D VSeriesPlotter::getPreferredDiagramAspectRatio() const
+{
+ drawing::Direction3D aRet(1.0,1.0,1.0);
+ if (!m_pPosHelper)
+ return aRet;
+
+ drawing::Direction3D aScale( m_pPosHelper->getScaledLogicWidth() );
+ aRet.DirectionZ = aScale.DirectionZ*0.2;
+ if(aRet.DirectionZ>1.0)
+ aRet.DirectionZ=1.0;
+ if(aRet.DirectionZ>10)
+ aRet.DirectionZ=10;
+ return aRet;
+}
+
+void VSeriesPlotter::releaseShapes()
+{
+ for (std::vector<VDataSeriesGroup> const & rGroupVector : m_aZSlots)
+ {
+ for (VDataSeriesGroup const & rGroup : rGroupVector)
+ {
+ //iterate through all series in this x slot
+ for (std::unique_ptr<VDataSeries> const & pSeries : rGroup.m_aSeriesVector)
+ {
+ pSeries->releaseShapes();
+ }
+ }
+ }
+}
+
+rtl::Reference<SvxShapeGroupAnyD> VSeriesPlotter::getSeriesGroupShape( VDataSeries* pDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
+{
+ if( !pDataSeries->m_xGroupShape )
+ //create a group shape for this series and add to logic target:
+ pDataSeries->m_xGroupShape = createGroupShape( xTarget,pDataSeries->getCID() );
+ return pDataSeries->m_xGroupShape;
+}
+
+rtl::Reference<SvxShapeGroupAnyD> VSeriesPlotter::getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
+{
+ if(!pDataSeries->m_xFrontSubGroupShape)
+ {
+ //ensure that the series group shape is already created
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesShapes( getSeriesGroupShape( pDataSeries, xTarget ) );
+ //ensure that the back child is created first
+ getSeriesGroupShapeBackChild( pDataSeries, xTarget );
+ //use series group shape as parent for the new created front group shape
+ pDataSeries->m_xFrontSubGroupShape = createGroupShape( xSeriesShapes );
+ }
+ return pDataSeries->m_xFrontSubGroupShape;
+}
+
+rtl::Reference<SvxShapeGroupAnyD> VSeriesPlotter::getSeriesGroupShapeBackChild( VDataSeries* pDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
+{
+ if(!pDataSeries->m_xBackSubGroupShape)
+ {
+ //ensure that the series group shape is already created
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesShapes( getSeriesGroupShape( pDataSeries, xTarget ) );
+ //use series group shape as parent for the new created back group shape
+ pDataSeries->m_xBackSubGroupShape = createGroupShape( xSeriesShapes );
+ }
+ return pDataSeries->m_xBackSubGroupShape;
+}
+
+rtl::Reference<SvxShapeGroup> VSeriesPlotter::getLabelsGroupShape( VDataSeries& rDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget )
+{
+ //xTextTarget needs to be a 2D shape container always!
+ if(!rDataSeries.m_xLabelsGroupShape)
+ {
+ //create a 2D group shape for texts of this series and add to text target:
+ rDataSeries.m_xLabelsGroupShape = ShapeFactory::createGroup2D( xTextTarget, rDataSeries.getLabelsCID() );
+ }
+ return rDataSeries.m_xLabelsGroupShape;
+}
+
+rtl::Reference<SvxShapeGroupAnyD> VSeriesPlotter::getErrorBarsGroupShape( VDataSeries& rDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , bool bYError )
+{
+ rtl::Reference<SvxShapeGroupAnyD> &rShapeGroup =
+ bYError ? rDataSeries.m_xErrorYBarsGroupShape : rDataSeries.m_xErrorXBarsGroupShape;
+
+ if(!rShapeGroup)
+ {
+ //create a group shape for this series and add to logic target:
+ rShapeGroup = createGroupShape( xTarget,rDataSeries.getErrorBarsCID(bYError) );
+ }
+ return rShapeGroup;
+
+}
+
+OUString VSeriesPlotter::getLabelTextForValue( VDataSeries const & rDataSeries
+ , sal_Int32 nPointIndex
+ , double fValue
+ , bool bAsPercentage )
+{
+ OUString aNumber;
+
+ if (m_apNumberFormatterWrapper)
+ {
+ sal_Int32 nNumberFormatKey = 0;
+ if( rDataSeries.hasExplicitNumberFormat(nPointIndex,bAsPercentage) )
+ nNumberFormatKey = rDataSeries.getExplicitNumberFormat(nPointIndex,bAsPercentage);
+ else if( bAsPercentage )
+ {
+ sal_Int32 nPercentFormat = DiagramHelper::getPercentNumberFormat( m_apNumberFormatterWrapper->getNumberFormatsSupplier() );
+ if( nPercentFormat != -1 )
+ nNumberFormatKey = nPercentFormat;
+ }
+ else
+ {
+ nNumberFormatKey = rDataSeries.detectNumberFormatKey( nPointIndex );
+ }
+ if(nNumberFormatKey<0)
+ nNumberFormatKey=0;
+
+ Color nLabelCol;
+ bool bColChanged;
+ aNumber = m_apNumberFormatterWrapper->getFormattedString(
+ nNumberFormatKey, fValue, nLabelCol, bColChanged );
+ //@todo: change color of label if bColChanged is true
+ }
+ else
+ {
+ const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
+ const OUString& aNumDecimalSep = rLocaleDataWrapper.getNumDecimalSep();
+ assert(aNumDecimalSep.getLength() > 0);
+ sal_Unicode cDecSeparator = aNumDecimalSep[0];
+ aNumber = ::rtl::math::doubleToUString( fValue, rtl_math_StringFormat_G /*rtl_math_StringFormat*/
+ , 3/*DecPlaces*/ , cDecSeparator );
+ }
+ return aNumber;
+}
+
+rtl::Reference<SvxShapeText> VSeriesPlotter::createDataLabel( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , VDataSeries& rDataSeries
+ , sal_Int32 nPointIndex
+ , double fValue
+ , double fSumValue
+ , const awt::Point& rScreenPosition2D
+ , LabelAlignment eAlignment
+ , sal_Int32 nOffset
+ , sal_Int32 nTextWidth )
+{
+ rtl::Reference<SvxShapeText> xTextShape;
+ Sequence<uno::Reference<XDataPointCustomLabelField>> aCustomLabels;
+
+ try
+ {
+ const uno::Reference< css::beans::XPropertySet >& xPropertySet(
+ rDataSeries.getPropertiesOfPoint( nPointIndex ) );
+ if( xPropertySet.is() )
+ {
+ uno::Any aAny = xPropertySet->getPropertyValue( CHART_UNONAME_CUSTOM_LABEL_FIELDS );
+ if( aAny.hasValue() )
+ {
+ aAny >>= aCustomLabels;
+ }
+ }
+
+ awt::Point aScreenPosition2D(rScreenPosition2D);
+ if(eAlignment==LABEL_ALIGN_LEFT)
+ aScreenPosition2D.X -= nOffset;
+ else if(eAlignment==LABEL_ALIGN_RIGHT)
+ aScreenPosition2D.X += nOffset;
+ else if(eAlignment==LABEL_ALIGN_TOP)
+ aScreenPosition2D.Y -= nOffset;
+ else if(eAlignment==LABEL_ALIGN_BOTTOM)
+ aScreenPosition2D.Y += nOffset;
+
+ rtl::Reference<SvxShapeGroup> xTarget_ =
+ ShapeFactory::createGroup2D(
+ getLabelsGroupShape(rDataSeries, xTarget),
+ ObjectIdentifier::createPointCID( rDataSeries.getLabelCID_Stub(), nPointIndex));
+
+ //check whether the label needs to be created and how:
+ DataPointLabel* pLabel = rDataSeries.getDataPointLabelIfLabel( nPointIndex );
+
+ if( !pLabel )
+ return xTextShape;
+
+ //prepare legend symbol
+
+ // get the font size for the label through the "CharHeight" property
+ // attached to the passed data series entry.
+ // (By tracing font height values it results that for pie chart the
+ // font size is not the same for all labels, but here no font size
+ // modification occurs).
+ float fViewFontSize( 10.0 );
+ {
+ uno::Reference< beans::XPropertySet > xProps( rDataSeries.getPropertiesOfPoint( nPointIndex ) );
+ if( xProps.is() )
+ xProps->getPropertyValue( "CharHeight") >>= fViewFontSize;
+ fViewFontSize = convertPointToMm100(fViewFontSize);
+ }
+
+ // the font height is used for computing the size of an optional legend
+ // symbol to be prepended to the text label.
+ rtl::Reference< SvxShapeGroup > xSymbol;
+ if(pLabel->ShowLegendSymbol)
+ {
+ sal_Int32 nSymbolHeight = static_cast< sal_Int32 >( fViewFontSize * 0.6 );
+ awt::Size aCurrentRatio = getPreferredLegendKeyAspectRatio();
+ sal_Int32 nSymbolWidth = aCurrentRatio.Width;
+ if( aCurrentRatio.Height > 0 )
+ {
+ nSymbolWidth = nSymbolHeight* aCurrentRatio.Width/aCurrentRatio.Height;
+ }
+ awt::Size aMaxSymbolExtent( nSymbolWidth, nSymbolHeight );
+
+ if( rDataSeries.isVaryColorsByPoint() )
+ xSymbol = VSeriesPlotter::createLegendSymbolForPoint( aMaxSymbolExtent, rDataSeries, nPointIndex, xTarget_ );
+ else
+ xSymbol = VSeriesPlotter::createLegendSymbolForSeries( aMaxSymbolExtent, rDataSeries, xTarget_ );
+ }
+
+ //prepare text
+ bool bTextWrap = false;
+ OUString aSeparator(" ");
+ double fRotationDegrees = 0.0;
+ try
+ {
+ uno::Reference< beans::XPropertySet > xPointProps( rDataSeries.getPropertiesOfPoint( nPointIndex ) );
+ if(xPointProps.is())
+ {
+ xPointProps->getPropertyValue( "TextWordWrap" ) >>= bTextWrap;
+ xPointProps->getPropertyValue( "LabelSeparator" ) >>= aSeparator;
+ // Extract the optional text rotation through the
+ // "TextRotation" property attached to the passed data point.
+ xPointProps->getPropertyValue( "TextRotation" ) >>= fRotationDegrees;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ sal_Int32 nLineCountForSymbolsize = 0;
+ sal_uInt32 nTextListLength = 4;
+ sal_uInt32 nCustomLabelsCount = aCustomLabels.getLength();
+ Sequence< OUString > aTextList( nTextListLength );
+
+ bool bUseCustomLabel = nCustomLabelsCount > 0;
+ if( bUseCustomLabel )
+ {
+ nTextListLength = ( nCustomLabelsCount > 3 ) ? nCustomLabelsCount : 3;
+ aSeparator = "";
+ aTextList = Sequence< OUString >( nTextListLength );
+ auto pTextList = aTextList.getArray();
+ for( sal_uInt32 i = 0; i < nCustomLabelsCount; ++i )
+ {
+ switch( aCustomLabels[i]->getFieldType() )
+ {
+ case DataPointCustomLabelFieldType_VALUE:
+ {
+ pTextList[i] = getLabelTextForValue( rDataSeries, nPointIndex, fValue, false );
+ break;
+ }
+ case DataPointCustomLabelFieldType_CATEGORYNAME:
+ {
+ pTextList[i] = getCategoryName( nPointIndex );
+ break;
+ }
+ case DataPointCustomLabelFieldType_SERIESNAME:
+ {
+ OUString aRole;
+ if ( m_xChartTypeModel )
+ aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel();
+ const rtl::Reference< DataSeries >& xSeries( rDataSeries.getModel() );
+ pTextList[i] = xSeries->getLabelForRole( aRole );
+ break;
+ }
+ case DataPointCustomLabelFieldType_PERCENTAGE:
+ {
+ if(fSumValue == 0.0)
+ fSumValue = 1.0;
+ fValue /= fSumValue;
+ if(fValue < 0)
+ fValue *= -1.0;
+
+ pTextList[i] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, true);
+ break;
+ }
+ case DataPointCustomLabelFieldType_CELLRANGE:
+ {
+ if (aCustomLabels[i]->getDataLabelsRange())
+ pTextList[i] = aCustomLabels[i]->getString();
+ else
+ pTextList[i] = OUString();
+ break;
+ }
+ case DataPointCustomLabelFieldType_CELLREF:
+ {
+ // TODO: for now doesn't show placeholder
+ pTextList[i] = OUString();
+ break;
+ }
+ case DataPointCustomLabelFieldType_TEXT:
+ {
+ pTextList[i] = aCustomLabels[i]->getString();
+ break;
+ }
+ case DataPointCustomLabelFieldType_NEWLINE:
+ {
+ pTextList[i] = "\n";
+ break;
+ }
+ default:
+ break;
+ }
+ aCustomLabels[i]->setString( aTextList[i] );
+ }
+ }
+ else
+ {
+ auto pTextList = aTextList.getArray();
+ if( pLabel->ShowCategoryName )
+ {
+ pTextList[0] = getCategoryName( nPointIndex );
+ }
+
+ if( pLabel->ShowSeriesName )
+ {
+ OUString aRole;
+ if ( m_xChartTypeModel )
+ aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel();
+ const rtl::Reference< DataSeries >& xSeries( rDataSeries.getModel() );
+ pTextList[1] = xSeries->getLabelForRole( aRole );
+ }
+
+ if( pLabel->ShowNumber )
+ {
+ pTextList[2] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, false);
+ }
+
+ if( pLabel->ShowNumberInPercent )
+ {
+ if(fSumValue==0.0)
+ fSumValue=1.0;
+ fValue /= fSumValue;
+ if( fValue < 0 )
+ fValue*=-1.0;
+
+ pTextList[3] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, true);
+ }
+ }
+
+ for( auto const & line : std::as_const(aTextList) )
+ {
+ if( !line.isEmpty() )
+ {
+ ++nLineCountForSymbolsize;
+ }
+ }
+
+ //prepare properties for multipropertyset-interface of shape
+ tNameSequence* pPropNames;
+ tAnySequence* pPropValues;
+ if( !rDataSeries.getTextLabelMultiPropertyLists( nPointIndex, pPropNames, pPropValues ) )
+ return xTextShape;
+
+ // set text alignment for the text shape to be created.
+ LabelPositionHelper::changeTextAdjustment( *pPropValues, *pPropNames, eAlignment );
+
+ // check if data series entry percent value and absolute value have to
+ // be appended to the text label, and what should be the separator
+ // character (comma, space, new line). In case it is a new line we get
+ // a multi-line label.
+ bool bMultiLineLabel = ( aSeparator == "\n" );
+
+ if( bUseCustomLabel )
+ {
+ Sequence< uno::Reference< XFormattedString > > aFormattedLabels(
+ comphelper::containerToSequence<uno::Reference<XFormattedString>>(aCustomLabels));
+
+ // create text shape
+ xTextShape = ShapeFactory::
+ createText( xTarget_, aFormattedLabels, *pPropNames, *pPropValues,
+ ShapeFactory::makeTransformation( aScreenPosition2D ) );
+ }
+ else
+ {
+ // join text list elements
+ OUStringBuffer aText;
+ for( sal_uInt32 nN = 0; nN < nTextListLength; ++nN)
+ {
+ if( !aTextList[nN].isEmpty() )
+ {
+ if( !aText.isEmpty() )
+ {
+ aText.append(aSeparator);
+ }
+ aText.append( aTextList[nN] );
+ }
+ }
+
+ //create text shape
+ xTextShape = ShapeFactory::
+ createText( xTarget_, aText.makeStringAndClear(), *pPropNames, *pPropValues,
+ ShapeFactory::makeTransformation( aScreenPosition2D ) );
+ }
+
+ if( !xTextShape.is() )
+ return xTextShape;
+
+ // we need to use a default value for the maximum width property ?
+ if( nTextWidth == 0 && bTextWrap )
+ {
+ sal_Int32 nMinSize =
+ (m_aPageReferenceSize.Height < m_aPageReferenceSize.Width)
+ ? m_aPageReferenceSize.Height
+ : m_aPageReferenceSize.Width;
+ nTextWidth = nMinSize / 3;
+ }
+
+ // in case text must be wrapped set the maximum width property
+ // for the text shape
+ if( nTextWidth != 0 && bTextWrap )
+ {
+ // compute the height of a line of text
+ if( !bMultiLineLabel || nLineCountForSymbolsize <= 0 )
+ {
+ nLineCountForSymbolsize = 1;
+ }
+ awt::Size aTextSize = xTextShape->getSize();
+ sal_Int32 aTextLineHeight = aTextSize.Height / nLineCountForSymbolsize;
+
+ // set maximum text width
+ uno::Any aTextMaximumFrameWidth( nTextWidth );
+ xTextShape->SvxShape::setPropertyValue( "TextMaximumFrameWidth", aTextMaximumFrameWidth );
+
+ // compute the total lines of text
+ aTextSize = xTextShape->getSize();
+ nLineCountForSymbolsize = aTextSize.Height / aTextLineHeight;
+ }
+
+ // in case text is rotated, the transformation property of the text
+ // shape is modified.
+ if( fRotationDegrees != 0.0 )
+ {
+ const double fDegreesPi( -basegfx::deg2rad(fRotationDegrees) );
+ xTextShape->SvxShape::setPropertyValue( "Transformation", ShapeFactory::makeTransformation( aScreenPosition2D, fDegreesPi ) );
+ LabelPositionHelper::correctPositionForRotation( xTextShape, eAlignment, fRotationDegrees, true /*bRotateAroundCenter*/ );
+ }
+
+ awt::Point aTextShapePos(xTextShape->getPosition());
+ if( m_bPieLabelsAllowToMove && rDataSeries.isLabelCustomPos(nPointIndex) )
+ {
+ awt::Point aRelPos = rDataSeries.getLabelPosition(aTextShapePos, nPointIndex);
+ if( aRelPos.X != -1 )
+ {
+ xTextShape->setPosition(aRelPos);
+ if( !m_xChartTypeModel->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) &&
+ // "ShowCustomLeaderLines"
+ rDataSeries.getModel()->getFastPropertyValue( PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES ).get<sal_Bool>())
+ {
+ sal_Int32 nX1 = rScreenPosition2D.X;
+ sal_Int32 nY1 = rScreenPosition2D.Y;
+ sal_Int32 nX2 = nX1;
+ sal_Int32 nY2 = nY1;
+ ::basegfx::B2IRectangle aRect(BaseGFXHelper::makeRectangle(aRelPos, xTextShape->getSize()));
+ if (nX1 < aRelPos.X)
+ nX2 = aRelPos.X;
+ else if (nX1 > aRect.getMaxX())
+ nX2 = aRect.getMaxX();
+
+ if (nY1 < aRect.getMinY())
+ nY2 = aRect.getMinY();
+ else if (nY1 > aRect.getMaxY())
+ nY2 = aRect.getMaxY();
+
+ //when the line is very short compared to the page size don't create one
+ ::basegfx::B2DVector aLength(nX1 - nX2, nY1 - nY2);
+ double fPageDiagonaleLength
+ = std::hypot(m_aPageReferenceSize.Width, m_aPageReferenceSize.Height);
+ if ((aLength.getLength() / fPageDiagonaleLength) >= 0.01)
+ {
+ drawing::PointSequenceSequence aPoints{ { {nX1, nY1}, {nX2, nY2} } };
+
+ VLineProperties aVLineProperties;
+ ShapeFactory::createLine2D(xTarget, aPoints, &aVLineProperties);
+ }
+ }
+ }
+ }
+
+ // in case legend symbol has to be displayed, text shape position is
+ // slightly changed.
+ const awt::Point aUnrotatedTextPos(xTextShape->getPosition());
+ if( xSymbol.is() )
+ {
+ const awt::Point aOldTextPos( xTextShape->getPosition() );
+ awt::Point aNewTextPos( aOldTextPos );
+
+ awt::Point aSymbolPosition( aUnrotatedTextPos );
+ awt::Size aSymbolSize( xSymbol->getSize() );
+ awt::Size aTextSize = xTextShape->getSize();
+
+ sal_Int32 nXDiff = aSymbolSize.Width + static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.22 ) );//minimum 1mm
+ if( !bMultiLineLabel || nLineCountForSymbolsize <= 0 )
+ nLineCountForSymbolsize = 1;
+ aSymbolPosition.Y += ((aTextSize.Height/nLineCountForSymbolsize)/4);
+
+ if(eAlignment==LABEL_ALIGN_LEFT
+ || eAlignment==LABEL_ALIGN_LEFT_TOP
+ || eAlignment==LABEL_ALIGN_LEFT_BOTTOM)
+ {
+ aSymbolPosition.X -= nXDiff;
+ }
+ else if(eAlignment==LABEL_ALIGN_RIGHT
+ || eAlignment==LABEL_ALIGN_RIGHT_TOP
+ || eAlignment==LABEL_ALIGN_RIGHT_BOTTOM )
+ {
+ aNewTextPos.X += nXDiff;
+ }
+ else if(eAlignment==LABEL_ALIGN_TOP
+ || eAlignment==LABEL_ALIGN_BOTTOM
+ || eAlignment==LABEL_ALIGN_CENTER )
+ {
+ aSymbolPosition.X -= nXDiff/2;
+ aNewTextPos.X += nXDiff/2;
+ }
+
+ xSymbol->setPosition( aSymbolPosition );
+ xTextShape->setPosition( aNewTextPos );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ return xTextShape;
+}
+
+namespace
+{
+double lcl_getErrorBarLogicLength(
+ const uno::Sequence< double > & rData,
+ const uno::Reference< beans::XPropertySet >& xProp,
+ sal_Int32 nErrorBarStyle,
+ sal_Int32 nIndex,
+ bool bPositive,
+ bool bYError )
+{
+ double fResult = std::numeric_limits<double>::quiet_NaN();
+ try
+ {
+ switch( nErrorBarStyle )
+ {
+ case css::chart::ErrorBarStyle::NONE:
+ break;
+ case css::chart::ErrorBarStyle::VARIANCE:
+ fResult = StatisticsHelper::getVariance( rData );
+ break;
+ case css::chart::ErrorBarStyle::STANDARD_DEVIATION:
+ fResult = StatisticsHelper::getStandardDeviation( rData );
+ break;
+ case css::chart::ErrorBarStyle::RELATIVE:
+ {
+ double fPercent = 0;
+ if( xProp->getPropertyValue( bPositive
+ ? OUString("PositiveError")
+ : OUString("NegativeError") ) >>= fPercent )
+ {
+ if( nIndex >=0 && nIndex < rData.getLength() &&
+ ! std::isnan( rData[nIndex] ) &&
+ ! std::isnan( fPercent ))
+ {
+ fResult = rData[nIndex] * fPercent / 100.0;
+ }
+ }
+ }
+ break;
+ case css::chart::ErrorBarStyle::ABSOLUTE:
+ xProp->getPropertyValue( bPositive
+ ? OUString("PositiveError")
+ : OUString("NegativeError") ) >>= fResult;
+ break;
+ case css::chart::ErrorBarStyle::ERROR_MARGIN:
+ {
+ // todo: check if this is really what's called error-margin
+ double fPercent = 0;
+ if( xProp->getPropertyValue( bPositive
+ ? OUString("PositiveError")
+ : OUString("NegativeError") ) >>= fPercent )
+ {
+ double fMaxValue = -std::numeric_limits<double>::infinity();
+ for(double d : rData)
+ {
+ if(fMaxValue < d)
+ fMaxValue = d;
+ }
+ if( std::isfinite( fMaxValue ) &&
+ std::isfinite( fPercent ))
+ {
+ fResult = fMaxValue * fPercent / 100.0;
+ }
+ }
+ }
+ break;
+ case css::chart::ErrorBarStyle::STANDARD_ERROR:
+ fResult = StatisticsHelper::getStandardError( rData );
+ break;
+ case css::chart::ErrorBarStyle::FROM_DATA:
+ {
+ uno::Reference< chart2::data::XDataSource > xErrorBarData( xProp, uno::UNO_QUERY );
+ if( xErrorBarData.is())
+ fResult = StatisticsHelper::getErrorFromDataSource(
+ xErrorBarData, nIndex, bPositive, bYError);
+ }
+ break;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ return fResult;
+}
+
+void lcl_AddErrorBottomLine( const drawing::Position3D& rPosition, ::basegfx::B2DVector aMainDirection
+ , std::vector<std::vector<css::drawing::Position3D>>& rPoly, sal_Int32 nSequenceIndex )
+{
+ double fFixedWidth = 200.0;
+
+ aMainDirection.normalize();
+ ::basegfx::B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
+ aOrthoDirection.normalize();
+
+ ::basegfx::B2DVector aAnchor( rPosition.PositionX, rPosition.PositionY );
+ ::basegfx::B2DVector aStart = aAnchor + aOrthoDirection*fFixedWidth/2.0;
+ ::basegfx::B2DVector aEnd = aAnchor - aOrthoDirection*fFixedWidth/2.0;
+
+ AddPointToPoly( rPoly, drawing::Position3D( aStart.getX(), aStart.getY(), rPosition.PositionZ), nSequenceIndex );
+ AddPointToPoly( rPoly, drawing::Position3D( aEnd.getX(), aEnd.getY(), rPosition.PositionZ), nSequenceIndex );
+}
+
+::basegfx::B2DVector lcl_getErrorBarMainDirection(
+ const drawing::Position3D& rStart
+ , const drawing::Position3D& rBottomEnd
+ , PlottingPositionHelper const * pPosHelper
+ , const drawing::Position3D& rUnscaledLogicPosition
+ , bool bYError )
+{
+ ::basegfx::B2DVector aMainDirection( rStart.PositionX - rBottomEnd.PositionX
+ , rStart.PositionY - rBottomEnd.PositionY );
+ if( !aMainDirection.getLength() )
+ {
+ //get logic clip values:
+ double MinX = pPosHelper->getLogicMinX();
+ double MinY = pPosHelper->getLogicMinY();
+ double MaxX = pPosHelper->getLogicMaxX();
+ double MaxY = pPosHelper->getLogicMaxY();
+ double fZ = pPosHelper->getLogicMinZ();
+
+ if( bYError )
+ {
+ //main direction has constant x value
+ MinX = rUnscaledLogicPosition.PositionX;
+ MaxX = rUnscaledLogicPosition.PositionX;
+ }
+ else
+ {
+ //main direction has constant y value
+ MinY = rUnscaledLogicPosition.PositionY;
+ MaxY = rUnscaledLogicPosition.PositionY;
+ }
+
+ drawing::Position3D aStart = pPosHelper->transformLogicToScene( MinX, MinY, fZ, false );
+ drawing::Position3D aEnd = pPosHelper->transformLogicToScene( MaxX, MaxY, fZ, false );
+
+ aMainDirection = ::basegfx::B2DVector( aStart.PositionX - aEnd.PositionX
+ , aStart.PositionY - aEnd.PositionY );
+ }
+ if( !aMainDirection.getLength() )
+ {
+ //@todo
+ }
+ return aMainDirection;
+}
+
+drawing::Position3D lcl_transformMixedToScene( PlottingPositionHelper const * pPosHelper
+ , double fX /*scaled*/, double fY /*unscaled*/, double fZ /*unscaled*/ )
+{
+ if(!pPosHelper)
+ return drawing::Position3D(0,0,0);
+ pPosHelper->doLogicScaling( nullptr,&fY,&fZ );
+ pPosHelper->clipScaledLogicValues( &fX,&fY,&fZ );
+ return pPosHelper->transformScaledLogicToScene( fX, fY, fZ, false );
+}
+
+} // anonymous namespace
+
+void VSeriesPlotter::createErrorBar(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rUnscaledLogicPosition
+ , const uno::Reference< beans::XPropertySet > & xErrorBarProperties
+ , const VDataSeries& rVDataSeries
+ , sal_Int32 nIndex
+ , bool bYError /* = true */
+ , const double* pfScaledLogicX
+ )
+{
+ if( !ChartTypeHelper::isSupportingStatisticProperties( m_xChartTypeModel, m_nDimension ) )
+ return;
+
+ if( ! xErrorBarProperties.is())
+ return;
+
+ try
+ {
+ bool bShowPositive = false;
+ bool bShowNegative = false;
+ sal_Int32 nErrorBarStyle = css::chart::ErrorBarStyle::VARIANCE;
+
+ xErrorBarProperties->getPropertyValue( "ShowPositiveError") >>= bShowPositive;
+ xErrorBarProperties->getPropertyValue( "ShowNegativeError") >>= bShowNegative;
+ xErrorBarProperties->getPropertyValue( "ErrorBarStyle") >>= nErrorBarStyle;
+
+ if(!bShowPositive && !bShowNegative)
+ return;
+
+ if(nErrorBarStyle==css::chart::ErrorBarStyle::NONE)
+ return;
+
+ if (!m_pPosHelper)
+ return;
+
+ drawing::Position3D aUnscaledLogicPosition(rUnscaledLogicPosition);
+ if(nErrorBarStyle==css::chart::ErrorBarStyle::STANDARD_DEVIATION)
+ {
+ if (bYError)
+ aUnscaledLogicPosition.PositionY = rVDataSeries.getYMeanValue();
+ else
+ aUnscaledLogicPosition.PositionX = rVDataSeries.getXMeanValue();
+ }
+
+ bool bCreateNegativeBorder = false;//make a vertical line at the negative end of the error bar
+ bool bCreatePositiveBorder = false;//make a vertical line at the positive end of the error bar
+ drawing::Position3D aMiddle(aUnscaledLogicPosition);
+ const double fX = aUnscaledLogicPosition.PositionX;
+ const double fY = aUnscaledLogicPosition.PositionY;
+ const double fZ = aUnscaledLogicPosition.PositionZ;
+ double fScaledX = fX;
+ if( pfScaledLogicX )
+ fScaledX = *pfScaledLogicX;
+ else
+ m_pPosHelper->doLogicScaling( &fScaledX, nullptr, nullptr );
+
+ aMiddle = lcl_transformMixedToScene( m_pPosHelper, fScaledX, fY, fZ );
+
+ drawing::Position3D aNegative(aMiddle);
+ drawing::Position3D aPositive(aMiddle);
+
+ uno::Sequence< double > aData( bYError ? rVDataSeries.getAllY() : rVDataSeries.getAllX() );
+
+ if( bShowPositive )
+ {
+ double fLength = lcl_getErrorBarLogicLength( aData, xErrorBarProperties, nErrorBarStyle, nIndex, true, bYError );
+ if( std::isfinite( fLength ) )
+ {
+ double fLocalX = fX;
+ double fLocalY = fY;
+ if( bYError )
+ {
+ fLocalY+=fLength;
+ aPositive = lcl_transformMixedToScene( m_pPosHelper, fScaledX, fLocalY, fZ );
+ }
+ else
+ {
+ fLocalX+=fLength;
+ aPositive = m_pPosHelper->transformLogicToScene( fLocalX, fLocalY, fZ, true );
+ }
+ bCreatePositiveBorder = m_pPosHelper->isLogicVisible(fLocalX, fLocalY, fZ);
+ }
+ else
+ bShowPositive = false;
+ }
+
+ if( bShowNegative )
+ {
+ double fLength = lcl_getErrorBarLogicLength( aData, xErrorBarProperties, nErrorBarStyle, nIndex, false, bYError );
+ if( std::isfinite( fLength ) )
+ {
+ double fLocalX = fX;
+ double fLocalY = fY;
+ if( bYError )
+ {
+ fLocalY-=fLength;
+ aNegative = lcl_transformMixedToScene( m_pPosHelper, fScaledX, fLocalY, fZ );
+ }
+ else
+ {
+ fLocalX-=fLength;
+ aNegative = m_pPosHelper->transformLogicToScene( fLocalX, fLocalY, fZ, true );
+ }
+ if (std::isfinite(aNegative.PositionX) &&
+ std::isfinite(aNegative.PositionY) &&
+ std::isfinite(aNegative.PositionZ)) {
+ bCreateNegativeBorder = m_pPosHelper->isLogicVisible( fLocalX, fLocalY, fZ);
+ } else {
+ // If error bars result in a numerical problem (e.g., an
+ // error bar on a logarithmic chart that results in a point
+ // <= 0) then just turn off the error bar.
+ //
+ // TODO: This perhaps should display a warning, so the user
+ // knows why a bar is not appearing.
+ // TODO: This test could also be added to the positive case,
+ // though a numerical overflow there is less likely.
+ bShowNegative = false;
+ }
+ }
+ else
+ bShowNegative = false;
+ }
+
+ if(!bShowPositive && !bShowNegative)
+ return;
+
+ std::vector<std::vector<css::drawing::Position3D>> aPoly;
+
+ sal_Int32 nSequenceIndex=0;
+ if( bShowNegative )
+ AddPointToPoly( aPoly, aNegative, nSequenceIndex );
+ AddPointToPoly( aPoly, aMiddle, nSequenceIndex );
+ if( bShowPositive )
+ AddPointToPoly( aPoly, aPositive, nSequenceIndex );
+
+ if( bShowNegative && bCreateNegativeBorder )
+ {
+ ::basegfx::B2DVector aMainDirection = lcl_getErrorBarMainDirection( aMiddle, aNegative, m_pPosHelper, aUnscaledLogicPosition, bYError );
+ nSequenceIndex++;
+ lcl_AddErrorBottomLine( aNegative, aMainDirection, aPoly, nSequenceIndex );
+ }
+ if( bShowPositive && bCreatePositiveBorder )
+ {
+ ::basegfx::B2DVector aMainDirection = lcl_getErrorBarMainDirection( aMiddle, aPositive, m_pPosHelper, aUnscaledLogicPosition, bYError );
+ nSequenceIndex++;
+ lcl_AddErrorBottomLine( aPositive, aMainDirection, aPoly, nSequenceIndex );
+ }
+
+ rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D( xTarget, aPoly );
+ PropertyMapper::setMappedProperties( *xShape, xErrorBarProperties, PropertyMapper::getPropertyNameMapForLineProperties() );
+ }
+ catch( const uno::Exception & )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+}
+
+void VSeriesPlotter::addErrorBorder(
+ const drawing::Position3D& rPos0
+ ,const drawing::Position3D& rPos1
+ ,const rtl::Reference<SvxShapeGroupAnyD>& rTarget
+ ,const uno::Reference< beans::XPropertySet >& rErrorBorderProp )
+{
+ std::vector<std::vector<css::drawing::Position3D>> aPoly { { rPos0, rPos1} };
+ rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D(
+ rTarget, aPoly );
+ PropertyMapper::setMappedProperties( *xShape, rErrorBorderProp,
+ PropertyMapper::getPropertyNameMapForLineProperties() );
+}
+
+void VSeriesPlotter::createErrorRectangle(
+ const drawing::Position3D& rUnscaledLogicPosition
+ ,VDataSeries& rVDataSeries
+ ,sal_Int32 nIndex
+ ,const rtl::Reference<SvxShapeGroupAnyD>& rTarget
+ ,bool bUseXErrorData
+ ,bool bUseYErrorData )
+{
+ if ( m_nDimension != 2 )
+ return;
+
+ // error border properties
+ Reference< beans::XPropertySet > xErrorBorderPropX, xErrorBorderPropY;
+ if ( bUseXErrorData )
+ {
+ xErrorBorderPropX = rVDataSeries.getXErrorBarProperties( nIndex );
+ if ( !xErrorBorderPropX.is() )
+ return;
+ }
+ rtl::Reference<SvxShapeGroupAnyD> xErrorBorder_ShapesX =
+ getErrorBarsGroupShape( rVDataSeries, rTarget, false );
+
+ if ( bUseYErrorData )
+ {
+ xErrorBorderPropY = rVDataSeries.getYErrorBarProperties( nIndex );
+ if ( !xErrorBorderPropY.is() )
+ return;
+ }
+ rtl::Reference<SvxShapeGroupAnyD> xErrorBorder_ShapesY =
+ getErrorBarsGroupShape( rVDataSeries, rTarget, true );
+
+ if( !ChartTypeHelper::isSupportingStatisticProperties( m_xChartTypeModel, m_nDimension ) )
+ return;
+
+ try
+ {
+ bool bShowXPositive = false;
+ bool bShowXNegative = false;
+ bool bShowYPositive = false;
+ bool bShowYNegative = false;
+
+ sal_Int32 nErrorBorderStyleX = css::chart::ErrorBarStyle::VARIANCE;
+ sal_Int32 nErrorBorderStyleY = css::chart::ErrorBarStyle::VARIANCE;
+
+ if ( bUseXErrorData )
+ {
+ xErrorBorderPropX->getPropertyValue( "ErrorBarStyle" ) >>= nErrorBorderStyleX;
+ xErrorBorderPropX->getPropertyValue( "ShowPositiveError") >>= bShowXPositive;
+ xErrorBorderPropX->getPropertyValue( "ShowNegativeError") >>= bShowXNegative;
+ }
+ if ( bUseYErrorData )
+ {
+ xErrorBorderPropY->getPropertyValue( "ErrorBarStyle" ) >>= nErrorBorderStyleY;
+ xErrorBorderPropY->getPropertyValue( "ShowPositiveError") >>= bShowYPositive;
+ xErrorBorderPropY->getPropertyValue( "ShowNegativeError") >>= bShowYNegative;
+ }
+
+ if ( bUseXErrorData && nErrorBorderStyleX == css::chart::ErrorBarStyle::NONE )
+ bUseXErrorData = false;
+ if ( bUseYErrorData && nErrorBorderStyleY == css::chart::ErrorBarStyle::NONE )
+ bUseYErrorData = false;
+
+ if ( !bShowXPositive && !bShowXNegative && !bShowYPositive && !bShowYNegative )
+ return;
+
+ if ( !m_pPosHelper )
+ return;
+
+ drawing::Position3D aUnscaledLogicPosition( rUnscaledLogicPosition );
+ if ( bUseXErrorData && nErrorBorderStyleX == css::chart::ErrorBarStyle::STANDARD_DEVIATION )
+ aUnscaledLogicPosition.PositionX = rVDataSeries.getXMeanValue();
+ if ( bUseYErrorData && nErrorBorderStyleY == css::chart::ErrorBarStyle::STANDARD_DEVIATION )
+ aUnscaledLogicPosition.PositionY = rVDataSeries.getYMeanValue();
+
+ const double fX = aUnscaledLogicPosition.PositionX;
+ const double fY = aUnscaledLogicPosition.PositionY;
+ const double fZ = aUnscaledLogicPosition.PositionZ;
+ double fScaledX = fX;
+ m_pPosHelper->doLogicScaling( &fScaledX, nullptr, nullptr );
+
+ uno::Sequence< double > aDataX( rVDataSeries.getAllX() );
+ uno::Sequence< double > aDataY( rVDataSeries.getAllY() );
+
+ double fPosX = 0.0;
+ double fPosY = 0.0;
+ double fNegX = 0.0;
+ double fNegY = 0.0;
+ if ( bUseXErrorData )
+ {
+ if ( bShowXPositive )
+ fPosX = lcl_getErrorBarLogicLength( aDataX, xErrorBorderPropX,
+ nErrorBorderStyleX, nIndex, true, false );
+ if ( bShowXNegative )
+ fNegX = lcl_getErrorBarLogicLength( aDataX, xErrorBorderPropX,
+ nErrorBorderStyleX, nIndex, false, false );
+ }
+
+ if ( bUseYErrorData )
+ {
+ if ( bShowYPositive )
+ fPosY = lcl_getErrorBarLogicLength( aDataY, xErrorBorderPropY,
+ nErrorBorderStyleY, nIndex, true, true );
+ if ( bShowYNegative )
+ fNegY = lcl_getErrorBarLogicLength( aDataY, xErrorBorderPropY,
+ nErrorBorderStyleY, nIndex, false, true );
+ }
+
+ if ( !( std::isfinite( fPosX ) &&
+ std::isfinite( fPosY ) &&
+ std::isfinite( fNegX ) &&
+ std::isfinite( fNegY ) ) )
+ return;
+
+ drawing::Position3D aBottomLeft( lcl_transformMixedToScene( m_pPosHelper,
+ fX - fNegX, fY - fNegY, fZ ) );
+ drawing::Position3D aTopLeft( lcl_transformMixedToScene( m_pPosHelper,
+ fX - fNegX, fY + fPosY, fZ ) );
+ drawing::Position3D aTopRight( lcl_transformMixedToScene( m_pPosHelper,
+ fX + fPosX, fY + fPosY, fZ ) );
+ drawing::Position3D aBottomRight( lcl_transformMixedToScene( m_pPosHelper,
+ fX + fPosX, fY - fNegY, fZ ) );
+ if ( bUseXErrorData )
+ {
+ // top border
+ addErrorBorder( aTopLeft, aTopRight, xErrorBorder_ShapesX, xErrorBorderPropX );
+
+ // bottom border
+ addErrorBorder( aBottomRight, aBottomLeft, xErrorBorder_ShapesX, xErrorBorderPropX );
+ }
+
+ if ( bUseYErrorData )
+ {
+ // left border
+ addErrorBorder( aBottomLeft, aTopLeft, xErrorBorder_ShapesY, xErrorBorderPropY );
+
+ // right border
+ addErrorBorder( aTopRight, aBottomRight, xErrorBorder_ShapesY, xErrorBorderPropY );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2", "Exception in createErrorRectangle(). ");
+ }
+}
+
+void VSeriesPlotter::createErrorBar_X( const drawing::Position3D& rUnscaledLogicPosition
+ , VDataSeries& rVDataSeries, sal_Int32 nPointIndex
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
+{
+ if(m_nDimension!=2)
+ return;
+ // error bars
+ uno::Reference< beans::XPropertySet > xErrorBarProp(rVDataSeries.getXErrorBarProperties(nPointIndex));
+ if( xErrorBarProp.is())
+ {
+ rtl::Reference<SvxShapeGroupAnyD> xErrorBarsGroup_Shapes =
+ getErrorBarsGroupShape(rVDataSeries, xTarget, false);
+
+ createErrorBar( xErrorBarsGroup_Shapes
+ , rUnscaledLogicPosition, xErrorBarProp
+ , rVDataSeries, nPointIndex
+ , false /* bYError */
+ , nullptr );
+ }
+}
+
+void VSeriesPlotter::createErrorBar_Y( const drawing::Position3D& rUnscaledLogicPosition
+ , VDataSeries& rVDataSeries, sal_Int32 nPointIndex
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , double const * pfScaledLogicX )
+{
+ if(m_nDimension!=2)
+ return;
+ // error bars
+ uno::Reference< beans::XPropertySet > xErrorBarProp(rVDataSeries.getYErrorBarProperties(nPointIndex));
+ if( xErrorBarProp.is())
+ {
+ rtl::Reference<SvxShapeGroupAnyD> xErrorBarsGroup_Shapes =
+ getErrorBarsGroupShape(rVDataSeries, xTarget, true);
+
+ createErrorBar( xErrorBarsGroup_Shapes
+ , rUnscaledLogicPosition, xErrorBarProp
+ , rVDataSeries, nPointIndex
+ , true /* bYError */
+ , pfScaledLogicX );
+ }
+}
+
+void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries const & rVDataSeries,
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const rtl::Reference<SvxShapeGroupAnyD>& xEquationTarget,
+ bool bMaySkipPoints )
+{
+ if(m_nDimension!=2)
+ return;
+ rtl::Reference< DataSeries > xContainer( rVDataSeries.getModel() );
+ if(!xContainer.is())
+ return;
+
+ if (!m_pPosHelper)
+ return;
+
+ const std::vector< rtl::Reference< ::chart::RegressionCurveModel > > & aCurveList = xContainer->getRegressionCurves2();
+
+ for(std::size_t nN=0; nN<aCurveList.size(); nN++)
+ {
+ const auto & rCurve = aCurveList[nN];
+ uno::Reference< XRegressionCurveCalculator > xCalculator( rCurve->getCalculator() );
+ if( !xCalculator.is())
+ continue;
+
+ bool bAverageLine = RegressionCurveHelper::isMeanValueLine( rCurve );
+
+ sal_Int32 aDegree = 2;
+ sal_Int32 aPeriod = 2;
+ sal_Int32 aMovingAverageType = css::chart2::MovingAverageType::Prior;
+ double aExtrapolateForward = 0.0;
+ double aExtrapolateBackward = 0.0;
+ bool bForceIntercept = false;
+ double aInterceptValue = 0.0;
+
+ if ( !bAverageLine )
+ {
+ rCurve->getPropertyValue( "PolynomialDegree") >>= aDegree;
+ rCurve->getPropertyValue( "MovingAveragePeriod") >>= aPeriod;
+ rCurve->getPropertyValue( "MovingAverageType") >>= aMovingAverageType;
+ rCurve->getPropertyValue( "ExtrapolateForward") >>= aExtrapolateForward;
+ rCurve->getPropertyValue( "ExtrapolateBackward") >>= aExtrapolateBackward;
+ rCurve->getPropertyValue( "ForceIntercept") >>= bForceIntercept;
+ if (bForceIntercept)
+ rCurve->getPropertyValue( "InterceptValue") >>= aInterceptValue;
+ }
+
+ double fChartMinX = m_pPosHelper->getLogicMinX();
+ double fChartMaxX = m_pPosHelper->getLogicMaxX();
+
+ double fMinX = fChartMinX;
+ double fMaxX = fChartMaxX;
+
+ double fPointScale = 1.0;
+
+ if( !bAverageLine )
+ {
+ rVDataSeries.getMinMaxXValue(fMinX, fMaxX);
+ fMaxX += aExtrapolateForward;
+ fMinX -= aExtrapolateBackward;
+
+ fPointScale = (fMaxX - fMinX) / (fChartMaxX - fChartMinX);
+ // sanitize the value, tdf#119922
+ fPointScale = std::min(fPointScale, 1000.0);
+ }
+
+ xCalculator->setRegressionProperties(aDegree, bForceIntercept, aInterceptValue, aPeriod,
+ aMovingAverageType);
+ xCalculator->recalculateRegression(rVDataSeries.getAllX(), rVDataSeries.getAllY());
+ sal_Int32 nPointCount = 100 * fPointScale;
+
+ if ( nPointCount < 2 )
+ nPointCount = 2;
+
+ std::vector< ExplicitScaleData > aScales( m_pPosHelper->getScales());
+ uno::Reference< chart2::XScaling > xScalingX;
+ uno::Reference< chart2::XScaling > xScalingY;
+ if( aScales.size() >= 2 )
+ {
+ xScalingX.set( aScales[0].Scaling );
+ xScalingY.set( aScales[1].Scaling );
+ }
+
+ const uno::Sequence< geometry::RealPoint2D > aCalculatedPoints(
+ xCalculator->getCurveValues(
+ fMinX, fMaxX, nPointCount,
+ xScalingX, xScalingY, bMaySkipPoints ));
+
+ nPointCount = aCalculatedPoints.getLength();
+
+ drawing::PolyPolygonShape3D aRegressionPoly;
+ aRegressionPoly.SequenceX.realloc(1);
+ aRegressionPoly.SequenceY.realloc(1);
+ aRegressionPoly.SequenceZ.realloc(1);
+ auto pSequenceX = aRegressionPoly.SequenceX.getArray();
+ auto pSequenceY = aRegressionPoly.SequenceY.getArray();
+ auto pSequenceZ = aRegressionPoly.SequenceZ.getArray();
+ pSequenceX[0].realloc(nPointCount);
+ pSequenceY[0].realloc(nPointCount);
+ auto pSequenceX0 = pSequenceX[0].getArray();
+ auto pSequenceY0 = pSequenceY[0].getArray();
+
+ sal_Int32 nRealPointCount = 0;
+
+ for(geometry::RealPoint2D const & p : aCalculatedPoints)
+ {
+ double fLogicX = p.X;
+ double fLogicY = p.Y;
+ double fLogicZ = 0.0; //dummy
+
+ // fdo#51656: don't scale mean value lines
+ if(!bAverageLine)
+ m_pPosHelper->doLogicScaling( &fLogicX, &fLogicY, &fLogicZ );
+
+ if(!std::isnan(fLogicX) && !std::isinf(fLogicX) &&
+ !std::isnan(fLogicY) && !std::isinf(fLogicY) &&
+ !std::isnan(fLogicZ) && !std::isinf(fLogicZ) )
+ {
+ pSequenceX0[nRealPointCount] = fLogicX;
+ pSequenceY0[nRealPointCount] = fLogicY;
+ nRealPointCount++;
+ }
+ }
+ pSequenceX[0].realloc(nRealPointCount);
+ pSequenceY[0].realloc(nRealPointCount);
+ pSequenceZ[0].realloc(nRealPointCount);
+
+ drawing::PolyPolygonShape3D aClippedPoly;
+ Clipping::clipPolygonAtRectangle( aRegressionPoly, m_pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly );
+ aRegressionPoly = aClippedPoly;
+ m_pPosHelper->transformScaledLogicToScene( aRegressionPoly );
+
+ awt::Point aDefaultPos;
+ if( aRegressionPoly.SequenceX.hasElements() && aRegressionPoly.SequenceX[0].hasElements() )
+ {
+ VLineProperties aVLineProperties;
+ aVLineProperties.initFromPropertySet( rCurve );
+
+ //create an extra group shape for each curve for selection handling
+ rtl::Reference<SvxShapeGroupAnyD> xRegressionGroupShapes =
+ createGroupShape( xTarget, rVDataSeries.getDataCurveCID( nN, bAverageLine ) );
+ rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D(
+ xRegressionGroupShapes, PolyToPointSequence( aRegressionPoly ), &aVLineProperties );
+ ShapeFactory::setShapeName( xShape, "MarkHandles" );
+ aDefaultPos = xShape->getPosition();
+ }
+
+ // curve equation and correlation coefficient
+ uno::Reference< beans::XPropertySet > xEquationProperties( rCurve->getEquationProperties());
+ if( xEquationProperties.is())
+ {
+ createRegressionCurveEquationShapes(
+ rVDataSeries.getDataCurveEquationCID( nN ),
+ xEquationProperties, xEquationTarget, xCalculator,
+ aDefaultPos );
+ }
+ }
+}
+
+static sal_Int32 lcl_getOUStringMaxLineLength ( OUStringBuffer const & aString )
+{
+ const sal_Int32 nStringLength = aString.getLength();
+ sal_Int32 nMaxLineLength = 0;
+
+ for ( sal_Int32 i=0; i<nStringLength; i++ )
+ {
+ sal_Int32 indexSep = aString.indexOf( "\n", i );
+ if ( indexSep < 0 )
+ indexSep = nStringLength;
+ sal_Int32 nLineLength = indexSep - i;
+ if ( nLineLength > nMaxLineLength )
+ nMaxLineLength = nLineLength;
+ i = indexSep;
+ }
+
+ return nMaxLineLength;
+}
+
+void VSeriesPlotter::createRegressionCurveEquationShapes(
+ const OUString & rEquationCID,
+ const uno::Reference< beans::XPropertySet > & xEquationProperties,
+ const rtl::Reference<SvxShapeGroupAnyD>& xEquationTarget,
+ const uno::Reference< chart2::XRegressionCurveCalculator > & xRegressionCurveCalculator,
+ awt::Point aDefaultPos )
+{
+ OSL_ASSERT( xEquationProperties.is());
+ if( !xEquationProperties.is())
+ return;
+
+ bool bShowEquation = false;
+ bool bShowCorrCoeff = false;
+ if(!(( xEquationProperties->getPropertyValue( "ShowEquation") >>= bShowEquation ) &&
+ ( xEquationProperties->getPropertyValue( "ShowCorrelationCoefficient") >>= bShowCorrCoeff )))
+ return;
+
+ if( ! (bShowEquation || bShowCorrCoeff))
+ return;
+
+ OUStringBuffer aFormula;
+ sal_Int32 nNumberFormatKey = 0;
+ sal_Int32 nFormulaWidth = 0;
+ xEquationProperties->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nNumberFormatKey;
+ bool bResizeEquation = true;
+ sal_Int32 nMaxIteration = 2;
+ if ( bShowEquation )
+ {
+ OUString aXName, aYName;
+ if ( !(xEquationProperties->getPropertyValue( "XName" ) >>= aXName) )
+ aXName = OUString( "x" );
+ if ( !(xEquationProperties->getPropertyValue( "YName" ) >>= aYName) )
+ aYName = OUString( "f(x)" );
+ xRegressionCurveCalculator->setXYNames( aXName, aYName );
+ }
+
+ for ( sal_Int32 nCountIteration = 0; bResizeEquation && nCountIteration < nMaxIteration ; nCountIteration++ )
+ {
+ bResizeEquation = false;
+ if( bShowEquation )
+ {
+ if (m_apNumberFormatterWrapper)
+ { // iteration 0: default representation (no wrap)
+ // iteration 1: expected width (nFormulaWidth) is calculated
+ aFormula = xRegressionCurveCalculator->getFormattedRepresentation(
+ m_apNumberFormatterWrapper->getNumberFormatsSupplier(),
+ nNumberFormatKey, nFormulaWidth );
+ nFormulaWidth = lcl_getOUStringMaxLineLength( aFormula );
+ }
+ else
+ {
+ aFormula = xRegressionCurveCalculator->getRepresentation();
+ }
+
+ if( bShowCorrCoeff )
+ {
+ aFormula.append( "\n" );
+ }
+ }
+ if( bShowCorrCoeff )
+ {
+ aFormula.append( "R" + OUStringChar( aSuperscriptFigures[2] ) + " = " );
+ double fR( xRegressionCurveCalculator->getCorrelationCoefficient());
+ if (m_apNumberFormatterWrapper)
+ {
+ Color nLabelCol;
+ bool bColChanged;
+ aFormula.append(
+ m_apNumberFormatterWrapper->getFormattedString(
+ nNumberFormatKey, fR*fR, nLabelCol, bColChanged ));
+ //@todo: change color of label if bColChanged is true
+ }
+ else
+ {
+ const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
+ const OUString& aNumDecimalSep = rLocaleDataWrapper.getNumDecimalSep();
+ sal_Unicode aDecimalSep = aNumDecimalSep[0];
+ aFormula.append( ::rtl::math::doubleToUString(
+ fR*fR, rtl_math_StringFormat_G, 4, aDecimalSep, true ));
+ }
+ }
+
+ awt::Point aScreenPosition2D;
+ chart2::RelativePosition aRelativePosition;
+ if( xEquationProperties->getPropertyValue( "RelativePosition") >>= aRelativePosition )
+ {
+ //@todo decide whether x is primary or secondary
+ double fX = aRelativePosition.Primary*m_aPageReferenceSize.Width;
+ double fY = aRelativePosition.Secondary*m_aPageReferenceSize.Height;
+ aScreenPosition2D.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
+ aScreenPosition2D.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
+ }
+ else
+ aScreenPosition2D = aDefaultPos;
+
+ if( !aFormula.isEmpty())
+ {
+ // set fill and line properties on creation
+ tNameSequence aNames;
+ tAnySequence aValues;
+ PropertyMapper::getPreparedTextShapePropertyLists( xEquationProperties, aNames, aValues );
+
+ rtl::Reference<SvxShapeText> xTextShape = ShapeFactory::createText(
+ xEquationTarget, aFormula.makeStringAndClear(),
+ aNames, aValues, ShapeFactory::makeTransformation( aScreenPosition2D ));
+
+ ShapeFactory::setShapeName( xTextShape, rEquationCID );
+ awt::Size aSize( xTextShape->getSize() );
+ awt::Point aPos( RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
+ aScreenPosition2D, aSize, aRelativePosition.Anchor ) );
+ //ensure that the equation is fully placed within the page (if possible)
+ if( (aPos.X + aSize.Width) > m_aPageReferenceSize.Width )
+ aPos.X = m_aPageReferenceSize.Width - aSize.Width;
+ if( aPos.X < 0 )
+ {
+ aPos.X = 0;
+ if ( nFormulaWidth > 0 )
+ {
+ bResizeEquation = true;
+ if ( nCountIteration < nMaxIteration-1 )
+ xEquationTarget->remove( xTextShape ); // remove equation
+ nFormulaWidth *= m_aPageReferenceSize.Width / static_cast< double >(aSize.Width);
+ nFormulaWidth -= nCountIteration;
+ if ( nFormulaWidth < 0 )
+ nFormulaWidth = 0;
+ }
+ }
+ if( (aPos.Y + aSize.Height) > m_aPageReferenceSize.Height )
+ aPos.Y = m_aPageReferenceSize.Height - aSize.Height;
+ if( aPos.Y < 0 )
+ aPos.Y = 0;
+ if ( !bResizeEquation || nCountIteration == nMaxIteration-1 )
+ xTextShape->setPosition(aPos); // if equation was not removed
+ }
+ }
+}
+
+void VSeriesPlotter::setTimeResolutionOnXAxis( tools::Long TimeResolution, const Date& rNullDate )
+{
+ m_nTimeResolution = TimeResolution;
+ m_aNullDate = rNullDate;
+}
+
+// MinimumAndMaximumSupplier
+tools::Long VSeriesPlotter::calculateTimeResolutionOnXAxis()
+{
+ tools::Long nRet = css::chart::TimeUnit::YEAR;
+ if (!m_pExplicitCategoriesProvider)
+ return nRet;
+
+ const std::vector<double>& rDateCategories = m_pExplicitCategoriesProvider->getDateCategories();
+ if (rDateCategories.empty())
+ return nRet;
+
+ std::vector<double>::const_iterator aIt = rDateCategories.begin(), aEnd = rDateCategories.end();
+
+ aIt = std::find_if(aIt, aEnd, [](const double& rDateCategory) { return !std::isnan(rDateCategory); });
+ if (aIt == aEnd)
+ return nRet;
+
+ Date aNullDate(30,12,1899);
+ if (m_apNumberFormatterWrapper)
+ aNullDate = m_apNumberFormatterWrapper->getNullDate();
+
+ Date aPrevious(aNullDate); aPrevious.AddDays(rtl::math::approxFloor(*aIt));
+ ++aIt;
+ for(;aIt!=aEnd;++aIt)
+ {
+ if (std::isnan(*aIt))
+ continue;
+
+ Date aCurrent(aNullDate); aCurrent.AddDays(rtl::math::approxFloor(*aIt));
+ if( nRet == css::chart::TimeUnit::YEAR )
+ {
+ if( DateHelper::IsInSameYear( aPrevious, aCurrent ) )
+ nRet = css::chart::TimeUnit::MONTH;
+ }
+ if( nRet == css::chart::TimeUnit::MONTH )
+ {
+ if( DateHelper::IsInSameMonth( aPrevious, aCurrent ) )
+ nRet = css::chart::TimeUnit::DAY;
+ }
+ if( nRet == css::chart::TimeUnit::DAY )
+ break;
+ aPrevious=aCurrent;
+ }
+
+ return nRet;
+}
+double VSeriesPlotter::getMinimumX()
+{
+ double fMinimum, fMaximum;
+ getMinimumAndMaximumX( fMinimum, fMaximum );
+ return fMinimum;
+}
+double VSeriesPlotter::getMaximumX()
+{
+ double fMinimum, fMaximum;
+ getMinimumAndMaximumX( fMinimum, fMaximum );
+ return fMaximum;
+}
+
+double VSeriesPlotter::getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex )
+{
+ if( !m_bCategoryXAxis || ( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() ) )
+ {
+ double fMinY, fMaxY;
+ getMinimumAndMaximumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex );
+ return fMinY;
+ }
+
+ double fMinimum = std::numeric_limits<double>::infinity();
+ double fMaximum = -std::numeric_limits<double>::infinity();
+ for(std::vector<VDataSeriesGroup> & rXSlots : m_aZSlots)
+ {
+ for(VDataSeriesGroup & rXSlot : rXSlots)
+ {
+ double fLocalMinimum, fLocalMaximum;
+ rXSlot.calculateYMinAndMaxForCategoryRange(
+ static_cast<sal_Int32>(fMinimumX-1.0) //first category (index 0) matches with real number 1.0
+ , static_cast<sal_Int32>(fMaximumX-1.0) //first category (index 0) matches with real number 1.0
+ , isSeparateStackingForDifferentSigns( 1 )
+ , fLocalMinimum, fLocalMaximum, nAxisIndex );
+ if(fMaximum<fLocalMaximum)
+ fMaximum=fLocalMaximum;
+ if(fMinimum>fLocalMinimum)
+ fMinimum=fLocalMinimum;
+ }
+ }
+ if(std::isinf(fMinimum))
+ return std::numeric_limits<double>::quiet_NaN();
+ return fMinimum;
+}
+
+double VSeriesPlotter::getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex )
+{
+ if( !m_bCategoryXAxis || ( m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis() ) )
+ {
+ double fMinY, fMaxY;
+ getMinimumAndMaximumYInContinuousXRange( fMinY, fMaxY, fMinimumX, fMaximumX, nAxisIndex );
+ return fMaxY;
+ }
+
+ double fMinimum = std::numeric_limits<double>::infinity();
+ double fMaximum = -std::numeric_limits<double>::infinity();
+ for( std::vector< VDataSeriesGroup > & rXSlots : m_aZSlots)
+ {
+ for(VDataSeriesGroup & rXSlot : rXSlots)
+ {
+ double fLocalMinimum, fLocalMaximum;
+ rXSlot.calculateYMinAndMaxForCategoryRange(
+ static_cast<sal_Int32>(fMinimumX-1.0) //first category (index 0) matches with real number 1.0
+ , static_cast<sal_Int32>(fMaximumX-1.0) //first category (index 0) matches with real number 1.0
+ , isSeparateStackingForDifferentSigns( 1 )
+ , fLocalMinimum, fLocalMaximum, nAxisIndex );
+ if(fMaximum<fLocalMaximum)
+ fMaximum=fLocalMaximum;
+ if(fMinimum>fLocalMinimum)
+ fMinimum=fLocalMinimum;
+ }
+ }
+ if(std::isinf(fMaximum))
+ return std::numeric_limits<double>::quiet_NaN();
+ return fMaximum;
+}
+
+double VSeriesPlotter::getMinimumZ()
+{
+ //this is the default for all charts without a meaningful z axis
+ return 1.0;
+}
+double VSeriesPlotter::getMaximumZ()
+{
+ if( m_nDimension!=3 || m_aZSlots.empty() )
+ return getMinimumZ()+1;
+ return m_aZSlots.size();
+}
+
+namespace
+{
+ bool lcl_isValueAxis( sal_Int32 nDimensionIndex, bool bCategoryXAxis )
+ {
+ // default implementation: true for Y axes, and for value X axis
+ if( nDimensionIndex == 0 )
+ return !bCategoryXAxis;
+ return nDimensionIndex == 1;
+ }
+}
+
+bool VSeriesPlotter::isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex )
+{
+ return lcl_isValueAxis( nDimensionIndex, m_bCategoryXAxis );
+}
+
+bool VSeriesPlotter::isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex )
+{
+ // do not expand axes in 3D charts
+ return (m_nDimension < 3) && lcl_isValueAxis( nDimensionIndex, m_bCategoryXAxis );
+}
+
+bool VSeriesPlotter::isExpandWideValuesToZero( sal_Int32 nDimensionIndex )
+{
+ // default implementation: only for Y axis
+ return nDimensionIndex == 1;
+}
+
+bool VSeriesPlotter::isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex )
+{
+ // default implementation: only for Y axis
+ return nDimensionIndex == 1;
+}
+
+bool VSeriesPlotter::isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex )
+{
+ // default implementation: only for Y axis
+ return nDimensionIndex == 1;
+}
+
+void VSeriesPlotter::getMinimumAndMaximumX( double& rfMinimum, double& rfMaximum ) const
+{
+ rfMinimum = std::numeric_limits<double>::infinity();
+ rfMaximum = -std::numeric_limits<double>::infinity();
+
+ for (auto const& ZSlot : m_aZSlots)
+ {
+ for (auto const& XSlot : ZSlot)
+ {
+ double fLocalMinimum, fLocalMaximum;
+ XSlot.getMinimumAndMaximumX( fLocalMinimum, fLocalMaximum );
+ if( !std::isnan(fLocalMinimum) && fLocalMinimum< rfMinimum )
+ rfMinimum = fLocalMinimum;
+ if( !std::isnan(fLocalMaximum) && fLocalMaximum> rfMaximum )
+ rfMaximum = fLocalMaximum;
+ }
+ }
+ if(std::isinf(rfMinimum))
+ rfMinimum = std::numeric_limits<double>::quiet_NaN();
+ if(std::isinf(rfMaximum))
+ rfMaximum = std::numeric_limits<double>::quiet_NaN();
+}
+
+void VSeriesPlotter::getMinimumAndMaximumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const
+{
+ rfMinY = std::numeric_limits<double>::infinity();
+ rfMaxY = -std::numeric_limits<double>::infinity();
+
+ for (auto const& ZSlot : m_aZSlots)
+ {
+ for (auto const& XSlot : ZSlot)
+ {
+ double fLocalMinimum, fLocalMaximum;
+ XSlot.getMinimumAndMaximumYInContinuousXRange( fLocalMinimum, fLocalMaximum, fMinX, fMaxX, nAxisIndex );
+ if( !std::isnan(fLocalMinimum) && fLocalMinimum< rfMinY )
+ rfMinY = fLocalMinimum;
+ if( !std::isnan(fLocalMaximum) && fLocalMaximum> rfMaxY )
+ rfMaxY = fLocalMaximum;
+ }
+ }
+ if(std::isinf(rfMinY))
+ rfMinY = std::numeric_limits<double>::quiet_NaN();
+ if(std::isinf(rfMaxY))
+ rfMaxY = std::numeric_limits<double>::quiet_NaN();
+}
+
+sal_Int32 VSeriesPlotter::getPointCount() const
+{
+ sal_Int32 nRet = 0;
+
+ for (auto const& ZSlot : m_aZSlots)
+ {
+ for (auto const& XSlot : ZSlot)
+ {
+ sal_Int32 nPointCount = XSlot.getPointCount();
+ if( nPointCount>nRet )
+ nRet = nPointCount;
+ }
+ }
+ return nRet;
+}
+
+void VSeriesPlotter::setNumberFormatsSupplier(
+ const uno::Reference< util::XNumberFormatsSupplier > & xNumFmtSupplier )
+{
+ m_apNumberFormatterWrapper.reset( new NumberFormatterWrapper( xNumFmtSupplier ));
+}
+
+void VSeriesPlotter::setColorScheme( const uno::Reference< XColorScheme >& xColorScheme )
+{
+ m_xColorScheme = xColorScheme;
+}
+
+void VSeriesPlotter::setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider )
+{
+ m_pExplicitCategoriesProvider = pExplicitCategoriesProvider;
+}
+
+sal_Int32 VDataSeriesGroup::getPointCount() const
+{
+ if(!m_bMaxPointCountDirty)
+ return m_nMaxPointCount;
+
+ sal_Int32 nRet = 0;
+
+ for (std::unique_ptr<VDataSeries> const & pSeries : m_aSeriesVector)
+ {
+ sal_Int32 nPointCount = pSeries->getTotalPointCount();
+ if( nPointCount>nRet )
+ nRet = nPointCount;
+ }
+ m_nMaxPointCount=nRet;
+ m_aListOfCachedYValues.clear();
+ m_aListOfCachedYValues.resize(m_nMaxPointCount);
+ m_bMaxPointCountDirty=false;
+ return nRet;
+}
+
+sal_Int32 VDataSeriesGroup::getAttachedAxisIndexForFirstSeries() const
+{
+ sal_Int32 nRet = 0;
+
+ if (!m_aSeriesVector.empty())
+ nRet = m_aSeriesVector[0]->getAttachedAxisIndex();
+
+ return nRet;
+}
+
+void VDataSeriesGroup::getMinimumAndMaximumX( double& rfMinimum, double& rfMaximum ) const
+{
+
+ rfMinimum = std::numeric_limits<double>::infinity();
+ rfMaximum = -std::numeric_limits<double>::infinity();
+
+ for (std::unique_ptr<VDataSeries> const & pSeries : m_aSeriesVector)
+ {
+ sal_Int32 nPointCount = pSeries->getTotalPointCount();
+ for(sal_Int32 nN=0;nN<nPointCount;nN++)
+ {
+ double fX = pSeries->getXValue( nN );
+ if( std::isnan(fX) )
+ continue;
+ if(rfMaximum<fX)
+ rfMaximum=fX;
+ if(rfMinimum>fX)
+ rfMinimum=fX;
+ }
+ }
+ if(std::isinf(rfMinimum))
+ rfMinimum = std::numeric_limits<double>::quiet_NaN();
+ if(std::isinf(rfMaximum))
+ rfMaximum = std::numeric_limits<double>::quiet_NaN();
+}
+
+namespace {
+
+/**
+ * Keep track of minimum and maximum Y values for one or more data series.
+ * When multiple data series exist, that indicates that the data series are
+ * stacked.
+ *
+ * <p>For each X value, we calculate separate Y value ranges for each data
+ * series in the first pass. In the second pass, we calculate the minimum Y
+ * value by taking the absolute minimum value of all data series, whereas
+ * the maximum Y value is the sum of all the series maximum Y values.</p>
+ *
+ * <p>Once that's done for all X values, the final min / max Y values get
+ * calculated by taking the absolute min / max Y values across all the X
+ * values.</p>
+ */
+class PerXMinMaxCalculator
+{
+ typedef std::pair<double, double> MinMaxType;
+ typedef std::map<size_t, MinMaxType> SeriesMinMaxType;
+ typedef std::map<double, SeriesMinMaxType> GroupMinMaxType;
+ typedef std::unordered_map<double, MinMaxType> TotalStoreType;
+ GroupMinMaxType m_SeriesGroup;
+ size_t mnCurSeries;
+
+public:
+ PerXMinMaxCalculator() : mnCurSeries(0) {}
+
+ void nextSeries() { ++mnCurSeries; }
+
+ void setValue(double fX, double fY)
+ {
+ SeriesMinMaxType* pStore = getByXValue(fX); // get storage for given X value.
+ if (!pStore)
+ // This shouldn't happen!
+ return;
+
+ SeriesMinMaxType::iterator it = pStore->lower_bound(mnCurSeries);
+ if (it != pStore->end() && !pStore->key_comp()(mnCurSeries, it->first))
+ {
+ MinMaxType& r = it->second;
+ // A min-max pair already exists for this series. Update it.
+ if (fY < r.first)
+ r.first = fY;
+ if (r.second < fY)
+ r.second = fY;
+ }
+ else
+ {
+ // No existing pair. Insert a new one.
+ pStore->insert(
+ it, SeriesMinMaxType::value_type(
+ mnCurSeries, MinMaxType(fY,fY)));
+ }
+ }
+
+ void getTotalRange(double& rfMin, double& rfMax) const
+ {
+ TotalStoreType aStore;
+ getTotalStore(aStore);
+
+ if (aStore.empty())
+ {
+ rfMin = std::numeric_limits<double>::quiet_NaN();
+ rfMax = std::numeric_limits<double>::quiet_NaN();
+ return;
+ }
+
+ TotalStoreType::const_iterator it = aStore.begin(), itEnd = aStore.end();
+ rfMin = it->second.first;
+ rfMax = it->second.second;
+ for (++it; it != itEnd; ++it)
+ {
+ if (rfMin > it->second.first)
+ rfMin = it->second.first;
+ if (rfMax < it->second.second)
+ rfMax = it->second.second;
+ }
+ }
+
+private:
+ /**
+ * Parse all data and reduce them into a set of global Y value ranges per
+ * X value.
+ */
+ void getTotalStore(TotalStoreType& rStore) const
+ {
+ TotalStoreType aStore;
+ for (auto const& it : m_SeriesGroup)
+ {
+ double fX = it.first;
+
+ const SeriesMinMaxType& rSeries = it.second;
+ for (auto const& series : rSeries)
+ {
+ double fYMin = series.second.first, fYMax = series.second.second;
+ TotalStoreType::iterator itr = aStore.find(fX);
+ if (itr == aStore.end())
+ // New min-max pair for give X value.
+ aStore.emplace(fX, std::pair<double,double>(fYMin,fYMax));
+ else
+ {
+ MinMaxType& r = itr->second;
+ if (fYMin < r.first)
+ r.first = fYMin; // min y-value
+
+ r.second += fYMax; // accumulative max y-value.
+ }
+ }
+ }
+ rStore.swap(aStore);
+ }
+
+ SeriesMinMaxType* getByXValue(double fX)
+ {
+ GroupMinMaxType::iterator it = m_SeriesGroup.find(fX);
+ if (it == m_SeriesGroup.end())
+ {
+ std::pair<GroupMinMaxType::iterator,bool> r =
+ m_SeriesGroup.insert(std::make_pair(fX, SeriesMinMaxType{}));
+
+ if (!r.second)
+ // insertion failed.
+ return nullptr;
+
+ it = r.first;
+ }
+
+ return &it->second;
+ }
+};
+
+}
+
+void VDataSeriesGroup::getMinimumAndMaximumYInContinuousXRange(
+ double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const
+{
+ rfMinY = std::numeric_limits<double>::quiet_NaN();
+ rfMaxY = std::numeric_limits<double>::quiet_NaN();
+
+ if (m_aSeriesVector.empty())
+ // No data series. Bail out.
+ return;
+
+ PerXMinMaxCalculator aRangeCalc;
+ for (const std::unique_ptr<VDataSeries> & pSeries : m_aSeriesVector)
+ {
+ if (!pSeries)
+ continue;
+
+ for (sal_Int32 i = 0, n = pSeries->getTotalPointCount(); i < n; ++i)
+ {
+ if (nAxisIndex != pSeries->getAttachedAxisIndex())
+ continue;
+
+ double fX = pSeries->getXValue(i);
+ if (std::isnan(fX))
+ continue;
+
+ if (fX < fMinX || fX > fMaxX)
+ // Outside specified X range. Skip it.
+ continue;
+
+ double fY = pSeries->getYValue(i);
+ if (std::isnan(fY))
+ continue;
+
+ aRangeCalc.setValue(fX, fY);
+ }
+ aRangeCalc.nextSeries();
+ }
+
+ aRangeCalc.getTotalRange(rfMinY, rfMaxY);
+}
+
+void VDataSeriesGroup::calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex
+ , bool bSeparateStackingForDifferentSigns
+ , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex ) const
+{
+ assert(nCategoryIndex >= 0);
+ assert(nCategoryIndex < getPointCount());
+
+ rfMinimumY = std::numeric_limits<double>::infinity();
+ rfMaximumY = -std::numeric_limits<double>::infinity();
+
+ if(m_aSeriesVector.empty())
+ return;
+
+ CachedYValues aCachedYValues = m_aListOfCachedYValues[nCategoryIndex][nAxisIndex];
+ if( !aCachedYValues.m_bValuesDirty )
+ {
+ //return cached values
+ rfMinimumY = aCachedYValues.m_fMinimumY;
+ rfMaximumY = aCachedYValues.m_fMaximumY;
+ return;
+ }
+
+ double fTotalSum = std::numeric_limits<double>::quiet_NaN();
+ double fPositiveSum = std::numeric_limits<double>::quiet_NaN();
+ double fNegativeSum = std::numeric_limits<double>::quiet_NaN();
+ double fFirstPositiveY = std::numeric_limits<double>::quiet_NaN();
+ double fFirstNegativeY = std::numeric_limits<double>::quiet_NaN();
+
+ if( bSeparateStackingForDifferentSigns )
+ {
+ for (const std::unique_ptr<VDataSeries> & pSeries: m_aSeriesVector)
+ {
+ if( nAxisIndex != pSeries->getAttachedAxisIndex() )
+ continue;
+
+ double fValueMinY = pSeries->getMinimumofAllDifferentYValues( nCategoryIndex );
+ double fValueMaxY = pSeries->getMaximumofAllDifferentYValues( nCategoryIndex );
+
+ if( fValueMaxY >= 0 )
+ {
+ if( std::isnan( fPositiveSum ) )
+ fPositiveSum = fFirstPositiveY = fValueMaxY;
+ else
+ fPositiveSum += fValueMaxY;
+ }
+ if( fValueMinY < 0 )
+ {
+ if(std::isnan( fNegativeSum ))
+ fNegativeSum = fFirstNegativeY = fValueMinY;
+ else
+ fNegativeSum += fValueMinY;
+ }
+ }
+ rfMinimumY = std::isnan( fNegativeSum ) ? fFirstPositiveY : fNegativeSum;
+ rfMaximumY = std::isnan( fPositiveSum ) ? fFirstNegativeY : fPositiveSum;
+ }
+ else
+ {
+ for (const std::unique_ptr<VDataSeries> & pSeries: m_aSeriesVector)
+ {
+ if( nAxisIndex != pSeries->getAttachedAxisIndex() )
+ continue;
+
+ double fValueMinY = pSeries->getMinimumofAllDifferentYValues( nCategoryIndex );
+ double fValueMaxY = pSeries->getMaximumofAllDifferentYValues( nCategoryIndex );
+
+ if( std::isnan( fTotalSum ) )
+ {
+ rfMinimumY = fValueMinY;
+ rfMaximumY = fTotalSum = fValueMaxY;
+ }
+ else
+ {
+ fTotalSum += fValueMaxY;
+ if( rfMinimumY > fTotalSum )
+ rfMinimumY = fTotalSum;
+ if( rfMaximumY < fTotalSum )
+ rfMaximumY = fTotalSum;
+ }
+ }
+ }
+
+ aCachedYValues.m_fMinimumY = rfMinimumY;
+ aCachedYValues.m_fMaximumY = rfMaximumY;
+ aCachedYValues.m_bValuesDirty = false;
+ m_aListOfCachedYValues[nCategoryIndex][nAxisIndex]=aCachedYValues;
+}
+
+void VDataSeriesGroup::calculateYMinAndMaxForCategoryRange(
+ sal_Int32 nStartCategoryIndex, sal_Int32 nEndCategoryIndex
+ , bool bSeparateStackingForDifferentSigns
+ , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex )
+{
+ //@todo maybe cache these values
+ rfMinimumY = std::numeric_limits<double>::infinity();
+ rfMaximumY = -std::numeric_limits<double>::infinity();
+
+ //iterate through the given categories
+ if(nStartCategoryIndex<0)
+ nStartCategoryIndex=0;
+ const sal_Int32 nPointCount = getPointCount();//necessary to create m_aListOfCachedYValues
+ if(nPointCount <= 0)
+ return;
+ if (nEndCategoryIndex >= nPointCount)
+ nEndCategoryIndex = nPointCount - 1;
+ if(nEndCategoryIndex<0)
+ nEndCategoryIndex=0;
+ for( sal_Int32 nCatIndex = nStartCategoryIndex; nCatIndex <= nEndCategoryIndex; nCatIndex++ )
+ {
+ double fMinimumY = std::numeric_limits<double>::quiet_NaN();
+ double fMaximumY = std::numeric_limits<double>::quiet_NaN();
+
+ calculateYMinAndMaxForCategory( nCatIndex
+ , bSeparateStackingForDifferentSigns, fMinimumY, fMaximumY, nAxisIndex );
+
+ if(rfMinimumY > fMinimumY)
+ rfMinimumY = fMinimumY;
+ if(rfMaximumY < fMaximumY)
+ rfMaximumY = fMaximumY;
+ }
+}
+
+double VSeriesPlotter::getTransformedDepth() const
+{
+ double MinZ = m_pMainPosHelper->getLogicMinZ();
+ double MaxZ = m_pMainPosHelper->getLogicMaxZ();
+ m_pMainPosHelper->doLogicScaling( nullptr, nullptr, &MinZ );
+ m_pMainPosHelper->doLogicScaling( nullptr, nullptr, &MaxZ );
+ return FIXED_SIZE_FOR_3D_CHART_VOLUME/(MaxZ-MinZ);
+}
+
+void VSeriesPlotter::addSecondaryValueScale( const ExplicitScaleData& rScale, sal_Int32 nAxisIndex )
+{
+ if( nAxisIndex<1 )
+ return;
+
+ m_aSecondaryValueScales[nAxisIndex]=rScale;
+}
+
+PlottingPositionHelper& VSeriesPlotter::getPlottingPositionHelper( sal_Int32 nAxisIndex ) const
+{
+ PlottingPositionHelper* pRet = nullptr;
+ if(nAxisIndex>0)
+ {
+ tSecondaryPosHelperMap::const_iterator aPosIt = m_aSecondaryPosHelperMap.find( nAxisIndex );
+ if( aPosIt != m_aSecondaryPosHelperMap.end() )
+ {
+ pRet = aPosIt->second.get();
+ }
+ else if (m_pPosHelper)
+ {
+ tSecondaryValueScales::const_iterator aScaleIt = m_aSecondaryValueScales.find( nAxisIndex );
+ if( aScaleIt != m_aSecondaryValueScales.end() )
+ {
+ m_aSecondaryPosHelperMap[nAxisIndex] = m_pPosHelper->createSecondaryPosHelper( aScaleIt->second );
+ pRet = m_aSecondaryPosHelperMap[nAxisIndex].get();
+ }
+ }
+ }
+ if( !pRet )
+ pRet = m_pMainPosHelper;
+ pRet->setTimeResolution( m_nTimeResolution, m_aNullDate );
+ return *pRet;
+}
+
+void VSeriesPlotter::rearrangeLabelToAvoidOverlapIfRequested( const awt::Size& /*rPageSize*/ )
+{
+}
+
+VDataSeries* VSeriesPlotter::getFirstSeries() const
+{
+ for (std::vector<VDataSeriesGroup> const & rGroup : m_aZSlots)
+ {
+ if (!rGroup.empty())
+ {
+ if (!rGroup[0].m_aSeriesVector.empty())
+ {
+ VDataSeries* pSeries = rGroup[0].m_aSeriesVector[0].get();
+ if (pSeries)
+ return pSeries;
+ }
+ }
+ }
+ return nullptr;
+}
+
+OUString VSeriesPlotter::getCategoryName( sal_Int32 nPointIndex ) const
+{
+ if (m_pExplicitCategoriesProvider)
+ {
+ Sequence< OUString > aCategories(m_pExplicitCategoriesProvider->getSimpleCategories());
+ if (nPointIndex >= 0 && nPointIndex < aCategories.getLength())
+ {
+ return aCategories[nPointIndex];
+ }
+ }
+ return OUString();
+}
+
+std::vector<VDataSeries const*> VSeriesPlotter::getAllSeries() const
+{
+ std::vector<VDataSeries const*> aAllSeries;
+ for (std::vector<VDataSeriesGroup> const & rXSlot : m_aZSlots)
+ {
+ for(VDataSeriesGroup const & rGroup : rXSlot)
+ {
+ for (std::unique_ptr<VDataSeries> const & p : rGroup.m_aSeriesVector)
+ aAllSeries.push_back(p.get());
+ }
+ }
+ return aAllSeries;
+}
+
+
+std::vector<VDataSeries*> VSeriesPlotter::getAllSeries()
+{
+ std::vector<VDataSeries*> aAllSeries;
+ for (std::vector<VDataSeriesGroup> const & rXSlot : m_aZSlots)
+ {
+ for(VDataSeriesGroup const & rGroup : rXSlot)
+ {
+ for (std::unique_ptr<VDataSeries> const & p : rGroup.m_aSeriesVector)
+ aAllSeries.push_back(p.get());
+ }
+ }
+ return aAllSeries;
+}
+
+uno::Sequence<OUString> VSeriesPlotter::getSeriesNames() const
+{
+ std::vector<OUString> aRetVector;
+
+ OUString aRole;
+ if (m_xChartTypeModel.is())
+ aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel();
+
+ for (auto const& rGroup : m_aZSlots)
+ {
+ if (!rGroup.empty())
+ {
+ VDataSeriesGroup const & rSeriesGroup(rGroup[0]);
+ if (!rSeriesGroup.m_aSeriesVector.empty())
+ {
+ VDataSeries const * pSeries = rSeriesGroup.m_aSeriesVector[0].get();
+ rtl::Reference< DataSeries > xSeries( pSeries ? pSeries->getModel() : nullptr );
+ if( xSeries.is() )
+ {
+ OUString aSeriesName( xSeries->getLabelForRole( aRole ) );
+ aRetVector.push_back( aSeriesName );
+ }
+ }
+ }
+ }
+ return comphelper::containerToSequence( aRetVector );
+}
+
+uno::Sequence<OUString> VSeriesPlotter::getAllSeriesNames() const
+{
+ std::vector<OUString> aRetVector;
+
+ OUString aRole;
+ if (m_xChartTypeModel.is())
+ aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel();
+
+ for (VDataSeries const* pSeries : getAllSeries())
+ {
+ if (pSeries)
+ {
+ OUString aSeriesName(pSeries->getModel()->getLabelForRole(aRole));
+ aRetVector.push_back(aSeriesName);
+ }
+ }
+ return comphelper::containerToSequence(aRetVector);
+}
+
+void VSeriesPlotter::setPageReferenceSize( const css::awt::Size & rPageRefSize )
+{
+ m_aPageReferenceSize = rPageRefSize;
+
+ // set reference size also at all data series
+
+ for (auto const & outer : m_aZSlots)
+ for (VDataSeriesGroup const & rGroup : outer)
+ {
+ for (std::unique_ptr<VDataSeries> const & pSeries : rGroup.m_aSeriesVector)
+ {
+ pSeries->setPageReferenceSize(m_aPageReferenceSize);
+ }
+ }
+}
+
+//better performance for big data
+void VSeriesPlotter::setCoordinateSystemResolution( const Sequence< sal_Int32 >& rCoordinateSystemResolution )
+{
+ m_aCoordinateSystemResolution = rCoordinateSystemResolution;
+}
+
+bool VSeriesPlotter::WantToPlotInFrontOfAxisLine()
+{
+ return ChartTypeHelper::isSeriesInFrontOfAxisLine( m_xChartTypeModel );
+}
+
+bool VSeriesPlotter::shouldSnapRectToUsedArea()
+{
+ return m_nDimension != 3;
+}
+
+std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntries(
+ const awt::Size& rEntryKeyAspectRatio
+ , LegendPosition eLegendPosition
+ , const Reference< beans::XPropertySet >& xTextProperties
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const Reference< uno::XComponentContext >& xContext
+ , ChartModel& rModel
+ )
+{
+ std::vector< ViewLegendEntry > aResult;
+
+ if( xTarget.is() )
+ {
+ rtl::Reference< Diagram > xDiagram = rModel.getFirstChartDiagram();
+ rtl::Reference< BaseCoordinateSystem > xCooSys(xDiagram->getBaseCoordinateSystems()[0]);
+ bool bSwapXAndY = false;
+
+ try
+ {
+ xCooSys->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY;
+ }
+ catch( const uno::Exception& )
+ {
+ }
+
+ //iterate through all series
+ bool bBreak = false;
+ bool bFirstSeries = true;
+
+
+ for (std::vector<VDataSeriesGroup> const & rGroupVector : m_aZSlots)
+ {
+ for (VDataSeriesGroup const & rGroup : rGroupVector)
+ {
+ for (std::unique_ptr<VDataSeries> const & pSeries : rGroup.m_aSeriesVector)
+ {
+ if (!pSeries)
+ continue;
+
+ // "ShowLegendEntry"
+ if (!pSeries->getModel()->getFastPropertyValue(PROP_DATASERIES_SHOW_LEGEND_ENTRY).get<sal_Bool>())
+ {
+ continue;
+ }
+
+ std::vector<ViewLegendEntry> aSeriesEntries(
+ createLegendEntriesForSeries(
+ rEntryKeyAspectRatio, *pSeries, xTextProperties,
+ xTarget, xContext));
+
+ //add series entries to the result now
+
+ // use only the first series if VaryColorsByPoint is set for the first series
+ if (bFirstSeries && pSeries->isVaryColorsByPoint())
+ bBreak = true;
+ bFirstSeries = false;
+
+ // add entries reverse if chart is stacked in y-direction and the legend position is right or left.
+ // If the legend is top or bottom and we have a stacked bar-chart the normal order
+ // is the correct one, unless the chart type is horizontal bar-chart.
+ bool bReverse = false;
+ if ( bSwapXAndY )
+ {
+ StackingDirection eStackingDirection( pSeries->getStackingDirection() );
+ bReverse = ( eStackingDirection != StackingDirection_Y_STACKING );
+ }
+ else if ( eLegendPosition == LegendPosition_LINE_START || eLegendPosition == LegendPosition_LINE_END )
+ {
+ StackingDirection eStackingDirection( pSeries->getStackingDirection() );
+ bReverse = ( eStackingDirection == StackingDirection_Y_STACKING );
+ }
+
+ if (bReverse)
+ aResult.insert( aResult.begin(), aSeriesEntries.begin(), aSeriesEntries.end() );
+ else
+ aResult.insert( aResult.end(), aSeriesEntries.begin(), aSeriesEntries.end() );
+ }
+ if (bBreak)
+ return aResult;
+ }
+ }
+ }
+
+ return aResult;
+}
+
+std::vector<ViewLegendSymbol> VSeriesPlotter::createSymbols(const awt::Size& rEntryKeyAspectRatio
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const Reference<uno::XComponentContext>& xContext)
+{
+ std::vector<ViewLegendSymbol> aResult;
+
+ if( xTarget.is() )
+ {
+ bool bBreak = false;
+ bool bFirstSeries = true;
+
+ for (std::vector<VDataSeriesGroup> const & rGroupVector : m_aZSlots)
+ {
+ for (VDataSeriesGroup const & rGroup : rGroupVector)
+ {
+ for (std::unique_ptr<VDataSeries> const & pSeries : rGroup.m_aSeriesVector)
+ {
+ if (!pSeries)
+ continue;
+
+ std::vector<ViewLegendSymbol> aSeriesSymbols = createSymbolsForSeries(rEntryKeyAspectRatio, *pSeries, xTarget, xContext);
+
+ //add series entries to the result now
+
+ // use only the first series if VaryColorsByPoint is set for the first series
+ if (bFirstSeries && pSeries->isVaryColorsByPoint())
+ bBreak = true;
+
+ bFirstSeries = false;
+
+ aResult.insert(aResult.end(), aSeriesSymbols.begin(), aSeriesSymbols.end());
+ }
+ if (bBreak)
+ return aResult;
+ }
+ }
+ }
+
+ return aResult;
+}
+
+namespace
+{
+bool lcl_HasVisibleLine( const uno::Reference< beans::XPropertySet >& xProps, bool& rbHasDashedLine )
+{
+ bool bHasVisibleLine = false;
+ rbHasDashedLine = false;
+ drawing::LineStyle aLineStyle = drawing::LineStyle_NONE;
+ if( xProps.is() && ( xProps->getPropertyValue( "LineStyle") >>= aLineStyle ) )
+ {
+ if( aLineStyle != drawing::LineStyle_NONE )
+ bHasVisibleLine = true;
+ if( aLineStyle == drawing::LineStyle_DASH )
+ rbHasDashedLine = true;
+ }
+ return bHasVisibleLine;
+}
+
+bool lcl_HasRegressionCurves( const VDataSeries& rSeries, bool& rbHasDashedLine )
+{
+ bool bHasRegressionCurves = false;
+ rtl::Reference< DataSeries > xRegrCont( rSeries.getModel() );
+ for( const rtl::Reference< RegressionCurveModel > & rCurve : xRegrCont->getRegressionCurves2() )
+ {
+ bHasRegressionCurves = true;
+ lcl_HasVisibleLine( rCurve, rbHasDashedLine );
+ }
+ return bHasRegressionCurves;
+}
+}
+LegendSymbolStyle VSeriesPlotter::getLegendSymbolStyle()
+{
+ return LegendSymbolStyle::Box;
+}
+
+awt::Size VSeriesPlotter::getPreferredLegendKeyAspectRatio()
+{
+ awt::Size aRet(1000,1000);
+ if( m_nDimension==3 )
+ return aRet;
+
+ bool bSeriesAllowsLines = (getLegendSymbolStyle() == LegendSymbolStyle::Line);
+ bool bHasLines = false;
+ bool bHasDashedLines = false;
+ //iterate through all series
+ for (VDataSeries* pSeries : getAllSeries())
+ {
+ if( bSeriesAllowsLines )
+ {
+ bool bCurrentDashed = false;
+ if( lcl_HasVisibleLine( pSeries->getPropertiesOfSeries(), bCurrentDashed ) )
+ {
+ bHasLines = true;
+ if( bCurrentDashed )
+ {
+ bHasDashedLines = true;
+ break;
+ }
+ }
+ }
+ bool bRegressionHasDashedLines=false;
+ if( lcl_HasRegressionCurves( *pSeries, bRegressionHasDashedLines ) )
+ {
+ bHasLines = true;
+ if( bRegressionHasDashedLines )
+ {
+ bHasDashedLines = true;
+ break;
+ }
+ }
+ }
+ if( bHasLines )
+ {
+ if( bHasDashedLines )
+ aRet = awt::Size(1600,-1);
+ else
+ aRet = awt::Size(800,-1);
+ }
+ return aRet;
+}
+
+uno::Any VSeriesPlotter::getExplicitSymbol( const VDataSeries& /*rSeries*/, sal_Int32 /*nPointIndex*/ )
+{
+ return uno::Any();
+}
+
+rtl::Reference<SvxShapeGroup> VSeriesPlotter::createLegendSymbolForSeries(
+ const awt::Size& rEntryKeyAspectRatio
+ , const VDataSeries& rSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
+{
+
+ LegendSymbolStyle eLegendSymbolStyle = getLegendSymbolStyle();
+ uno::Any aExplicitSymbol( getExplicitSymbol( rSeries, -1 ) );
+
+ VLegendSymbolFactory::PropertyType ePropType =
+ VLegendSymbolFactory::PropertyType::FilledSeries;
+
+ // todo: maybe the property-style does not solely depend on the
+ // legend-symbol type
+ switch( eLegendSymbolStyle )
+ {
+ case LegendSymbolStyle::Line:
+ ePropType = VLegendSymbolFactory::PropertyType::LineSeries;
+ break;
+ default:
+ break;
+ }
+ rtl::Reference<SvxShapeGroup> xShape = VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio,
+ xTarget, eLegendSymbolStyle,
+ rSeries.getPropertiesOfSeries(), ePropType, aExplicitSymbol );
+
+ return xShape;
+}
+
+rtl::Reference< SvxShapeGroup > VSeriesPlotter::createLegendSymbolForPoint(
+ const awt::Size& rEntryKeyAspectRatio
+ , const VDataSeries& rSeries
+ , sal_Int32 nPointIndex
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
+{
+
+ LegendSymbolStyle eLegendSymbolStyle = getLegendSymbolStyle();
+ uno::Any aExplicitSymbol( getExplicitSymbol(rSeries,nPointIndex) );
+
+ VLegendSymbolFactory::PropertyType ePropType =
+ VLegendSymbolFactory::PropertyType::FilledSeries;
+
+ // todo: maybe the property-style does not solely depend on the
+ // legend-symbol type
+ switch( eLegendSymbolStyle )
+ {
+ case LegendSymbolStyle::Line:
+ ePropType = VLegendSymbolFactory::PropertyType::LineSeries;
+ break;
+ default:
+ break;
+ }
+
+ // the default properties for the data point are the data series properties.
+ // If a data point has own attributes overwrite them
+ Reference< beans::XPropertySet > xSeriesProps( rSeries.getPropertiesOfSeries() );
+ Reference< beans::XPropertySet > xPointSet( xSeriesProps );
+ if( rSeries.isAttributedDataPoint( nPointIndex ) )
+ xPointSet.set( rSeries.getPropertiesOfPoint( nPointIndex ));
+
+ // if a data point has no own color use a color from the diagram's color scheme
+ if( ! rSeries.hasPointOwnColor( nPointIndex ))
+ {
+ Reference< util::XCloneable > xCloneable( xPointSet,uno::UNO_QUERY );
+ if( xCloneable.is() && m_xColorScheme.is() )
+ {
+ xPointSet.set( xCloneable->createClone(), uno::UNO_QUERY );
+ Reference< container::XChild > xChild( xPointSet, uno::UNO_QUERY );
+ if( xChild.is())
+ xChild->setParent( xSeriesProps );
+
+ OSL_ASSERT( xPointSet.is());
+ xPointSet->setPropertyValue(
+ "Color", uno::Any( m_xColorScheme->getColorByIndex( nPointIndex )));
+ }
+ }
+
+ rtl::Reference< SvxShapeGroup > xShape = VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio,
+ xTarget, eLegendSymbolStyle, xPointSet, ePropType, aExplicitSymbol );
+
+ return xShape;
+}
+
+std::vector< ViewLegendEntry > VSeriesPlotter::createLegendEntriesForSeries(
+ const awt::Size& rEntryKeyAspectRatio
+ , const VDataSeries& rSeries
+ , const Reference< beans::XPropertySet >& xTextProperties
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const Reference< uno::XComponentContext >& xContext
+ )
+{
+ std::vector< ViewLegendEntry > aResult;
+
+ if( ! ( xTarget.is() && xContext.is() ) )
+ return aResult;
+
+ try
+ {
+ ViewLegendEntry aEntry;
+ OUString aLabelText;
+ bool bVaryColorsByPoint = rSeries.isVaryColorsByPoint();
+ bool bIsPie = m_xChartTypeModel->getChartType().equalsIgnoreAsciiCase(
+ CHART2_SERVICE_NAME_CHARTTYPE_PIE);
+ try
+ {
+ if (bIsPie)
+ {
+ bool bDonut = false;
+ // "UseRings"
+ if ((m_xChartTypeModel->getFastPropertyValue(PROP_PIECHARTTYPE_USE_RINGS) >>= bDonut) && bDonut)
+ bIsPie = false;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ }
+
+ if (bVaryColorsByPoint || bIsPie)
+ {
+ Sequence< OUString > aCategoryNames;
+ if( m_pExplicitCategoriesProvider )
+ aCategoryNames = m_pExplicitCategoriesProvider->getSimpleCategories();
+ Sequence<sal_Int32> deletedLegendEntries;
+ try
+ {
+ // "DeletedLegendEntries"
+ rSeries.getModel()->getFastPropertyValue(PROP_DATASERIES_DELETED_LEGEND_ENTRIES) >>= deletedLegendEntries;
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ for( sal_Int32 nIdx=0; nIdx<aCategoryNames.getLength(); ++nIdx )
+ {
+ bool deletedLegendEntry = false;
+ for (const auto& deletedLegendEntryIdx : std::as_const(deletedLegendEntries))
+ {
+ if (nIdx == deletedLegendEntryIdx)
+ {
+ deletedLegendEntry = true;
+ break;
+ }
+ }
+ if (deletedLegendEntry)
+ continue;
+
+ // symbol
+ rtl::Reference< SvxShapeGroup > xSymbolGroup(ShapeFactory::createGroup2D( xTarget ));
+
+ // create the symbol
+ rtl::Reference< SvxShapeGroup > xShape = createLegendSymbolForPoint( rEntryKeyAspectRatio,
+ rSeries, nIdx, xSymbolGroup );
+
+ // set CID to symbol for selection
+ if( xShape.is() )
+ {
+ aEntry.xSymbol = xSymbolGroup;
+
+ OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_DATA_POINT, nIdx ) );
+ aChildParticle = ObjectIdentifier::addChildParticle( aChildParticle, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) );
+ OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle );
+ ShapeFactory::setShapeName( xShape, aCID );
+ }
+
+ // label
+ aLabelText = aCategoryNames[nIdx];
+ if( xShape.is() || !aLabelText.isEmpty() )
+ {
+ aEntry.xLabel = FormattedStringHelper::createFormattedString( aLabelText, xTextProperties );
+ aResult.push_back(aEntry);
+ }
+ }
+ }
+ else
+ {
+ // symbol
+ rtl::Reference< SvxShapeGroup > xSymbolGroup(ShapeFactory::createGroup2D( xTarget ));
+
+ // create the symbol
+ rtl::Reference<SvxShapeGroup> xShape = createLegendSymbolForSeries(
+ rEntryKeyAspectRatio, rSeries, xSymbolGroup );
+
+ // set CID to symbol for selection
+ if( xShape.is())
+ {
+ aEntry.xSymbol = xSymbolGroup;
+
+ OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) );
+ OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle );
+ ShapeFactory::setShapeName( xShape, aCID );
+ }
+
+ // label
+ aLabelText = rSeries.getModel()->getLabelForRole( m_xChartTypeModel.is() ? m_xChartTypeModel->getRoleOfSequenceForSeriesLabel() : "values-y");
+ aEntry.xLabel = FormattedStringHelper::createFormattedString( aLabelText, xTextProperties );
+
+ aResult.push_back(aEntry);
+ }
+
+ // don't show legend entry of regression curve & friends if this type of chart
+ // doesn't support statistics #i63016#, fdo#37197
+ if (!ChartTypeHelper::isSupportingStatisticProperties( m_xChartTypeModel, m_nDimension ))
+ return aResult;
+
+ rtl::Reference< DataSeries > xRegrCont = rSeries.getModel();
+ if( xRegrCont.is())
+ {
+ const std::vector< rtl::Reference< RegressionCurveModel > > & aCurves = xRegrCont->getRegressionCurves2();
+ sal_Int32 i = 0, nCount = aCurves.size();
+ for( i=0; i<nCount; ++i )
+ {
+ //label
+ OUString aResStr( RegressionCurveHelper::getUINameForRegressionCurve( aCurves[i] ) );
+ replaceParamterInString( aResStr, u"%SERIESNAME", aLabelText );
+ aEntry.xLabel = FormattedStringHelper::createFormattedString( aResStr, xTextProperties );
+
+ // symbol
+ rtl::Reference<SvxShapeGroup> xSymbolGroup(ShapeFactory::createGroup2D( xTarget ));
+
+ // create the symbol
+ rtl::Reference<SvxShapeGroup> xShape = VLegendSymbolFactory::createSymbol( rEntryKeyAspectRatio,
+ xSymbolGroup, LegendSymbolStyle::Line,
+ aCurves[i],
+ VLegendSymbolFactory::PropertyType::Line, uno::Any() );
+
+ // set CID to symbol for selection
+ if( xShape.is())
+ {
+ aEntry.xSymbol = xSymbolGroup;
+
+ bool bAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[i] );
+ ObjectType eObjectType = bAverageLine ? OBJECTTYPE_DATA_AVERAGE_LINE : OBJECTTYPE_DATA_CURVE;
+ OUString aChildParticle( ObjectIdentifier::createChildParticleWithIndex( eObjectType, i ) );
+ aChildParticle = ObjectIdentifier::addChildParticle( aChildParticle, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_LEGEND_ENTRY, 0 ) );
+ OUString aCID = ObjectIdentifier::createClassifiedIdentifierForParticles( rSeries.getSeriesParticle(), aChildParticle );
+ ShapeFactory::setShapeName( xShape, aCID );
+ }
+
+ aResult.push_back(aEntry);
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+ return aResult;
+}
+
+std::vector<ViewLegendSymbol> VSeriesPlotter::createSymbolsForSeries(
+ const awt::Size& rEntryKeyAspectRatio
+ , const VDataSeries& rSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const Reference<uno::XComponentContext>& xContext)
+{
+ std::vector<ViewLegendSymbol> aResult;
+
+ if (!(xTarget.is() && xContext.is()))
+ return aResult;
+
+ try
+ {
+ ViewLegendSymbol aEntry;
+ // symbol
+ rtl::Reference<SvxShapeGroup> xSymbolGroup(ShapeFactory::createGroup2D(xTarget));
+
+ // create the symbol
+ rtl::Reference<SvxShapeGroup> xShape = createLegendSymbolForSeries(rEntryKeyAspectRatio, rSeries, xSymbolGroup );
+
+ // set CID to symbol for selection
+ if (xShape.is())
+ {
+ aEntry.xSymbol = xSymbolGroup;
+ aResult.push_back(aEntry);
+ }
+ }
+ catch (const uno::Exception &)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+ return aResult;
+}
+
+VSeriesPlotter* VSeriesPlotter::createSeriesPlotter(
+ const rtl::Reference<ChartType>& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bExcludingPositioning )
+{
+ if (!xChartTypeModel.is())
+ return nullptr;
+
+ OUString aChartType = xChartTypeModel->getChartType();
+
+ VSeriesPlotter* pRet=nullptr;
+ if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ) )
+ pRet = new BarChart(xChartTypeModel,nDimensionCount);
+ else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_BAR ) )
+ pRet = new BarChart(xChartTypeModel,nDimensionCount);
+ else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_AREA ) )
+ pRet = new AreaChart(xChartTypeModel,nDimensionCount,true);
+ else if( aChartType.equalsIgnoreAsciiCase( CHART2_SERVICE_NAME_CHARTTYPE_LINE ) )
+ pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,true);
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) )
+ pRet = new AreaChart(xChartTypeModel,nDimensionCount,false,true);
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) )
+ pRet = new BubbleChart(xChartTypeModel,nDimensionCount);
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) )
+ pRet = new PieChart(xChartTypeModel,nDimensionCount, bExcludingPositioning );
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_NET) )
+ pRet = new NetChart(xChartTypeModel,nDimensionCount,true,std::make_unique<PolarPlottingPositionHelper>());
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET) )
+ pRet = new NetChart(xChartTypeModel,nDimensionCount,false,std::make_unique<PolarPlottingPositionHelper>());
+ else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
+ pRet = new CandleStickChart(xChartTypeModel,nDimensionCount);
+ else
+ pRet = new AreaChart(xChartTypeModel,nDimensionCount,false,true);
+ return pRet;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/diagram/VDiagram.cxx b/chart2/source/view/diagram/VDiagram.cxx
new file mode 100644
index 0000000000..ff660a485d
--- /dev/null
+++ b/chart2/source/view/diagram/VDiagram.cxx
@@ -0,0 +1,703 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ShapeFactory.hxx>
+#include <VDiagram.hxx>
+#include <Diagram.hxx>
+#include <PropertyMapper.hxx>
+#include <ViewDefines.hxx>
+#include <Stripe.hxx>
+#include <ObjectIdentifier.hxx>
+#include <DiagramHelper.hxx>
+#include <ChartType.hxx>
+#include <BaseGFXHelper.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ThreeDHelper.hxx>
+#include <defines.hxx>
+#include <editeng/unoprnms.hxx>
+#include <svx/scene3d.hxx>
+#include <svx/e3dsceneupdater.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+VDiagram::VDiagram(
+ const rtl::Reference<Diagram> & xDiagram, const drawing::Direction3D& rPreferredAspectRatio,
+ sal_Int32 nDimension )
+ : m_nDimensionCount(nDimension)
+ , m_xDiagram(xDiagram)
+ , m_aPreferredAspectRatio(rPreferredAspectRatio)
+ , m_fXAnglePi(0)
+ , m_fYAnglePi(0)
+ , m_fZAnglePi(0)
+ , m_bRightAngledAxes(false)
+{
+ if( m_nDimensionCount != 3)
+ return;
+
+ xDiagram->getRotationAngle( m_fXAnglePi, m_fYAnglePi, m_fZAnglePi );
+ if( ChartTypeHelper::isSupportingRightAngledAxes(
+ m_xDiagram->getChartTypeByIndex( 0 ) ) )
+ {
+ if(xDiagram.is())
+ xDiagram->getPropertyValue("RightAngledAxes") >>= m_bRightAngledAxes;
+ if( m_bRightAngledAxes )
+ {
+ ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi );
+ m_fZAnglePi=0.0;
+ }
+ }
+}
+
+VDiagram::~VDiagram()
+{
+}
+
+void VDiagram::init( const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
+{
+ m_xTarget = xTarget;
+}
+
+void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize )
+{
+ m_aAvailablePosIncludingAxes = rPos;
+ m_aAvailableSizeIncludingAxes = rSize;
+
+ if( m_nDimensionCount == 3 )
+ createShapes_3d();
+ else
+ createShapes_2d();
+}
+
+::basegfx::B2IRectangle VDiagram::adjustPosAndSize( const awt::Point& rPos, const awt::Size& rSize )
+{
+ ::basegfx::B2IRectangle aAllowedRect( BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
+ ::basegfx::B2IRectangle aNewInnerRect( BaseGFXHelper::makeRectangle(rPos,rSize) );
+ aNewInnerRect.intersect( aAllowedRect );
+
+ if( m_nDimensionCount == 3 )
+ aNewInnerRect = adjustPosAndSize_3d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
+ else
+ aNewInnerRect = adjustPosAndSize_2d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
+
+ return aNewInnerRect;
+}
+
+::basegfx::B2IRectangle VDiagram::adjustPosAndSize_2d( const awt::Point& rPos, const awt::Size& rAvailableSize )
+{
+ m_aCurrentPosWithoutAxes = rPos;
+ m_aCurrentSizeWithoutAxes = rAvailableSize;
+ if( m_aPreferredAspectRatio.DirectionX > 0 && m_aPreferredAspectRatio.DirectionY > 0)
+ {
+ //do not change aspect ratio
+ awt::Size aAspectRatio( static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME),
+ static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME ));
+ m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
+ rAvailableSize, aAspectRatio );
+ //center diagram position
+ m_aCurrentPosWithoutAxes = ShapeFactory::calculateTopLeftPositionToCenterObject(
+ rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
+
+ }
+
+ if( m_xWall2D.is() )
+ {
+ m_xWall2D->setSize( m_aCurrentSizeWithoutAxes);
+ m_xWall2D->setPosition(m_aCurrentPosWithoutAxes);
+ }
+
+ return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
+}
+
+void VDiagram::createShapes_2d()
+{
+ OSL_PRECOND(m_xTarget.is(), "is not proper initialized");
+ if (!m_xTarget.is())
+ return;
+
+ //create group shape
+ rtl::Reference<SvxShapeGroupAnyD> xOuterGroup_Shapes = ShapeFactory::createGroup2D(m_xTarget);
+ m_xOuterGroupShape = xOuterGroup_Shapes;
+
+ rtl::Reference<SvxShapeGroupAnyD> xGroupForWall( ShapeFactory::createGroup2D(xOuterGroup_Shapes,"PlotAreaExcludingAxes") );
+
+ //create independent group shape as container for datapoints and such things
+ m_xCoordinateRegionShape = ShapeFactory::createGroup2D(xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID");
+
+ bool bAddFloorAndWall = m_xDiagram->isSupportingFloorAndWall();
+
+ //add back wall
+ {
+ m_xWall2D = ShapeFactory::createRectangle( xGroupForWall );
+
+ try
+ {
+ OSL_ENSURE( m_xDiagram.is(), "Invalid Diagram model" );
+ if( m_xDiagram.is() )
+ {
+ uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall());
+ if( xWallProp.is())
+ PropertyMapper::setMappedProperties( *m_xWall2D, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
+ }
+ if( !bAddFloorAndWall )
+ {
+ //we always need this object as dummy object for correct scene dimensions
+ //but it should not be visible in this case:
+ ShapeFactory::makeShapeInvisible( m_xWall2D );
+ }
+ else
+ {
+ //CID for selection handling
+ OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
+ m_xWall2D->SvxShape::setPropertyValue( UNO_NAME_MISC_OBJ_NAME, uno::Any( aWallCID ) );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+
+ //position and size for diagram
+ adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
+}
+
+static E3dScene* lcl_getE3dScene( const rtl::Reference<SvxShapeGroupAnyD>& xShape )
+{
+ return DynCastE3dScene(xShape->GetSdrObject());
+}
+
+static void lcl_setLightSources(
+ const uno::Reference< beans::XPropertySet > & xSource,
+ const uno::Reference< beans::XPropertySet > & xDest )
+{
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8));
+
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8));
+
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7));
+ xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8,
+ xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8));
+}
+
+namespace
+{
+
+void lcl_ensureScaleValue( double& rfScale )
+{
+ OSL_ENSURE(rfScale>0, "calculation error for automatic 3D height in chart");
+ if( rfScale<0 )
+ rfScale = 1.0;
+ else if( rfScale<0.2 )
+ rfScale = 0.2;
+ else if( rfScale>5.0 )
+ rfScale = 5.0;
+}
+
+}
+
+void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize )
+{
+ OSL_PRECOND(m_xAspectRatio3D.is(), "created shape offers no XPropertySet");
+ if( !m_xAspectRatio3D.is())
+ return;
+
+ try
+ {
+ double fScaleX = m_aPreferredAspectRatio.DirectionX;
+ double fScaleY = m_aPreferredAspectRatio.DirectionY;
+ double fScaleZ = m_aPreferredAspectRatio.DirectionZ;
+
+ //normalize scale factors
+ {
+ double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
+ fScaleX/=fMax;
+ fScaleY/=fMax;
+ fScaleZ/=fMax;
+ }
+
+ if( fScaleX<0 || fScaleY<0 || fScaleZ<0 )
+ {
+ //calculate automatic 3D aspect ratio that fits good into the given 2D area
+ double fW = rAvailableSize.Width;
+ double fH = rAvailableSize.Height;
+
+ double sx = fabs(sin(m_fXAnglePi));
+ double sy = fabs(sin(m_fYAnglePi));
+ double cz = fabs(cos(m_fZAnglePi));
+ double sz = fabs(sin(m_fZAnglePi));
+
+ if(m_bRightAngledAxes)
+ {
+ //base equations:
+ //fH*zoomfactor == sx*fScaleZ + fScaleY;
+ //fW*zoomfactor == sy*fScaleZ + fScaleX;
+
+ if( fScaleX>0 && fScaleZ>0 )
+ {
+ //calculate fScaleY:
+ if( !::basegfx::fTools::equalZero(fW) )
+ {
+ fScaleY = (fH/fW)*(sy*fScaleZ+fScaleX)-(sx*fScaleZ);
+ lcl_ensureScaleValue( fScaleY );
+ }
+ else
+ fScaleY = 1.0;//looking from top or bottom the height is irrelevant
+ }
+ else if( fScaleY>0 && fScaleZ>0 )
+ {
+ //calculate fScaleX:
+ if( !::basegfx::fTools::equalZero(fH) )
+ {
+ fScaleX = (fW/fH)*(sx*fScaleZ+fScaleY)-(sy*fScaleZ);
+ lcl_ensureScaleValue(fScaleX);
+ }
+ else
+ fScaleX = 1.0;//looking from top or bottom height is irrelevant
+ }
+ else
+ {
+ //todo
+ OSL_FAIL("not implemented yet");
+
+ if( fScaleX<0 )
+ fScaleX = 1.0;
+ if( fScaleY<0 )
+ fScaleY = 1.0;
+ if( fScaleZ<0 )
+ fScaleZ = 1.0;
+ }
+ }
+ else
+ {
+ //base equations:
+ //fH*zoomfactor == cz*fScaleY + sz*fScaleX;
+ //fW*zoomfactor == cz*fScaleX + sz*fScaleY;
+ //==> fScaleY*(fH*sz-fW*cz) == fScaleX*(fW*sz-fH*cz);
+ if( fScaleX>0 && fScaleZ>0 )
+ {
+ //calculate fScaleY:
+ double fDivide = fH*sz-fW*cz;
+ if( !::basegfx::fTools::equalZero(fDivide) )
+ {
+ fScaleY = fScaleX*(fW*sz-fH*cz) / fDivide;
+ lcl_ensureScaleValue(fScaleY);
+ }
+ else
+ fScaleY = 1.0;//looking from top or bottom the height is irrelevant
+
+ }
+ else if( fScaleY>0 && fScaleZ>0 )
+ {
+ //calculate fScaleX:
+ double fDivide = fW*sz-fH*cz;
+ if( !::basegfx::fTools::equalZero(fDivide) )
+ {
+ fScaleX = fScaleY*(fH*sz-fW*cz) / fDivide;
+ lcl_ensureScaleValue(fScaleX);
+ }
+ else
+ fScaleX = 1.0;//looking from top or bottom height is irrelevant
+ }
+ else
+ {
+ //todo
+ OSL_FAIL("not implemented yet");
+
+ if( fScaleX<0 )
+ fScaleX = 1.0;
+ if( fScaleY<0 )
+ fScaleY = 1.0;
+ if( fScaleZ<0 )
+ fScaleZ = 1.0;
+ }
+ }
+ }
+
+ //normalize scale factors
+ {
+ double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
+ fScaleX/=fMax;
+ fScaleY/=fMax;
+ fScaleZ/=fMax;
+ }
+
+ // identity matrix
+ ::basegfx::B3DHomMatrix aResult;
+ aResult.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
+ -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
+ -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
+ aResult.scale( fScaleX, fScaleY, fScaleZ );
+ aResult.translate( FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
+ FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
+ FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
+
+ // To get the 3D aspect ratio's effect on the 2D scene size, the scene's 2D size needs to be adapted to
+ // 3D content changes here. The tooling class remembers the current 3D transformation stack
+ // and in its destructor, calculates a new 2D SnapRect for the scene and it's modified 3D geometry.
+ E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));
+
+ m_xAspectRatio3D->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
+ , uno::Any(BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aResult )) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+::basegfx::B2IRectangle VDiagram::adjustPosAndSize_3d( const awt::Point& rPos, const awt::Size& rAvailableSize )
+{
+ adjustAspectRatio3d( rAvailableSize );
+
+ //do not change aspect ratio of 3D scene with 2D bound rect
+ m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
+ rAvailableSize, m_xOuterGroupShape->getSize() );
+ m_xOuterGroupShape->setSize( m_aCurrentSizeWithoutAxes );
+
+ //center diagram position
+ m_aCurrentPosWithoutAxes= ShapeFactory::calculateTopLeftPositionToCenterObject(
+ rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
+ m_xOuterGroupShape->setPosition(m_aCurrentPosWithoutAxes);
+
+ return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
+}
+
+void VDiagram::createShapes_3d()
+{
+ OSL_PRECOND(m_xTarget.is(), "is not proper initialized");
+ if (!m_xTarget.is())
+ return;
+
+ //create shape
+ rtl::Reference<Svx3DSceneObject> xShapes = ShapeFactory::createGroup3D( m_xTarget, "PlotAreaExcludingAxes" );
+ m_xOuterGroupShape = xShapes;
+
+ rtl::Reference<SvxShapeGroupAnyD> xOuterGroup_Shapes = m_xOuterGroupShape;
+
+ //create additional group to manipulate the aspect ratio of the whole diagram:
+ xOuterGroup_Shapes = ShapeFactory::createGroup3D( xOuterGroup_Shapes );
+
+ m_xAspectRatio3D = xOuterGroup_Shapes;
+
+ bool bAddFloorAndWall = m_xDiagram->isSupportingFloorAndWall();
+
+ const bool bDoubleSided = false;
+
+ //add walls
+ {
+ uno::Reference< beans::XPropertySet > xWallProp;
+ if( m_xDiagram.is() )
+ xWallProp.set( m_xDiagram->getWall() );
+
+ OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
+ if( !bAddFloorAndWall )
+ aWallCID.clear();
+ rtl::Reference<Svx3DSceneObject> xWallGroup_Shapes = ShapeFactory::createGroup3D( xOuterGroup_Shapes, aWallCID );
+
+ CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( m_xDiagram ) );
+ CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( m_xDiagram ) );
+
+ //add left wall
+ {
+ short nRotatedTexture = ( eBackWallPos==CuboidPlanePosition_Front ) ? 3 : 1;
+ double xPos = 0.0;
+ if( eLeftWallPos==CuboidPlanePosition_Right )
+ xPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
+ Stripe aStripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
+ , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
+ , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
+ if( eLeftWallPos==CuboidPlanePosition_Right )
+ {
+ nRotatedTexture = ( eBackWallPos==CuboidPlanePosition_Front ) ? 2 : 0;
+ aStripe = Stripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
+ , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
+ , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) );
+ }
+ aStripe.InvertNormal(true);
+
+ rtl::Reference<Svx3DPolygonObject> xShape =
+ ShapeFactory::createStripe( xWallGroup_Shapes, aStripe
+ , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture );
+ if( !bAddFloorAndWall )
+ {
+ //we always need this object as dummy object for correct scene dimensions
+ //but it should not be visible in this case:
+ ShapeFactory::makeShapeInvisible( xShape );
+ }
+ }
+ //add back wall
+ {
+ short nRotatedTexture = 0;
+ double zPos = 0.0;
+ if( eBackWallPos==CuboidPlanePosition_Front )
+ zPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
+ Stripe aStripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
+ , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
+ , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
+ if( eBackWallPos==CuboidPlanePosition_Front )
+ {
+ aStripe = Stripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
+ , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0)
+ , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
+ nRotatedTexture = 3;
+ }
+ aStripe.InvertNormal(true);
+
+ rtl::Reference<Svx3DPolygonObject> xShape =
+ ShapeFactory::createStripe(xWallGroup_Shapes, aStripe
+ , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture );
+ if( !bAddFloorAndWall )
+ {
+ //we always need this object as dummy object for correct scene dimensions
+ //but it should not be visible in this case:
+ ShapeFactory::makeShapeInvisible( xShape );
+ }
+ }
+ }
+
+ try
+ {
+ //perspective
+ {
+ //ignore distance and focal length from file format and model completely
+ //use vrp only to indicate the distance of the camera and thus influence the perspective
+ m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_DISTANCE, uno::Any(
+ static_cast<sal_Int32>(m_xDiagram->getCameraDistance())));
+ m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE,
+ m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE));
+ }
+
+ //light
+ {
+ m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE,
+ m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE));
+ m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR,
+ m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR));
+ m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING,
+ m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING));
+ lcl_setLightSources( m_xDiagram, m_xOuterGroupShape );
+ }
+
+ //rotation
+ {
+ //set diagrams rotation is set exclusively via the transformation matrix
+ //don't set a camera at all!
+ //the camera's rotation is incorporated into this matrix
+
+ ::basegfx::B3DHomMatrix aEffectiveTransformation;
+ aEffectiveTransformation.translate(-FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0);
+
+ if(!m_bRightAngledAxes)
+ aEffectiveTransformation.rotate(m_fXAnglePi,m_fYAnglePi,m_fZAnglePi);
+ else
+ aEffectiveTransformation.shearXY(m_fYAnglePi,-m_fXAnglePi);
+
+ //#i98497# 3D charts are rendered with wrong size
+ E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));
+
+ m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX,
+ uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTransformation ) ) );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+
+ //add floor plate
+ {
+ uno::Reference< beans::XPropertySet > xFloorProp;
+ if( m_xDiagram.is() )
+ xFloorProp.set( m_xDiagram->getFloor() );
+
+ Stripe aStripe( drawing::Position3D(0,0,0)
+ , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
+ , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
+ aStripe.InvertNormal(true);
+
+ rtl::Reference<Svx3DPolygonObject> xShape =
+ ShapeFactory::createStripe(xOuterGroup_Shapes, aStripe
+ , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided );
+
+ CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( m_xDiagram ) );
+ if( !bAddFloorAndWall || (eBottomPos!=CuboidPlanePosition_Bottom) )
+ {
+ //we always need this object as dummy object for correct scene dimensions
+ //but it should not be visible in this case:
+ ShapeFactory::makeShapeInvisible( xShape );
+ }
+ else
+ {
+ OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, u"" ) );//@todo read CID from model
+ ShapeFactory::setShapeName( xShape, aFloorCID );
+ }
+ }
+
+ //create an additional scene for the smaller inner coordinate region:
+ {
+ rtl::Reference<Svx3DSceneObject> xShapes2 = ShapeFactory::createGroup3D( xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID" );
+ m_xCoordinateRegionShape = xShapes2;
+
+ try
+ {
+ double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
+ double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
+ double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
+
+ ::basegfx::B3DHomMatrix aM;
+ aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale);
+ aM.scale( fXScale, fYScale, fZScale );
+ E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));
+
+ xShapes2->SvxShape::setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
+ , uno::Any(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+
+ m_aCurrentPosWithoutAxes = m_aAvailablePosIncludingAxes;
+ m_aCurrentSizeWithoutAxes = m_aAvailableSizeIncludingAxes;
+ adjustPosAndSize_3d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
+}
+
+basegfx::B2IRectangle VDiagram::getCurrentRectangle() const
+{
+ return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
+}
+
+void VDiagram::reduceToMinimumSize()
+{
+ if( !m_xOuterGroupShape.is() )
+ return;
+
+ awt::Size aMaxSize( m_aAvailableSizeIncludingAxes );
+ awt::Point aMaxPos( m_aAvailablePosIncludingAxes );
+
+ sal_Int32 nNewWidth = std::round(aMaxSize.Width/2.2);
+ sal_Int32 nNewHeight = std::round(aMaxSize.Height/2.2);
+ awt::Size aNewSize( nNewWidth, nNewHeight );
+ awt::Point aNewPos( aMaxPos );
+ aNewPos.X += nNewWidth;
+ aNewPos.Y += nNewHeight;
+
+ adjustPosAndSize( aNewPos, aNewSize );
+}
+
+::basegfx::B2IRectangle VDiagram::adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect )
+{
+ awt::Point aNewPos = m_aCurrentPosWithoutAxes;
+ awt::Size aNewSize = m_aCurrentSizeWithoutAxes;
+
+ basegfx::B2IRectangle aAvailableOuterRect =
+ BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes);
+
+ sal_Int32 nDeltaWidth = aAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth();
+ sal_Int32 nDeltaHeight = aAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight();
+ if( (aNewSize.Width + nDeltaWidth) < aAvailableOuterRect.getWidth()/3 )
+ nDeltaWidth = aAvailableOuterRect.getWidth()/3 - aNewSize.Width;
+ aNewSize.Width += nDeltaWidth;
+
+ if( (aNewSize.Height + nDeltaHeight) < aAvailableOuterRect.getHeight()/3 )
+ nDeltaHeight = aAvailableOuterRect.getHeight()/3 - aNewSize.Height;
+ aNewSize.Height += nDeltaHeight;
+
+ sal_Int32 nDiffLeft = rConsumedOuterRect.getMinX() - aAvailableOuterRect.getMinX();
+ sal_Int32 nDiffRight = aAvailableOuterRect.getMaxX() - rConsumedOuterRect.getMaxX();
+ if( nDiffLeft >= 0 )
+ aNewPos.X -= nDiffLeft;
+ else if( nDiffRight >= 0 )
+ {
+ if( nDiffRight > -nDiffLeft )
+ aNewPos.X += abs(nDiffLeft);
+ else if( nDiffRight > abs(nDeltaWidth) )
+ aNewPos.X += nDiffRight;
+ else
+ aNewPos.X += abs(nDeltaWidth);
+ }
+
+ sal_Int32 nDiffUp = rConsumedOuterRect.getMinY() - aAvailableOuterRect.getMinY();
+ sal_Int32 nDiffDown = aAvailableOuterRect.getMaxY() - rConsumedOuterRect.getMaxY();
+ if( nDiffUp >= 0 )
+ aNewPos.Y -= nDiffUp;
+ else if( nDiffDown >= 0 )
+ {
+ if( nDiffDown > -nDiffUp )
+ aNewPos.Y += abs(nDiffUp);
+ else if( nDiffDown > abs(nDeltaHeight) )
+ aNewPos.Y += nDiffDown;
+ else
+ aNewPos.Y += abs(nDeltaHeight);
+ }
+
+ return adjustPosAndSize( aNewPos, aNewSize );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/Clipping.hxx b/chart2/source/view/inc/Clipping.hxx
new file mode 100644
index 0000000000..e816e7aa79
--- /dev/null
+++ b/chart2/source/view/inc/Clipping.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <basegfx/range/b2drectangle.hxx>
+
+namespace com::sun::star::drawing { struct PolyPolygonShape3D; }
+namespace com::sun::star::drawing { struct Position3D; }
+
+namespace chart
+{
+
+class Clipping
+{
+ /** This class uses the Liang-Biarsky parametric line-clipping algorithm as described in:
+ Computer Graphics: principles and practice, 2nd ed.,
+ James D. Foley et al.,
+ Section 3.12.4 on page 117.
+ */
+
+public:
+ /** @descr The intersection between an open polygon and a rectangle is
+ calculated and the resulting lines are placed into the poly-polygon aResult.
+ @param rPolygon The polygon is required to be open, ie. its start and end point
+ have different coordinates and that it is continuous, ie. has no holes.
+ @param rRectangle The clipping area.
+ @param aResult The resulting lines that are the parts of the given polygon lying inside
+ the clipping area are stored into aResult whose prior content is deleted first.
+ */
+ static void clipPolygonAtRectangle(
+ const css::drawing::PolyPolygonShape3D& rPolygon
+ , const ::basegfx::B2DRectangle& rRectangle
+ , css::drawing::PolyPolygonShape3D& aResult
+ , bool bSplitPiecesToDifferentPolygons = true );
+ static void clipPolygonAtRectangle(
+ const std::vector<std::vector<css::drawing::Position3D>>& rPolygon
+ , const ::basegfx::B2DRectangle& rRectangle
+ , std::vector<std::vector<css::drawing::Position3D>>& aResult
+ , bool bSplitPiecesToDifferentPolygons = true );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/DataTableView.hxx b/chart2/source/view/inc/DataTableView.hxx
new file mode 100644
index 0000000000..0bccaaddde
--- /dev/null
+++ b/chart2/source/view/inc/DataTableView.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+#pragma once
+
+#include <svx/unoshape.hxx>
+#include <svx/unodraw/SvxTableShape.hxx>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/table/XTable.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <DataTable.hxx>
+#include "VLineProperties.hxx"
+
+namespace chart
+{
+class VSeriesPlotter;
+class ChartModel;
+class LegendEntryProvider;
+
+/**
+ * DataTableView is responsible to create the table object, set the cell
+ * properties accordingly to the model and fill it with the chart series
+ * data.
+ */
+class DataTableView final
+{
+private:
+ rtl::Reference<::chart::ChartModel> m_xChartModel;
+ // the target shape
+ rtl::Reference<SvxShapeGroupAnyD> m_xTarget;
+ // the data table shape
+ rtl::Reference<SvxTableShape> m_xTableShape;
+ // the data table model
+ rtl::Reference<DataTable> m_xDataTableModel;
+ css::uno::Reference<css::uno::XComponentContext> m_xComponentContext;
+ css::uno::Reference<css::table::XTable> m_xTable;
+ VLineProperties m_aLineProperties;
+ std::vector<VSeriesPlotter*> m_pSeriesPlotterList;
+
+ // data series names
+ std::vector<OUString> m_aDataSeriesNames;
+ // X axis names
+ std::vector<OUString> m_aXValues;
+ // list of data series values
+ std::vector<std::vector<OUString>> m_pDataSeriesValues;
+
+ // if the header vales should be aligned with the x-axis vales
+ bool m_bAlignAxisValuesWithColumns;
+
+ /** Set the char and paragraph properties for the input (value) cell */
+ void
+ setCellCharAndParagraphProperties(css::uno::Reference<css::beans::XPropertySet>& xPropertySet);
+
+ /** Set the common cell properties (for all cells in the data table,
+ * including headers)
+ */
+ void setCellProperties(css::uno::Reference<css::beans::XPropertySet>& xPropertySet, bool bLeft,
+ bool bTop, bool bRight, bool bBottom);
+
+public:
+ DataTableView(rtl::Reference<::chart::ChartModel> const& xChartDoc,
+ rtl::Reference<DataTable> const& rDataTableModel,
+ css::uno::Reference<css::uno::XComponentContext> const& rComponentContext,
+ bool bAlignAxisValuesWithColumns);
+
+ /** Initializes and prepares the target and data table shape */
+ void initializeShapes(const rtl::Reference<SvxShapeGroupAnyD>& xTarget);
+
+ /** Prepares the values of the chart, which will be shown it the data table */
+ void initializeValues(std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList);
+
+ /** Creates the data table and fills the values */
+ void createShapes(basegfx::B2DVector const& rStart, basegfx::B2DVector const& rEnd,
+ sal_Int32 nAxisStepWidth);
+
+ /** Repositions the data table shape */
+ void changePosition(sal_Int32 x, sal_Int32 y);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/DateHelper.hxx b/chart2/source/view/inc/DateHelper.hxx
new file mode 100644
index 0000000000..8c37851b7d
--- /dev/null
+++ b/chart2/source/view/inc/DateHelper.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <tools/date.hxx>
+#include <tools/long.hxx>
+
+namespace chart
+{
+
+class DateHelper
+{
+public:
+ static bool IsInSameYear( const Date& rD1, const Date& rD2 );
+ static bool IsInSameMonth( const Date& rD1, const Date& rD2 );
+
+ static Date GetDateSomeMonthsAway( const Date& rD, sal_Int32 nMonthDistance );
+ static Date GetDateSomeYearsAway( const Date& rD, sal_Int32 nYearDistance );
+ static bool IsLessThanOneMonthAway( const Date& rD1, const Date& rD2 );
+ static bool IsLessThanOneYearAway( const Date& rD1, const Date& rD2 );
+
+ static double RasterizeDateValue( double fValue, const Date& rNullDate, tools::Long TimeResolution );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/LabelAlignment.hxx b/chart2/source/view/inc/LabelAlignment.hxx
new file mode 100644
index 0000000000..425f5c6c3e
--- /dev/null
+++ b/chart2/source/view/inc/LabelAlignment.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+namespace chart
+{
+enum LabelAlignment
+{
+ LABEL_ALIGN_CENTER,
+ LABEL_ALIGN_LEFT,
+ LABEL_ALIGN_TOP,
+ LABEL_ALIGN_RIGHT,
+ LABEL_ALIGN_BOTTOM,
+ LABEL_ALIGN_LEFT_TOP,
+ LABEL_ALIGN_LEFT_BOTTOM,
+ LABEL_ALIGN_RIGHT_TOP,
+ LABEL_ALIGN_RIGHT_BOTTOM
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/LabelPositionHelper.hxx b/chart2/source/view/inc/LabelPositionHelper.hxx
new file mode 100644
index 0000000000..4f2f3ba279
--- /dev/null
+++ b/chart2/source/view/inc/LabelPositionHelper.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "LabelAlignment.hxx"
+#include "PropertyMapper.hxx"
+#include <com/sun/star/awt/Point.hpp>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+
+namespace com::sun::star::drawing { struct Position3D; }
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::drawing { class XShape; }
+
+namespace chart
+{
+
+class LabelPositionHelper
+{
+public:
+ LabelPositionHelper() = delete;
+ LabelPositionHelper(
+ sal_Int32 nDimensionCount
+ , rtl::Reference<SvxShapeGroupAnyD> xLogicTarget );
+ virtual ~LabelPositionHelper();
+
+ css::awt::Point transformSceneToScreenPosition(
+ const css::drawing::Position3D& rScenePosition3D ) const;
+
+ static void changeTextAdjustment( tAnySequence& rPropValues, const tNameSequence& rPropNames, LabelAlignment eAlignment);
+ static void doDynamicFontResize( tAnySequence& rPropValues, const tNameSequence& rPropNames
+ , const css::uno::Reference< css::beans::XPropertySet >& xAxisModelProps
+ , const css::awt::Size& rNewReferenceSize );
+
+ static void correctPositionForRotation( const rtl::Reference<SvxShapeText>& xShape2DText
+ , LabelAlignment eLabelAlignment, const double fRotationAngle, bool bRotateAroundCenter );
+
+protected:
+ sal_Int32 m_nDimensionCount;
+
+private:
+ //these members are only necessary for transformation from 3D to 2D
+ rtl::Reference<SvxShapeGroupAnyD> m_xLogicTarget;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/LegendEntryProvider.hxx b/chart2/source/view/inc/LegendEntryProvider.hxx
new file mode 100644
index 0000000000..ce7722b0ed
--- /dev/null
+++ b/chart2/source/view/inc/LegendEntryProvider.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart2/XFormattedString2.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+#include <vector>
+
+namespace chart { class ChartModel; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::drawing { class XShape; }
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+class FormattedString;
+
+enum class LegendSymbolStyle
+{
+ /** A square box with border.
+ */
+ Box,
+
+ /** A line like with a symbol.
+ */
+ Line,
+
+ /** A bordered circle which has the same bounding-box as the
+ <member>BOX</member>.
+ */
+ Circle
+};
+
+struct ViewLegendEntry
+{
+ /** The legend symbol that represents a data series or other
+ information contained in the legend
+ */
+ rtl::Reference< SvxShapeGroup > xSymbol;
+
+ /** The descriptive text for a legend entry.
+ */
+ rtl::Reference< ::chart::FormattedString > xLabel;
+};
+
+
+struct ViewLegendSymbol
+{
+ /** The legend symbol that represents a data series or other
+ information contained in the legend
+ */
+ rtl::Reference<SvxShapeGroup> xSymbol;
+};
+
+class LegendEntryProvider
+{
+public:
+ virtual css::awt::Size getPreferredLegendKeyAspectRatio()=0;
+
+ virtual std::vector< ViewLegendEntry > createLegendEntries(
+ const css::awt::Size& rEntryKeyAspectRatio,
+ css::chart2::LegendPosition eLegendPosition,
+ const css::uno::Reference< css::beans::XPropertySet >& xTextProperties,
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const css::uno::Reference< css::uno::XComponentContext >& xContext,
+ ChartModel& rModel
+ ) = 0;
+
+protected:
+ ~LegendEntryProvider() {}
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/Linear3DTransformation.hxx b/chart2/source/view/inc/Linear3DTransformation.hxx
new file mode 100644
index 0000000000..456f6e4c4b
--- /dev/null
+++ b/chart2/source/view/inc/Linear3DTransformation.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "PlottingPositionHelper.hxx"
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+
+namespace chart
+{
+
+class Linear3DTransformation final : public XTransformation2
+{
+public:
+ Linear3DTransformation( const css::drawing::HomogenMatrix& rHomMatrix, bool bSwapXAndY );
+ virtual ~Linear3DTransformation() override;
+
+ // ____ XTransformation2 ____
+ virtual css::drawing::Position3D transform(
+ const css::drawing::Position3D& rSourceValues ) const override;
+ virtual css::drawing::Position3D transform(
+ const css::uno::Sequence< double >& rSourceValues ) const override;
+
+private:
+ css::drawing::HomogenMatrix m_Matrix;
+ bool m_bSwapXAndY;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/MinimumAndMaximumSupplier.hxx b/chart2/source/view/inc/MinimumAndMaximumSupplier.hxx
new file mode 100644
index 0000000000..cbb5e55ba7
--- /dev/null
+++ b/chart2/source/view/inc/MinimumAndMaximumSupplier.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <tools/date.hxx>
+#include <tools/long.hxx>
+#include <set>
+
+namespace chart
+{
+
+class MinimumAndMaximumSupplier
+{
+public:
+ virtual double getMinimumX() = 0;
+ virtual double getMaximumX() = 0;
+
+ //problem y maybe not is always the second border to ask for
+ virtual double getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) = 0;
+ virtual double getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) = 0;
+
+ //problem: z maybe not independent in future
+ virtual double getMinimumZ() = 0;
+ virtual double getMaximumZ() = 0;
+
+ virtual bool isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex ) = 0;
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex ) = 0;
+ virtual bool isExpandWideValuesToZero( sal_Int32 nDimensionIndex ) = 0;
+ virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex ) = 0;
+ virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) = 0;
+
+ //return a constant out of css::chart::TimeUnit that allows to display the smallest distance between occurring dates
+ virtual tools::Long calculateTimeResolutionOnXAxis() = 0;
+ virtual void setTimeResolutionOnXAxis( tools::Long nTimeResolution, const Date& rNullDate ) = 0;
+
+protected:
+ ~MinimumAndMaximumSupplier() {}
+};
+
+class MergedMinimumAndMaximumSupplier final : public MinimumAndMaximumSupplier
+{
+public:
+ MergedMinimumAndMaximumSupplier();
+ virtual ~MergedMinimumAndMaximumSupplier();
+
+ void addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier );
+ bool hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier );
+ void clearMinimumAndMaximumSupplierList();
+
+ //--MinimumAndMaximumSupplier
+ virtual double getMinimumX() override;
+ virtual double getMaximumX() override;
+ virtual double getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) override;
+ virtual double getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) override;
+ virtual double getMinimumZ() override;
+ virtual double getMaximumZ() override;
+
+ virtual bool isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex ) override;
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex ) override;
+ virtual bool isExpandWideValuesToZero( sal_Int32 nDimensionIndex ) override;
+ virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex ) override;
+ virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) override;
+
+ virtual tools::Long calculateTimeResolutionOnXAxis() override;
+ virtual void setTimeResolutionOnXAxis( tools::Long nTimeResolution, const Date& rNullDate ) override;
+
+private:
+ typedef std::set< MinimumAndMaximumSupplier* > MinimumAndMaximumSupplierSet;
+ MinimumAndMaximumSupplierSet m_aMinimumAndMaximumSupplierList;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/PlotterBase.hxx b/chart2/source/view/inc/PlotterBase.hxx
new file mode 100644
index 0000000000..73695507fd
--- /dev/null
+++ b/chart2/source/view/inc/PlotterBase.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <svx/unoshape.hxx>
+#include <vector>
+
+namespace com::sun::star::drawing { struct HomogenMatrix; }
+namespace com::sun::star::drawing { struct Position3D; }
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+
+namespace chart { struct ExplicitScaleData; }
+
+namespace chart
+{
+
+class PlottingPositionHelper;
+class ShapeFactory;
+
+/** This class provides methods for setting axis scales and for performing
+ * scene to screen transformations. It is used as the base class for all
+ * plotter classes.
+ */
+class PlotterBase
+{
+public:
+ PlotterBase( sal_Int32 nDimension );
+ virtual ~PlotterBase();
+
+ /// @throws css::uno::RuntimeException
+ virtual void initPlotter(
+ const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget
+ , const rtl::Reference<SvxShapeGroupAnyD>& xFinalTarget
+ , const OUString& rCID
+ );
+
+ virtual void setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis );
+
+ virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix );
+
+ virtual void createShapes() = 0;
+
+ static bool isValidPosition( const css::drawing::Position3D& rPos );
+
+protected: //methods
+ rtl::Reference< SvxShapeGroupAnyD >
+ createGroupShape( const rtl::Reference< SvxShapeGroupAnyD >& xTarget
+ , const OUString& rName=OUString() );
+
+protected: //member
+ rtl::Reference< SvxShapeGroupAnyD > m_xLogicTarget;
+ rtl::Reference< SvxShapeGroupAnyD > m_xFinalTarget;
+ OUString m_aCID;
+
+ const sal_Int32 m_nDimension;
+ // needs to be created and deleted by the derived class
+ PlottingPositionHelper* m_pPosHelper;
+};
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/PlottingPositionHelper.hxx b/chart2/source/view/inc/PlottingPositionHelper.hxx
new file mode 100644
index 0000000000..916668dd6c
--- /dev/null
+++ b/chart2/source/view/inc/PlottingPositionHelper.hxx
@@ -0,0 +1,463 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <chartview/ExplicitScaleValues.hxx>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <tools/long.hxx>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::drawing { struct HomogenMatrix; }
+namespace com::sun::star::drawing { struct PolyPolygonShape3D; }
+
+namespace chart
+{
+
+class ShapeFactory;
+
+/** allows the transformation of numeric values from one
+ coordinate-system into another. Values may be transformed using
+ any mapping.
+ This is a non-UNO variant of the css::chart2::XTransformation interface,
+ but using more efficient calling and returning types.
+ */
+class XTransformation2
+{
+public:
+ virtual ~XTransformation2();
+ /** transforms the given input data tuple, given in the source
+ coordinate system, according to the internal transformation
+ rules, into a tuple of transformed coordinates in the
+ destination coordinate system.
+
+ <p>Note that both coordinate systems may have different
+ dimensions, e.g., if a transformation does simply a projection
+ into a lower-dimensional space.</p>
+
+ @param aValues a source tuple of data that is to be
+ transformed. The length of this sequence must be
+ equivalent to the dimension of the source coordinate
+ system.
+
+ @return the transformed data tuple. The length of this
+ sequence is equal to the dimension of the output
+ coordinate system.
+
+ @throws ::com::sun::star::lang::IllegalArgumentException
+ if the dimension of the input vector is not equal to the
+ dimension given in getSourceDimension().
+ */
+ virtual css::drawing::Position3D transform(
+ const css::drawing::Position3D& rSourceValues ) const = 0;
+ virtual css::drawing::Position3D transform(
+ const css::uno::Sequence< double >& rSourceValues ) const = 0;
+};
+
+
+class PlottingPositionHelper
+{
+public:
+ PlottingPositionHelper();
+ PlottingPositionHelper( const PlottingPositionHelper& rSource );
+ virtual ~PlottingPositionHelper();
+
+ virtual std::unique_ptr<PlottingPositionHelper> clone() const;
+ std::unique_ptr<PlottingPositionHelper> createSecondaryPosHelper( const ExplicitScaleData& rSecondaryScale );
+
+ virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix);
+
+ virtual void setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis );
+ const std::vector< ExplicitScaleData >& getScales() const { return m_aScales;}
+
+ //better performance for big data
+ inline void setCoordinateSystemResolution( const css::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution );
+ inline bool isSameForGivenResolution( double fX, double fY, double fZ
+ , double fX2, double fY2, double fZ2 );
+
+ inline bool isStrongLowerRequested( sal_Int32 nDimensionIndex ) const;
+ inline bool isLogicVisible( double fX, double fY, double fZ ) const;
+ inline void doLogicScaling( double* pX, double* pY, double* pZ ) const;
+ inline void doUnshiftedLogicScaling( double* pX, double* pY, double* pZ ) const;
+ inline void clipLogicValues( double* pX, double* pY, double* pZ ) const;
+ void clipScaledLogicValues( double* pX, double* pY, double* pZ ) const;
+ inline bool clipYRange( double& rMin, double& rMax ) const;
+
+ inline void doLogicScaling( css::drawing::Position3D& rPos ) const;
+
+ virtual ::chart::XTransformation2*
+ getTransformationScaledLogicToScene() const;
+
+ virtual css::drawing::Position3D
+ transformLogicToScene( double fX, double fY, double fZ, bool bClip ) const;
+
+ virtual css::drawing::Position3D
+ transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const;
+
+ void transformScaledLogicToScene( css::drawing::PolyPolygonShape3D& rPoly ) const;
+ void transformScaledLogicToScene( std::vector<std::vector<css::drawing::Position3D>>& rPoly ) const;
+
+ static css::awt::Point transformSceneToScreenPosition(
+ const css::drawing::Position3D& rScenePosition3D
+ , const rtl::Reference<SvxShapeGroupAnyD>& xSceneTarget
+ , sal_Int32 nDimensionCount );
+
+ inline double getLogicMinX() const;
+ inline double getLogicMinY() const;
+ inline double getLogicMinZ() const;
+ inline double getLogicMaxX() const;
+ inline double getLogicMaxY() const;
+ inline double getLogicMaxZ() const;
+
+ inline bool isMathematicalOrientationX() const;
+ inline bool isMathematicalOrientationY() const;
+ inline bool isMathematicalOrientationZ() const;
+
+ ::basegfx::B2DRectangle getScaledLogicClipDoubleRect() const;
+ css::drawing::Direction3D getScaledLogicWidth() const;
+
+ inline bool isSwapXAndY() const;
+
+ bool isPercentY() const;
+
+ double getBaseValueY() const;
+
+ inline bool maySkipPointsInRegressionCalculation() const;
+
+ void setTimeResolution( tools::Long nTimeResolution, const Date& rNullDate );
+ virtual void setScaledCategoryWidth( double fScaledCategoryWidth );
+ void AllowShiftXAxisPos( bool bAllowShift );
+ void AllowShiftZAxisPos( bool bAllowShift );
+
+protected: //member
+ std::vector< ExplicitScaleData > m_aScales;
+ ::basegfx::B3DHomMatrix m_aMatrixScreenToScene;
+
+ //this is calculated based on m_aScales and m_aMatrixScreenToScene
+ mutable std::unique_ptr< ::chart::XTransformation2 > m_xTransformationLogicToScene;
+
+ bool m_bSwapXAndY;//e.g. true for bar chart and false for column chart
+
+ sal_Int32 m_nXResolution;
+ sal_Int32 m_nYResolution;
+ sal_Int32 m_nZResolution;
+
+ bool m_bMaySkipPointsInRegressionCalculation;
+
+ bool m_bDateAxis;
+ tools::Long m_nTimeResolution;
+ Date m_aNullDate;
+
+ double m_fScaledCategoryWidth;
+ bool m_bAllowShiftXAxisPos;
+ bool m_bAllowShiftZAxisPos;
+};
+
+class PolarPlottingPositionHelper : public PlottingPositionHelper
+{
+public:
+ PolarPlottingPositionHelper();
+ PolarPlottingPositionHelper( const PolarPlottingPositionHelper& rSource );
+ virtual ~PolarPlottingPositionHelper() override;
+
+ virtual std::unique_ptr<PlottingPositionHelper> clone() const override;
+
+ virtual void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix) override;
+ virtual void setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis ) override;
+
+ const ::basegfx::B3DHomMatrix& getUnitCartesianToScene() const { return m_aUnitCartesianToScene;}
+
+ virtual ::chart::XTransformation2*
+ getTransformationScaledLogicToScene() const override;
+
+ //the resulting values provided by the following 3 methods should be used
+ //for input to the transformation received with
+ //'getTransformationScaledLogicToScene'
+
+ /** Given a value in the radius axis scale range, it returns the normalized
+ * value.
+ */
+ double transformToRadius( double fLogicValueOnRadiusAxis, bool bDoScaling=true ) const;
+
+ /** Given a value in the angle axis scale range (e.g. [0,1] for pie charts)
+ * this method returns the related angle in degree.
+ */
+ double transformToAngleDegree( double fLogicValueOnAngleAxis, bool bDoScaling=true ) const;
+
+ /** Given 2 values in the angle axis scale range (e.g. [0,1] for pie charts)
+ * this method returns the angle between the 2 values keeping into account
+ * the correct axis orientation; (for instance, this method is used for
+ * computing the angle width of a pie slice).
+ */
+ double getWidthAngleDegree( double& fStartLogicValueOnAngleAxis, double& fEndLogicValueOnAngleAxis ) const;
+
+ virtual css::drawing::Position3D
+ transformLogicToScene( double fX, double fY, double fZ, bool bClip ) const override;
+ virtual css::drawing::Position3D
+ transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const override;
+ css::drawing::Position3D
+ transformAngleRadiusToScene( double fLogicValueOnAngleAxis, double fLogicValueOnRadiusAxis, double fLogicZ, bool bDoScaling=true ) const;
+
+ /** It returns the scene coordinates of the passed point: this point is
+ * described through a normalized cylindrical coordinate system.
+ * (For a pie chart the origin of the coordinate system is the pie center).
+ */
+ css::drawing::Position3D
+ transformUnitCircleToScene( double fUnitAngleDegree, double fUnitRadius, double fLogicZ ) const;
+
+ using PlottingPositionHelper::transformScaledLogicToScene;
+
+ double getOuterLogicRadius() const;
+
+ inline bool isMathematicalOrientationAngle() const;
+ inline bool isMathematicalOrientationRadius() const;
+public:
+ ///m_bSwapXAndY (inherited): by default the X axis (scale[0]) represents
+ ///the angle axis and the Y axis (scale[1]) represents the radius axis;
+ ///when this parameter is true, the opposite happens (this is the case for
+ ///pie charts).
+
+ ///Offset for radius axis in absolute logic scaled values (1.0 == 1 category)
+ ///For a donut, it represents the non-normalized inner radius (see notes for
+ ///transformToRadius)
+ double m_fRadiusOffset;
+ ///Offset for angle axis in real degree.
+ ///For a pie it represents the angle offset at which the first slice have to
+ ///start;
+ double m_fAngleDegreeOffset;
+
+private:
+ ::basegfx::B3DHomMatrix m_aUnitCartesianToScene;
+
+ ::basegfx::B3DHomMatrix impl_calculateMatrixUnitCartesianToScene( const ::basegfx::B3DHomMatrix& rMatrixScreenToScene ) const;
+};
+
+bool PolarPlottingPositionHelper::isMathematicalOrientationAngle() const
+{
+ const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[2];
+ if( css::chart2::AxisOrientation_MATHEMATICAL==rScale.Orientation )
+ return true;
+ return false;
+}
+bool PolarPlottingPositionHelper::isMathematicalOrientationRadius() const
+{
+ const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
+ if( css::chart2::AxisOrientation_MATHEMATICAL==rScale.Orientation )
+ return true;
+ return false;
+}
+
+//better performance for big data
+void PlottingPositionHelper::setCoordinateSystemResolution( const css::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution )
+{
+ m_nXResolution = 1000;
+ m_nYResolution = 1000;
+ m_nZResolution = 1000;
+ if( rCoordinateSystemResolution.getLength() > 0 )
+ m_nXResolution = rCoordinateSystemResolution[0];
+ if( rCoordinateSystemResolution.getLength() > 1 )
+ m_nYResolution = rCoordinateSystemResolution[1];
+ if( rCoordinateSystemResolution.getLength() > 2 )
+ m_nZResolution = rCoordinateSystemResolution[2];
+}
+
+bool PlottingPositionHelper::isSameForGivenResolution( double fX, double fY, double fZ
+ , double fX2, double fY2, double fZ2 /*these values are all expected tp be scaled already*/ )
+{
+ if( !std::isfinite(fX) || !std::isfinite(fY) || !std::isfinite(fZ)
+ || !std::isfinite(fX2) || !std::isfinite(fY2) || !std::isfinite(fZ2) )
+ return false;
+
+ double fScaledMinX = getLogicMinX();
+ double fScaledMinY = getLogicMinY();
+ double fScaledMinZ = getLogicMinZ();
+ double fScaledMaxX = getLogicMaxX();
+ double fScaledMaxY = getLogicMaxY();
+ double fScaledMaxZ = getLogicMaxZ();
+
+ doLogicScaling( &fScaledMinX, &fScaledMinY, &fScaledMinZ );
+ doLogicScaling( &fScaledMaxX, &fScaledMaxY, &fScaledMaxZ);
+
+ bool bSameX = ( static_cast<sal_Int32>(m_nXResolution*(fX - fScaledMinX)/(fScaledMaxX-fScaledMinX))
+ == static_cast<sal_Int32>(m_nXResolution*(fX2 - fScaledMinX)/(fScaledMaxX-fScaledMinX)) );
+
+ bool bSameY = ( static_cast<sal_Int32>(m_nYResolution*(fY - fScaledMinY)/(fScaledMaxY-fScaledMinY))
+ == static_cast<sal_Int32>(m_nYResolution*(fY2 - fScaledMinY)/(fScaledMaxY-fScaledMinY)) );
+
+ bool bSameZ = ( static_cast<sal_Int32>(m_nZResolution*(fZ - fScaledMinZ)/(fScaledMaxZ-fScaledMinZ))
+ == static_cast<sal_Int32>(m_nZResolution*(fZ2 - fScaledMinZ)/(fScaledMaxZ-fScaledMinZ)) );
+
+ return (bSameX && bSameY && bSameZ);
+}
+
+bool PlottingPositionHelper::isStrongLowerRequested( sal_Int32 nDimensionIndex ) const
+{
+ if( m_aScales.empty() )
+ return false;
+ if( 0==nDimensionIndex )
+ return m_bAllowShiftXAxisPos && m_aScales[nDimensionIndex].m_bShiftedCategoryPosition;
+ else if( 2==nDimensionIndex )
+ return m_bAllowShiftZAxisPos && m_aScales[nDimensionIndex].m_bShiftedCategoryPosition;
+ return false;
+}
+
+bool PlottingPositionHelper::isLogicVisible(
+ double fX, double fY, double fZ ) const
+{
+ return fX >= m_aScales[0].Minimum && ( isStrongLowerRequested(0) ? fX < m_aScales[0].Maximum : fX <= m_aScales[0].Maximum )
+ && fY >= m_aScales[1].Minimum && fY <= m_aScales[1].Maximum
+ && fZ >= m_aScales[2].Minimum && ( isStrongLowerRequested(2) ? fZ < m_aScales[2].Maximum : fZ <= m_aScales[2].Maximum );
+}
+
+void PlottingPositionHelper::doLogicScaling( double* pX, double* pY, double* pZ ) const
+{
+ if(pX)
+ {
+ if( m_aScales[0].Scaling.is())
+ *pX = m_aScales[0].Scaling->doScaling(*pX);
+ if( m_bAllowShiftXAxisPos && m_aScales[0].m_bShiftedCategoryPosition )
+ (*pX) += m_fScaledCategoryWidth/2.0;
+ }
+ if(pY && m_aScales[1].Scaling.is())
+ *pY = m_aScales[1].Scaling->doScaling(*pY);
+ if(pZ)
+ {
+ if( m_aScales[2].Scaling.is())
+ *pZ = m_aScales[2].Scaling->doScaling(*pZ);
+ if( m_bAllowShiftZAxisPos && m_aScales[2].m_bShiftedCategoryPosition)
+ (*pZ) += 0.5;
+ }
+}
+
+void PlottingPositionHelper::doUnshiftedLogicScaling( double* pX, double* pY, double* pZ ) const
+{
+ if(pX && m_aScales[0].Scaling.is())
+ *pX = m_aScales[0].Scaling->doScaling(*pX);
+ if(pY && m_aScales[1].Scaling.is())
+ *pY = m_aScales[1].Scaling->doScaling(*pY);
+ if(pZ && m_aScales[2].Scaling.is())
+ *pZ = m_aScales[2].Scaling->doScaling(*pZ);
+}
+
+void PlottingPositionHelper::doLogicScaling( css::drawing::Position3D& rPos ) const
+{
+ doLogicScaling( &rPos.PositionX, &rPos.PositionY, &rPos.PositionZ );
+}
+
+void PlottingPositionHelper::clipLogicValues( double* pX, double* pY, double* pZ ) const
+{
+ if(pX)
+ {
+ if( *pX < m_aScales[0].Minimum )
+ *pX = m_aScales[0].Minimum;
+ else if( *pX > m_aScales[0].Maximum )
+ *pX = m_aScales[0].Maximum;
+ }
+ if(pY)
+ {
+ if( *pY < m_aScales[1].Minimum )
+ *pY = m_aScales[1].Minimum;
+ else if( *pY > m_aScales[1].Maximum )
+ *pY = m_aScales[1].Maximum;
+ }
+ if(pZ)
+ {
+ if( *pZ < m_aScales[2].Minimum )
+ *pZ = m_aScales[2].Minimum;
+ else if( *pZ > m_aScales[2].Maximum )
+ *pZ = m_aScales[2].Maximum;
+ }
+}
+
+inline bool PlottingPositionHelper::clipYRange( double& rMin, double& rMax ) const
+{
+ //returns true if something remains
+ if( rMin > rMax )
+ std::swap( rMin, rMax );
+ if( rMin > getLogicMaxY() )
+ return false;
+ if( rMax < getLogicMinY() )
+ return false;
+ if( rMin < getLogicMinY() )
+ rMin = getLogicMinY();
+ if( rMax > getLogicMaxY() )
+ rMax = getLogicMaxY();
+ return true;
+}
+
+inline double PlottingPositionHelper::getLogicMinX() const
+{
+ return m_aScales[0].Minimum;
+}
+inline double PlottingPositionHelper::getLogicMinY() const
+{
+ return m_aScales[1].Minimum;
+}
+inline double PlottingPositionHelper::getLogicMinZ() const
+{
+ return m_aScales[2].Minimum;
+}
+
+inline double PlottingPositionHelper::getLogicMaxX() const
+{
+ return m_aScales[0].Maximum;
+}
+inline double PlottingPositionHelper::getLogicMaxY() const
+{
+ return m_aScales[1].Maximum;
+}
+inline double PlottingPositionHelper::getLogicMaxZ() const
+{
+ return m_aScales[2].Maximum;
+}
+inline bool PlottingPositionHelper::isMathematicalOrientationX() const
+{
+ return css::chart2::AxisOrientation_MATHEMATICAL == m_aScales[0].Orientation;
+}
+inline bool PlottingPositionHelper::isMathematicalOrientationY() const
+{
+ return css::chart2::AxisOrientation_MATHEMATICAL == m_aScales[1].Orientation;
+}
+inline bool PlottingPositionHelper::isMathematicalOrientationZ() const
+{
+ return css::chart2::AxisOrientation_MATHEMATICAL == m_aScales[2].Orientation;
+}
+inline bool PlottingPositionHelper::isSwapXAndY() const
+{
+ return m_bSwapXAndY;
+}
+inline bool PlottingPositionHelper::maySkipPointsInRegressionCalculation() const
+{
+ return m_bMaySkipPointsInRegressionCalculation;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/PolarLabelPositionHelper.hxx b/chart2/source/view/inc/PolarLabelPositionHelper.hxx
new file mode 100644
index 0000000000..84f4ff1dc8
--- /dev/null
+++ b/chart2/source/view/inc/PolarLabelPositionHelper.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "LabelPositionHelper.hxx"
+#include <com/sun/star/awt/Point.hpp>
+
+namespace chart
+{
+
+class PolarPlottingPositionHelper;
+
+class PolarLabelPositionHelper final : public LabelPositionHelper
+{
+public:
+ PolarLabelPositionHelper(
+ PolarPlottingPositionHelper* pPosHelper
+ , sal_Int32 nDimensionCount
+ , const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget );
+ virtual ~PolarLabelPositionHelper() override;
+
+ css::awt::Point getLabelScreenPositionAndAlignmentForLogicValues(
+ LabelAlignment& rAlignment
+ , double fLogicValueOnAngleAxis
+ , double fLogicValueOnRadiusAxis
+ , double fLogicZ
+ , sal_Int32 nScreenValueOffsetInRadiusDirection ) const;
+
+ /** Calculate the anchor point position for a text label.
+ * When the requested label placement is of `INSIDE` or `OUTSIDE` type the
+ * returned anchor point for the text label is the middle point of the
+ * outer arc for the given slice; when the requested label placement is of
+ * `CENTER` type the returned anchor point for the text label is the
+ * middle point of the line segment bisecting the slice.
+ * The text alignment is always centered when the requested label
+ * placement is of `CENTER` type else it is dependent on the value of the
+ * angle defined by the horizontal axis and the ray bisecting the slice.
+ *
+ */
+ css::awt::Point getLabelScreenPositionAndAlignmentForUnitCircleValues(
+ LabelAlignment& rAlignment, sal_Int32 nLabelPlacement /*see css::chart::DataLabelPlacement*/
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , double fLogicZ
+ , sal_Int32 nScreenValueOffsetInRadiusDirection ) const;
+
+private:
+ PolarPlottingPositionHelper* m_pPosHelper;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/PropertyMapper.hxx b/chart2/source/view/inc/PropertyMapper.hxx
new file mode 100644
index 0000000000..c4d9a1fa25
--- /dev/null
+++ b/chart2/source/view/inc/PropertyMapper.hxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/config.h>
+
+#include <unordered_map>
+
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Reference.h>
+
+namespace com::sun::star::beans { class XPropertySet; }
+class SvxShape;
+
+namespace chart
+{
+
+typedef std::unordered_map<OUString, OUString> tPropertyNameMap;
+typedef std::unordered_map<OUString, css::uno::Any> tPropertyNameValueMap;
+typedef css::uno::Sequence< OUString > tNameSequence;
+typedef css::uno::Sequence< css::uno::Any > tAnySequence;
+
+/**
+ * PropertyMapper provides easy mapping of the property names of various
+ * objects in the chart model, to the property names of the destination
+ * shape objects (those whose service names begin with
+ * com.sun.star.drawing.).
+ */
+class PropertyMapper
+{
+public:
+ static void setMappedProperties(
+ const css::uno::Reference< css::beans::XPropertySet >& xTarget
+ , const css::uno::Reference< css::beans::XPropertySet >& xSource
+ , const tPropertyNameMap& rMap );
+
+ static void setMappedProperties(
+ SvxShape& xTarget
+ , const css::uno::Reference< css::beans::XPropertySet >& xSource
+ , const tPropertyNameMap& rMap );
+
+ /**
+ * Fetch property values from the source object and map it to the
+ * destination container. Only those properties that are explicitly set
+ * will be inserted into the destination container.
+ *
+ * @param rValueMap destination container
+ * @param rNameMap property name mapping rule
+ * @param xSourceProp source object from which the property values are
+ * pulled.
+ */
+ static void getValueMap(
+ tPropertyNameValueMap& rValueMap
+ , const tPropertyNameMap& rNameMap
+ , const css::uno::Reference< css::beans::XPropertySet >& xSourceProp
+ );
+
+ static void getMultiPropertyListsFromValueMap(
+ tNameSequence& rNames
+ , tAnySequence& rValues
+ , const tPropertyNameValueMap& rValueMap
+ );
+
+ static css::uno::Any*
+ getValuePointer( tAnySequence& rPropValues
+ , const tNameSequence& rPropNames
+ , std::u16string_view rPropName );
+
+ static css::uno::Any*
+ getValuePointerForLimitedSpace( tAnySequence& rPropValues
+ , const tNameSequence& rPropNames
+ , bool bLimitedHeight );
+
+ static void setMultiProperties(
+ const tNameSequence& rNames
+ , const tAnySequence& rValues
+ , SvxShape& xTarget );
+
+ static const tPropertyNameMap& getPropertyNameMapForCharacterProperties();
+ static const tPropertyNameMap& getPropertyNameMapForParagraphProperties();
+ static const tPropertyNameMap& getPropertyNameMapForFillProperties();
+ static const tPropertyNameMap& getPropertyNameMapForLineProperties();
+ static const tPropertyNameMap& getPropertyNameMapForFillAndLineProperties();
+ static const tPropertyNameMap& getPropertyNameMapForTextShapeProperties();
+
+ static const tPropertyNameMap& getPropertyNameMapForFilledSeriesProperties();
+ static const tPropertyNameMap& getPropertyNameMapForLineSeriesProperties();
+ static const tPropertyNameMap& getPropertyNameMapForTextLabelProperties();
+
+ static void getTextLabelMultiPropertyLists(
+ const css::uno::Reference< css::beans::XPropertySet >& xSourceProp
+ , tNameSequence& rPropNames, tAnySequence& rPropValues
+ , bool bName=true
+ , sal_Int32 nLimitedSpace=-1
+ , bool bLimitedHeight=false
+ , bool bSupportsLabelBorder = true);
+
+ /** adds line-, fill- and character properties and sets some suitable
+ defaults for auto-grow properties
+ */
+ static void getPreparedTextShapePropertyLists(
+ const css::uno::Reference< css::beans::XPropertySet >& xSourceProp
+ , tNameSequence& rPropNames
+ , tAnySequence& rPropValues );
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/ScaleAutomatism.hxx b/chart2/source/view/inc/ScaleAutomatism.hxx
new file mode 100644
index 0000000000..1141c9e87c
--- /dev/null
+++ b/chart2/source/view/inc/ScaleAutomatism.hxx
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/chart2/ScaleData.hpp>
+
+#include <tools/date.hxx>
+
+namespace chart { struct ExplicitIncrementData; }
+namespace chart { struct ExplicitScaleData; }
+
+namespace chart
+{
+
+/** This class implements the calculation of automatic axis limits.
+ *
+ * This class is used for calculating axis scales and increments in the form
+ * of instances of `ExplicitScaleData` and `ExplicitIncrementData` classes.
+ * When a `ScaleAutomatism` instance is created a `ScaleData` object is passed
+ * to the constructor. Objects of `ScaleData` type are initialized by
+ * the `createCoordinateSystem` method of some chart type (e.g.
+ * the `PieChartType` class) and belong to some `Axis` object, they can be
+ * accessed through the `XAxis` interface (`XAxis::getScaleData`).
+ */
+class ScaleAutomatism
+{
+public:
+ explicit ScaleAutomatism(
+ const css::chart2::ScaleData& rSourceScale, const Date& rNullDate );
+
+ /** Expands own value range with the passed minimum and maximum.
+ *
+ * It allows to set up the `m_fValueMinimum` and the `m_fValueMaximum`
+ * parameters which are used by the `calculateExplicitScaleAndIncrement`
+ * method for initializing the `Minimum` and `Maximum` properties of the
+ * explicit scale when the same properties of the `ScaleData` object are
+ * undefined (that is empty `uno::Any` objects).
+ */
+ void expandValueRange( double fMinimum, double fMaximum );
+ void resetValueRange();
+
+ /** Sets additional auto scaling options.
+ @param bExpandBorderToIncrementRhythm If true, expands automatic
+ borders to the fixed or calculated increment rhythm.
+ @param bExpandIfValuesCloseToBorder If true, expands automatic borders
+ if values are too close (closer than 1/21 of visible area).
+ @param bExpandWideValuesToZero If true, expands automatic border to
+ zero, if source values are positive only or negative only, and if
+ the absolute values are wide spread (at least one value is less
+ than 5/6 of absolute maximum), or if all values are equal.
+ @param bExpandNarrowValuesTowardZero If true, expands automatic border
+ toward zero (50% of the visible range), if source values are
+ positive only or negative only, and if the absolute values are
+ close to the absolute maximum (no value is less than 5/6 of
+ absolute maximum). */
+ void setAutoScalingOptions(
+ bool bExpandBorderToIncrementRhythm,
+ bool bExpandIfValuesCloseToBorder,
+ bool bExpandWideValuesToZero,
+ bool bExpandNarrowValuesTowardZero );
+
+ /** Sets the maximum allowed number of automatic main increments.
+ @descr The number of main increments may be limited e.g. by the length
+ of the axis and the font size of the axis caption text. */
+ void setMaximumAutoMainIncrementCount( sal_Int32 nMaximumAutoMainIncrementCount );
+
+ /** Sets the time resolution to be used in case it is not set explicitly within the scale
+ */
+ void setAutomaticTimeResolution( sal_Int32 nTimeResolution );
+
+ /** Fills the passed scale data and increment data according to the own settings.
+ *
+ * It performs the initialization of the passed explicit scale and
+ * explicit increment parameters, mainly the initialization is achieved by
+ * using the `ScaleData` object as data source. However other parameters
+ * which affect the behavior of this method can be set through
+ * the `setAutoScalingOptions` and the `expandValueRange` methods.
+ */
+ void calculateExplicitScaleAndIncrement(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement ) const;
+
+ const css::chart2::ScaleData& getScale() const { return m_aSourceScale;}
+ const Date& getNullDate() const { return m_aNullDate;}
+
+private:
+ /** Fills the passed scale data and increment data for category scaling. */
+ void calculateExplicitIncrementAndScaleForCategory(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const;
+
+ /** Fills the passed scale data and increment data for logarithmic scaling. */
+ void calculateExplicitIncrementAndScaleForLogarithmic(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const;
+
+ /** Fills the passed scale data and increment data for linear scaling. */
+ void calculateExplicitIncrementAndScaleForLinear(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const;
+
+ /** Fills the passed scale data and increment data for date-time axis. */
+ void calculateExplicitIncrementAndScaleForDateTimeAxis(
+ ExplicitScaleData& rExplicitScale,
+ ExplicitIncrementData& rExplicitIncrement,
+ bool bAutoMinimum, bool bAutoMaximum ) const;
+
+private:
+ css::chart2::ScaleData m_aSourceScale;
+
+ double m_fValueMinimum; /// Minimum of all source values.
+ double m_fValueMaximum; /// Maximum of all source values.
+ sal_Int32 m_nMaximumAutoMainIncrementCount; /// Maximum number of automatic main increments.
+ bool m_bExpandBorderToIncrementRhythm; /// true = Expand to main increments.
+ bool m_bExpandIfValuesCloseToBorder; /// true = Expand if values are too close to the borders.
+ bool m_bExpandWideValuesToZero; /// true = Expand wide spread values to zero.
+ bool m_bExpandNarrowValuesTowardZero; /// true = Expand narrow range toward zero (add half of range).
+ sal_Int32 m_nTimeResolution;// a constant out of css::chart::TimeUnit
+
+ Date m_aNullDate;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/ShapeFactory.hxx b/chart2/source/view/inc/ShapeFactory.hxx
new file mode 100644
index 0000000000..b44612e74a
--- /dev/null
+++ b/chart2/source/view/inc/ShapeFactory.hxx
@@ -0,0 +1,301 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "PropertyMapper.hxx"
+#include <basegfx/range/b2irectangle.hxx>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <svx/unoshape.hxx>
+#include <svx/unodraw/SvxTableShape.hxx>
+#include <svx/unopage.hxx>
+
+namespace chart { struct VLineProperties; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XFormattedString; }
+namespace com::sun::star::drawing { class XShape; }
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::drawing { struct HomogenMatrix; }
+namespace com::sun::star::drawing { struct PolyPolygonShape3D; }
+namespace com::sun::star::drawing { struct Position3D; }
+namespace com::sun::star::graphic { class XGraphic; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace com::sun::star::drawing { struct Direction3D; }
+
+namespace chart
+{
+class Stripe;
+
+// Be careful here not to clash with the SYMBOL_FOO #defines in
+// <vcl/vclenum.hxx>
+enum SymbolEnum { Symbol_Square=0
+ , Symbol_Diamond
+ , Symbol_DownArrow
+ , Symbol_UpArrow
+ , Symbol_RightArrow
+ , Symbol_LeftArrow
+ , Symbol_Bowtie
+ , Symbol_Sandglass
+ , Symbol_Circle
+ , Symbol_Star
+ , Symbol_X
+ , Symbol_Plus
+ , Symbol_Asterisk
+ , Symbol_HorizontalBar
+ , Symbol_VerticalBar
+ , Symbol_COUNT
+};
+
+
+class ShapeFactory
+{
+public:
+ enum class StackPosition { Top, Bottom };
+
+ ShapeFactory() = delete;
+
+ static rtl::Reference< SvxShapeGroup >
+ createGroup2D(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const OUString& aName = OUString() );
+
+ static rtl::Reference< SvxShapeGroup >
+ createGroup2D(
+ const rtl::Reference<SvxDrawPage>& xTarget
+ , const OUString& aName = OUString() );
+
+ static rtl::Reference<Svx3DSceneObject>
+ createGroup3D(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const OUString& aName = OUString() );
+
+ static rtl::Reference<Svx3DExtrudeObject>
+ createCube( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D& rPosition
+ , const css::drawing::Direction3D& rSize
+ , sal_Int32 nRotateZAngleHundredthDegree
+ , const css::uno::Reference< css::beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap
+ , bool bRounded = false);
+
+ static rtl::Reference<Svx3DLatheObject>
+ createCylinder( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D& rPosition
+ , const css::drawing::Direction3D& rSize
+ , sal_Int32 nRotateZAngleHundredthDegree );
+
+ static rtl::Reference<Svx3DSceneObject>
+ createPyramid( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D& rPosition
+ , const css::drawing::Direction3D& rSize
+ , double fTopHeight
+ , bool bRotateZ
+ , const css::uno::Reference< css::beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap);
+
+ static rtl::Reference<Svx3DLatheObject>
+ createCone( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D& rPosition
+ , const css::drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree );
+
+ static rtl::Reference<SvxShapePolyPolygon>
+ createPieSegment2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , const css::drawing::Direction3D& rOffset
+ , const css::drawing::HomogenMatrix& rUnitCircleToScene );
+
+ static rtl::Reference<Svx3DExtrudeObject>
+ createPieSegment( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , const css::drawing::Direction3D& rOffset
+ , const css::drawing::HomogenMatrix& rUnitCircleToScene
+ , double fDepth );
+
+ static rtl::Reference<Svx3DPolygonObject>
+ createStripe( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const Stripe& rStripe
+ , const css::uno::Reference< css::beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap
+ , bool bDoubleSided
+ , short nRotatedTexture = 0 //0 to 7 are the different possibilities
+ , bool bFlatNormals=true );
+
+ static rtl::Reference<Svx3DExtrudeObject>
+ createArea3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon
+ , double fDepth);
+
+ static rtl::Reference<SvxShapePolyPolygon>
+ createArea2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon);
+
+ static rtl::Reference<SvxShapePolyPolygon>
+ createSymbol2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D& rPos
+ , const css::drawing::Direction3D& rSize
+ , sal_Int32 nStandardSymbol
+ , sal_Int32 nBorderColor
+ , sal_Int32 nFillColor );
+
+ static rtl::Reference<SvxGraphicObject>
+ createGraphic2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D& rPos
+ , const css::drawing::Direction3D& rSize
+ , const css::uno::Reference< css::graphic::XGraphic >& xGraphic );
+
+ static rtl::Reference<SvxShapePolyPolygon>
+ createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::PointSequenceSequence& rPoints
+ , const VLineProperties* pLineProperties = nullptr );
+ static rtl::Reference<SvxShapePolyPolygon>
+ createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const std::vector<std::vector<css::drawing::Position3D>>& rPoints
+ , const VLineProperties* pLineProperties = nullptr );
+
+ static rtl::Reference<SvxShapePolyPolygon>
+ createLine ( const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const css::awt::Size& rSize, const css::awt::Point& rPosition );
+
+ static rtl::Reference<Svx3DPolygonObject>
+ createLine3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const std::vector<std::vector<css::drawing::Position3D>>& rPoints
+ , const VLineProperties& rLineProperties );
+
+ static rtl::Reference<SvxShapeCircle>
+ createCircle2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D& rPos
+ , const css::drawing::Direction3D& rSize );
+
+ static rtl::Reference<SvxShapeCircle>
+ createCircle( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::awt::Size& rSize
+ , const css::awt::Point& rPosition );
+
+ static rtl::Reference<SvxShapeText>
+ createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget2D
+ , const OUString& rText
+ , const tNameSequence& rPropNames
+ , const tAnySequence& rPropValues
+ , const css::uno::Any& rATransformation
+ );
+
+ static rtl::Reference<SvxShapeText>
+ createText(const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString
+ , const tNameSequence& rPropNames
+ , const tAnySequence& rPropValues
+ , const css::uno::Any& rATransformation);
+
+ static rtl::Reference<SvxShapeText>
+ createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget2D,
+ const css::awt::Size& rSize,
+ const css::awt::Point& rPosition,
+ css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString,
+ const css::uno::Reference< css::beans::XPropertySet > & xTextProperties,
+ double nRotation, const OUString& aName, sal_Int32 nTextMaxWidth );
+
+ static rtl::Reference<SvxTableShape> createTable(rtl::Reference<SvxShapeGroupAnyD> const& xTarget, OUString const& rName = OUString());
+
+ static rtl::Reference<SvxShapeRect>
+ createInvisibleRectangle(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::awt::Size& rSize );
+
+ static rtl::Reference<SvxShapeRect>
+ createRectangle(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const css::awt::Size& rSize,
+ const css::awt::Point& rPosition,
+ const tNameSequence& rPropNames,
+ const tAnySequence& rPropValues,
+ StackPosition ePos = StackPosition::Top );
+
+ static rtl::Reference<SvxShapeRect>
+ createRectangle(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget );
+
+ static rtl::Reference<SvxShapeGroupAnyD>
+ getOrCreateChartRootShape( const rtl::Reference<SvxDrawPage>& xPage );
+
+ static void setPageSize(const rtl::Reference<SvxShapeGroupAnyD>& xChartShapes,
+ const css::awt::Size& rSize);
+
+ static rtl::Reference<SvxShapeGroupAnyD>
+ getChartRootShape( const rtl::Reference<SvxDrawPage>& xPage );
+
+ static void makeShapeInvisible( const rtl::Reference< SvxShape >& rShape );
+
+ static void setShapeName( const rtl::Reference< SvxShape >& xShape
+ , const OUString& rName );
+
+ static OUString getShapeName( const css::uno::Reference< css::drawing::XShape >& xShape );
+
+ static css::uno::Any makeTransformation( const css::awt::Point& rScreenPosition2D, double fRotationAnglePi=0.0 );
+
+ static OUString getStackedString( const OUString& rString, bool bStacked );
+
+ static bool hasPolygonAnyLines( const std::vector<std::vector<css::drawing::Position3D>>& rPoly );
+ static bool isPolygonEmptyOrSinglePoint( const css::drawing::PolyPolygonShape3D& rPoly );
+ static bool isPolygonEmptyOrSinglePoint( const std::vector<std::vector<css::drawing::Position3D>>& rPoly );
+ static void closePolygon( css::drawing::PolyPolygonShape3D& rPoly );
+ static void closePolygon( std::vector<std::vector<css::drawing::Position3D>>& rPoly );
+
+ static css::awt::Size calculateNewSizeRespectingAspectRatio(
+ const css::awt::Size& rTargetSize
+ , const css::awt::Size& rSourceSizeWithCorrectAspectRatio );
+
+ static css::awt::Point calculateTopLeftPositionToCenterObject(
+ const css::awt::Point& rTargetAreaPosition
+ , const css::awt::Size& rTargetAreaSize
+ , const css::awt::Size& rObjectSize );
+
+ static ::basegfx::B2IRectangle getRectangleOfShape( SvxShape& rShape );
+
+ static css::awt::Size getSizeAfterRotation(
+ SvxShape& rShape, double fRotationAngleDegree );
+
+ static void removeSubShapes( const rtl::Reference<SvxShapeGroupAnyD>& xShapes );
+
+ static sal_Int32 getSymbolCount() { return Symbol_COUNT; }
+
+private:
+ static rtl::Reference<Svx3DExtrudeObject>
+ impl_createCube( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D& rPosition
+ , const css::drawing::Direction3D& rSize, sal_Int32 nRotateZAngleHundredthDegree
+ , bool bRounded );
+
+ static rtl::Reference<Svx3DLatheObject>
+ impl_createConeOrCylinder( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D& rPosition
+ , const css::drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
+ , bool bCylinder);
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/Stripe.hxx b/chart2/source/view/inc/Stripe.hxx
new file mode 100644
index 0000000000..0da5e0b5dc
--- /dev/null
+++ b/chart2/source/view/inc/Stripe.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <com/sun/star/uno/Any.h>
+
+namespace chart
+{
+
+/** A Stripe represents a 2 dimensional foursquare plane in a 3 dimensional room.
+
+@todo could: it is not necessary to have 4 point members here; it would be sufficient to have one point and 2 directions
+*/
+
+class Stripe
+{
+public:
+ Stripe( const css::drawing::Position3D& rPoint1
+ , const css::drawing::Direction3D& rDirectionToPoint2
+ , const css::drawing::Direction3D& rDirectionToPoint4 );
+
+ Stripe( const css::drawing::Position3D& rPoint1
+ , const css::drawing::Position3D& rPoint2
+ , double fDepth );
+
+ Stripe( const css::drawing::Position3D& rPoint1
+ , const css::drawing::Position3D& rPoint2
+ , const css::drawing::Position3D& rPoint3
+ , const css::drawing::Position3D& rPoint4 );
+
+ void SetManualNormal( const css::drawing::Direction3D& rNormal );
+ css::drawing::Direction3D getNormal() const;
+
+ void InvertNormal( bool bInvertNormal );
+
+ css::uno::Any getPolyPolygonShape3D() const;
+ css::uno::Any getNormalsPolygon() const;
+ static css::uno::Any getTexturePolygon( short nRotatedTexture ); //0 to 7 are the different possibilities
+
+private:
+ css::drawing::Position3D m_aPoint1;
+ css::drawing::Position3D m_aPoint2;
+ css::drawing::Position3D m_aPoint3;
+ css::drawing::Position3D m_aPoint4;
+
+ bool m_bInvertNormal;
+ bool m_bManualNormalSet;
+ css::drawing::Direction3D m_aManualNormal;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/VCoordinateSystem.hxx b/chart2/source/view/inc/VCoordinateSystem.hxx
new file mode 100644
index 0000000000..61dda842d0
--- /dev/null
+++ b/chart2/source/view/inc/VCoordinateSystem.hxx
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "MinimumAndMaximumSupplier.hxx"
+#include <ThreeDHelper.hxx>
+#include "VSeriesPlotter.hxx"
+#include <chartview/ExplicitScaleValues.hxx>
+#include <com/sun/star/drawing/HomogenMatrix.hpp>
+#include <com/sun/star/uno/Sequence.h>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+
+#include <map>
+#include <memory>
+#include <vector>
+
+namespace com::sun::star::awt { struct Rectangle; }
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XAxis; }
+namespace com::sun::star::chart2 { class XChartDocument; }
+namespace com::sun::star::chart2 { class XCoordinateSystem; }
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+class ExplicitCategoriesProvider;
+class ScaleAutomatism;
+class ChartModel;
+class Axis;
+class BaseCoordinateSystem;
+class GridProperties;
+class VAxisBase;
+
+class VCoordinateSystem
+{
+public:
+ virtual ~VCoordinateSystem();
+
+ static std::unique_ptr<VCoordinateSystem> createCoordinateSystem( const rtl::Reference<
+ ::chart::BaseCoordinateSystem >& xCooSysModel );
+
+ /// @throws css::uno::RuntimeException
+ void initPlottingTargets(
+ const rtl::Reference< SvxShapeGroupAnyD >& xLogicTarget
+ , const rtl::Reference< SvxShapeGroupAnyD >& xFinalTarget
+ , rtl::Reference<SvxShapeGroupAnyD>& xLogicTargetForSeriesBehindAxis );
+
+ void setParticle( const OUString& rCooSysParticle );
+
+ void setTransformationSceneToScreen( const css::drawing::HomogenMatrix& rMatrix );
+ const css::drawing::HomogenMatrix& getTransformationSceneToScreen() const { return m_aMatrixSceneToScreen;}
+
+ //better performance for big data
+ virtual css::uno::Sequence< sal_Int32 > getCoordinateSystemResolution( const css::awt::Size& rPageSize
+ , const css::awt::Size& rPageResolution );
+
+ ExplicitScaleData getExplicitScale( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const;
+ ExplicitIncrementData getExplicitIncrement( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const;
+
+ void setExplicitCategoriesProvider( ExplicitCategoriesProvider* /*takes ownership*/ );
+ ExplicitCategoriesProvider* getExplicitCategoriesProvider();
+
+ // returns a complete scale set for a given dimension and index; for example if nDimensionIndex==1 and nAxisIndex==2 you get returned the secondary x axis, main y axis and main z axis
+ std::vector< ExplicitScaleData > getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const;
+ // returns a complete increment set for a given dimension and index; for example if nDimensionIndex==1 and nAxisIndex==2 you get returned the secondary x axis, main y axis and main z axis
+ std::vector< ExplicitIncrementData > getExplicitIncrements( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const;
+
+ void addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier );
+ bool hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier );
+ void clearMinimumAndMaximumSupplierList();
+
+ /**
+ * It sets the scaling parameters for the passed `ScaleAutomatism` object.
+ * Especially it sets the `m_fValueMinimum` and the `m_fValueMaximum`
+ * parameters (see `ScaleAutomatism::expandValueRange`).
+ * The value to be assigned to these two parameters is retrieved by
+ * invoking the `getMinimum` and `getMaximum` methods of the minimum-maximum
+ * supplier object that belongs to the given coordinate system.
+ * The minimum-maximum supplier object is set in the
+ * `SeriesPlotterContainer::initializeCooSysAndSeriesPlotter` method to the
+ * series plotter which is based on the coordinate system (see notes for
+ * the method). For instance for a pie chart the `m_fValueMinimum` and the
+ * `m_fValueMaximum` parameters are initialized by the `PieChart::getMinimum`
+ * and `PieChart::getMaximum` methods.
+ */
+ void prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex );
+
+ void setExplicitScaleAndIncrement( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex
+ , const ExplicitScaleData& rExplicitScale
+ , const ExplicitIncrementData& rExplicitIncrement );
+
+ void set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos );
+
+ const rtl::Reference< ::chart::BaseCoordinateSystem >&
+ getModel() const { return m_xCooSysModel;}
+
+ /**
+ * Create "view" axis objects 'VAxis' from the coordinate system model.
+ */
+ virtual void createVAxisList(
+ const rtl::Reference<::chart::ChartModel> & xChartDoc,
+ const css::awt::Size& rFontReferenceSize,
+ const css::awt::Rectangle& rMaximumSpaceForLabels,
+ bool bLimitSpaceForLabels,
+ std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList,
+ css::uno::Reference<css::uno::XComponentContext> const& rComponentContext);
+
+ virtual void initVAxisInList();
+ virtual void updateScalesAndIncrementsOnAxes();
+
+ void createMaximumAxesLabels();
+ void createAxesLabels();
+ void updatePositions();
+ void createAxesShapes();
+
+ virtual void createGridShapes();
+
+ bool getPropertySwapXAndYAxis() const;
+
+ sal_Int32 getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex ) const;
+
+ bool needSeriesNamesForAxis() const;
+ void setSeriesNamesForAxis( const css::uno::Sequence< OUString >& rSeriesNames );
+
+protected: //methods
+ VCoordinateSystem( rtl::Reference< ::chart::BaseCoordinateSystem > xCooSys );
+
+ rtl::Reference< ::chart::Axis >
+ getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const;
+ static std::vector< rtl::Reference< ::chart::GridProperties > >
+ getGridListFromAxis( const rtl::Reference< ::chart::Axis >& xAxis );
+
+ VAxisBase* getVAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+
+ OUString createCIDForAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+ OUString createCIDForGrid( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+
+ sal_Int32 getNumberFormatKeyForAxis( const rtl::Reference< ::chart::Axis >& xAxis
+ , const rtl::Reference<::chart::ChartModel>& xChartDoc);
+
+private: //methods
+ static void impl_adjustDimension( sal_Int32& rDimensionIndex );
+ void impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex, sal_Int32& rAxisIndex ) const;
+
+protected: //member
+ rtl::Reference< ::chart::BaseCoordinateSystem > m_xCooSysModel;
+
+ OUString m_aCooSysParticle;
+
+ typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex; //first index is the dimension, second index is the axis index that indicates whether this is a main or secondary axis
+
+ rtl::Reference<SvxShapeGroupAnyD> m_xLogicTargetForGrids;
+ rtl::Reference<SvxShapeGroupAnyD> m_xLogicTargetForAxes;
+ rtl::Reference<SvxShapeGroupAnyD> m_xFinalTarget;
+ css::drawing::HomogenMatrix m_aMatrixSceneToScreen;
+
+ CuboidPlanePosition m_eLeftWallPos;
+ CuboidPlanePosition m_eBackWallPos;
+ CuboidPlanePosition m_eBottomPos;
+
+ /**
+ * Collection of min-max suppliers which are basically different chart
+ * types present in the same coordinate system. This is used only for
+ * auto-scaling purposes.
+ */
+ MergedMinimumAndMaximumSupplier m_aMergedMinMaxSupplier;
+
+ css::uno::Sequence< OUString > m_aSeriesNamesForZAxis;
+
+ typedef std::map< tFullAxisIndex, std::shared_ptr< VAxisBase > > tVAxisMap;
+
+ tVAxisMap m_aAxisMap;
+
+private:
+ std::vector< ExplicitScaleData > m_aExplicitScales;
+ std::vector< ExplicitIncrementData > m_aExplicitIncrements;
+
+ typedef std::map< tFullAxisIndex, ExplicitScaleData > tFullExplicitScaleMap;
+ typedef std::map< tFullAxisIndex, ExplicitIncrementData > tFullExplicitIncrementMap;
+
+ tFullExplicitScaleMap m_aSecondaryExplicitScales;
+ tFullExplicitIncrementMap m_aSecondaryExplicitIncrements;
+
+ std::unique_ptr< ExplicitCategoriesProvider > m_apExplicitCategoriesProvider;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/VDataSeries.hxx b/chart2/source/view/inc/VDataSeries.hxx
new file mode 100644
index 0000000000..0ab4fffe0e
--- /dev/null
+++ b/chart2/source/view/inc/VDataSeries.hxx
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "PropertyMapper.hxx"
+
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/awt/Point.hpp>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+
+#include <memory>
+#include <map>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XChartType; }
+namespace com::sun::star::chart2 { class XDataSeries; }
+namespace com::sun::star::chart2::data { class XDataSequence; }
+namespace com::sun::star::drawing { class XShapes; }
+
+namespace chart
+{
+class ChartType;
+class DataSeries;
+
+class VDataSequence
+{
+public:
+ void init( const css::uno::Reference<css::chart2::data::XDataSequence>& xModel );
+ bool is() const;
+ void clear();
+ double getValue( sal_Int32 index ) const;
+ sal_Int32 detectNumberFormatKey( sal_Int32 index ) const;
+ sal_Int32 getLength() const;
+
+ css::uno::Reference<css::chart2::data::XDataSequence> m_xModel;
+ mutable css::uno::Sequence<double> m_aValues;
+};
+
+class VDataSeries final
+{
+public:
+ VDataSeries( const rtl::Reference<::chart::DataSeries>& xDataSeries );
+
+ ~VDataSeries();
+
+ VDataSeries(const VDataSeries&) = delete;
+ const VDataSeries& operator=(const VDataSeries&) = delete;
+
+ const rtl::Reference<::chart::DataSeries>& getModel() const;
+
+ void setCategoryXAxis();
+ void setXValues( const css::uno::Reference<css::chart2::data::XDataSequence>& xValues );
+ void setXValuesIfNone( const css::uno::Reference<css::chart2::data::XDataSequence>& xValues );
+ void setParticle( const OUString& rSeriesParticle );
+ void setGlobalSeriesIndex( sal_Int32 nGlobalSeriesIndex );
+ void setPageReferenceSize( const css::awt::Size & rPageRefSize );
+
+ sal_Int32 getTotalPointCount() const { return m_nPointCount;}
+ double getXValue( sal_Int32 index ) const;
+ double getYValue( sal_Int32 index ) const;
+
+ void getMinMaxXValue( double& fMin, double& fMax ) const;
+
+ double getY_Min( sal_Int32 index ) const;
+ double getY_Max( sal_Int32 index ) const;
+ double getY_First( sal_Int32 index ) const;
+ double getY_Last( sal_Int32 index ) const;
+
+ double getBubble_Size( sal_Int32 index ) const;
+
+ double getMinimumofAllDifferentYValues( sal_Int32 index ) const;
+ double getMaximumofAllDifferentYValues( sal_Int32 index ) const;
+
+ double getValueByProperty( sal_Int32 index, const OUString& rPropName ) const;
+
+ bool hasPropertyMapping( const OUString& rPropName ) const;
+
+ css::uno::Sequence< double > const & getAllX() const;
+ css::uno::Sequence< double > const & getAllY() const;
+
+ double getXMeanValue() const;
+ double getYMeanValue() const;
+
+ bool hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const;
+ sal_Int32 getExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const;
+ sal_Int32 detectNumberFormatKey( sal_Int32 nPointIndex ) const;
+
+ sal_Int32 getLabelPlacement(
+ sal_Int32 nPointIndex, const rtl::Reference<::chart::ChartType>& xChartType,
+ bool bSwapXAndY ) const;
+
+ css::awt::Point getLabelPosition( css::awt::Point aTextShapePos, sal_Int32 nPointIndex ) const;
+ bool isLabelCustomPos( sal_Int32 nPointIndex ) const;
+
+ css::uno::Reference<css::beans::XPropertySet> getPropertiesOfPoint( sal_Int32 index ) const;
+
+ const css::uno::Reference<css::beans::XPropertySet> & getPropertiesOfSeries() const;
+
+ css::chart2::Symbol* getSymbolProperties( sal_Int32 index ) const;
+
+ css::uno::Reference<css::beans::XPropertySet> getXErrorBarProperties( sal_Int32 index ) const;
+
+ css::uno::Reference<css::beans::XPropertySet> getYErrorBarProperties( sal_Int32 index ) const;
+
+ bool hasPointOwnColor( sal_Int32 index ) const;
+
+ css::chart2::StackingDirection getStackingDirection() const;
+ sal_Int32 getAttachedAxisIndex() const;
+ void setAttachedAxisIndex( sal_Int32 nAttachedAxisIndex );
+
+ void doSortByXValues();
+
+ void setConnectBars( bool bConnectBars );
+ bool getConnectBars() const;
+
+ void setGroupBarsPerAxis( bool bGroupBarsPerAxis );
+ bool getGroupBarsPerAxis() const;
+
+ void setStartingAngle( sal_Int32 nStartingAngle );
+ sal_Int32 getStartingAngle() const;
+
+ void setRoleOfSequenceForDataLabelNumberFormatDetection( std::u16string_view rRole );
+
+ //this is only temporarily here for area chart:
+ std::vector<std::vector<css::drawing::Position3D>> m_aPolyPolygonShape3D;
+ sal_Int32 m_nPolygonIndex;
+ double m_fLogicMinX;
+ double m_fLogicMaxX;
+
+ //this is here for deep stacking:
+ double m_fLogicZPos;//from 0 to series count -1
+
+ const OUString& getCID() const { return m_aCID;}
+ const OUString& getSeriesParticle() const { return m_aSeriesParticle;}
+ const OUString& getPointCID_Stub() const { return m_aPointCID_Stub;}
+ OUString getErrorBarsCID( bool bYError ) const;
+ OUString getLabelsCID() const;
+ const OUString& getLabelCID_Stub() const { return m_aLabelCID_Stub;}
+ OUString getDataCurveCID( sal_Int32 nCurveIndex, bool bAverageLine ) const;
+
+ css::chart2::DataPointLabel* getDataPointLabelIfLabel( sal_Int32 index ) const;
+ bool getTextLabelMultiPropertyLists( sal_Int32 index, tNameSequence*& pPropNames, tAnySequence*& pPropValues ) const;
+
+ OUString getDataCurveEquationCID( sal_Int32 nCurveIndex ) const;
+ bool isAttributedDataPoint( sal_Int32 index ) const;
+
+ bool isVaryColorsByPoint() const;
+
+ void releaseShapes();
+
+ void setMissingValueTreatment( sal_Int32 nMissingValueTreatment );
+ sal_Int32 getMissingValueTreatment() const;
+
+ void setOldTimeBased( VDataSeries* pOldSeries, double nPercent );
+ VDataSeries* createCopyForTimeBased() const;
+
+private: //methods
+ css::chart2::DataPointLabel* getDataPointLabel( sal_Int32 index ) const;
+ void adaptPointCache( sal_Int32 nNewPointIndex ) const;
+
+ // for copies for time based charting
+ VDataSeries();
+
+public: //member
+ rtl::Reference<SvxShapeGroupAnyD> m_xGroupShape;
+ rtl::Reference<SvxShapeGroup> m_xLabelsGroupShape;
+ rtl::Reference<SvxShapeGroupAnyD> m_xErrorXBarsGroupShape;
+ rtl::Reference<SvxShapeGroupAnyD> m_xErrorYBarsGroupShape;
+
+ //the following group shapes will be created as children of m_xGroupShape on demand
+ //they can be used to assure that some parts of a series shape are always in front of others (e.g. symbols in front of lines)
+ rtl::Reference<SvxShapeGroupAnyD> m_xFrontSubGroupShape;
+ rtl::Reference<SvxShapeGroupAnyD> m_xBackSubGroupShape;
+
+private: //member
+ rtl::Reference<::chart::DataSeries> m_xDataSeries;
+ css::uno::Reference<css::beans::XPropertySet> m_xDataSeriesProps; // cached
+
+ //all points given by the model data (here are not only the visible points meant)
+ sal_Int32 m_nPointCount;
+
+ VDataSequence m_aValues_X;
+ VDataSequence m_aValues_Y;
+ VDataSequence m_aValues_Z;
+
+ VDataSequence m_aValues_Y_Min;
+ VDataSequence m_aValues_Y_Max;
+ VDataSequence m_aValues_Y_First;
+ VDataSequence m_aValues_Y_Last;
+
+ VDataSequence m_aValues_Bubble_Size;
+
+ VDataSequence* m_pValueSequenceForDataLabelNumberFormatDetection;
+
+ std::map<OUString, VDataSequence> m_PropertyMap;
+
+ mutable double m_fXMeanValue;
+ mutable double m_fYMeanValue;
+
+ css::uno::Sequence<sal_Int32> m_aAttributedDataPointIndexList;
+
+ css::chart2::StackingDirection m_eStackingDirection;
+
+ sal_Int32 m_nAxisIndex;//indicates whether this is attached to a main or secondary axis
+
+ bool m_bConnectBars;
+
+ bool m_bGroupBarsPerAxis;
+
+ sal_Int32 m_nStartingAngle;
+
+ OUString m_aSeriesParticle;
+ OUString m_aCID;
+ OUString m_aPointCID_Stub;
+ OUString m_aLabelCID_Stub;
+
+ sal_Int32 m_nGlobalSeriesIndex;
+
+ //some cached values for data labels as they are very expensive
+ mutable std::optional<css::chart2::DataPointLabel>
+ m_oLabel_Series;
+ mutable std::optional<tNameSequence> m_oLabelPropNames_Series;
+ mutable std::optional<tAnySequence> m_oLabelPropValues_Series;
+ mutable std::optional<css::chart2::Symbol> m_oSymbolProperties_Series;
+
+ mutable std::optional<css::chart2::DataPointLabel>
+ m_oLabel_AttributedPoint;
+ mutable std::unique_ptr<tNameSequence> m_apLabelPropNames_AttributedPoint;
+ mutable std::unique_ptr<tAnySequence> m_apLabelPropValues_AttributedPoint;
+ mutable std::optional<css::chart2::Symbol> m_oSymbolProperties_AttributedPoint;
+ mutable std::optional<css::chart2::Symbol> m_oSymbolProperties_InvisibleSymbolForSelection;
+ mutable sal_Int32 m_nCurrentAttributedPoint;
+ css::awt::Size m_aReferenceSize;
+
+ sal_Int32 m_nMissingValueTreatment;
+ bool m_bAllowPercentValueInDataLabel;
+
+ // for time based charting
+ VDataSeries* mpOldSeries;
+ double mnPercent;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/VDiagram.hxx b/chart2/source/view/inc/VDiagram.hxx
new file mode 100644
index 0000000000..ab391f7bc0
--- /dev/null
+++ b/chart2/source/view/inc/VDiagram.hxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <basegfx/range/b2irectangle.hxx>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/awt/Point.hpp>
+#include <svx/unoshape.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::chart2 { class XDiagram; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace com::sun::star::drawing { class XShape; }
+
+
+namespace chart
+{
+class Diagram;
+class ShapeFactory;
+
+/** The VDiagram is responsible to generate the visible parts of the Diagram
+that is wall, floor, axes and data series.
+The axes and data series are subobjects which are created and managed by the
+diagram.
+*/
+
+class VDiagram final
+{
+public: //methods
+ VDiagram( const rtl::Reference<::chart::Diagram>& xDiagram,
+ const css::drawing::Direction3D& rPreferredAspectRatio,
+ sal_Int32 nDimension );
+ ~VDiagram();
+
+ void init(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget );
+
+ void createShapes( const css::awt::Point& rPos
+ , const css::awt::Size& rSize );
+
+ const rtl::Reference<SvxShapeGroupAnyD> &
+ getCoordinateRegion() const { return m_xCoordinateRegionShape; }
+
+ /**
+ * Get current bounding rectangle for the diagram without axes.
+ */
+ basegfx::B2IRectangle getCurrentRectangle() const;
+
+ void reduceToMinimumSize();
+
+ ::basegfx::B2IRectangle adjustPosAndSize( const css::awt::Point& rPos
+ , const css::awt::Size& rAvailableSize );
+
+ ::basegfx::B2IRectangle adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect );
+
+private: //methods
+ void createShapes_2d();
+ void createShapes_3d();
+
+ ::basegfx::B2IRectangle adjustPosAndSize_2d( const css::awt::Point& rPos
+ , const css::awt::Size& rAvailableSize );
+ ::basegfx::B2IRectangle adjustPosAndSize_3d( const css::awt::Point& rPos
+ , const css::awt::Size& rAvailableSize );
+
+ void adjustAspectRatio3d( const css::awt::Size& rAvailableSize );
+
+private: //members
+ VDiagram(const VDiagram& rD) = delete;
+
+ rtl::Reference<SvxShapeGroupAnyD> m_xTarget;
+
+ // this is the surrounding shape which contains floor, wall and coordinate
+ rtl::Reference<SvxShapeGroupAnyD> m_xOuterGroupShape;
+ // this is an additional inner shape that represents the coordinate region - that is - where to place data points
+ rtl::Reference<SvxShapeGroupAnyD> m_xCoordinateRegionShape;
+ rtl::Reference<SvxShapeRect> m_xWall2D;
+
+ sal_Int32 m_nDimensionCount;
+ rtl::Reference< ::chart::Diagram > m_xDiagram;
+
+ css::drawing::Direction3D m_aPreferredAspectRatio;
+ css::uno::Reference< css::beans::XPropertySet > m_xAspectRatio3D;
+
+ double m_fXAnglePi;
+ double m_fYAnglePi;
+ double m_fZAnglePi;
+
+ css::awt::Point m_aAvailablePosIncludingAxes;
+ css::awt::Size m_aAvailableSizeIncludingAxes;
+
+ css::awt::Point m_aCurrentPosWithoutAxes;
+ css::awt::Size m_aCurrentSizeWithoutAxes;
+
+ bool m_bRightAngledAxes;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/VLegendSymbolFactory.hxx b/chart2/source/view/inc/VLegendSymbolFactory.hxx
new file mode 100644
index 0000000000..f637a58949
--- /dev/null
+++ b/chart2/source/view/inc/VLegendSymbolFactory.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "LegendEntryProvider.hxx"
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::drawing { class XShape; }
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace com::sun::star::uno { class Any; }
+
+namespace chart::VLegendSymbolFactory
+{
+ enum class PropertyType
+ {
+ FilledSeries,
+ LineSeries,
+ Line,
+ };
+
+ rtl::Reference< SvxShapeGroup >
+ createSymbol(
+ const css::awt::Size& rEntryKeyAspectRatio,
+ const rtl::Reference<SvxShapeGroupAnyD>& rSymbolContainer,
+ LegendSymbolStyle eStyle,
+ const css::uno::Reference< css::beans::XPropertySet > & xLegendEntryProperties,
+ PropertyType ePropertyType,
+ const css::uno::Any& rExplicitSymbol /*should contain a css::chart2::Symbol without automatic symbol if the charttype does support symbols else empty*/);
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/VLineProperties.hxx b/chart2/source/view/inc/VLineProperties.hxx
new file mode 100644
index 0000000000..aa1c88ce74
--- /dev/null
+++ b/chart2/source/view/inc/VLineProperties.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/uno/Reference.h>
+
+namespace com::sun::star::beans
+{
+class XPropertySet;
+}
+
+namespace chart
+{
+struct VLineProperties
+{
+ css::uno::Any Color; //type sal_Int32 UNO_NAME_LINECOLOR
+ css::uno::Any LineStyle; //type drawing::LineStyle for property UNO_NAME_LINESTYLE
+ css::uno::Any Transparence; //type sal_Int16 for property UNO_NAME_LINETRANSPARENCE
+ css::uno::Any Width; //type sal_Int32 for property UNO_NAME_LINEWIDTH
+ css::uno::Any DashName; //type OUString for property "LineDashName"
+ css::uno::Any LineCap; //type drawing::LineCap for property UNO_NAME_LINECAP
+
+ VLineProperties();
+ void initFromPropertySet(const css::uno::Reference<css::beans::XPropertySet>& xProp);
+
+ bool isLineVisible() const;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/VPolarTransformation.hxx b/chart2/source/view/inc/VPolarTransformation.hxx
new file mode 100644
index 0000000000..23f3c3b718
--- /dev/null
+++ b/chart2/source/view/inc/VPolarTransformation.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "PlottingPositionHelper.hxx"
+
+namespace chart
+{
+
+class VPolarTransformation final : public XTransformation2
+{
+public:
+ VPolarTransformation( const PolarPlottingPositionHelper& rPositionHelper );
+ virtual ~VPolarTransformation() override;
+
+ // ____ XTransformation2 ____
+ virtual css::drawing::Position3D transform(
+ const css::uno::Sequence< double >& rSourceValues ) const override;
+ virtual css::drawing::Position3D transform(
+ const css::drawing::Position3D& rSourceValues ) const override;
+
+private:
+ PolarPlottingPositionHelper m_aPositionHelper;
+ ::basegfx::B3DHomMatrix m_aUnitCartesianToScene;
+};
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/VSeriesPlotter.hxx b/chart2/source/view/inc/VSeriesPlotter.hxx
new file mode 100644
index 0000000000..eaf27495d0
--- /dev/null
+++ b/chart2/source/view/inc/VSeriesPlotter.hxx
@@ -0,0 +1,448 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include "PlotterBase.hxx"
+#include "VDataSeries.hxx"
+#include "LabelAlignment.hxx"
+#include "MinimumAndMaximumSupplier.hxx"
+#include "LegendEntryProvider.hxx"
+#include <basegfx/range/b2irectangle.hxx>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+
+namespace com::sun::star::awt { struct Point; }
+namespace com::sun::star::chart2 { class XChartType; }
+
+
+namespace chart { class ExplicitCategoriesProvider; }
+namespace chart { struct ExplicitScaleData; }
+namespace chart { class ChartModel; }
+
+namespace com::sun::star {
+ namespace util {
+ class XNumberFormatsSupplier;
+ }
+ namespace chart2 {
+ class XColorScheme;
+ class XRegressionCurveCalculator;
+ }
+}
+
+namespace chart {
+
+class ChartType;
+class NumberFormatterWrapper;
+
+class AxesNumberFormats
+{
+public:
+ AxesNumberFormats() {};
+
+ void setFormat( sal_Int32 nFormatKey, sal_Int32 nDimIndex, sal_Int32 nAxisIndex )
+ {
+ m_aNumberFormatMap[tFullAxisIndex(nDimIndex,nAxisIndex)] = nFormatKey;
+ }
+
+private:
+ typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex;
+ std::map< tFullAxisIndex, sal_Int32 > m_aNumberFormatMap;
+};
+
+/**
+ * A list of series that have the same CoordinateSystem. They are used to be
+ * plotted maybe in a stacked manner by a plotter.
+ */
+class VDataSeriesGroup final
+{
+public:
+ VDataSeriesGroup() = delete;
+ VDataSeriesGroup( std::unique_ptr<VDataSeries> pSeries );
+ VDataSeriesGroup(VDataSeriesGroup&&) noexcept;
+ ~VDataSeriesGroup();
+
+ void addSeries( std::unique_ptr<VDataSeries> pSeries );//takes ownership of pSeries
+ sal_Int32 getSeriesCount() const;
+ void deleteSeries();
+
+ sal_Int32 getPointCount() const;
+ sal_Int32 getAttachedAxisIndexForFirstSeries() const;
+
+ void getMinimumAndMaximumX( double& rfMinimum, double& rfMaximum ) const;
+ void getMinimumAndMaximumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const;
+
+ void calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex
+ , bool bSeparateStackingForDifferentSigns
+ , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex ) const;
+ void calculateYMinAndMaxForCategoryRange( sal_Int32 nStartCategoryIndex, sal_Int32 nEndCategoryIndex
+ , bool bSeparateStackingForDifferentSigns
+ , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex );
+
+ std::vector< std::unique_ptr<VDataSeries> > m_aSeriesVector;
+
+private:
+ //cached values
+ struct CachedYValues
+ {
+ CachedYValues();
+
+ bool m_bValuesDirty;
+ double m_fMinimumY;
+ double m_fMaximumY;
+ };
+
+ mutable bool m_bMaxPointCountDirty;
+ mutable sal_Int32 m_nMaxPointCount;
+ typedef std::map< sal_Int32, CachedYValues > tCachedYValuesPerAxisIndexMap;
+ mutable std::vector< tCachedYValuesPerAxisIndexMap > m_aListOfCachedYValues;
+};
+
+class VSeriesPlotter : public PlotterBase, public MinimumAndMaximumSupplier, public LegendEntryProvider
+{
+public:
+ VSeriesPlotter() = delete;
+
+ virtual ~VSeriesPlotter() override;
+
+ /**
+ * A new series can be positioned relative to other series in a chart.
+ * This positioning has two dimensions. First a series can be placed
+ * next to each other on the category axis. This position is indicated by xSlot.
+ * Second a series can be stacked on top of another. This position is indicated by ySlot.
+ * The positions are counted from 0 on.
+ * xSlot < 0 : append the series to already existing x series
+ * xSlot > occupied : append the series to already existing x series
+ *
+ * If the xSlot is already occupied the given ySlot decides what should happen:
+ * ySlot < -1 : move all existing series in the xSlot to next slot
+ * ySlot == -1 : stack on top at given x position
+ * ySlot == already occupied : insert at given y and x position
+ * ySlot > occupied : stack on top at given x position
+ */
+ virtual void addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot );
+
+ /** a value <= 0 for a directions means that this direction can be stretched arbitrary
+ */
+ virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const;
+
+ /** this enables you to handle series on the same x axis with different y axis
+ the property AttachedAxisIndex at a dataseries indicates which value scale is to use
+ (0==AttachedAxisIndex or a not set AttachedAxisIndex property indicates that this series should be scaled at the main y-axis;
+ 1==AttachedAxisIndex indicates that the series should be scaled at the first secondary axis if there is any otherwise at the main y axis
+ and so on.
+ The parameter nAxisIndex matches this DataSeries property 'AttachedAxisIndex'.
+ nAxisIndex must be greater than 0. nAxisIndex==1 refers to the first secondary axis.
+ )
+
+ @throws css::uno::RuntimeException
+ */
+
+ void addSecondaryValueScale( const ExplicitScaleData& rScale, sal_Int32 nAxisIndex );
+
+ // MinimumAndMaximumSupplier
+
+ virtual double getMinimumX() override;
+ virtual double getMaximumX() override;
+
+ virtual double getMinimumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) override;
+ virtual double getMaximumYInRange( double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex ) override;
+
+ virtual double getMinimumZ() override;
+ virtual double getMaximumZ() override;
+
+ virtual bool isExpandBorderToIncrementRhythm( sal_Int32 nDimensionIndex ) override;
+ virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex ) override;
+ virtual bool isExpandWideValuesToZero( sal_Int32 nDimensionIndex ) override;
+ virtual bool isExpandNarrowValuesTowardZero( sal_Int32 nDimensionIndex ) override;
+ virtual bool isSeparateStackingForDifferentSigns( sal_Int32 nDimensionIndex ) override;
+
+ virtual tools::Long calculateTimeResolutionOnXAxis() override;
+ virtual void setTimeResolutionOnXAxis( tools::Long nTimeResolution, const Date& rNullDate ) override;
+
+ void getMinimumAndMaximumX( double& rfMinimum, double& rfMaximum ) const;
+ void getMinimumAndMaximumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const;
+
+
+ // Methods for handling legends and legend entries.
+
+ virtual std::vector< ViewLegendEntry > createLegendEntries(
+ const css::awt::Size& rEntryKeyAspectRatio,
+ css::chart2::LegendPosition eLegendPosition,
+ const css::uno::Reference< css::beans::XPropertySet >& xTextProperties,
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const css::uno::Reference< css::uno::XComponentContext >& xContext,
+ ChartModel& rModel
+ ) override;
+
+ virtual LegendSymbolStyle getLegendSymbolStyle();
+ virtual css::awt::Size getPreferredLegendKeyAspectRatio() override;
+
+ virtual css::uno::Any getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex/*-1 for series symbol*/ );
+
+ rtl::Reference<SvxShapeGroup> createLegendSymbolForSeries(
+ const css::awt::Size& rEntryKeyAspectRatio
+ , const VDataSeries& rSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget );
+
+ rtl::Reference< SvxShapeGroup > createLegendSymbolForPoint(
+ const css::awt::Size& rEntryKeyAspectRatio
+ , const VDataSeries& rSeries
+ , sal_Int32 nPointIndex
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget );
+
+ std::vector< ViewLegendEntry > createLegendEntriesForSeries(
+ const css::awt::Size& rEntryKeyAspectRatio,
+ const VDataSeries& rSeries,
+ const css::uno::Reference< css::beans::XPropertySet >& xTextProperties,
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const css::uno::Reference< css::uno::XComponentContext >& xContext
+ );
+
+ std::vector<ViewLegendSymbol> createSymbols(
+ const css::awt::Size& rEntryKeyAspectRatio
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::uno::Reference<css::uno::XComponentContext>& xContext);
+
+ std::vector<ViewLegendSymbol> createSymbolsForSeries(
+ const css::awt::Size& rEntryKeyAspectRatio
+ , const VDataSeries& rSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::uno::Reference<css::uno::XComponentContext>& xContext);
+
+ std::vector<VDataSeries*> getAllSeries();
+ std::vector<VDataSeries const*> getAllSeries() const;
+
+ // This method creates a series plotter of the requested type; e.g. : return new PieChart...
+ static VSeriesPlotter* createSeriesPlotter( const rtl::Reference< ::chart::ChartType >& xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bExcludingPositioning /*for pie and donut charts labels and exploded segments are excluded from the given size*/);
+
+ sal_Int32 getPointCount() const;
+
+ // Methods for number formats and color schemes
+
+ void setNumberFormatsSupplier( const css::uno::Reference< css::util::XNumberFormatsSupplier > & xNumFmtSupplier );
+
+ void setColorScheme( const css::uno::Reference< css::chart2::XColorScheme >& xColorScheme );
+
+ void setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider );
+
+ ExplicitCategoriesProvider* getExplicitCategoriesProvider() { return m_pExplicitCategoriesProvider; }
+
+ //get series names for the z axis labels
+ css::uno::Sequence<OUString> getSeriesNames() const;
+
+ //get all series names
+ css::uno::Sequence<OUString> getAllSeriesNames() const;
+
+ void setPageReferenceSize( const css::awt::Size & rPageRefSize );
+ //better performance for big data
+ void setCoordinateSystemResolution( const css::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution );
+ bool PointsWereSkipped() const { return m_bPointsWereSkipped;}
+ void setPieLabelsAllowToMove( bool bIsPieOrDonut ) { m_bPieLabelsAllowToMove = bIsPieOrDonut; };
+ void setAvailableOuterRect( const basegfx::B2IRectangle& aAvailableOuterRect ) { m_aAvailableOuterRect = aAvailableOuterRect; };
+
+ //return the depth for a logic 1
+ double getTransformedDepth() const;
+
+ void releaseShapes();
+
+ virtual void rearrangeLabelToAvoidOverlapIfRequested( const css::awt::Size& rPageSize );
+
+ bool WantToPlotInFrontOfAxisLine();
+ virtual bool shouldSnapRectToUsedArea();
+
+ /// This method returns a text string representation of the passed numeric
+ /// value by exploiting a NumberFormatterWrapper object.
+ OUString getLabelTextForValue(VDataSeries const & rDataSeries, sal_Int32 nPointIndex,
+ double fValue, bool bAsPercentage);
+
+protected:
+
+ VSeriesPlotter( rtl::Reference< ::chart::ChartType > xChartTypeModel
+ , sal_Int32 nDimensionCount
+ , bool bCategoryXAxis=true );
+
+ // Methods for group shapes.
+
+ rtl::Reference<SvxShapeGroupAnyD>
+ getSeriesGroupShape( VDataSeries* pDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget );
+
+ //the following group shapes will be created as children of SeriesGroupShape on demand
+ //they can be used to assure that some parts of a series shape are always in front of others (e.g. symbols in front of lines)
+ //parameter xTarget will be used as parent for the series group shape
+ rtl::Reference<SvxShapeGroupAnyD>
+ getSeriesGroupShapeFrontChild( VDataSeries* pDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget );
+ rtl::Reference<SvxShapeGroupAnyD>
+ getSeriesGroupShapeBackChild( VDataSeries* pDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget );
+
+ /// This method creates a 2D group shape for containing all text shapes
+ /// needed for this series; the group is added to the text target;
+ static rtl::Reference<SvxShapeGroup>
+ getLabelsGroupShape( VDataSeries& rDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget );
+
+ rtl::Reference<SvxShapeGroupAnyD>
+ getErrorBarsGroupShape( VDataSeries& rDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget, bool bYError );
+
+ /** This method creates a text shape for a label related to a data point
+ * and append it to the root text shape group (xTarget).
+ *
+ * @param xTarget
+ * the main root text shape group.
+ * @param rDataSeries
+ * the data series, the data point belongs to.
+ * @param nPointIndex
+ * the index of the data point the label is related to.
+ * @param fValue
+ * the value of the data point.
+ * @param fSumValue
+ * the sum of all data point values in the data series.
+ * @param rScreenPosition2D
+ * the anchor point position for the label.
+ * @param eAlignment
+ * the required alignment of the label.
+ * @param offset
+ * an optional offset depending on the label alignment.
+ * @param nTextWidth
+ * the maximum width of a text label (used for text wrapping).
+ *
+ * @return
+ * a reference to the created text shape.
+ */
+ rtl::Reference<SvxShapeText>
+ createDataLabel( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , VDataSeries& rDataSeries
+ , sal_Int32 nPointIndex
+ , double fValue
+ , double fSumValue
+ , const css::awt::Point& rScreenPosition2D
+ , LabelAlignment eAlignment
+ , sal_Int32 nOffset=0
+ , sal_Int32 nTextWidth = 0 );
+
+ /** creates two T-shaped error bars in both directions (up/down or
+ left/right depending on the bVertical parameter)
+
+ @param rPos
+ logic coordinates
+
+ @param xErrorBarProperties
+ the XPropertySet returned by the DataPoint-property "ErrorBarX" or
+ "ErrorBarY".
+
+ @param nIndex
+ the index of the data point in rData for which the calculation is
+ done.
+
+ @param bVertical
+ for y-error bars this is true, for x-error-bars it is false.
+ */
+ void createErrorBar(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const css::drawing::Position3D & rPos
+ , const css::uno::Reference< css::beans::XPropertySet > & xErrorBarProperties
+ , const VDataSeries& rVDataSeries
+ , sal_Int32 nIndex
+ , bool bVertical
+ , const double* pfScaledLogicX
+ );
+
+ void createErrorRectangle(
+ const css::drawing::Position3D& rUnscaledLogicPosition
+ , VDataSeries& rVDataSeries
+ , sal_Int32 nIndex
+ , const rtl::Reference<SvxShapeGroupAnyD>& rTarget
+ , bool bUseXErrorData
+ , bool bUseYErrorData
+ );
+
+ static void addErrorBorder(
+ const css::drawing::Position3D& rPos0
+ , const css::drawing::Position3D& rPos1
+ , const rtl::Reference<SvxShapeGroupAnyD>& rTarget
+ , const css::uno::Reference< css::beans::XPropertySet >& rErrorBorderProp );
+
+ void createErrorBar_X( const css::drawing::Position3D& rUnscaledLogicPosition
+ , VDataSeries& rVDataSeries, sal_Int32 nPointIndex
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget );
+
+ void createErrorBar_Y( const css::drawing::Position3D& rUnscaledLogicPosition
+ , VDataSeries& rVDataSeries, sal_Int32 nPointIndex
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , double const * pfScaledLogicX );
+
+ void createRegressionCurvesShapes( VDataSeries const & rVDataSeries
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const rtl::Reference<SvxShapeGroupAnyD>& xEquationTarget
+ , bool bMaySkipPointsInRegressionCalculation );
+
+ void createRegressionCurveEquationShapes( const OUString & rEquationCID
+ , const css::uno::Reference< css::beans::XPropertySet > & xEquationProperties
+ , const rtl::Reference<SvxShapeGroupAnyD>& xEquationTarget
+ , const css::uno::Reference< css::chart2::XRegressionCurveCalculator > & xRegressionCurveCalculator
+ , css::awt::Point aDefaultPos );
+
+ virtual PlottingPositionHelper& getPlottingPositionHelper( sal_Int32 nAxisIndex ) const;//nAxisIndex indicates whether the position belongs to the main axis ( nAxisIndex==0 ) or secondary axis ( nAxisIndex==1 )
+
+ VDataSeries* getFirstSeries() const;
+
+ OUString getCategoryName( sal_Int32 nPointIndex ) const;
+
+protected:
+ PlottingPositionHelper* m_pMainPosHelper;
+
+ rtl::Reference< ::chart::ChartType > m_xChartTypeModel;
+
+ std::vector< std::vector< VDataSeriesGroup > > m_aZSlots;
+
+ bool m_bCategoryXAxis;//true->xvalues are indices (this would not be necessary if series for category chart wouldn't have x-values)
+ tools::Long m_nTimeResolution;
+ Date m_aNullDate;
+
+ std::unique_ptr< NumberFormatterWrapper > m_apNumberFormatterWrapper;
+
+ css::uno::Reference< css::chart2::XColorScheme > m_xColorScheme;
+
+ ExplicitCategoriesProvider* m_pExplicitCategoriesProvider;
+
+ //better performance for big data
+ css::uno::Sequence< sal_Int32 > m_aCoordinateSystemResolution;
+ bool m_bPointsWereSkipped;
+ bool m_bPieLabelsAllowToMove;
+ basegfx::B2IRectangle m_aAvailableOuterRect;
+ css::awt::Size m_aPageReferenceSize;
+
+private:
+ typedef std::map< sal_Int32 , ExplicitScaleData > tSecondaryValueScales;
+ tSecondaryValueScales m_aSecondaryValueScales;
+
+ typedef std::map< sal_Int32 , std::unique_ptr<PlottingPositionHelper> > tSecondaryPosHelperMap;
+ mutable tSecondaryPosHelperMap m_aSecondaryPosHelperMap;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/inc/ViewDefines.hxx b/chart2/source/view/inc/ViewDefines.hxx
new file mode 100644
index 0000000000..b8b82be956
--- /dev/null
+++ b/chart2/source/view/inc/ViewDefines.hxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sal/types.h>
+
+namespace chart
+{
+#define CHART_3DOBJECT_SEGMENTCOUNT (sal_Int32(32))
+//There needs to be a little distance between grid lines and walls in 3D, otherwise the lines are partly hidden by the walls
+#define GRID_TO_WALL_DISTANCE (1.0)
+
+const double ZDIRECTION = 1.0;
+const sal_Int32 AXIS2D_TICKLENGTH = 150; //value like in old chart
+const sal_Int32 AXIS2D_TICKLABELSPACING = 100; //value like in old chart
+
+} //end namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/AxisUsage.hxx b/chart2/source/view/main/AxisUsage.hxx
new file mode 100644
index 0000000000..8345187075
--- /dev/null
+++ b/chart2/source/view/main/AxisUsage.hxx
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include <memory>
+#include <map>
+
+#include <VCoordinateSystem.hxx>
+#include <AxisHelper.hxx>
+#include <ScaleAutomatism.hxx>
+
+namespace chart
+{
+//first index is the dimension, second index is the axis index that indicates whether this is a main or secondary axis
+typedef std::pair<sal_Int32, sal_Int32> tFullAxisIndex;
+typedef std::map<VCoordinateSystem*, tFullAxisIndex> tCoordinateSystemMap;
+
+/** This class handles a collection of coordinate systems and is used for
+ * executing some action on all coordinate systems such as
+ * "prepareAutomaticAxisScaling" and "setExplicitScaleAndIncrement".
+ * Moreover it contains the "aAutoScaling" object that is an instance of
+ * the "ScaleAutomatism" class. The initialization of "aAutoScaling" is
+ * performed in the "SeriesPlotterContainer::initAxisUsageList" method and is
+ * used in the "SeriesPlotterContainer::doAutoScaling" for calculating explicit
+ * scale and increment objects (see "SeriesPlotterContainer::doAutoScaling").
+ */
+class AxisUsage
+{
+public:
+ AxisUsage()
+ : aAutoScaling(AxisHelper::createDefaultScale(), Date(Date::SYSTEM))
+ {
+ }
+
+ void addCoordinateSystem(VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex,
+ sal_Int32 nAxisIndex)
+ {
+ if (!pCooSys)
+ return;
+
+ tFullAxisIndex aFullAxisIndex(nDimensionIndex, nAxisIndex);
+ tCoordinateSystemMap::const_iterator aFound(aCoordinateSystems.find(pCooSys));
+
+ //use one scale only once for each coordinate system
+ //main axis are preferred over secondary axis
+ //value scales are preferred
+ if (aFound != aCoordinateSystems.end())
+ {
+ sal_Int32 nFoundAxisIndex = aFound->second.second;
+ if (nFoundAxisIndex < nAxisIndex)
+ return;
+ sal_Int32 nFoundDimension = aFound->second.first;
+ if (nFoundDimension == 1)
+ return;
+ if (nFoundDimension < nDimensionIndex)
+ return;
+ }
+ aCoordinateSystems[pCooSys] = aFullAxisIndex;
+
+ //set maximum scale index
+ auto aIter = aMaxIndexPerDimension.find(nDimensionIndex);
+ if (aIter != aMaxIndexPerDimension.end())
+ {
+ sal_Int32 nCurrentMaxIndex = aIter->second;
+ if (nCurrentMaxIndex < nAxisIndex)
+ aMaxIndexPerDimension[nDimensionIndex] = nAxisIndex;
+ }
+ else
+ aMaxIndexPerDimension[nDimensionIndex] = nAxisIndex;
+ }
+
+ std::vector<VCoordinateSystem*> getCoordinateSystems(sal_Int32 nDimensionIndex,
+ sal_Int32 nAxisIndex)
+ {
+ std::vector<VCoordinateSystem*> aRet;
+
+ for (auto const& coordinateSystem : aCoordinateSystems)
+ {
+ if (coordinateSystem.second.first != nDimensionIndex)
+ continue;
+ if (coordinateSystem.second.second != nAxisIndex)
+ continue;
+ aRet.push_back(coordinateSystem.first);
+ }
+
+ return aRet;
+ }
+
+ sal_Int32 getMaxAxisIndexForDimension(sal_Int32 nDimensionIndex)
+ {
+ sal_Int32 nRet = -1;
+ auto aIter = aMaxIndexPerDimension.find(nDimensionIndex);
+ if (aIter != aMaxIndexPerDimension.end())
+ nRet = aIter->second;
+ return nRet;
+ }
+
+ void prepareAutomaticAxisScaling(ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex,
+ sal_Int32 nAxisIndex)
+ {
+ std::vector<VCoordinateSystem*> aVCooSysList = getCoordinateSystems(nDimIndex, nAxisIndex);
+ for (VCoordinateSystem* pVCoordinateSystem : aVCooSysList)
+ pVCoordinateSystem->prepareAutomaticAxisScaling(rScaleAutomatism, nDimIndex,
+ nAxisIndex);
+ }
+
+ void setExplicitScaleAndIncrement(sal_Int32 nDimIndex, sal_Int32 nAxisIndex,
+ const ExplicitScaleData& rScale,
+ const ExplicitIncrementData& rInc)
+ {
+ std::vector<VCoordinateSystem*> aVCooSysList = getCoordinateSystems(nDimIndex, nAxisIndex);
+ for (VCoordinateSystem* pVCoordinateSystem : aVCooSysList)
+ pVCoordinateSystem->setExplicitScaleAndIncrement(nDimIndex, nAxisIndex, rScale, rInc);
+ }
+
+ ScaleAutomatism aAutoScaling;
+
+private:
+ tCoordinateSystemMap aCoordinateSystems;
+ std::map<sal_Int32, sal_Int32> aMaxIndexPerDimension;
+};
+
+} //end chart2 namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/ChartItemPool.cxx b/chart2/source/view/main/ChartItemPool.cxx
new file mode 100644
index 0000000000..8f787cd4bd
--- /dev/null
+++ b/chart2/source/view/main/ChartItemPool.cxx
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "ChartItemPool.hxx"
+#include <chartview/ChartSfxItemIds.hxx>
+#include <DataSeries.hxx>
+#include <FormattedString.hxx>
+#include <Legend.hxx>
+#include <Axis.hxx>
+#include <svx/chrtitem.hxx>
+#include <svx/sdangitm.hxx>
+#include <svx/svdpool.hxx>
+#include <svx/svx3ditems.hxx>
+#include <svl/intitem.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/ilstitem.hxx>
+#include <comphelper/processfactory.hxx>
+#include <editeng/editids.hrc>
+#include <svx/svxids.hrc>
+#include <vector>
+
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart2/MovingAverageType.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+
+namespace chart
+{
+
+ChartItemPool::ChartItemPool():
+ SfxItemPool( "ChartItemPool" , SCHATTR_START, SCHATTR_END, nullptr, nullptr ),
+ pItemInfos(new SfxItemInfo[SCHATTR_END - SCHATTR_START + 1])
+{
+ /**************************************************************************
+ * PoolDefaults
+ **************************************************************************/
+ std::vector<SfxPoolItem*>* ppPoolDefaults = new std::vector<SfxPoolItem*>(SCHATTR_END - SCHATTR_START + 1);
+ std::vector<SfxPoolItem*>& rPoolDefaults = *ppPoolDefaults;
+ rPoolDefaults[SCHATTR_DATADESCR_SHOW_NUMBER - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_NUMBER);
+ rPoolDefaults[SCHATTR_DATADESCR_SHOW_PERCENTAGE- SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_PERCENTAGE);
+ rPoolDefaults[SCHATTR_DATADESCR_SHOW_CATEGORY - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_CATEGORY);
+ rPoolDefaults[SCHATTR_DATADESCR_SHOW_SYMBOL - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_SYMBOL);
+ rPoolDefaults[SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME);
+ rPoolDefaults[SCHATTR_DATADESCR_WRAP_TEXT - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_WRAP_TEXT);
+ rPoolDefaults[SCHATTR_DATADESCR_SEPARATOR - SCHATTR_START] = new SfxStringItem(SCHATTR_DATADESCR_SEPARATOR," ");
+ rPoolDefaults[SCHATTR_DATADESCR_PLACEMENT - SCHATTR_START] = new SfxInt32Item(SCHATTR_DATADESCR_PLACEMENT,0);
+ rPoolDefaults[SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS - SCHATTR_START] = new SfxIntegerListItem(SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS, std::vector < sal_Int32 >() );
+ rPoolDefaults[SCHATTR_DATADESCR_NO_PERCENTVALUE - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_NO_PERCENTVALUE);
+ rPoolDefaults[SCHATTR_DATADESCR_CUSTOM_LEADER_LINES - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_CUSTOM_LEADER_LINES, true);
+ rPoolDefaults[SCHATTR_PERCENT_NUMBERFORMAT_VALUE - SCHATTR_START] = new SfxUInt32Item(SCHATTR_PERCENT_NUMBERFORMAT_VALUE, 0);
+ rPoolDefaults[SCHATTR_PERCENT_NUMBERFORMAT_SOURCE - SCHATTR_START] = new SfxBoolItem(SCHATTR_PERCENT_NUMBERFORMAT_SOURCE);
+
+ //legend
+ rPoolDefaults[SCHATTR_LEGEND_POS - SCHATTR_START] = new SfxInt32Item(SCHATTR_LEGEND_POS, sal_Int32(css::chart2::LegendPosition_LINE_END) );
+ rPoolDefaults[SCHATTR_LEGEND_SHOW - SCHATTR_START] = new SfxBoolItem(SCHATTR_LEGEND_SHOW, true);
+ rPoolDefaults[SCHATTR_LEGEND_NO_OVERLAY - SCHATTR_START] = new SfxBoolItem(SCHATTR_LEGEND_NO_OVERLAY, true);
+
+ //text
+ rPoolDefaults[SCHATTR_TEXT_DEGREES - SCHATTR_START] = new SdrAngleItem(SCHATTR_TEXT_DEGREES, 0_deg100);
+ rPoolDefaults[SCHATTR_TEXT_STACKED - SCHATTR_START] = new SfxBoolItem(SCHATTR_TEXT_STACKED,false);
+
+ //statistic
+ rPoolDefaults[SCHATTR_STAT_AVERAGE - SCHATTR_START] = new SfxBoolItem (SCHATTR_STAT_AVERAGE);
+ rPoolDefaults[SCHATTR_STAT_KIND_ERROR - SCHATTR_START] = new SvxChartKindErrorItem (SvxChartKindError::NONE, SCHATTR_STAT_KIND_ERROR);
+ rPoolDefaults[SCHATTR_STAT_PERCENT - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_PERCENT);
+ rPoolDefaults[SCHATTR_STAT_BIGERROR - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_BIGERROR);
+ rPoolDefaults[SCHATTR_STAT_CONSTPLUS - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_CONSTPLUS);
+ rPoolDefaults[SCHATTR_STAT_CONSTMINUS - SCHATTR_START] = new SvxDoubleItem (0.0, SCHATTR_STAT_CONSTMINUS);
+ rPoolDefaults[SCHATTR_STAT_INDICATE - SCHATTR_START] = new SvxChartIndicateItem (SvxChartIndicate::NONE, SCHATTR_STAT_INDICATE);
+ rPoolDefaults[SCHATTR_STAT_RANGE_POS - SCHATTR_START] = new SfxStringItem (SCHATTR_STAT_RANGE_POS, OUString());
+ rPoolDefaults[SCHATTR_STAT_RANGE_NEG - SCHATTR_START] = new SfxStringItem (SCHATTR_STAT_RANGE_NEG, OUString());
+ rPoolDefaults[SCHATTR_STAT_ERRORBAR_TYPE - SCHATTR_START] = new SfxBoolItem(SCHATTR_STAT_ERRORBAR_TYPE, true);
+
+ rPoolDefaults[SCHATTR_STYLE_DEEP - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_DEEP, false);
+ rPoolDefaults[SCHATTR_STYLE_3D - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_3D, false);
+ rPoolDefaults[SCHATTR_STYLE_VERTICAL - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_VERTICAL, false);
+ rPoolDefaults[SCHATTR_STYLE_BASETYPE - SCHATTR_START] = new SfxInt32Item(SCHATTR_STYLE_BASETYPE, 0);
+ rPoolDefaults[SCHATTR_STYLE_LINES - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_LINES, false);
+ rPoolDefaults[SCHATTR_STYLE_PERCENT - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_PERCENT, false);
+ rPoolDefaults[SCHATTR_STYLE_STACKED - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_STACKED, false);
+ rPoolDefaults[SCHATTR_STYLE_SPLINES - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SPLINES, 0); //Bug: was Bool! test ->Fileformat (touches only 5's)
+ rPoolDefaults[SCHATTR_STYLE_SYMBOL - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SYMBOL, 0);
+ rPoolDefaults[SCHATTR_STYLE_SHAPE - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SHAPE, 0);
+
+ rPoolDefaults[SCHATTR_AXIS - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS,2); //2 = Y-Axis!!!
+
+ //axis scale
+ rPoolDefaults[SCHATTR_AXISTYPE - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXISTYPE, CHART_AXIS_REALNUMBER);
+ rPoolDefaults[SCHATTR_AXIS_REVERSE - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_REVERSE,false);
+ rPoolDefaults[SCHATTR_AXIS_AUTO_MIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_MIN);
+ rPoolDefaults[SCHATTR_AXIS_MIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_MIN);
+ rPoolDefaults[SCHATTR_AXIS_AUTO_MAX - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_MAX);
+ rPoolDefaults[SCHATTR_AXIS_MAX - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_MAX);
+ rPoolDefaults[SCHATTR_AXIS_AUTO_STEP_MAIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_MAIN);
+ rPoolDefaults[SCHATTR_AXIS_STEP_MAIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_STEP_MAIN);
+ rPoolDefaults[SCHATTR_AXIS_MAIN_TIME_UNIT - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_MAIN_TIME_UNIT,2);
+ rPoolDefaults[SCHATTR_AXIS_AUTO_STEP_HELP - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_HELP);
+ rPoolDefaults[SCHATTR_AXIS_STEP_HELP - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_STEP_HELP,0);
+ rPoolDefaults[SCHATTR_AXIS_HELP_TIME_UNIT - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_HELP_TIME_UNIT,2);
+ rPoolDefaults[SCHATTR_AXIS_AUTO_TIME_RESOLUTION - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_TIME_RESOLUTION);
+ rPoolDefaults[SCHATTR_AXIS_TIME_RESOLUTION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_TIME_RESOLUTION,2);
+ rPoolDefaults[SCHATTR_AXIS_LOGARITHM - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_LOGARITHM);
+ rPoolDefaults[SCHATTR_AXIS_AUTO_DATEAXIS - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_DATEAXIS);
+ rPoolDefaults[SCHATTR_AXIS_ALLOW_DATEAXIS - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_ALLOW_DATEAXIS);
+ rPoolDefaults[SCHATTR_AXIS_AUTO_ORIGIN - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_AUTO_ORIGIN);
+ rPoolDefaults[SCHATTR_AXIS_ORIGIN - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_ORIGIN);
+
+ //axis position
+ rPoolDefaults[SCHATTR_AXIS_TICKS - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_TICKS,CHAXIS_MARK_OUTER);
+ rPoolDefaults[SCHATTR_AXIS_HELPTICKS - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_HELPTICKS,0);
+ rPoolDefaults[SCHATTR_AXIS_POSITION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_POSITION,0);
+ rPoolDefaults[SCHATTR_AXIS_POSITION_VALUE - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_AXIS_POSITION_VALUE);
+ rPoolDefaults[SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT - SCHATTR_START] = new SfxUInt32Item(SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT,0);
+ rPoolDefaults[SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION,false);
+ rPoolDefaults[SCHATTR_AXIS_LABEL_POSITION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_LABEL_POSITION,0);
+ rPoolDefaults[SCHATTR_AXIS_MARK_POSITION - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_MARK_POSITION,0);
+
+ //axis label
+ rPoolDefaults[SCHATTR_AXIS_SHOWDESCR - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_SHOWDESCR,false);
+ rPoolDefaults[SCHATTR_AXIS_LABEL_ORDER - SCHATTR_START] = new SvxChartTextOrderItem(SvxChartTextOrder::SideBySide, SCHATTR_AXIS_LABEL_ORDER);
+ rPoolDefaults[SCHATTR_AXIS_LABEL_OVERLAP - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_LABEL_OVERLAP,false);
+ rPoolDefaults[SCHATTR_AXIS_LABEL_BREAK - SCHATTR_START] = new SfxBoolItem(SCHATTR_AXIS_LABEL_BREAK, false );
+
+ rPoolDefaults[SCHATTR_SYMBOL_BRUSH - SCHATTR_START] = new SvxBrushItem(SCHATTR_SYMBOL_BRUSH);
+ rPoolDefaults[SCHATTR_STOCK_VOLUME - SCHATTR_START] = new SfxBoolItem(SCHATTR_STOCK_VOLUME,false);
+ rPoolDefaults[SCHATTR_STOCK_UPDOWN - SCHATTR_START] = new SfxBoolItem(SCHATTR_STOCK_UPDOWN,false);
+ rPoolDefaults[SCHATTR_SYMBOL_SIZE - SCHATTR_START] = new SvxSizeItem(SCHATTR_SYMBOL_SIZE,Size(0,0));
+ rPoolDefaults[SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY - SCHATTR_START] = new SfxBoolItem(SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, false);
+
+ // new for New Chart
+ rPoolDefaults[SCHATTR_BAR_OVERLAP - SCHATTR_START] = new SfxInt32Item(SCHATTR_BAR_OVERLAP,0);
+ rPoolDefaults[SCHATTR_BAR_GAPWIDTH - SCHATTR_START] = new SfxInt32Item(SCHATTR_BAR_GAPWIDTH,0);
+ rPoolDefaults[SCHATTR_BAR_CONNECT - SCHATTR_START] = new SfxBoolItem(SCHATTR_BAR_CONNECT, false);
+ rPoolDefaults[SCHATTR_NUM_OF_LINES_FOR_BAR - SCHATTR_START] = new SfxInt32Item( SCHATTR_NUM_OF_LINES_FOR_BAR, 0 );
+ rPoolDefaults[SCHATTR_SPLINE_ORDER - SCHATTR_START] = new SfxInt32Item( SCHATTR_SPLINE_ORDER, 3 );
+ rPoolDefaults[SCHATTR_SPLINE_RESOLUTION - SCHATTR_START] = new SfxInt32Item( SCHATTR_SPLINE_RESOLUTION, 20 );
+ rPoolDefaults[SCHATTR_GROUP_BARS_PER_AXIS - SCHATTR_START] = new SfxBoolItem(SCHATTR_GROUP_BARS_PER_AXIS, false);
+ rPoolDefaults[SCHATTR_STARTING_ANGLE - SCHATTR_START] = new SdrAngleItem( SCHATTR_STARTING_ANGLE, 9000_deg100 );
+ rPoolDefaults[SCHATTR_CLOCKWISE - SCHATTR_START] = new SfxBoolItem( SCHATTR_CLOCKWISE, false );
+
+ rPoolDefaults[SCHATTR_MISSING_VALUE_TREATMENT - SCHATTR_START] = new SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT, 0);
+ rPoolDefaults[SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS - SCHATTR_START] = new SfxIntegerListItem(SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS, std::vector < sal_Int32 >() );
+ rPoolDefaults[SCHATTR_INCLUDE_HIDDEN_CELLS - SCHATTR_START] = new SfxBoolItem(SCHATTR_INCLUDE_HIDDEN_CELLS, true);
+ rPoolDefaults[SCHATTR_HIDE_LEGEND_ENTRY - SCHATTR_START] = new SfxBoolItem(SCHATTR_HIDE_LEGEND_ENTRY, false);
+
+ rPoolDefaults[SCHATTR_AXIS_FOR_ALL_SERIES - SCHATTR_START] = new SfxInt32Item(SCHATTR_AXIS_FOR_ALL_SERIES, 0);
+
+ rPoolDefaults[SCHATTR_REGRESSION_TYPE - SCHATTR_START] = new SvxChartRegressItem (SvxChartRegress::NONE, SCHATTR_REGRESSION_TYPE);
+ rPoolDefaults[SCHATTR_REGRESSION_SHOW_EQUATION - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SHOW_EQUATION, false);
+ rPoolDefaults[SCHATTR_REGRESSION_SHOW_COEFF - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SHOW_COEFF, false);
+ rPoolDefaults[SCHATTR_REGRESSION_DEGREE - SCHATTR_START] = new SfxInt32Item(SCHATTR_REGRESSION_DEGREE, 2);
+ rPoolDefaults[SCHATTR_REGRESSION_PERIOD - SCHATTR_START] = new SfxInt32Item(SCHATTR_REGRESSION_PERIOD, 2);
+ rPoolDefaults[SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD);
+ rPoolDefaults[SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD);
+ rPoolDefaults[SCHATTR_REGRESSION_SET_INTERCEPT - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SET_INTERCEPT, false);
+ rPoolDefaults[SCHATTR_REGRESSION_INTERCEPT_VALUE - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_REGRESSION_INTERCEPT_VALUE);
+ rPoolDefaults[SCHATTR_REGRESSION_CURVE_NAME - SCHATTR_START] = new SfxStringItem(SCHATTR_REGRESSION_CURVE_NAME, OUString());
+ rPoolDefaults[SCHATTR_REGRESSION_XNAME - SCHATTR_START] = new SfxStringItem(SCHATTR_REGRESSION_XNAME, "x");
+ rPoolDefaults[SCHATTR_REGRESSION_YNAME - SCHATTR_START] = new SfxStringItem(SCHATTR_REGRESSION_YNAME, "f(x)");
+ rPoolDefaults[SCHATTR_REGRESSION_MOVING_TYPE - SCHATTR_START] = new SfxInt32Item(SCHATTR_REGRESSION_MOVING_TYPE, css::chart2::MovingAverageType::Prior);
+
+ rPoolDefaults[SCHATTR_DATA_TABLE_HORIZONTAL_BORDER - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATA_TABLE_HORIZONTAL_BORDER, false);
+ rPoolDefaults[SCHATTR_DATA_TABLE_VERTICAL_BORDER - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATA_TABLE_VERTICAL_BORDER, false);
+ rPoolDefaults[SCHATTR_DATA_TABLE_OUTLINE - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATA_TABLE_OUTLINE, false);
+ rPoolDefaults[SCHATTR_DATA_TABLE_KEYS - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATA_TABLE_KEYS, false);
+
+ /**************************************************************************
+ * ItemInfos
+ **************************************************************************/
+ const sal_uInt16 nMax = SCHATTR_END - SCHATTR_START + 1;
+ for( sal_uInt16 i = 0; i < nMax; i++ )
+ {
+ // _nSID, _bNeedsPoolRegistration, _bShareable
+ pItemInfos[i]._nSID = 0;
+ pItemInfos[i]._bNeedsPoolRegistration = false;
+ pItemInfos[i]._bShareable = true;
+ }
+
+ // slot ids differing from which ids
+ pItemInfos[SCHATTR_SYMBOL_BRUSH - SCHATTR_START]._nSID = SID_ATTR_BRUSH;
+ pItemInfos[SCHATTR_STYLE_SYMBOL - SCHATTR_START]._nSID = SID_ATTR_SYMBOLTYPE;
+ pItemInfos[SCHATTR_SYMBOL_SIZE - SCHATTR_START]._nSID = SID_ATTR_SYMBOLSIZE;
+
+ SetDefaults(ppPoolDefaults);
+ SetItemInfos(pItemInfos.get());
+}
+
+ChartItemPool::ChartItemPool(const ChartItemPool& rPool):
+ SfxItemPool(rPool)
+{
+}
+
+ChartItemPool::~ChartItemPool()
+{
+ Delete();
+ // release and delete static pool default items
+ ReleaseDefaults(true);
+}
+
+rtl::Reference<SfxItemPool> ChartItemPool::Clone() const
+{
+ return new ChartItemPool(*this);
+}
+
+MapUnit ChartItemPool::GetMetric(sal_uInt16 /* nWhich */) const
+{
+ return MapUnit::Map100thMM;
+}
+
+rtl::Reference<SfxItemPool> ChartItemPool::CreateChartItemPool()
+{
+ // There are various default values which want to call
+ // OutputDevice::GetDefaultFont. Unfortunately, when processing
+ // UNO methods which may get called from out of process, this
+ // happens on a thread that does not take the SolarMutex, which
+ // causes trouble in ImplFontCache.
+ // Trying to take the SolarMutex when initialising these default
+ // leads to ABBA deadlocks.
+ // So rather just trigger the initialisation of these things here.
+ StaticDataSeriesDefaults();
+ StaticAxisDefaults();
+ StaticLegendDefaults();
+ StaticFormattedStringDefaults();
+
+ return new ChartItemPool();
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/ChartItemPool.hxx b/chart2/source/view/main/ChartItemPool.hxx
new file mode 100644
index 0000000000..74a7ab1ebb
--- /dev/null
+++ b/chart2/source/view/main/ChartItemPool.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <tools/mapunit.hxx>
+#include <svl/itempool.hxx>
+#include <memory>
+
+namespace chart
+{
+class ChartItemPool : public SfxItemPool
+{
+private:
+ std::unique_ptr<SfxItemInfo[]> pItemInfos;
+
+public:
+ ChartItemPool();
+ ChartItemPool(const ChartItemPool& rPool);
+ virtual ~ChartItemPool() override;
+
+ virtual rtl::Reference<SfxItemPool> Clone() const override;
+ MapUnit GetMetric(sal_uInt16 nWhich) const override;
+
+ /// creates a pure chart item pool
+ static rtl::Reference<SfxItemPool> CreateChartItemPool();
+};
+
+} // namespace chart
+
+// INCLUDED_CHART2_SOURCE_VIEW_MAIN_CHARTITEMPOOL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx
new file mode 100644
index 0000000000..bed80f49b3
--- /dev/null
+++ b/chart2/source/view/main/ChartView.cxx
@@ -0,0 +1,2080 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_feature_desktop.h>
+
+#include "SeriesPlotterContainer.hxx"
+
+#include <ChartView.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <Diagram.hxx>
+#include <ChartType.hxx>
+#include <DataSeries.hxx>
+#include <NumberFormatterWrapper.hxx>
+#include <VDiagram.hxx>
+#include "VTitle.hxx"
+#include "VButton.hxx"
+#include <ShapeFactory.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <VCoordinateSystem.hxx>
+#include <VSeriesPlotter.hxx>
+#include <CommonConverters.hxx>
+#include <TitleHelper.hxx>
+#include <Legend.hxx>
+#include <LegendHelper.hxx>
+#include "VLegend.hxx"
+#include <PropertyMapper.hxx>
+#include <ChartModel.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ScaleAutomatism.hxx>
+#include <ObjectIdentifier.hxx>
+#include <DiagramHelper.hxx>
+#include <RelativePositionHelper.hxx>
+#include <servicenames.hxx>
+#include <Axis.hxx>
+#include <AxisHelper.hxx>
+#include "AxisUsage.hxx"
+#include <AxisIndexDefines.hxx>
+#include <BaseGFXHelper.hxx>
+#include <DataSeriesHelper.hxx>
+#include <DateHelper.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <defines.hxx>
+#include <comphelper/dumpxmltostring.hxx>
+#include <unonames.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/eeitem.hxx>
+#include <tools/globname.hxx>
+#include <comphelper/fileformat.h>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <rtl/math.hxx>
+#include <unotools/streamwrap.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/unopage.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <osl/mutex.hxx>
+#include <svx/unofill.hxx>
+#include <drawinglayer/XShapeDumper.hxx>
+#include <sfx2/objsh.hxx>
+
+#include <time.h>
+
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart/TimeUnit.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
+#include <com/sun/star/chart2/data/PivotTableFieldEntry.hpp>
+#include <com/sun/star/drawing/GraphicExportFilter.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <svl/itempool.hxx>
+#include <svl/ctloptions.hxx>
+#include <comphelper/classids.hxx>
+#include <servicenames_charttypes.hxx>
+
+
+#include <rtl/ustring.hxx>
+
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/stream.hxx>
+
+#include <memory>
+#include <libxml/xmlwriter.h>
+
+namespace chart {
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+
+struct CreateShapeParam2D
+{
+ css::awt::Rectangle maRemainingSpace;
+
+ std::shared_ptr<SeriesPlotterContainer> mpSeriesPlotterContainer;
+
+ std::shared_ptr<VTitle> mpVTitleX;
+ std::shared_ptr<VTitle> mpVTitleY;
+ std::shared_ptr<VTitle> mpVTitleZ;
+
+ std::shared_ptr<VTitle> mpVTitleSecondX;
+ std::shared_ptr<VTitle> mpVTitleSecondY;
+
+ rtl::Reference<SvxShapeRect> mxMarkHandles;
+ rtl::Reference<SvxShapeRect> mxPlotAreaWithAxes;
+
+ rtl::Reference<SvxShapeGroup> mxDiagramWithAxesShapes;
+
+ bool mbAutoPosTitleX;
+ bool mbAutoPosTitleY;
+ bool mbAutoPosTitleZ;
+
+ bool mbAutoPosSecondTitleX;
+ bool mbAutoPosSecondTitleY;
+
+ bool mbUseFixedInnerSize;
+
+ CreateShapeParam2D() :
+ mbAutoPosTitleX(true),
+ mbAutoPosTitleY(true),
+ mbAutoPosTitleZ(true),
+ mbAutoPosSecondTitleX(true),
+ mbAutoPosSecondTitleY(true),
+ mbUseFixedInnerSize(false) {}
+};
+
+
+
+ChartView::ChartView(
+ uno::Reference<uno::XComponentContext> xContext,
+ ChartModel& rModel)
+ : m_xCC(std::move(xContext))
+ , mrChartModel(rModel)
+ , m_bViewDirty(true)
+ , m_bInViewUpdate(false)
+ , m_bViewUpdatePending(false)
+ , m_bRefreshAddIn(true)
+ , m_aPageResolution(1000,1000)
+ , m_bPointsWereSkipped(false)
+ , m_nScaleXNumerator(1)
+ , m_nScaleXDenominator(1)
+ , m_nScaleYNumerator(1)
+ , m_nScaleYDenominator(1)
+ , m_bSdrViewIsInEditMode(false)
+ , m_aResultingDiagramRectangleExcludingAxes(0,0,0,0)
+{
+ init();
+}
+
+void ChartView::init()
+{
+ if( !m_pDrawModelWrapper )
+ {
+ SolarMutexGuard aSolarGuard;
+ m_pDrawModelWrapper = std::make_shared< DrawModelWrapper >();
+ m_xShapeFactory = m_pDrawModelWrapper->getShapeFactory();
+ m_xDrawPage = m_pDrawModelWrapper->getMainDrawPage();
+ StartListening( m_pDrawModelWrapper->getSdrModel() );
+ }
+}
+
+void SAL_CALL ChartView::initialize( const uno::Sequence< uno::Any >& )
+{
+ init();
+}
+
+ChartView::~ChartView()
+{
+ maTimeBased.maTimer.Stop();
+ // #i120831#. In ChartView::initialize(), m_xShapeFactory is created from SdrModel::getUnoModel() and indirectly
+ // from SfxBaseModel, it needs call dispose() to make sure SfxBaseModel object is freed correctly.
+ uno::Reference< lang::XComponent > xComp( m_xShapeFactory, uno::UNO_QUERY);
+ if ( xComp.is() )
+ xComp->dispose();
+
+ if( m_pDrawModelWrapper )
+ {
+ SolarMutexGuard aSolarGuard;
+ EndListening( m_pDrawModelWrapper->getSdrModel() );
+ m_pDrawModelWrapper.reset();
+ }
+ m_xDrawPage = nullptr;
+ impl_deleteCoordinateSystems();
+}
+
+void ChartView::impl_deleteCoordinateSystems()
+{
+ //delete all coordinate systems
+ m_aVCooSysList.clear();
+}
+
+// datatransfer::XTransferable
+namespace
+{
+constexpr OUString lcl_aGDIMetaFileMIMEType(
+ u"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""_ustr );
+constexpr OUString lcl_aGDIMetaFileMIMETypeHighContrast(
+ u"application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\""_ustr );
+} // anonymous namespace
+
+void ChartView::getMetaFile( const uno::Reference< io::XOutputStream >& xOutStream
+ , bool bUseHighContrast )
+{
+ if( !m_xDrawPage.is() )
+ return;
+
+ // creating the graphic exporter
+ uno::Reference< drawing::XGraphicExportFilter > xExporter = drawing::GraphicExportFilter::create( m_xCC );
+
+ uno::Sequence< beans::PropertyValue > aFilterData{
+ comphelper::makePropertyValue("ExportOnlyBackground", false),
+ comphelper::makePropertyValue("HighContrast", bUseHighContrast),
+ comphelper::makePropertyValue("Version", sal_Int32(SOFFICE_FILEFORMAT_50)),
+ comphelper::makePropertyValue("CurrentPage", uno::Reference< uno::XInterface >( static_cast<cppu::OWeakObject*>(m_xDrawPage.get()), uno::UNO_QUERY )),
+ //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
+ comphelper::makePropertyValue("ScaleXNumerator", m_nScaleXNumerator),
+ comphelper::makePropertyValue("ScaleXDenominator", m_nScaleXDenominator),
+ comphelper::makePropertyValue("ScaleYNumerator", m_nScaleYNumerator),
+ comphelper::makePropertyValue("ScaleYDenominator", m_nScaleYDenominator)
+ };
+
+ uno::Sequence< beans::PropertyValue > aProps{
+ comphelper::makePropertyValue("FilterName", OUString("SVM")),
+ comphelper::makePropertyValue("OutputStream", xOutStream),
+ comphelper::makePropertyValue("FilterData", aFilterData)
+ };
+
+ xExporter->setSourceDocument( m_xDrawPage );
+ if( xExporter->filter( aProps ) )
+ {
+ xOutStream->flush();
+ xOutStream->closeOutput();
+ uno::Reference< io::XSeekable > xSeekable( xOutStream, uno::UNO_QUERY );
+ if( xSeekable.is() )
+ xSeekable->seek(0);
+ }
+}
+
+uno::Any SAL_CALL ChartView::getTransferData( const datatransfer::DataFlavor& aFlavor )
+{
+ bool bHighContrastMetaFile( aFlavor.MimeType == lcl_aGDIMetaFileMIMETypeHighContrast);
+ uno::Any aRet;
+ if( ! (bHighContrastMetaFile || aFlavor.MimeType == lcl_aGDIMetaFileMIMEType) )
+ return aRet;
+
+ update();
+
+ SvMemoryStream aStream( 1024, 1024 );
+ rtl::Reference<utl::OStreamWrapper> pStreamWrapper = new utl::OStreamWrapper( aStream );
+
+ this->getMetaFile( pStreamWrapper, bHighContrastMetaFile );
+
+ pStreamWrapper->seek(0);
+ sal_Int32 nBytesToRead = pStreamWrapper->available();
+ uno::Sequence< sal_Int8 > aSeq( nBytesToRead );
+ pStreamWrapper->readBytes( aSeq, nBytesToRead);
+ aRet <<= aSeq;
+ pStreamWrapper->closeInput();
+
+ return aRet;
+}
+uno::Sequence< datatransfer::DataFlavor > SAL_CALL ChartView::getTransferDataFlavors()
+{
+ return
+ {
+ { lcl_aGDIMetaFileMIMEType, "GDIMetaFile", cppu::UnoType<uno::Sequence< sal_Int8 >>::get() },
+ { lcl_aGDIMetaFileMIMETypeHighContrast, "GDIMetaFile", cppu::UnoType<uno::Sequence< sal_Int8 >>::get() }
+ };
+}
+sal_Bool SAL_CALL ChartView::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
+{
+ return ( aFlavor.MimeType == lcl_aGDIMetaFileMIMEType ||
+ aFlavor.MimeType == lcl_aGDIMetaFileMIMETypeHighContrast );
+}
+
+// lang::XServiceInfo
+
+OUString SAL_CALL ChartView::getImplementationName()
+{
+ return CHART_VIEW_SERVICE_IMPLEMENTATION_NAME;
+}
+
+sal_Bool SAL_CALL ChartView::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ChartView::getSupportedServiceNames()
+{
+ return { CHART_VIEW_SERVICE_NAME };
+}
+
+static ::basegfx::B3DHomMatrix createTransformationSceneToScreen(
+ const ::basegfx::B2IRectangle& rDiagramRectangleWithoutAxes )
+{
+ ::basegfx::B3DHomMatrix aM;
+ aM.scale(double(rDiagramRectangleWithoutAxes.getWidth())/FIXED_SIZE_FOR_3D_CHART_VOLUME
+ , -double(rDiagramRectangleWithoutAxes.getHeight())/FIXED_SIZE_FOR_3D_CHART_VOLUME, 1.0 );
+ aM.translate(double(rDiagramRectangleWithoutAxes.getMinX())
+ , double(rDiagramRectangleWithoutAxes.getMinY()+rDiagramRectangleWithoutAxes.getHeight()-1), 0);
+ return aM;
+}
+
+namespace
+{
+
+bool lcl_IsPieOrDonut( const rtl::Reference< Diagram >& xDiagram )
+{
+ //special treatment for pie charts
+ //the size is checked after complete creation to get the datalabels into the given space
+
+ //todo: this is just a workaround at the moment for pie and donut labels
+ return xDiagram->isPieOrDonutChart();
+}
+
+void lcl_setDefaultWritingMode( const std::shared_ptr< DrawModelWrapper >& pDrawModelWrapper, ChartModel& rModel)
+{
+ //get writing mode from parent document:
+ if( !SvtCTLOptions::IsCTLFontEnabled() )
+ return;
+
+ try
+ {
+ sal_Int16 nWritingMode=-1;
+ uno::Reference< beans::XPropertySet > xParentProps( rModel.getParent(), uno::UNO_QUERY );
+ uno::Reference< style::XStyleFamiliesSupplier > xStyleFamiliesSupplier( xParentProps, uno::UNO_QUERY );
+ if( xStyleFamiliesSupplier.is() )
+ {
+ uno::Reference< container::XNameAccess > xStylesFamilies( xStyleFamiliesSupplier->getStyleFamilies() );
+ if( xStylesFamilies.is() )
+ {
+ if( !xStylesFamilies->hasByName( "PageStyles" ) )
+ {
+ //draw/impress is parent document
+ uno::Reference< lang::XMultiServiceFactory > xFatcory( xParentProps, uno::UNO_QUERY );
+ if( xFatcory.is() )
+ {
+ uno::Reference< beans::XPropertySet > xDrawDefaults( xFatcory->createInstance( "com.sun.star.drawing.Defaults" ), uno::UNO_QUERY );
+ if( xDrawDefaults.is() )
+ xDrawDefaults->getPropertyValue( "WritingMode" ) >>= nWritingMode;
+ }
+ }
+ else
+ {
+ uno::Reference< container::XNameAccess > xPageStyles( xStylesFamilies->getByName( "PageStyles" ), uno::UNO_QUERY );
+ if( xPageStyles.is() )
+ {
+ OUString aPageStyle;
+
+ uno::Reference< text::XTextDocument > xTextDocument( xParentProps, uno::UNO_QUERY );
+ if( xTextDocument.is() )
+ {
+ //writer is parent document
+ //retrieve the current page style from the text cursor property PageStyleName
+
+ uno::Reference< text::XTextEmbeddedObjectsSupplier > xTextEmbeddedObjectsSupplier( xTextDocument, uno::UNO_QUERY );
+ if( xTextEmbeddedObjectsSupplier.is() )
+ {
+ uno::Reference< container::XNameAccess > xEmbeddedObjects( xTextEmbeddedObjectsSupplier->getEmbeddedObjects() );
+ if( xEmbeddedObjects.is() )
+ {
+ uno::Sequence< OUString > aNames( xEmbeddedObjects->getElementNames() );
+
+ sal_Int32 nCount = aNames.getLength();
+ for( sal_Int32 nN=0; nN<nCount; nN++ )
+ {
+ uno::Reference< beans::XPropertySet > xEmbeddedProps( xEmbeddedObjects->getByName( aNames[nN] ), uno::UNO_QUERY );
+ if( xEmbeddedProps.is() )
+ {
+ static OUString aChartCLSID = SvGlobalName( SO3_SCH_CLASSID ).GetHexName();
+ OUString aCLSID;
+ xEmbeddedProps->getPropertyValue( "CLSID" ) >>= aCLSID;
+ if( aCLSID == aChartCLSID )
+ {
+ uno::Reference< text::XTextContent > xEmbeddedObject( xEmbeddedProps, uno::UNO_QUERY );
+ if( xEmbeddedObject.is() )
+ {
+ uno::Reference< text::XTextRange > xAnchor( xEmbeddedObject->getAnchor() );
+ if( xAnchor.is() )
+ {
+ uno::Reference< beans::XPropertySet > xAnchorProps( xAnchor, uno::UNO_QUERY );
+ if( xAnchorProps.is() )
+ {
+ xAnchorProps->getPropertyValue( "WritingMode" ) >>= nWritingMode;
+ }
+ uno::Reference< text::XText > xText( xAnchor->getText() );
+ if( xText.is() )
+ {
+ uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
+ if( xTextCursorProps.is() )
+ xTextCursorProps->getPropertyValue( "PageStyleName" ) >>= aPageStyle;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ if( aPageStyle.isEmpty() )
+ {
+ uno::Reference< text::XText > xText( xTextDocument->getText() );
+ if( xText.is() )
+ {
+ uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
+ if( xTextCursorProps.is() )
+ xTextCursorProps->getPropertyValue( "PageStyleName" ) >>= aPageStyle;
+ }
+ }
+ if(aPageStyle.isEmpty())
+ aPageStyle = "Standard";
+ }
+ else
+ {
+ //Calc is parent document
+ Reference< com::sun::star::beans::XPropertySetInfo > xInfo = xParentProps->getPropertySetInfo();
+ if (xInfo->hasPropertyByName("PageStyle"))
+ {
+ xParentProps->getPropertyValue( "PageStyle" ) >>= aPageStyle;
+ }
+ if(aPageStyle.isEmpty())
+ aPageStyle = "Default";
+ }
+ if( nWritingMode == -1 || nWritingMode == text::WritingMode2::PAGE )
+ {
+ uno::Reference< beans::XPropertySet > xPageStyle( xPageStyles->getByName( aPageStyle ), uno::UNO_QUERY );
+ Reference< com::sun::star::beans::XPropertySetInfo > xInfo = xPageStyle->getPropertySetInfo();
+ if (xInfo->hasPropertyByName("WritingMode"))
+ {
+ if( xPageStyle.is() )
+ xPageStyle->getPropertyValue( "WritingMode" ) >>= nWritingMode;
+ }
+ }
+ }
+ }
+ }
+ }
+ if( nWritingMode != -1 && nWritingMode != text::WritingMode2::PAGE )
+ {
+ if( pDrawModelWrapper )
+ pDrawModelWrapper->GetItemPool().SetPoolDefaultItem(SvxFrameDirectionItem(static_cast<SvxFrameDirection>(nWritingMode), EE_PARA_WRITINGDIR) );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+}
+
+sal_Int16 lcl_getDefaultWritingModeFromPool( const std::shared_ptr<DrawModelWrapper>& pDrawModelWrapper )
+{
+ sal_Int16 nWritingMode = text::WritingMode2::LR_TB;
+ if(!pDrawModelWrapper)
+ return nWritingMode;
+
+ const SfxPoolItem& rItem = pDrawModelWrapper->GetItemPool().GetDefaultItem(EE_PARA_WRITINGDIR);
+ nWritingMode
+ = static_cast<sal_Int16>(static_cast<const SvxFrameDirectionItem&>(rItem).GetValue());
+ return nWritingMode;
+}
+
+} //end anonymous namespace
+
+awt::Rectangle ChartView::impl_createDiagramAndContent( const CreateShapeParam2D& rParam, const awt::Size& rPageSize )
+{
+ //return the used rectangle
+ awt::Rectangle aUsedOuterRect(rParam.maRemainingSpace.X, rParam.maRemainingSpace.Y, 0, 0);
+
+ rtl::Reference< Diagram > xDiagram( mrChartModel.getFirstChartDiagram() );
+ if( !xDiagram.is())
+ return aUsedOuterRect;
+
+ sal_Int32 nDimensionCount = xDiagram->getDimension();
+ if(!nDimensionCount)
+ {
+ //@todo handle mixed dimension
+ nDimensionCount = 2;
+ }
+
+ basegfx::B2IRectangle aAvailableOuterRect = BaseGFXHelper::makeRectangle(rParam.maRemainingSpace);
+
+ const std::vector< std::unique_ptr<VCoordinateSystem> >& rVCooSysList( rParam.mpSeriesPlotterContainer->getCooSysList() );
+ auto& rSeriesPlotterList = rParam.mpSeriesPlotterContainer->getSeriesPlotterList();
+
+ //create VAxis, so they can give necessary information for automatic scaling
+ uno::Reference<util::XNumberFormatsSupplier> const xNumberFormatsSupplier(
+ mrChartModel.getNumberFormatsSupplier());
+
+ for (auto& rpVCooSys : rVCooSysList)
+ {
+ if (nDimensionCount == 3)
+ {
+ CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xDiagram ) );
+ CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xDiagram ) );
+ CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xDiagram ) );
+ rpVCooSys->set3DWallPositions( eLeftWallPos, eBackWallPos, eBottomPos );
+ }
+ rpVCooSys->createVAxisList(&mrChartModel, rPageSize, rParam.maRemainingSpace,
+ rParam.mbUseFixedInnerSize, rSeriesPlotterList, getComponentContext());
+ }
+
+ // - prepare list of all axis and how they are used
+ Date aNullDate = NumberFormatterWrapper( xNumberFormatsSupplier ).getNullDate();
+ rParam.mpSeriesPlotterContainer->initAxisUsageList(aNullDate);
+ rParam.mpSeriesPlotterContainer->doAutoScaling( mrChartModel );
+ rParam.mpSeriesPlotterContainer->setScalesFromCooSysToPlotter();
+ rParam.mpSeriesPlotterContainer->setNumberFormatsFromAxes();
+
+ //create shapes
+
+ //aspect ratio
+ drawing::Direction3D aPreferredAspectRatio =
+ rParam.mpSeriesPlotterContainer->getPreferredAspectRatio();
+
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesTargetInFrontOfAxis;
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesTargetBehindAxis;
+ VDiagram aVDiagram(xDiagram, aPreferredAspectRatio, nDimensionCount);
+ {//create diagram
+ aVDiagram.init(rParam.mxDiagramWithAxesShapes);
+ aVDiagram.createShapes(
+ awt::Point(rParam.maRemainingSpace.X, rParam.maRemainingSpace.Y),
+ awt::Size(rParam.maRemainingSpace.Width, rParam.maRemainingSpace.Height));
+
+ xSeriesTargetInFrontOfAxis = aVDiagram.getCoordinateRegion();
+ // It is preferable to use full size than minimum for pie charts
+ if (!rParam.mbUseFixedInnerSize)
+ aVDiagram.reduceToMinimumSize();
+ }
+
+ rtl::Reference<SvxShapeGroup> xTextTargetShapes =
+ ShapeFactory::createGroup2D(rParam.mxDiagramWithAxesShapes);
+
+ // - create axis and grids for all coordinate systems
+
+ //init all coordinate systems
+ for (auto& rpVCooSys : rVCooSysList)
+ {
+ rpVCooSys->initPlottingTargets(xSeriesTargetInFrontOfAxis, xTextTargetShapes, xSeriesTargetBehindAxis);
+
+ rpVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
+
+ rpVCooSys->initVAxisInList();
+ }
+
+ //calculate resulting size respecting axis label layout and fontscaling
+
+ rtl::Reference<SvxShapeGroup> xBoundingShape(rParam.mxDiagramWithAxesShapes);
+ ::basegfx::B2IRectangle aConsumedOuterRect;
+
+ //use first coosys only so far; todo: calculate for more than one coosys if we have more in future
+ //todo: this is just a workaround at the moment for pie and donut labels
+ bool bIsPieOrDonut = lcl_IsPieOrDonut(xDiagram);
+ if( !bIsPieOrDonut && (!rVCooSysList.empty()) )
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[0].get();
+ pVCooSys->createMaximumAxesLabels();
+
+ aConsumedOuterRect = ShapeFactory::getRectangleOfShape(*xBoundingShape);
+ ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.getCurrentRectangle() );
+ if (!rParam.mbUseFixedInnerSize)
+ aNewInnerRect = aVDiagram.adjustInnerSize( aConsumedOuterRect );
+
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aNewInnerRect ) ));
+
+ //redo autoscaling to get size and text dependent automatic main increment count
+ rParam.mpSeriesPlotterContainer->doAutoScaling( mrChartModel );
+ rParam.mpSeriesPlotterContainer->updateScalesAndIncrementsOnAxes();
+ rParam.mpSeriesPlotterContainer->setScalesFromCooSysToPlotter();
+
+ pVCooSys->createAxesLabels();
+
+ bool bLessSpaceConsumedThanExpected = false;
+ {
+ aConsumedOuterRect = ShapeFactory::getRectangleOfShape(*xBoundingShape);
+ if( aConsumedOuterRect.getMinX() > aAvailableOuterRect.getMinX()
+ || aConsumedOuterRect.getMaxX() < aAvailableOuterRect.getMaxX()
+ || aConsumedOuterRect.getMinY() > aAvailableOuterRect.getMinY()
+ || aConsumedOuterRect.getMinY() < aAvailableOuterRect.getMaxY() )
+ {
+ bLessSpaceConsumedThanExpected = true;
+ }
+ }
+
+ if (bLessSpaceConsumedThanExpected && !rParam.mbUseFixedInnerSize)
+ {
+ aVDiagram.adjustInnerSize( aConsumedOuterRect );
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
+
+ // Need to re-adjust again if the labels have changed height because of
+ // text can break. Ideally this shouldn't be needed, but the chart height
+ // isn't readjusted otherwise.
+ pVCooSys->createAxesLabels();
+ aConsumedOuterRect = ShapeFactory::getRectangleOfShape(*xBoundingShape);
+ aVDiagram.adjustInnerSize(aConsumedOuterRect);
+ pVCooSys->setTransformationSceneToScreen(B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen(aVDiagram.getCurrentRectangle())));
+
+ }
+ pVCooSys->updatePositions();//todo: logically this belongs to the condition above, but it seems also to be necessary to give the axes group shapes the right bounding rects for hit test - probably caused by bug i106183 -> check again if fixed
+ }
+
+ //create axes and grids for the final size
+ for (auto& rpVCooSys : rVCooSysList)
+ {
+ rpVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
+
+ rpVCooSys->createAxesShapes();
+ rpVCooSys->createGridShapes();
+ }
+
+ // - create data series for all charttypes
+ m_bPointsWereSkipped = false;
+ for( const std::unique_ptr<VSeriesPlotter>& aPlotter : rSeriesPlotterList )
+ {
+ VSeriesPlotter* pSeriesPlotter = aPlotter.get();
+ rtl::Reference<SvxShapeGroupAnyD> xSeriesTarget;
+ if( pSeriesPlotter->WantToPlotInFrontOfAxisLine() )
+ xSeriesTarget = xSeriesTargetInFrontOfAxis;
+ else
+ {
+ xSeriesTarget = xSeriesTargetBehindAxis;
+ OSL_ENSURE( !bIsPieOrDonut, "not implemented yet! - during a complete recreation this shape is destroyed so no series can be created anymore" );
+ }
+ pSeriesPlotter->initPlotter( xSeriesTarget,xTextTargetShapes,OUString() );
+ pSeriesPlotter->setPageReferenceSize( rPageSize );
+ VCoordinateSystem* pVCooSys = SeriesPlotterContainer::getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
+ if(nDimensionCount==2)
+ pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
+ //better performance for big data
+ {
+ //calculate resolution for coordinate system
+ Sequence<sal_Int32> aCoordinateSystemResolution = pVCooSys->getCoordinateSystemResolution( rPageSize, m_aPageResolution );
+ pSeriesPlotter->setCoordinateSystemResolution( aCoordinateSystemResolution );
+ }
+ // Do not allow to move data labels in case of pie or donut chart, yet!
+ pSeriesPlotter->setPieLabelsAllowToMove(!bIsPieOrDonut);
+ // use the pagesize as remaining space if we have a fixed inner size
+ if( rParam.mbUseFixedInnerSize )
+ aAvailableOuterRect = BaseGFXHelper::makeRectangle(awt::Rectangle(0, 0, rPageSize.Width, rPageSize.Height));
+ // set the available space for data labels to avoid moving out from chart area
+ pSeriesPlotter->setAvailableOuterRect(aAvailableOuterRect);
+ pSeriesPlotter->createShapes();
+ m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
+ }
+
+ //recreate all with corrected sizes if requested
+ if( bIsPieOrDonut )
+ {
+ m_bPointsWereSkipped = false;
+
+ aConsumedOuterRect = ShapeFactory::getRectangleOfShape(*xBoundingShape);
+ ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.getCurrentRectangle() );
+ if (!rParam.mbUseFixedInnerSize)
+ aNewInnerRect = aVDiagram.adjustInnerSize( aConsumedOuterRect );
+
+ for( std::unique_ptr<VSeriesPlotter>& aPlotter : rSeriesPlotterList )
+ {
+ aPlotter->releaseShapes();
+ }
+
+ //clear and recreate
+ ShapeFactory::removeSubShapes( xSeriesTargetInFrontOfAxis ); //xSeriesTargetBehindAxis is a sub shape of xSeriesTargetInFrontOfAxis and will be removed here
+ xSeriesTargetBehindAxis.clear();
+ ShapeFactory::removeSubShapes( xTextTargetShapes );
+
+ //set new transformation
+ for (auto& rpVCooSys : rVCooSysList)
+ {
+ auto aMatrix = createTransformationSceneToScreen(aNewInnerRect);
+ rpVCooSys->setTransformationSceneToScreen(B3DHomMatrixToHomogenMatrix(aMatrix));
+ }
+
+ // - create data series for all charttypes
+ for( std::unique_ptr<VSeriesPlotter>& aPlotter : rSeriesPlotterList )
+ {
+ VCoordinateSystem* pVCooSys = SeriesPlotterContainer::getCooSysForPlotter( rVCooSysList, aPlotter.get() );
+ if(nDimensionCount==2)
+ aPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
+ // Now we can move data labels in case of pie or donut chart!
+ aPlotter->setPieLabelsAllowToMove(bIsPieOrDonut);
+ aPlotter->createShapes();
+ m_bPointsWereSkipped = m_bPointsWereSkipped || aPlotter->PointsWereSkipped();
+ }
+
+ for( std::unique_ptr<VSeriesPlotter>& aPlotter : rSeriesPlotterList )
+ aPlotter->rearrangeLabelToAvoidOverlapIfRequested(rPageSize);
+ }
+
+ if (rParam.mbUseFixedInnerSize)
+ {
+ aUsedOuterRect = awt::Rectangle( aConsumedOuterRect.getMinX(), aConsumedOuterRect.getMinY(), aConsumedOuterRect.getWidth(), aConsumedOuterRect.getHeight() );
+ }
+ else
+ aUsedOuterRect = rParam.maRemainingSpace;
+
+ bool bSnapRectToUsedArea = false;
+ for( std::unique_ptr<VSeriesPlotter>& aPlotter : rSeriesPlotterList )
+ {
+ bSnapRectToUsedArea = aPlotter->shouldSnapRectToUsedArea();
+ if(bSnapRectToUsedArea)
+ break;
+ }
+ if(bSnapRectToUsedArea)
+ {
+ if (rParam.mbUseFixedInnerSize)
+ m_aResultingDiagramRectangleExcludingAxes = getRectangleOfObject( "PlotAreaExcludingAxes" );
+ else
+ {
+ ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle();
+ m_aResultingDiagramRectangleExcludingAxes = BaseGFXHelper::toAwtRectangle(aConsumedInnerRect);
+ }
+ }
+ else
+ {
+ if (rParam.mbUseFixedInnerSize)
+ m_aResultingDiagramRectangleExcludingAxes = rParam.maRemainingSpace;
+ else
+ {
+ ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle();
+ m_aResultingDiagramRectangleExcludingAxes = BaseGFXHelper::toAwtRectangle(aConsumedInnerRect);
+ }
+ }
+
+ if (rParam.mxMarkHandles.is())
+ {
+ awt::Point aPos(rParam.maRemainingSpace.X, rParam.maRemainingSpace.Y);
+ awt::Size aSize(rParam.maRemainingSpace.Width, rParam.maRemainingSpace.Height);
+
+ bool bPosSizeExcludeAxesProperty = true;
+ xDiagram->getPropertyValue("PosSizeExcludeAxes") >>= bPosSizeExcludeAxesProperty;
+ if (rParam.mbUseFixedInnerSize || bPosSizeExcludeAxesProperty)
+ {
+ aPos = awt::Point( m_aResultingDiagramRectangleExcludingAxes.X, m_aResultingDiagramRectangleExcludingAxes.Y );
+ aSize = awt::Size( m_aResultingDiagramRectangleExcludingAxes.Width, m_aResultingDiagramRectangleExcludingAxes.Height );
+ }
+ rParam.mxMarkHandles->setPosition(aPos);
+ rParam.mxMarkHandles->setSize(aSize);
+ }
+
+ return aUsedOuterRect;
+}
+
+bool ChartView::getExplicitValuesForAxis(
+ rtl::Reference< Axis > xAxis
+ , ExplicitScaleData& rExplicitScale
+ , ExplicitIncrementData& rExplicitIncrement )
+{
+ SolarMutexGuard aSolarGuard;
+
+ impl_updateView();
+
+ if(!xAxis.is())
+ return false;
+
+ rtl::Reference< BaseCoordinateSystem > xCooSys = AxisHelper::getCoordinateSystemOfAxis(xAxis, mrChartModel.getFirstChartDiagram() );
+ const VCoordinateSystem* pVCooSys = SeriesPlotterContainer::findInCooSysList(m_aVCooSysList, xCooSys);
+ if(!pVCooSys)
+ return false;
+
+ sal_Int32 nDimensionIndex=-1;
+ sal_Int32 nAxisIndex=-1;
+ if( !AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
+ return false;
+
+ rExplicitScale = pVCooSys->getExplicitScale(nDimensionIndex,nAxisIndex);
+ rExplicitIncrement = pVCooSys->getExplicitIncrement(nDimensionIndex,nAxisIndex);
+ if( !rExplicitScale.m_bShiftedCategoryPosition )
+ return true;
+
+ //remove 'one' from max
+ if( rExplicitScale.AxisType == css::chart2::AxisType::DATE )
+ {
+ Date aMaxDate(rExplicitScale.NullDate); aMaxDate.AddDays(::rtl::math::approxFloor(rExplicitScale.Maximum));
+ //for explicit scales with shifted categories we need one interval more
+ switch( rExplicitScale.TimeResolution )
+ {
+ case css::chart::TimeUnit::DAY:
+ --aMaxDate;
+ break;
+ case css::chart::TimeUnit::MONTH:
+ aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate,-1);
+ break;
+ case css::chart::TimeUnit::YEAR:
+ aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate,-1);
+ break;
+ }
+ rExplicitScale.Maximum = aMaxDate - rExplicitScale.NullDate;
+ }
+ else if( rExplicitScale.AxisType == css::chart2::AxisType::CATEGORY )
+ rExplicitScale.Maximum -= 1.0;
+ else if( rExplicitScale.AxisType == css::chart2::AxisType::SERIES )
+ rExplicitScale.Maximum -= 1.0;
+ return true;
+}
+
+SdrPage* ChartView::getSdrPage()
+{
+ if(m_xDrawPage)
+ return m_xDrawPage->GetSdrPage();
+
+ return nullptr;
+}
+
+rtl::Reference< SvxShape > ChartView::getShapeForCID( const OUString& rObjectCID )
+{
+ SolarMutexGuard aSolarGuard;
+ SdrObject* pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, this->getSdrPage() );
+ if( !pObj )
+ return nullptr;
+
+ uno::Reference< drawing::XShape > xShape = pObj->getUnoShape();
+ rtl::Reference<SvxShape> xShape2 = dynamic_cast<SvxShape*>(xShape.get());
+ assert(xShape2 || !xShape);
+ return xShape2;
+}
+
+awt::Rectangle ChartView::getDiagramRectangleExcludingAxes()
+{
+ impl_updateView();
+ return m_aResultingDiagramRectangleExcludingAxes;
+}
+
+awt::Rectangle ChartView::getRectangleOfObject( const OUString& rObjectCID, bool bSnapRect )
+{
+ impl_updateView();
+
+ awt::Rectangle aRet;
+ rtl::Reference< SvxShape > xShape = getShapeForCID(rObjectCID);
+ if(xShape.is())
+ {
+ //special handling for axis for old api:
+ //same special handling for diagram
+ ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) );
+ if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_DIAGRAM )
+ {
+ SolarMutexGuard aSolarGuard;
+ SdrObject* pRootSdrObject = xShape->GetSdrObject();
+ if( pRootSdrObject )
+ {
+ SdrObjList* pRootList = pRootSdrObject->GetSubList();
+ if( pRootList )
+ {
+ OUString aShapeName = "MarkHandles";
+ if( eObjectType == OBJECTTYPE_DIAGRAM )
+ aShapeName = "PlotAreaIncludingAxes";
+ SdrObject* pShape = DrawModelWrapper::getNamedSdrObject( aShapeName, pRootList );
+ if( pShape )
+ {
+ xShape = dynamic_cast<SvxShape*>(pShape->getUnoShape().get());
+ assert(xShape);
+ }
+ }
+ }
+ }
+
+ awt::Size aSize( xShape->getSize() );
+ awt::Point aPoint( xShape->getPosition() );
+ aRet = awt::Rectangle( aPoint.X, aPoint.Y, aSize.Width, aSize.Height );
+ if( bSnapRect )
+ {
+ //for rotated objects the shape size and position differs from the visible rectangle
+ SdrObject* pSdrObject = xShape->GetSdrObject();
+ if( pSdrObject )
+ {
+ tools::Rectangle aSnapRect( pSdrObject->GetSnapRect() );
+ aRet = awt::Rectangle(aSnapRect.Left(),aSnapRect.Top(),aSnapRect.GetWidth(),aSnapRect.GetHeight());
+ }
+ }
+ }
+ return aRet;
+}
+
+std::shared_ptr< DrawModelWrapper > ChartView::getDrawModelWrapper()
+{
+ return m_pDrawModelWrapper;
+}
+
+namespace
+{
+
+constexpr double constPageLayoutDistancePercentage = 0.02;
+constexpr sal_Int32 constPageLayoutFixedDistance = 350;
+
+bool getAvailablePosAndSizeForDiagram(
+ CreateShapeParam2D& rParam, const awt::Size & rPageSize, rtl::Reference<Diagram> const& xDiagram)
+{
+ uno::Reference<beans::XPropertySet> const& xProp(xDiagram);
+ rParam.mbUseFixedInnerSize = false;
+
+ //@todo: we need a size dependent on the axis labels
+ rtl::Reference<ChartType> xChartType;
+ if (xDiagram)
+ xChartType = xDiagram->getChartTypeByIndex(0);
+
+ sal_Int32 nXDistance = sal_Int32(rPageSize.Width * constPageLayoutDistancePercentage);
+ sal_Int32 nYDistance = sal_Int32(rPageSize.Height * constPageLayoutDistancePercentage);
+
+ // Only pie chart uses fixed size margins
+ if (xChartType.is() && xChartType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_PIE)
+ {
+ nXDistance = constPageLayoutFixedDistance;
+ nYDistance = constPageLayoutFixedDistance;
+ }
+
+ rParam.maRemainingSpace.X += nXDistance;
+ rParam.maRemainingSpace.Width -= 2*nXDistance;
+ rParam.maRemainingSpace.Y += nYDistance;
+ rParam.maRemainingSpace.Height -= 2*nYDistance;
+
+ bool bPosSizeExcludeAxes = false;
+ if( xProp.is() )
+ xProp->getPropertyValue( "PosSizeExcludeAxes" ) >>= bPosSizeExcludeAxes;
+
+ //size:
+ css::chart2::RelativeSize aRelativeSize;
+ if( xProp.is() && (xProp->getPropertyValue( "RelativeSize" )>>=aRelativeSize) )
+ {
+ rParam.maRemainingSpace.Height = static_cast<sal_Int32>(aRelativeSize.Secondary*rPageSize.Height);
+ rParam.maRemainingSpace.Width = static_cast<sal_Int32>(aRelativeSize.Primary*rPageSize.Width);
+ rParam.mbUseFixedInnerSize = bPosSizeExcludeAxes;
+ }
+
+ if (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0)
+ return false;
+
+ //position:
+ chart2::RelativePosition aRelativePosition;
+ if( xProp.is() && (xProp->getPropertyValue( "RelativePosition" )>>=aRelativePosition) )
+ {
+ //@todo decide whether x is primary or secondary
+
+ //the coordinates re relative to the page
+ double fX = aRelativePosition.Primary*rPageSize.Width;
+ double fY = aRelativePosition.Secondary*rPageSize.Height;
+
+ awt::Point aPos = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
+ awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY)),
+ awt::Size(rParam.maRemainingSpace.Width, rParam.maRemainingSpace.Height),
+ aRelativePosition.Anchor);
+
+ rParam.maRemainingSpace.X = aPos.X;
+ rParam.maRemainingSpace.Y = aPos.Y;
+
+ rParam.mbUseFixedInnerSize = bPosSizeExcludeAxes;
+ }
+
+ //ensure that the diagram does not lap out right side or out of bottom
+ if (rParam.maRemainingSpace.Y + rParam.maRemainingSpace.Height > rPageSize.Height)
+ rParam.maRemainingSpace.Height = rPageSize.Height - rParam.maRemainingSpace.Y;
+
+ if (rParam.maRemainingSpace.X + rParam.maRemainingSpace.Width > rPageSize.Width)
+ rParam.maRemainingSpace.Width = rPageSize.Width - rParam.maRemainingSpace.X;
+
+ return true;
+}
+
+enum class TitleAlignment { ALIGN_LEFT, ALIGN_TOP, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_Z };
+
+void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment
+ , awt::Rectangle const & rDiagramPlusAxesRect, const awt::Size & rPageSize )
+{
+ if(!pVTitle)
+ return;
+
+ awt::Point aNewPosition(0,0);
+ awt::Size aTitleSize = pVTitle->getFinalSize();
+ sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height * constPageLayoutDistancePercentage);
+ sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width * constPageLayoutDistancePercentage);
+ switch (eAlignment)
+ {
+ case TitleAlignment::ALIGN_TOP:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
+ , rDiagramPlusAxesRect.Y - aTitleSize.Height/2 - nYDistance );
+ break;
+ case TitleAlignment::ALIGN_BOTTOM:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height + aTitleSize.Height/2 + nYDistance );
+ break;
+ case TitleAlignment::ALIGN_LEFT:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X - aTitleSize.Width/2 - nXDistance
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
+ break;
+ case TitleAlignment::ALIGN_RIGHT:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
+ break;
+ case TitleAlignment::ALIGN_Z:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height - aTitleSize.Height/2 );
+ break;
+ }
+
+ sal_Int32 nMaxY = rPageSize.Height - aTitleSize.Height/2;
+ sal_Int32 nMaxX = rPageSize.Width - aTitleSize.Width/2;
+ sal_Int32 nMinX = aTitleSize.Width/2;
+ sal_Int32 nMinY = aTitleSize.Height/2;
+ if( aNewPosition.Y > nMaxY )
+ aNewPosition.Y = nMaxY;
+ if( aNewPosition.X > nMaxX )
+ aNewPosition.X = nMaxX;
+ if( aNewPosition.Y < nMinY )
+ aNewPosition.Y = nMinY;
+ if( aNewPosition.X < nMinX )
+ aNewPosition.X = nMinX;
+
+ pVTitle->changePosition( aNewPosition );
+}
+
+std::shared_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType
+ , const rtl::Reference<SvxShapeGroupAnyD>& xPageShapes
+ , ChartModel& rModel
+ , awt::Rectangle& rRemainingSpace
+ , const awt::Size & rPageSize
+ , TitleAlignment eAlignment
+ , bool& rbAutoPosition )
+{
+ std::shared_ptr<VTitle> apVTitle;
+
+ // #i109336# Improve auto positioning in chart
+ double fPercentage = constPageLayoutDistancePercentage;
+ sal_Int32 nXDistance = static_cast< sal_Int32 >( rPageSize.Width * fPercentage );
+ sal_Int32 nYDistance = static_cast< sal_Int32 >( rPageSize.Height * fPercentage );
+ if ( eType == TitleHelper::MAIN_TITLE )
+ {
+ nYDistance += 135; // 1/100 mm
+ }
+ else if ( eType == TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION )
+ {
+ nYDistance = 420; // 1/100 mm
+ }
+ else if ( eType == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION )
+ {
+ nXDistance = 450; // 1/100 mm
+ }
+
+ rtl::Reference< Title > xTitle( TitleHelper::getTitle( eType, rModel ) );
+ OUString aCompleteString = TitleHelper::getCompleteString(xTitle);
+ if (aCompleteString.isEmpty() || !VTitle::isVisible(xTitle))
+ return apVTitle;
+
+ //create title
+ awt::Size aTextMaxWidth(rPageSize.Width, rPageSize.Height);
+ bool bYAxisTitle = false;
+ if (eType == TitleHelper::MAIN_TITLE || eType == TitleHelper::SUB_TITLE)
+ {
+ aTextMaxWidth.Width = static_cast<sal_Int32>(rPageSize.Width * 0.8);
+ aTextMaxWidth.Height = static_cast<sal_Int32>(rPageSize.Height * 0.5);
+ }
+ else if (eType == TitleHelper::X_AXIS_TITLE || eType == TitleHelper::SECONDARY_X_AXIS_TITLE
+ || eType == TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION)
+ {
+ aTextMaxWidth.Width = static_cast<sal_Int32>(rPageSize.Width * 0.8);
+ aTextMaxWidth.Height = static_cast<sal_Int32>(rPageSize.Height * 0.2);
+ }
+ else if (eType == TitleHelper::Y_AXIS_TITLE || eType == TitleHelper::SECONDARY_Y_AXIS_TITLE
+ || eType == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION)
+ {
+ aTextMaxWidth.Width = static_cast<sal_Int32>(rPageSize.Width * 0.2);
+ aTextMaxWidth.Height = static_cast<sal_Int32>(rPageSize.Height * 0.8);
+ bYAxisTitle = true;
+ }
+ apVTitle = std::make_shared<VTitle>(xTitle);
+ OUString aCID = ObjectIdentifier::createClassifiedIdentifierForObject(xTitle, &rModel);
+ apVTitle->init(xPageShapes, aCID);
+ apVTitle->createShapes(awt::Point(0, 0), rPageSize, aTextMaxWidth, bYAxisTitle);
+ awt::Size aTitleUnrotatedSize = apVTitle->getUnrotatedSize();
+ awt::Size aTitleSize = apVTitle->getFinalSize();
+
+ //position
+ rbAutoPosition = true;
+ awt::Point aNewPosition(0,0);
+ chart2::RelativePosition aRelativePosition;
+ if (xTitle.is() && (xTitle->getPropertyValue("RelativePosition") >>= aRelativePosition))
+ {
+ rbAutoPosition = false;
+
+ //@todo decide whether x is primary or secondary
+ double fX = aRelativePosition.Primary*rPageSize.Width;
+ double fY = aRelativePosition.Secondary*rPageSize.Height;
+
+ double fAnglePi = apVTitle->getRotationAnglePi();
+ aNewPosition = RelativePositionHelper::getCenterOfAnchoredObject(
+ awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY))
+ , aTitleUnrotatedSize, aRelativePosition.Anchor, fAnglePi );
+ }
+ else //auto position
+ {
+ switch( eAlignment )
+ {
+ case TitleAlignment::ALIGN_TOP:
+ aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
+ , rRemainingSpace.Y + aTitleSize.Height/2 + nYDistance );
+ break;
+ case TitleAlignment::ALIGN_BOTTOM:
+ aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
+ , rRemainingSpace.Y + rRemainingSpace.Height - aTitleSize.Height/2 - nYDistance );
+ break;
+ case TitleAlignment::ALIGN_LEFT:
+ aNewPosition = awt::Point( rRemainingSpace.X + aTitleSize.Width/2 + nXDistance
+ , rRemainingSpace.Y + rRemainingSpace.Height/2 );
+ break;
+ case TitleAlignment::ALIGN_RIGHT:
+ aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width - aTitleSize.Width/2 - nXDistance
+ , rRemainingSpace.Y + rRemainingSpace.Height/2 );
+ break;
+ case TitleAlignment::ALIGN_Z:
+ break;
+
+ }
+ }
+ apVTitle->changePosition( aNewPosition );
+
+ //remaining space
+ switch( eAlignment )
+ {
+ case TitleAlignment::ALIGN_TOP:
+ // Push the remaining space down from top.
+ rRemainingSpace.Y += ( aTitleSize.Height + nYDistance );
+ rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
+ break;
+ case TitleAlignment::ALIGN_BOTTOM:
+ // Push the remaining space up from bottom.
+ rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
+ break;
+ case TitleAlignment::ALIGN_LEFT:
+ // Push the remaining space to the right from left edge.
+ rRemainingSpace.X += ( aTitleSize.Width + nXDistance );
+ rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
+ break;
+ case TitleAlignment::ALIGN_RIGHT:
+ // Push the remaining space to the left from right edge.
+ rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
+ break;
+ case TitleAlignment::ALIGN_Z:
+ break;
+ }
+
+ return apVTitle;
+}
+
+bool lcl_createLegend( const rtl::Reference< Legend > & xLegend
+ , const rtl::Reference<SvxShapeGroupAnyD>& xPageShapes
+ , const uno::Reference< uno::XComponentContext > & xContext
+ , awt::Rectangle & rRemainingSpace
+ , const awt::Size & rPageSize
+ , ChartModel& rModel
+ , std::vector< LegendEntryProvider* >&& rLegendEntryProviderList
+ , sal_Int16 nDefaultWritingMode )
+{
+ if (!VLegend::isVisible(xLegend))
+ return false;
+
+ awt::Size rDefaultLegendSize;
+ VLegend aVLegend( xLegend, xContext, std::move(rLegendEntryProviderList),
+ xPageShapes, rModel);
+ aVLegend.setDefaultWritingMode( nDefaultWritingMode );
+ aVLegend.createShapes( awt::Size( rRemainingSpace.Width, rRemainingSpace.Height ),
+ rPageSize, rDefaultLegendSize );
+ aVLegend.changePosition( rRemainingSpace, rPageSize, rDefaultLegendSize );
+ return true;
+}
+
+void lcl_createButtons(const rtl::Reference<SvxShapeGroupAnyD>& xPageShapes,
+ ChartModel& rModel,
+ awt::Rectangle& rRemainingSpace)
+{
+ uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(rModel.getDataProvider(), uno::UNO_QUERY);
+ if (!xPivotTableDataProvider.is())
+ return;
+
+ uno::Reference<beans::XPropertySet> xModelPage(rModel.getPageBackground());
+
+ awt::Size aSize(4000, 700); // size of the button
+
+ tools::Long x = 0;
+
+ if (xPivotTableDataProvider->getPageFields().hasElements())
+ {
+ x = 0;
+
+ const css::uno::Sequence<chart2::data::PivotTableFieldEntry> aPivotFieldEntries = xPivotTableDataProvider->getPageFields();
+ for (css::chart2::data::PivotTableFieldEntry const & rPageFieldEntry : aPivotFieldEntries)
+ {
+ VButton aButton;
+ aButton.init(xPageShapes);
+ awt::Point aNewPosition(rRemainingSpace.X + x + 100, rRemainingSpace.Y + 100);
+ sal_Int32 nDimensionIndex = rPageFieldEntry.DimensionIndex;
+ OUString aFieldOutputDescription = xPivotTableDataProvider->getFieldOutputDescription(nDimensionIndex);
+ aButton.setLabel(rPageFieldEntry.Name + " | " + aFieldOutputDescription);
+ aButton.setCID("FieldButton.Page." + OUString::number(nDimensionIndex));
+ aButton.setPosition(aNewPosition);
+ aButton.setSize(aSize);
+ if (rPageFieldEntry.HasHiddenMembers)
+ aButton.setArrowColor(Color(0x0000FF));
+
+ aButton.createShapes(xModelPage);
+ x += aSize.Width + 100;
+ }
+ rRemainingSpace.Y += (aSize.Height + 100 + 100);
+ rRemainingSpace.Height -= (aSize.Height + 100 + 100);
+ }
+
+ aSize = awt::Size(3000, 700); // size of the button
+
+ if (!xPivotTableDataProvider->getRowFields().hasElements())
+ return;
+
+ x = 200;
+ const css::uno::Sequence<chart2::data::PivotTableFieldEntry> aPivotFieldEntries = xPivotTableDataProvider->getRowFields();
+ for (css::chart2::data::PivotTableFieldEntry const & rRowFieldEntry : aPivotFieldEntries)
+ {
+ VButton aButton;
+ aButton.init(xPageShapes);
+ awt::Point aNewPosition(rRemainingSpace.X + x + 100,
+ rRemainingSpace.Y + rRemainingSpace.Height - aSize.Height - 100);
+ aButton.setLabel(rRowFieldEntry.Name);
+ aButton.setCID("FieldButton.Row." + OUString::number(rRowFieldEntry.DimensionIndex));
+ aButton.setPosition(aNewPosition);
+ aButton.setSize(aSize);
+ if ( rRowFieldEntry.Name == "Data" )
+ {
+ aButton.setBGColor( Color(0x00F6F6F6) );
+ aButton.showArrow( false );
+ }
+ else if (rRowFieldEntry.HasHiddenMembers)
+ aButton.setArrowColor(Color(0x0000FF));
+ aButton.createShapes(xModelPage);
+ x += aSize.Width + 100;
+ }
+ rRemainingSpace.Height -= (aSize.Height + 100 + 100);
+}
+
+void formatPage(
+ ChartModel& rChartModel
+ , const awt::Size& rPageSize
+ , const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ )
+{
+ try
+ {
+ uno::Reference< beans::XPropertySet > xModelPage( rChartModel.getPageBackground());
+ if( ! xModelPage.is())
+ return;
+
+ //format page
+ tPropertyNameValueMap aNameValueMap;
+ PropertyMapper::getValueMap( aNameValueMap, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage );
+
+ OUString aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) );
+ aNameValueMap.emplace( "Name", uno::Any( aCID ) ); //CID OUString
+
+ tNameSequence aNames;
+ tAnySequence aValues;
+ PropertyMapper::getMultiPropertyListsFromValueMap( aNames, aValues, aNameValueMap );
+
+ ShapeFactory::createRectangle(
+ xTarget, rPageSize, awt::Point(0, 0), aNames, aValues);
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+}
+
+void lcl_removeEmptyGroupShapes( const SdrObject& rParent )
+{
+ SdrObjList* pObjList = rParent.getChildrenOfSdrObject();
+ if (!pObjList || pObjList->GetObjCount() == 0)
+ return;
+
+ //iterate from back!
+ for(auto nIdx = static_cast<sal_Int32>(pObjList->GetObjCount() - 1); nIdx >= 0; --nIdx)
+ {
+ SdrObject* pChildSdrObject = pObjList->GetObj(nIdx);
+ SdrObjList* pChildObjList = pChildSdrObject->getChildrenOfSdrObject();
+ if (!pChildObjList)
+ continue;
+ if (pChildObjList->GetObjCount() == 0)
+ {
+ //remove empty group shape
+ pObjList->NbcRemoveObject(nIdx);
+ }
+ else
+ lcl_removeEmptyGroupShapes(*pChildSdrObject);
+ }
+}
+
+}
+
+void ChartView::impl_refreshAddIn()
+{
+ if( !m_bRefreshAddIn )
+ return;
+
+ uno::Reference< beans::XPropertySet > xProp( static_cast< ::cppu::OWeakObject* >( &mrChartModel ), uno::UNO_QUERY );
+ if( !xProp.is())
+ return;
+
+ try
+ {
+ uno::Reference< util::XRefreshable > xAddIn;
+ xProp->getPropertyValue( "AddIn" ) >>= xAddIn;
+ if( xAddIn.is() )
+ {
+ bool bRefreshAddInAllowed = true;
+ xProp->getPropertyValue( "RefreshAddInAllowed" ) >>= bRefreshAddInAllowed;
+ if( bRefreshAddInAllowed )
+ xAddIn->refresh();
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void ChartView::createShapes()
+{
+ SolarMutexGuard aSolarGuard;
+
+ std::unique_lock aTimedGuard(maTimeMutex);
+ if(mrChartModel.isTimeBased())
+ {
+ maTimeBased.bTimeBased = true;
+ }
+
+ //make sure add-in is refreshed after creating the shapes
+ const ::comphelper::ScopeGuard aGuard( [this]() { this->impl_refreshAddIn(); } );
+
+ m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle(0,0,0,0);
+ impl_deleteCoordinateSystems();
+ if( m_pDrawModelWrapper )
+ {
+ // #i12587# support for shapes in chart
+ m_pDrawModelWrapper->getSdrModel().EnableUndo( false );
+ m_pDrawModelWrapper->clearMainDrawPage();
+ }
+
+ lcl_setDefaultWritingMode( m_pDrawModelWrapper, mrChartModel );
+
+ awt::Size aPageSize = mrChartModel.getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
+
+ if(!mxRootShape.is())
+ mxRootShape = ShapeFactory::getOrCreateChartRootShape( m_xDrawPage );
+
+ SdrPage* pPage = getSdrPage();
+
+ if (pPage) //it is necessary to use the implementation here as the uno page does not provide a propertyset
+ {
+ pPage->SetSize(Size(aPageSize.Width,aPageSize.Height));
+ }
+ else
+ {
+ OSL_FAIL("could not set page size correctly");
+ }
+ ShapeFactory::setPageSize(mxRootShape, aPageSize);
+
+ createShapes2D(aPageSize);
+
+ // #i12587# support for shapes in chart
+ if ( m_pDrawModelWrapper )
+ {
+ m_pDrawModelWrapper->getSdrModel().EnableUndo( true );
+ }
+
+ if(maTimeBased.bTimeBased)
+ {
+ maTimeBased.nFrame++;
+ }
+}
+
+// util::XEventListener (base of XCloseListener)
+void SAL_CALL ChartView::disposing( const lang::EventObject& /* rSource */ )
+{
+}
+
+namespace
+{
+// Disables setting the chart's modified state, as well as its parent's (if exists).
+// Painting a chart must not set these states.
+struct ChartModelDisableSetModified
+{
+ ChartModel& mrChartModel;
+ SfxObjectShell* mpParentShell;
+ bool mbWasUnmodified;
+ ChartModelDisableSetModified(ChartModel& rChartModel)
+ : mrChartModel(rChartModel)
+ , mpParentShell(SfxObjectShell::GetShellFromComponent(rChartModel.getParent()))
+ , mbWasUnmodified(!rChartModel.isModified())
+ {
+ if (mpParentShell && mpParentShell->IsEnableSetModified())
+ mpParentShell->EnableSetModified(false);
+ else
+ mpParentShell = nullptr;
+ }
+ ~ChartModelDisableSetModified()
+ {
+ if (mbWasUnmodified && mrChartModel.isModified())
+ mrChartModel.setModified(false);
+ if (mpParentShell)
+ mpParentShell->EnableSetModified(true);
+ }
+};
+}
+
+void ChartView::impl_updateView( bool bCheckLockedCtrler )
+{
+ if( !m_pDrawModelWrapper )
+ return;
+
+ // #i12587# support for shapes in chart
+ if ( m_bSdrViewIsInEditMode )
+ {
+ return;
+ }
+
+ if (bCheckLockedCtrler && mrChartModel.hasControllersLocked())
+ return;
+
+ if( !m_bViewDirty || m_bInViewUpdate )
+ return;
+
+ m_bInViewUpdate = true;
+ //bool bOldRefreshAddIn = m_bRefreshAddIn;
+ //m_bRefreshAddIn = false;
+ try
+ {
+ impl_notifyModeChangeListener("invalid");
+
+ //prepare draw model
+ {
+ SolarMutexGuard aSolarGuard;
+ m_pDrawModelWrapper->lockControllers();
+ }
+
+ // Rendering the chart must not set its (or its parent) modified status
+ ChartModelDisableSetModified dontSetModified(mrChartModel);
+
+ //create chart view
+ {
+ m_bViewDirty = false;
+ m_bViewUpdatePending = false;
+ createShapes();
+
+ if( m_bViewDirty )
+ {
+ //avoid recursions due to add-in
+ m_bRefreshAddIn = false;
+ m_bViewDirty = false;
+ m_bViewUpdatePending = false;
+ //delete old chart view
+ createShapes();
+ m_bRefreshAddIn = true;
+ }
+ }
+
+ m_bViewDirty = m_bViewUpdatePending;
+ m_bViewUpdatePending = false;
+ m_bInViewUpdate = false;
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ m_bViewDirty = m_bViewUpdatePending;
+ m_bViewUpdatePending = false;
+ m_bInViewUpdate = false;
+ }
+
+ {
+ SolarMutexGuard aSolarGuard;
+ m_pDrawModelWrapper->unlockControllers();
+ }
+
+ impl_notifyModeChangeListener("valid");
+
+ //m_bRefreshAddIn = bOldRefreshAddIn;
+}
+
+// ____ XModifyListener ____
+void SAL_CALL ChartView::modified( const lang::EventObject& /* aEvent */ )
+{
+ m_bViewDirty = true;
+ if( m_bInViewUpdate )
+ m_bViewUpdatePending = true;
+
+ impl_notifyModeChangeListener("dirty");
+}
+
+//SfxListener
+void ChartView::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ //#i77362 change notification for changes on additional shapes are missing
+ if( m_bInViewUpdate )
+ return;
+
+ // #i12587# support for shapes in chart
+ if ( m_bSdrViewIsInEditMode )
+ {
+ uno::Reference< view::XSelectionSupplier > xSelectionSupplier( mrChartModel.getCurrentController(), uno::UNO_QUERY );
+ if ( xSelectionSupplier.is() )
+ {
+ OUString aSelObjCID;
+ uno::Any aSelObj( xSelectionSupplier->getSelection() );
+ aSelObj >>= aSelObjCID;
+ if ( !aSelObjCID.isEmpty() )
+ {
+ return;
+ }
+ }
+ }
+
+ if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
+ return;
+ const SdrHint* pSdrHint = static_cast< const SdrHint* >(&rHint);
+
+ bool bShapeChanged = false;
+ switch( pSdrHint->GetKind() )
+ {
+ case SdrHintKind::ObjectChange:
+ bShapeChanged = true;
+ break;
+ case SdrHintKind::ObjectInserted:
+ bShapeChanged = true;
+ break;
+ case SdrHintKind::ObjectRemoved:
+ bShapeChanged = true;
+ break;
+ case SdrHintKind::ModelCleared:
+ bShapeChanged = true;
+ break;
+ case SdrHintKind::EndEdit:
+ bShapeChanged = true;
+ break;
+ default:
+ break;
+ }
+
+ if(bShapeChanged)
+ {
+ //#i76053# do not send view modified notifications for changes on the hidden page which contains e.g. the symbols for the dialogs
+ if( ChartView::getSdrPage() != pSdrHint->GetPage() )
+ bShapeChanged=false;
+ }
+
+ if(!bShapeChanged)
+ return;
+
+ mrChartModel.setModified(true);
+}
+
+void ChartView::impl_notifyModeChangeListener( const OUString& rNewMode )
+{
+ try
+ {
+ std::unique_lock g(m_aMutex);
+ if( m_aModeChangeListeners.getLength(g) )
+ {
+ util::ModeChangeEvent aEvent( static_cast< uno::XWeak* >( this ), rNewMode );
+ m_aModeChangeListeners.notifyEach( g, &css::util::XModeChangeListener::modeChanged, aEvent);
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+}
+
+// ____ XModeChangeBroadcaster ____
+
+void SAL_CALL ChartView::addModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aModeChangeListeners.addInterface(g, xListener );
+}
+void SAL_CALL ChartView::removeModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
+{
+ std::unique_lock g(m_aMutex);
+ m_aModeChangeListeners.removeInterface(g, xListener );
+}
+void SAL_CALL ChartView::addModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
+{
+
+}
+void SAL_CALL ChartView::removeModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
+{
+
+}
+
+// ____ XUpdatable ____
+void SAL_CALL ChartView::update()
+{
+ impl_updateView();
+
+ //#i100778# migrate all imported or old documents to a plot area sizing exclusive axes (in case the save settings allow for this):
+ //Although in general it is a bad idea to change the model from within the view this is exceptionally the best place to do this special conversion.
+ //When a view update is requested (what happens for creating the metafile or displaying
+ //the chart in edit mode or printing) it is most likely that all necessary information is available - like the underlying spreadsheet data for example.
+ //Those data are important for the correct axis label sizes which are needed during conversion.
+ if( DiagramHelper::switchDiagramPositioningToExcludingPositioning( mrChartModel, true, false ) )
+ impl_updateView();
+}
+
+void SAL_CALL ChartView::updateSoft()
+{
+ update();
+}
+
+void SAL_CALL ChartView::updateHard()
+{
+ impl_updateView(false);
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL ChartView::getPropertySetInfo()
+{
+ OSL_FAIL("not implemented");
+ return nullptr;
+}
+
+void SAL_CALL ChartView::setPropertyValue( const OUString& rPropertyName
+ , const Any& rValue )
+{
+ if( rPropertyName == "Resolution" )
+ {
+ awt::Size aNewResolution;
+ if( ! (rValue >>= aNewResolution) )
+ throw lang::IllegalArgumentException( "Property 'Resolution' requires value of type awt::Size", nullptr, 0 );
+
+ if( m_aPageResolution.Width!=aNewResolution.Width || m_aPageResolution.Height!=aNewResolution.Height )
+ {
+ //set modified only when the new resolution is higher and points were skipped before
+ bool bSetModified = m_bPointsWereSkipped && (m_aPageResolution.Width<aNewResolution.Width || m_aPageResolution.Height<aNewResolution.Height);
+
+ m_aPageResolution = aNewResolution;
+
+ if( bSetModified )
+ this->modified( lang::EventObject( static_cast< uno::XWeak* >( this ) ) );
+ }
+ }
+ else if( rPropertyName == "ZoomFactors" )
+ {
+ //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
+ uno::Sequence< beans::PropertyValue > aZoomFactors;
+ if( ! (rValue >>= aZoomFactors) )
+ throw lang::IllegalArgumentException( "Property 'ZoomFactors' requires value of type Sequence< PropertyValue >", nullptr, 0 );
+
+ sal_Int32 nFilterArgs = aZoomFactors.getLength();
+ const beans::PropertyValue* pDataValues = aZoomFactors.getConstArray();
+ while( nFilterArgs-- )
+ {
+ if ( pDataValues->Name == "ScaleXNumerator" )
+ pDataValues->Value >>= m_nScaleXNumerator;
+ else if ( pDataValues->Name == "ScaleXDenominator" )
+ pDataValues->Value >>= m_nScaleXDenominator;
+ else if ( pDataValues->Name == "ScaleYNumerator" )
+ pDataValues->Value >>= m_nScaleYNumerator;
+ else if ( pDataValues->Name == "ScaleYDenominator" )
+ pDataValues->Value >>= m_nScaleYDenominator;
+
+ pDataValues++;
+ }
+ }
+ else if( rPropertyName == "SdrViewIsInEditMode" )
+ {
+ //#i77362 change notification for changes on additional shapes are missing
+ if( ! (rValue >>= m_bSdrViewIsInEditMode) )
+ throw lang::IllegalArgumentException( "Property 'SdrViewIsInEditMode' requires value of type sal_Bool", nullptr, 0 );
+ }
+ else
+ throw beans::UnknownPropertyException( "unknown property was tried to set to chart wizard " + rPropertyName, nullptr );
+}
+
+Any SAL_CALL ChartView::getPropertyValue( const OUString& rPropertyName )
+{
+ if( rPropertyName != "Resolution" )
+ throw beans::UnknownPropertyException( "unknown property was tried to get from chart wizard " + rPropertyName, nullptr );
+
+ return Any(m_aPageResolution);
+}
+
+void SAL_CALL ChartView::addPropertyChangeListener(
+ const OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* xListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+void SAL_CALL ChartView::removePropertyChangeListener(
+ const OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* aListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL ChartView::addVetoableChangeListener( const OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL ChartView::removeVetoableChangeListener( const OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
+{
+ OSL_FAIL("not implemented");
+}
+
+// ____ XMultiServiceFactory ____
+
+Reference< uno::XInterface > ChartView::createInstance( const OUString& aServiceSpecifier )
+{
+ SolarMutexGuard aSolarGuard;
+
+ SdrModel* pModel = ( m_pDrawModelWrapper ? &m_pDrawModelWrapper->getSdrModel() : nullptr );
+ if ( pModel )
+ {
+ if ( aServiceSpecifier == "com.sun.star.drawing.DashTable" )
+ {
+ if ( !m_xDashTable.is() )
+ {
+ m_xDashTable = SvxUnoDashTable_createInstance( pModel );
+ }
+ return m_xDashTable;
+ }
+ else if ( aServiceSpecifier == "com.sun.star.drawing.GradientTable" )
+ {
+ if ( !m_xGradientTable.is() )
+ {
+ m_xGradientTable = SvxUnoGradientTable_createInstance( pModel );
+ }
+ return m_xGradientTable;
+ }
+ else if ( aServiceSpecifier == "com.sun.star.drawing.HatchTable" )
+ {
+ if ( !m_xHatchTable.is() )
+ {
+ m_xHatchTable = SvxUnoHatchTable_createInstance( pModel );
+ }
+ return m_xHatchTable;
+ }
+ else if ( aServiceSpecifier == "com.sun.star.drawing.BitmapTable" )
+ {
+ if ( !m_xBitmapTable.is() )
+ {
+ m_xBitmapTable = SvxUnoBitmapTable_createInstance( pModel );
+ }
+ return m_xBitmapTable;
+ }
+ else if ( aServiceSpecifier == "com.sun.star.drawing.TransparencyGradientTable" )
+ {
+ if ( !m_xTransGradientTable.is() )
+ {
+ m_xTransGradientTable = SvxUnoTransGradientTable_createInstance( pModel );
+ }
+ return m_xTransGradientTable;
+ }
+ else if ( aServiceSpecifier == "com.sun.star.drawing.MarkerTable" )
+ {
+ if ( !m_xMarkerTable.is() )
+ {
+ m_xMarkerTable = SvxUnoMarkerTable_createInstance( pModel );
+ }
+ return m_xMarkerTable;
+ }
+ }
+
+ return nullptr;
+}
+
+Reference< uno::XInterface > ChartView::createInstanceWithArguments( const OUString& ServiceSpecifier, const uno::Sequence< uno::Any >& Arguments )
+{
+ OSL_ENSURE( Arguments.hasElements(), "ChartView::createInstanceWithArguments: arguments are ignored" );
+ return createInstance( ServiceSpecifier );
+}
+
+uno::Sequence< OUString > ChartView::getAvailableServiceNames()
+{
+ uno::Sequence< OUString > aServiceNames{ "com.sun.star.drawing.DashTable",
+ "com.sun.star.drawing.GradientTable",
+ "com.sun.star.drawing.HatchTable",
+ "com.sun.star.drawing.BitmapTable",
+ "com.sun.star.drawing.TransparencyGradientTable",
+ "com.sun.star.drawing.MarkerTable" };
+
+ return aServiceNames;
+}
+
+OUString ChartView::dump(OUString const & kind)
+{
+ if (kind.isEmpty()) {
+ return comphelper::dumpXmlToString([this](auto writer) { return dumpAsXml(writer); });
+ }
+
+ // kind == "shapes":
+#if HAVE_FEATURE_DESKTOP
+ // Used for unit tests and in chartcontroller only, no need to drag in this when cross-compiling
+ // for non-desktop
+ impl_updateView();
+ sal_Int32 n = m_xDrawPage->getCount();
+ OUStringBuffer aBuffer;
+ for(sal_Int32 i = 0; i < n; ++i)
+ {
+ uno::Reference< drawing::XShapes > xShape(m_xDrawPage->getByIndex(i), uno::UNO_QUERY);
+ if(xShape.is())
+ {
+ OUString aString = XShapeDumper::dump(uno::Reference<drawing::XShapes>(mxRootShape));
+ aBuffer.append(aString);
+ }
+ else
+ {
+ uno::Reference< drawing::XShape > xSingleShape(m_xDrawPage->getByIndex(i), uno::UNO_QUERY);
+ if(!xSingleShape.is())
+ continue;
+ OUString aString = XShapeDumper::dump(xSingleShape);
+ aBuffer.append(aString);
+ }
+ aBuffer.append("\n\n");
+ }
+
+ return aBuffer.makeStringAndClear();
+#else
+ return OUString();
+#endif
+}
+
+void ChartView::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ChartView"));
+ (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
+
+ if (m_pDrawModelWrapper)
+ {
+ m_pDrawModelWrapper->dumpAsXml(pWriter);
+ }
+
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+void ChartView::setViewDirty()
+{
+ std::unique_lock aGuard(maTimeMutex);
+ m_bViewDirty = true;
+}
+
+IMPL_LINK_NOARG(ChartView, UpdateTimeBased, Timer *, void)
+{
+ setViewDirty();
+ update();
+}
+
+void ChartView::createShapes2D( const awt::Size& rPageSize )
+{
+ // todo: it would be nicer to just pass the page m_xDrawPage and format it,
+ // but the draw page does not support XPropertySet
+ formatPage( mrChartModel, rPageSize, mxRootShape );
+
+ CreateShapeParam2D aParam;
+ aParam.maRemainingSpace.X = 0;
+ aParam.maRemainingSpace.Y = 0;
+ aParam.maRemainingSpace.Width = rPageSize.Width;
+ aParam.maRemainingSpace.Height = rPageSize.Height;
+
+ //create the group shape for diagram and axes first to have title and legends on top of it
+ rtl::Reference< Diagram > xDiagram( mrChartModel.getFirstChartDiagram() );
+ bool bHasRelativeSize = false;
+ if( xDiagram.is() && xDiagram->getPropertyValue("RelativeSize").hasValue() )
+ bHasRelativeSize = true;
+
+ OUString aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, OUString::number( 0 ) ) );//todo: other index if more than one diagram is possible
+ rtl::Reference<SvxShapeGroup> xDiagramPlusAxesPlusMarkHandlesGroup_Shapes =
+ ShapeFactory::createGroup2D(mxRootShape,aDiagramCID);
+
+ aParam.mxMarkHandles = ShapeFactory::createInvisibleRectangle(
+ xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0));
+ ShapeFactory::setShapeName(aParam.mxMarkHandles, "MarkHandles");
+
+ aParam.mxPlotAreaWithAxes = ShapeFactory::createInvisibleRectangle(
+ xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0, 0));
+ ShapeFactory::setShapeName(aParam.mxPlotAreaWithAxes, "PlotAreaIncludingAxes");
+
+ aParam.mxDiagramWithAxesShapes = ShapeFactory::createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes);
+
+ bool bAutoPositionDummy = true;
+
+ // create buttons
+ lcl_createButtons(mxRootShape, mrChartModel, aParam.maRemainingSpace);
+
+ lcl_createTitle(
+ TitleHelper::MAIN_TITLE, mxRootShape, mrChartModel,
+ aParam.maRemainingSpace, rPageSize, TitleAlignment::ALIGN_TOP, bAutoPositionDummy);
+ if (!bHasRelativeSize && (aParam.maRemainingSpace.Width <= 0 || aParam.maRemainingSpace.Height <= 0))
+ return;
+
+ lcl_createTitle(
+ TitleHelper::SUB_TITLE, mxRootShape, mrChartModel,
+ aParam.maRemainingSpace, rPageSize, TitleAlignment::ALIGN_TOP, bAutoPositionDummy );
+ if (!bHasRelativeSize && (aParam.maRemainingSpace.Width <= 0 || aParam.maRemainingSpace.Height <= 0))
+ return;
+
+ aParam.mpSeriesPlotterContainer = std::make_shared<SeriesPlotterContainer>(m_aVCooSysList);
+ aParam.mpSeriesPlotterContainer->initializeCooSysAndSeriesPlotter( mrChartModel );
+ if(maTimeBased.bTimeBased && maTimeBased.nFrame != 0)
+ {
+ auto& rSeriesPlotter = aParam.mpSeriesPlotterContainer->getSeriesPlotterList();
+ size_t n = rSeriesPlotter.size();
+ for(size_t i = 0; i < n; ++i)
+ {
+ std::vector<VDataSeries*> aAllNewDataSeries = rSeriesPlotter[i]->getAllSeries();
+ std::vector< VDataSeries* >& rAllOldDataSeries =
+ maTimeBased.m_aDataSeriesList[i];
+ size_t m = std::min(aAllNewDataSeries.size(), rAllOldDataSeries.size());
+ for(size_t j = 0; j < m; ++j)
+ {
+ aAllNewDataSeries[j]->setOldTimeBased(
+ rAllOldDataSeries[j], (maTimeBased.nFrame % 60)/60.0);
+ }
+ }
+ }
+
+ lcl_createLegend(
+ LegendHelper::getLegend( mrChartModel ), mxRootShape, getComponentContext(),
+ aParam.maRemainingSpace, rPageSize, mrChartModel, aParam.mpSeriesPlotterContainer->getLegendEntryProviderList(),
+ lcl_getDefaultWritingModeFromPool( m_pDrawModelWrapper ) );
+
+ if (!bHasRelativeSize && (aParam.maRemainingSpace.Width <= 0 || aParam.maRemainingSpace.Height <= 0))
+ return;
+
+ if (!createAxisTitleShapes2D(aParam, rPageSize, bHasRelativeSize))
+ return;
+
+ bool bDummy = false;
+ bool bIsVertical = xDiagram && xDiagram->getVertical(bDummy, bDummy);
+
+ if (getAvailablePosAndSizeForDiagram(aParam, rPageSize, xDiagram))
+ {
+ awt::Rectangle aUsedOuterRect = impl_createDiagramAndContent(aParam, rPageSize);
+
+ if (aParam.mxPlotAreaWithAxes.is())
+ {
+ aParam.mxPlotAreaWithAxes->setPosition(awt::Point(aUsedOuterRect.X, aUsedOuterRect.Y));
+ aParam.mxPlotAreaWithAxes->setSize(awt::Size(aUsedOuterRect.Width, aUsedOuterRect.Height));
+ }
+
+ //correct axis title position
+ awt::Rectangle aDiagramPlusAxesRect( aUsedOuterRect );
+ if (aParam.mbAutoPosTitleX)
+ changePositionOfAxisTitle(aParam.mpVTitleX.get(), TitleAlignment::ALIGN_BOTTOM, aDiagramPlusAxesRect, rPageSize);
+ if (aParam.mbAutoPosTitleY)
+ changePositionOfAxisTitle(aParam.mpVTitleY.get(), TitleAlignment::ALIGN_LEFT, aDiagramPlusAxesRect, rPageSize);
+ if (aParam.mbAutoPosTitleZ)
+ changePositionOfAxisTitle(aParam.mpVTitleZ.get(), TitleAlignment::ALIGN_Z, aDiagramPlusAxesRect, rPageSize);
+ if (aParam.mbAutoPosSecondTitleX)
+ changePositionOfAxisTitle(aParam.mpVTitleSecondX.get(), bIsVertical? TitleAlignment::ALIGN_RIGHT : TitleAlignment::ALIGN_TOP, aDiagramPlusAxesRect, rPageSize);
+ if (aParam.mbAutoPosSecondTitleY)
+ changePositionOfAxisTitle(aParam.mpVTitleSecondY.get(), bIsVertical? TitleAlignment::ALIGN_TOP : TitleAlignment::ALIGN_RIGHT, aDiagramPlusAxesRect, rPageSize);
+ }
+
+ //cleanup: remove all empty group shapes to avoid grey border lines:
+ lcl_removeEmptyGroupShapes( *mxRootShape->GetSdrObject() );
+
+ if(maTimeBased.bTimeBased && maTimeBased.nFrame % 60 == 0)
+ {
+ // create copy of the data for next frame
+ auto& rSeriesPlotter = aParam.mpSeriesPlotterContainer->getSeriesPlotterList();
+ size_t n = rSeriesPlotter.size();
+ maTimeBased.m_aDataSeriesList.clear();
+ maTimeBased.m_aDataSeriesList.resize(n);
+ for(size_t i = 0; i < n; ++i)
+ {
+ std::vector<VDataSeries*> aAllNewDataSeries = rSeriesPlotter[i]->getAllSeries();
+ std::vector<VDataSeries*>& rAllOldDataSeries = maTimeBased.m_aDataSeriesList[i];
+ size_t m = aAllNewDataSeries.size();
+ for(size_t j = 0; j < m; ++j)
+ {
+ rAllOldDataSeries.push_back( aAllNewDataSeries[j]->
+ createCopyForTimeBased() );
+ }
+ }
+
+ maTimeBased.maTimer.Stop();
+ }
+
+ if(maTimeBased.bTimeBased && !maTimeBased.maTimer.IsActive())
+ {
+ maTimeBased.maTimer.SetTimeout(15);
+ maTimeBased.maTimer.SetInvokeHandler(LINK(this, ChartView, UpdateTimeBased));
+ maTimeBased.maTimer.Start();
+ }
+}
+
+bool ChartView::createAxisTitleShapes2D( CreateShapeParam2D& rParam, const css::awt::Size& rPageSize, bool bHasRelativeSize )
+{
+ rtl::Reference<Diagram> xDiagram = mrChartModel.getFirstChartDiagram();
+
+ rtl::Reference< ChartType > xChartType;
+ sal_Int32 nDimension = 0;
+ if (xDiagram)
+ {
+ xChartType = xDiagram->getChartTypeByIndex( 0 );
+ nDimension = xDiagram->getDimension();
+ }
+
+ if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 0 ) )
+ rParam.mpVTitleX = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, mxRootShape, mrChartModel
+ , rParam.maRemainingSpace, rPageSize, TitleAlignment::ALIGN_BOTTOM, rParam.mbAutoPosTitleX );
+ if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0))
+ return false;
+
+ if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 1 ) )
+ rParam.mpVTitleY = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, mxRootShape, mrChartModel
+ , rParam.maRemainingSpace, rPageSize, TitleAlignment::ALIGN_LEFT, rParam.mbAutoPosTitleY );
+ if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0))
+ return false;
+
+ if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 2 ) )
+ rParam.mpVTitleZ = lcl_createTitle( TitleHelper::Z_AXIS_TITLE, mxRootShape, mrChartModel
+ , rParam.maRemainingSpace, rPageSize, TitleAlignment::ALIGN_RIGHT, rParam.mbAutoPosTitleZ );
+ if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0))
+ return false;
+
+ bool bDummy = false;
+ bool bIsVertical = xDiagram && xDiagram->getVertical( bDummy, bDummy );
+
+ if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension ) )
+ rParam.mpVTitleSecondX = lcl_createTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, mxRootShape, mrChartModel
+ , rParam.maRemainingSpace, rPageSize, bIsVertical? TitleAlignment::ALIGN_RIGHT : TitleAlignment::ALIGN_TOP, rParam.mbAutoPosSecondTitleX );
+ if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0))
+ return false;
+
+ if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension ) )
+ rParam.mpVTitleSecondY = lcl_createTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, mxRootShape, mrChartModel
+ , rParam.maRemainingSpace, rPageSize, bIsVertical? TitleAlignment::ALIGN_TOP : TitleAlignment::ALIGN_RIGHT, rParam.mbAutoPosSecondTitleY );
+ if (!bHasRelativeSize && (rParam.maRemainingSpace.Width <= 0 || rParam.maRemainingSpace.Height <= 0))
+ return false;
+
+ return true;
+}
+
+} //namespace chart
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_chart2_ChartView_get_implementation(css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ rtl::Reference<::chart::ChartModel> pChartModel = new ::chart::ChartModel(context);
+ return cppu::acquire(new ::chart::ChartView(context, *pChartModel));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/Clipping.cxx b/chart2/source/view/main/Clipping.cxx
new file mode 100644
index 0000000000..713e88c26b
--- /dev/null
+++ b/chart2/source/view/main/Clipping.cxx
@@ -0,0 +1,425 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <Clipping.hxx>
+#include <CommonConverters.hxx>
+#include <BaseGFXHelper.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using ::basegfx::B2DRectangle;
+using ::basegfx::B2DTuple;
+
+namespace{
+/** @descr This is a supporting function for lcl_clip2d. It computes a new parametric
+ value for an entering (dTE) or leaving (dTL) intersection point with one
+ of the edges bounding the clipping area.
+ For explanation of the parameters please refer to :
+
+ Liang-Biarsky parametric line-clipping algorithm as described in:
+ Computer Graphics: principles and practice, 2nd ed.,
+ James D. Foley et al.,
+ Section 3.12.4 on page 117.
+*/
+bool lcl_CLIPt(double fDenom,double fNum, double & fTE, double & fTL)
+{
+ double fT;
+
+ if (fDenom > 0) // Intersection enters: PE
+ {
+ fT = fNum / fDenom; // Parametric value at the intersection.
+ if (fT > fTL) // fTE and fTL crossover
+ return false; // therefore reject the line.
+ else if (fT > fTE) // A new fTE has been found.
+ fTE = fT;
+ }
+ else if (fDenom < 0) // Intersection leaves: PL
+ {
+ fT = fNum / fDenom; // Parametric Value at the intersection.
+ if (fT < fTE) // fTE and fTL crossover
+ return false; // therefore reject the line.
+ else if (fT < fTL) // A new fTL has been found.
+ fTL = fT;
+ }
+ else if (fNum > 0)
+ return false; // Line lies on the outside of the edge.
+
+ return true;
+}
+
+/** @descr The line given by its two endpoints rP0 and rP1 is clipped at the rectangle
+ rRectangle. If there is at least a part of it visible then sal_True is returned and
+ the endpoints of that part are stored in rP0 and rP1. The points rP0 and rP1
+ may have the same coordinates.
+ @param rP0 Start point of the line to clip. Modified to contain a start point inside
+ the clipping area if possible.
+ @param rP1 End point of the line to clip. Modified to contain an end point inside
+ the clipping area if possible.
+ @param rRectangle Clipping area.
+ @return If the line lies completely or partly inside the clipping area then TRUE
+ is returned. If the line lies completely outside then sal_False is returned and rP0 and
+ rP1 are left unmodified.
+*/
+bool lcl_clip2d(B2DTuple& rPoint0, B2DTuple& rPoint1, const B2DRectangle& rRectangle)
+{
+ //Direction vector of the line.
+ B2DTuple aDirection = rPoint1 - rPoint0;
+
+ if( aDirection.getX()==0 && aDirection.getY()==0 && rRectangle.isInside(rPoint0) )
+ {
+ // Degenerate case of a zero length line.
+ return true;
+ }
+ else
+ {
+ // Values of the line parameter where the line enters resp. leaves the rectangle.
+ double fTE = 0,
+ fTL = 1;
+
+ // Test whether at least a part lies in the four half-planes with respect to
+ // the rectangles four edges.
+ if( lcl_CLIPt(aDirection.getX(), rRectangle.getMinX() - rPoint0.getX(), fTE, fTL) )
+ if( lcl_CLIPt(-aDirection.getX(), rPoint0.getX() - rRectangle.getMaxX(), fTE, fTL) )
+ if( lcl_CLIPt(aDirection.getY(), rRectangle.getMinY() - rPoint0.getY(), fTE, fTL) )
+ if( lcl_CLIPt(-aDirection.getY(), rPoint0.getY() - rRectangle.getMaxY(), fTE, fTL) )
+ {
+ // At least a part is visible.
+ if (fTL < 1)
+ {
+ // Compute the new end point.
+ rPoint1.setX( rPoint0.getX() + fTL * aDirection.getX() );
+ rPoint1.setY( rPoint0.getY() + fTL * aDirection.getY() );
+ }
+ if (fTE > 0)
+ {
+ // Compute the new starting point.
+ rPoint0.setX( rPoint0.getX() + fTE * aDirection.getX() );
+ rPoint0.setY( rPoint0.getY() + fTE * aDirection.getY() );
+ }
+ return true;
+ }
+
+ // Line is not visible.
+ return false;
+ }
+}
+
+bool lcl_clip2d_(drawing::Position3D& rPoint0, drawing::Position3D& rPoint1, const B2DRectangle& rRectangle)
+{
+ B2DTuple aP0(rPoint0.PositionX,rPoint0.PositionY);
+ B2DTuple aP1(rPoint1.PositionX,rPoint1.PositionY);
+ bool bRet = lcl_clip2d( aP0, aP1, rRectangle );
+
+ rPoint0.PositionX = aP0.getX();
+ rPoint0.PositionY = aP0.getY();
+ rPoint1.PositionX = aP1.getX();
+ rPoint1.PositionY = aP1.getY();
+
+ return bRet;
+}
+
+unsigned int round_up_nearest_pow2(unsigned int v)
+{
+ // compute the next highest power of 2 of 32-bit v
+ --v;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ ++v;
+ return v;
+}
+
+void lcl_addPointToPoly( drawing::PolyPolygonShape3D& rPoly
+ , const drawing::Position3D& rPos
+ , sal_Int32 nPolygonIndex
+ , std::vector< sal_Int32 >& rResultPointCount
+ , sal_Int32 nReservePointCount )
+{
+ if(nPolygonIndex<0)
+ {
+ OSL_FAIL( "The polygon index needs to be > 0");
+ nPolygonIndex=0;
+ }
+
+ //make sure that we have enough polygons
+ if(nPolygonIndex >= rPoly.SequenceX.getLength() )
+ {
+ rPoly.SequenceX.realloc(nPolygonIndex+1);
+ rPoly.SequenceY.realloc(nPolygonIndex+1);
+ rPoly.SequenceZ.realloc(nPolygonIndex+1);
+ rResultPointCount.resize(nPolygonIndex+1,0);
+ }
+
+ drawing::DoubleSequence* pOuterSequenceX = &rPoly.SequenceX.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceY = &rPoly.SequenceY.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceZ = &rPoly.SequenceZ.getArray()[nPolygonIndex];
+
+ sal_Int32 nNewResultPointCount = rResultPointCount[nPolygonIndex]+1;
+ sal_Int32 nSeqLength = pOuterSequenceX->getLength();
+
+ if( nSeqLength <= nNewResultPointCount )
+ {
+ sal_Int32 nReallocLength = nReservePointCount > SAL_MAX_INT16 ? round_up_nearest_pow2(nNewResultPointCount) * 2 : nReservePointCount;
+ if( nNewResultPointCount > nReallocLength )
+ {
+ nReallocLength = nNewResultPointCount;
+ OSL_FAIL("this should not be the case to avoid performance problems");
+ }
+ pOuterSequenceX->realloc(nReallocLength);
+ pOuterSequenceY->realloc(nReallocLength);
+ pOuterSequenceZ->realloc(nReallocLength);
+ }
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ pInnerSequenceX[nNewResultPointCount-1] = rPos.PositionX;
+ pInnerSequenceY[nNewResultPointCount-1] = rPos.PositionY;
+ pInnerSequenceZ[nNewResultPointCount-1] = rPos.PositionZ;
+ rResultPointCount[nPolygonIndex]=nNewResultPointCount;
+}
+
+void lcl_addPointToPoly( std::vector<std::vector<css::drawing::Position3D>>& rPoly
+ , const drawing::Position3D& rPos
+ , sal_Int32 nPolygonIndex
+ , std::vector< sal_Int32 >& rResultPointCount
+ , sal_Int32 nReservePointCount )
+{
+ if(nPolygonIndex<0)
+ {
+ OSL_FAIL( "The polygon index needs to be > 0");
+ nPolygonIndex=0;
+ }
+
+ //make sure that we have enough polygons
+ if(o3tl::make_unsigned(nPolygonIndex) >= rPoly.size() )
+ {
+ rPoly.resize(nPolygonIndex+1);
+ rResultPointCount.resize(nPolygonIndex+1,0);
+ }
+
+ std::vector<css::drawing::Position3D>* pOuterSequence = &rPoly[nPolygonIndex];
+
+ sal_Int32 nNewResultPointCount = rResultPointCount[nPolygonIndex]+1;
+ sal_Int32 nSeqLength = pOuterSequence->size();
+
+ if( nSeqLength <= nNewResultPointCount )
+ {
+ sal_Int32 nReallocLength = nReservePointCount > SAL_MAX_INT16 ? round_up_nearest_pow2(nNewResultPointCount) * 2 : nReservePointCount;
+ if( nNewResultPointCount > nReallocLength )
+ {
+ nReallocLength = nNewResultPointCount;
+ OSL_FAIL("this should not be the case to avoid performance problems");
+ }
+ pOuterSequence->resize(nReallocLength);
+ }
+
+ css::drawing::Position3D* pInnerSequence = pOuterSequence->data();
+
+ pInnerSequence[nNewResultPointCount-1] = rPos;
+ rResultPointCount[nPolygonIndex]=nNewResultPointCount;
+}
+
+}//end anonymous namespace
+
+void Clipping::clipPolygonAtRectangle( const drawing::PolyPolygonShape3D& rPolygon
+ , const B2DRectangle& rRectangle
+ , drawing::PolyPolygonShape3D& aResult
+ , bool bSplitPiecesToDifferentPolygons )
+{
+ aResult.SequenceX.realloc(0);
+ aResult.SequenceY.realloc(0);
+ aResult.SequenceZ.realloc(0);
+
+ if(!rPolygon.SequenceX.hasElements())
+ return;
+
+ //need clipping?:
+ {
+ ::basegfx::B3DRange a3DRange( BaseGFXHelper::getBoundVolume( rPolygon ) );
+ ::basegfx::B2DRange a2DRange( a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY() );
+ if( rRectangle.isInside( a2DRange ) )
+ {
+ aResult = rPolygon;
+ return;
+ }
+ else
+ {
+ a2DRange.intersect( rRectangle );
+ if( a2DRange.isEmpty() )
+ return;
+ }
+ }
+
+ std::vector< sal_Int32 > aResultPointCount;//per polygon index
+
+ //apply clipping:
+ drawing::Position3D aFrom;
+ drawing::Position3D aTo;
+
+ sal_Int32 nNewPolyIndex = 0;
+ sal_Int32 nOldPolyCount = rPolygon.SequenceX.getLength();
+ for(sal_Int32 nOldPolyIndex=0; nOldPolyIndex<nOldPolyCount; nOldPolyIndex++, nNewPolyIndex++ )
+ {
+ sal_Int32 nOldPointCount = rPolygon.SequenceX[nOldPolyIndex].getLength();
+
+ // set last point to a position outside the rectangle, such that the first
+ // time lcl_clip2d returns true, the comparison to last will always yield false
+ drawing::Position3D aLast(rRectangle.getMinX()-1.0,rRectangle.getMinY()-1.0, 0.0 );
+
+ for(sal_Int32 nOldPoint=1; nOldPoint<nOldPointCount; nOldPoint++)
+ {
+ aFrom = getPointFromPoly(rPolygon,nOldPoint-1,nOldPolyIndex);
+ aTo = getPointFromPoly(rPolygon,nOldPoint,nOldPolyIndex);
+ if( lcl_clip2d_(aFrom, aTo, rRectangle) )
+ {
+ // compose a Polygon of as many consecutive points as possible
+ if(aFrom == aLast)
+ {
+ if( aTo != aFrom )
+ {
+ lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount );
+ }
+ }
+ else
+ {
+ if( bSplitPiecesToDifferentPolygons && nOldPoint!=1 )
+ {
+ if( nNewPolyIndex < aResult.SequenceX.getLength()
+ && aResultPointCount[nNewPolyIndex]>0 )
+ nNewPolyIndex++;
+ }
+ lcl_addPointToPoly( aResult, aFrom, nNewPolyIndex, aResultPointCount, nOldPointCount );
+ if( aTo != aFrom )
+ lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount );
+ }
+ aLast = aTo;
+ }
+ }
+ }
+ //free unused space
+ for( sal_Int32 nPolygonIndex = aResultPointCount.size(); nPolygonIndex--; )
+ {
+ drawing::DoubleSequence* pOuterSequenceX = &aResult.SequenceX.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceY = &aResult.SequenceY.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceZ = &aResult.SequenceZ.getArray()[nPolygonIndex];
+
+ sal_Int32 nUsedPointCount = aResultPointCount[nPolygonIndex];
+ pOuterSequenceX->realloc(nUsedPointCount);
+ pOuterSequenceY->realloc(nUsedPointCount);
+ pOuterSequenceZ->realloc(nUsedPointCount);
+ }
+}
+
+void Clipping::clipPolygonAtRectangle( const std::vector<std::vector<css::drawing::Position3D>>& rPolygon
+ , const B2DRectangle& rRectangle
+ , std::vector<std::vector<css::drawing::Position3D>>& aResult
+ , bool bSplitPiecesToDifferentPolygons )
+{
+ aResult.clear();
+
+ if(rPolygon.empty())
+ return;
+
+ //need clipping?:
+ {
+ ::basegfx::B3DRange a3DRange( BaseGFXHelper::getBoundVolume( rPolygon ) );
+ ::basegfx::B2DRange a2DRange( a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY() );
+ if( rRectangle.isInside( a2DRange ) )
+ {
+ aResult = rPolygon;
+ return;
+ }
+ else
+ {
+ a2DRange.intersect( rRectangle );
+ if( a2DRange.isEmpty() )
+ return;
+ }
+ }
+
+ std::vector< sal_Int32 > aResultPointCount;//per polygon index
+
+ //apply clipping:
+ drawing::Position3D aFrom;
+ drawing::Position3D aTo;
+
+ sal_Int32 nNewPolyIndex = 0;
+ sal_Int32 nOldPolyCount = rPolygon.size();
+ for(sal_Int32 nOldPolyIndex=0; nOldPolyIndex<nOldPolyCount; nOldPolyIndex++, nNewPolyIndex++ )
+ {
+ sal_Int32 nOldPointCount = rPolygon[nOldPolyIndex].size();
+
+ // set last point to a position outside the rectangle, such that the first
+ // time lcl_clip2d returns true, the comparison to last will always yield false
+ drawing::Position3D aLast(rRectangle.getMinX()-1.0,rRectangle.getMinY()-1.0, 0.0 );
+
+ for(sal_Int32 nOldPoint=1; nOldPoint<nOldPointCount; nOldPoint++)
+ {
+ aFrom = getPointFromPoly(rPolygon,nOldPoint-1,nOldPolyIndex);
+ aTo = getPointFromPoly(rPolygon,nOldPoint,nOldPolyIndex);
+ if( lcl_clip2d_(aFrom, aTo, rRectangle) )
+ {
+ // compose a Polygon of as many consecutive points as possible
+ if(aFrom == aLast)
+ {
+ if( aTo != aFrom )
+ {
+ lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount );
+ }
+ }
+ else
+ {
+ if( bSplitPiecesToDifferentPolygons && nOldPoint!=1 )
+ {
+ if( nNewPolyIndex < static_cast<sal_Int32>(aResult.size())
+ && aResultPointCount[nNewPolyIndex]>0 )
+ nNewPolyIndex++;
+ }
+ lcl_addPointToPoly( aResult, aFrom, nNewPolyIndex, aResultPointCount, nOldPointCount );
+ if( aTo != aFrom )
+ lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount );
+ }
+ aLast = aTo;
+ }
+ }
+ }
+ //free unused space
+ for( sal_Int32 nPolygonIndex = aResultPointCount.size(); nPolygonIndex--; )
+ {
+ std::vector<css::drawing::Position3D>* pOuterSequence = &aResult[nPolygonIndex];
+
+ sal_Int32 nUsedPointCount = aResultPointCount[nPolygonIndex];
+ pOuterSequence->resize(nUsedPointCount);
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/DataPointSymbolSupplier.cxx b/chart2/source/view/main/DataPointSymbolSupplier.cxx
new file mode 100644
index 0000000000..ff7f8370ac
--- /dev/null
+++ b/chart2/source/view/main/DataPointSymbolSupplier.cxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <chartview/DataPointSymbolSupplier.hxx>
+#include <ShapeFactory.hxx>
+#include <com/sun/star/drawing/Position3D.hpp>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+rtl::Reference< SvxShapeGroup > DataPointSymbolSupplier::create2DSymbolList(
+ const rtl::Reference<SvxDrawPage>& xTarget
+ , const drawing::Direction3D& rSize )
+{
+ rtl::Reference< SvxShapeGroup > xGroupShapes = ShapeFactory::createGroup2D( xTarget );
+
+ drawing::Position3D aPos(0,0,0);
+ for(sal_Int32 nS=0;nS<ShapeFactory::getSymbolCount();nS++)
+ {
+ ShapeFactory::createSymbol2D( xGroupShapes, aPos, rSize, nS, 0, 0 );
+ }
+ return xGroupShapes;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/DataTableView.cxx b/chart2/source/view/main/DataTableView.cxx
new file mode 100644
index 0000000000..c3c807ca09
--- /dev/null
+++ b/chart2/source/view/main/DataTableView.cxx
@@ -0,0 +1,558 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <DataTableView.hxx>
+#include <VSeriesPlotter.hxx>
+#include <ShapeFactory.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <ChartModel.hxx>
+#include <ObjectIdentifier.hxx>
+
+#include <svx/svdotable.hxx>
+
+#include <com/sun/star/table/BorderLine.hpp>
+#include <com/sun/star/table/BorderLine2.hpp>
+#include <com/sun/star/table/TableBorder.hpp>
+#include <com/sun/star/table/BorderLineStyle.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/util/XBroadcaster.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <o3tl/unit_conversion.hxx>
+
+using namespace css;
+
+namespace chart
+{
+namespace
+{
+void setTopCell(uno::Reference<beans::XPropertySet>& xPropertySet)
+{
+ xPropertySet->setPropertyValue("FillColor", uno::Any(Color(0xFFFFFF)));
+ xPropertySet->setPropertyValue("TextVerticalAdjust", uno::Any(drawing::TextVerticalAdjust_TOP));
+ xPropertySet->setPropertyValue("ParaAdjust", uno::Any(style::ParagraphAdjust_CENTER));
+
+ table::BorderLine2 aBorderLine;
+ aBorderLine.LineWidth = 0;
+ aBorderLine.Color = 0x000000;
+
+ xPropertySet->setPropertyValue("TopBorder", uno::Any(aBorderLine));
+ xPropertySet->setPropertyValue("LeftBorder", uno::Any(aBorderLine));
+}
+
+void copyProperty(uno::Reference<beans::XPropertySet>& xOut,
+ uno::Reference<beans::XPropertySet>& xIn, OUString const& sPropertyName)
+{
+ xOut->setPropertyValue(sPropertyName, xIn->getPropertyValue(sPropertyName));
+}
+
+uno::Reference<text::XTextRange> getFirstParagraph(uno::Reference<text::XText> const& xText)
+{
+ uno::Reference<text::XTextRange> xParagraph;
+ uno::Reference<container::XEnumerationAccess> xEnumAccess(xText, uno::UNO_QUERY);
+ if (!xEnumAccess.is())
+ return xParagraph;
+ uno::Reference<container::XEnumeration> xEnumeration(xEnumAccess->createEnumeration());
+ xParagraph.set(xEnumeration->nextElement(), uno::UNO_QUERY);
+ return xParagraph;
+}
+
+uno::Reference<beans::XPropertySet>
+getFirstParagraphProperties(uno::Reference<text::XText> const& xText)
+{
+ uno::Reference<beans::XPropertySet> xPropertySet;
+ auto xParagraph = getFirstParagraph(xText);
+ if (!xParagraph.is())
+ return xPropertySet;
+ xPropertySet.set(xParagraph, uno::UNO_QUERY);
+ return xPropertySet;
+}
+
+} // end anonymous namespace
+
+DataTableView::DataTableView(
+ rtl::Reference<::chart::ChartModel> const& xChartModel,
+ rtl::Reference<DataTable> const& rDataTableModel,
+ css::uno::Reference<css::uno::XComponentContext> const& rComponentContext,
+ bool bAlignAxisValuesWithColumns)
+ : m_xChartModel(xChartModel)
+ , m_xDataTableModel(rDataTableModel)
+ , m_xComponentContext(rComponentContext)
+ , m_bAlignAxisValuesWithColumns(bAlignAxisValuesWithColumns)
+{
+ uno::Reference<beans::XPropertySet> xPropertySet(m_xDataTableModel);
+ m_aLineProperties.initFromPropertySet(xPropertySet);
+}
+
+void DataTableView::setCellCharAndParagraphProperties(
+ uno::Reference<beans::XPropertySet>& xPropertySet)
+{
+ uno::Reference<beans::XPropertySet> xDataTableProperties(m_xDataTableModel);
+
+ copyProperty(xPropertySet, xDataTableProperties, "CharColor");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontFamily");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontFamilyAsian");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontFamilyComplex");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontCharSet");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontCharSetAsian");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontCharSetComplex");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontName");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontNameAsian");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontNameComplex");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontPitch");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontPitchAsian");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontPitchComplex");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontStyleName");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontStyleNameAsian");
+ copyProperty(xPropertySet, xDataTableProperties, "CharFontStyleNameComplex");
+
+ copyProperty(xPropertySet, xDataTableProperties, "CharHeight");
+ copyProperty(xPropertySet, xDataTableProperties, "CharHeightAsian");
+ copyProperty(xPropertySet, xDataTableProperties, "CharHeightComplex");
+ copyProperty(xPropertySet, xDataTableProperties, "CharKerning");
+ copyProperty(xPropertySet, xDataTableProperties, "CharLocale");
+ copyProperty(xPropertySet, xDataTableProperties, "CharLocaleAsian");
+ copyProperty(xPropertySet, xDataTableProperties, "CharLocaleComplex");
+ copyProperty(xPropertySet, xDataTableProperties, "CharPosture");
+ copyProperty(xPropertySet, xDataTableProperties, "CharPostureAsian");
+ copyProperty(xPropertySet, xDataTableProperties, "CharPostureComplex");
+ copyProperty(xPropertySet, xDataTableProperties, "CharRelief");
+ copyProperty(xPropertySet, xDataTableProperties, "CharShadowed");
+ copyProperty(xPropertySet, xDataTableProperties, "CharStrikeout");
+ copyProperty(xPropertySet, xDataTableProperties, "CharUnderline");
+ copyProperty(xPropertySet, xDataTableProperties, "CharUnderlineColor");
+ copyProperty(xPropertySet, xDataTableProperties, "CharUnderlineHasColor");
+ copyProperty(xPropertySet, xDataTableProperties, "CharOverline");
+ copyProperty(xPropertySet, xDataTableProperties, "CharOverlineColor");
+ copyProperty(xPropertySet, xDataTableProperties, "CharOverlineHasColor");
+ copyProperty(xPropertySet, xDataTableProperties, "CharWeight");
+ copyProperty(xPropertySet, xDataTableProperties, "CharWeightAsian");
+ copyProperty(xPropertySet, xDataTableProperties, "CharWeightComplex");
+ copyProperty(xPropertySet, xDataTableProperties, "CharWordMode");
+
+ drawing::FillStyle eFillStyle = drawing::FillStyle_NONE;
+ xDataTableProperties->getPropertyValue("FillStyle") >>= eFillStyle;
+ if (eFillStyle == drawing::FillStyle_SOLID)
+ {
+ sal_Int32 aColor = 0;
+ if (xDataTableProperties->getPropertyValue("FillColor") >>= aColor)
+ xPropertySet->setPropertyValue("CharBackColor", uno::Any(aColor));
+ }
+
+ xPropertySet->setPropertyValue("ParaAdjust", uno::Any(style::ParagraphAdjust_CENTER));
+}
+
+void DataTableView::setCellProperties(css::uno::Reference<beans::XPropertySet>& xPropertySet,
+ bool bLeft, bool bTop, bool bRight, bool bBottom)
+{
+ xPropertySet->setPropertyValue("FillColor", uno::Any(Color(0xFFFFFF)));
+
+ uno::Reference<beans::XPropertySet> xDataTableProperties(m_xDataTableModel);
+ float fFontHeight = 0.0;
+ xDataTableProperties->getPropertyValue("CharHeight") >>= fFontHeight;
+ fFontHeight = o3tl::convert(fFontHeight, o3tl::Length::pt, o3tl::Length::mm100);
+ sal_Int32 nXDistance = std::round(fFontHeight * 0.18f);
+ sal_Int32 nYDistance = std::round(fFontHeight * 0.30f);
+
+ xPropertySet->setPropertyValue("TextLeftDistance", uno::Any(nXDistance));
+ xPropertySet->setPropertyValue("TextRightDistance", uno::Any(nXDistance));
+ xPropertySet->setPropertyValue("TextUpperDistance", uno::Any(nYDistance));
+ xPropertySet->setPropertyValue("TextLowerDistance", uno::Any(nYDistance));
+
+ xPropertySet->setPropertyValue("TextVerticalAdjust", uno::Any(drawing::TextVerticalAdjust_TOP));
+
+ drawing::LineStyle eStyle = drawing::LineStyle_NONE;
+ m_aLineProperties.LineStyle >>= eStyle;
+
+ if (eStyle != drawing::LineStyle_NONE)
+ {
+ table::BorderLine2 aBorderLine;
+
+ sal_Int32 nWidth = 0;
+ m_aLineProperties.Width >>= nWidth;
+ aBorderLine.LineWidth = o3tl::convert(nWidth, o3tl::Length::mm100, o3tl::Length::twip);
+
+ sal_Int32 nColor = 0;
+ m_aLineProperties.Color >>= nColor;
+ aBorderLine.Color = nColor;
+
+ aBorderLine.LineStyle = table::BorderLineStyle::SOLID;
+
+ if (eStyle == drawing::LineStyle_DASH)
+ {
+ OUString aDashName;
+ m_aLineProperties.DashName >>= aDashName;
+ if (!aDashName.isEmpty() && m_xChartModel.is())
+ {
+ uno::Reference<container::XNameContainer> xDashTable(
+ m_xChartModel->createInstance("com.sun.star.drawing.DashTable"),
+ uno::UNO_QUERY);
+ if (xDashTable.is() && xDashTable->hasByName(aDashName))
+ {
+ drawing::LineDash aLineDash;
+ xDashTable->getByName(aDashName) >>= aLineDash;
+
+ if (aLineDash.Dots == 0 && aLineDash.Dashes == 0)
+ aBorderLine.LineStyle = table::BorderLineStyle::SOLID;
+ else if (aLineDash.Dots == 1 && aLineDash.Dashes == 0)
+ aBorderLine.LineStyle = table::BorderLineStyle::DOTTED;
+ else if (aLineDash.Dots == 0 && aLineDash.Dashes == 1)
+ aBorderLine.LineStyle = table::BorderLineStyle::DASHED;
+ else if (aLineDash.Dots == 1 && aLineDash.Dashes == 1)
+ aBorderLine.LineStyle = table::BorderLineStyle::DASH_DOT;
+ else if (aLineDash.Dots == 2 && aLineDash.Dashes == 1)
+ aBorderLine.LineStyle = table::BorderLineStyle::DASH_DOT_DOT;
+ else
+ aBorderLine.LineStyle = table::BorderLineStyle::DASHED;
+ }
+ }
+ }
+
+ if (bLeft)
+ xPropertySet->setPropertyValue("LeftBorder", uno::Any(aBorderLine));
+ if (bTop)
+ xPropertySet->setPropertyValue("TopBorder", uno::Any(aBorderLine));
+ if (bRight)
+ xPropertySet->setPropertyValue("RightBorder", uno::Any(aBorderLine));
+ if (bBottom)
+ xPropertySet->setPropertyValue("BottomBorder", uno::Any(aBorderLine));
+ }
+}
+
+void DataTableView::createShapes(basegfx::B2DVector const& rStart, basegfx::B2DVector const& rEnd,
+ sal_Int32 nAxisStepWidth)
+{
+ if (!m_xTarget.is())
+ return;
+
+ // Remove shapes first before we add the new ones
+ ShapeFactory::removeSubShapes(m_xTarget);
+ auto sParticle = ObjectIdentifier::createParticleForDataTable(m_xChartModel);
+ auto sCID = ObjectIdentifier::createClassifiedIdentifierForParticle(sParticle);
+ m_xTableShape = ShapeFactory::createTable(m_xTarget, sCID);
+
+ // calculate the table size
+ auto rDelta = rEnd - rStart;
+ sal_Int32 nTableSize = basegfx::fround(rDelta.getX());
+ m_xTableShape->setSize({ nTableSize, 0 });
+
+ try
+ {
+ m_xTableShape->getPropertyValue("Model") >>= m_xTable;
+ }
+ catch (const uno::Exception&)
+ {
+ return;
+ }
+
+ if (!m_xTable.is())
+ return;
+
+ uno::Reference<util::XBroadcaster> xBroadcaster(m_xTable, uno::UNO_QUERY);
+
+ if (!xBroadcaster.is())
+ return;
+
+ xBroadcaster->lockBroadcasts();
+
+ auto* pTableObject = static_cast<sdr::table::SdrTableObj*>(m_xTableShape->GetSdrObject());
+
+ // get the data table properties from the model
+ bool bHBorder = false;
+ bool bVBorder = false;
+ bool bOutline = false;
+ bool bKeys = false;
+
+ std::vector<ViewLegendSymbol> aSymbols;
+
+ m_xDataTableModel->getPropertyValue("HBorder") >>= bHBorder;
+ m_xDataTableModel->getPropertyValue("VBorder") >>= bVBorder;
+ m_xDataTableModel->getPropertyValue("Outline") >>= bOutline;
+ m_xDataTableModel->getPropertyValue("Keys") >>= bKeys;
+
+ // set the data table row and column size
+ sal_Int32 nColumnCount = m_aXValues.size();
+ uno::Reference<table::XTableColumns> xTableColumns = m_xTable->getColumns();
+ xTableColumns->insertByIndex(0, nColumnCount);
+
+ sal_Int32 nRowCount = m_aDataSeriesNames.size();
+ uno::Reference<table::XTableRows> xTableRows = m_xTable->getRows();
+ xTableRows->insertByIndex(0, nRowCount);
+
+ sal_Int32 nColumnWidth = 0.0;
+
+ // If we don't align, we have to calculate the column width ourselves,
+ // otherwise the column width is taken from the x-axis width
+ if (m_bAlignAxisValuesWithColumns)
+ nColumnWidth = nAxisStepWidth;
+ else
+ nColumnWidth = double(nTableSize) / nColumnCount;
+
+ // Setup empty top-left cell
+ {
+ uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(0, 0);
+ uno::Reference<beans::XPropertySet> xPropertySet(xCell, uno::UNO_QUERY);
+ if (xPropertySet.is())
+ {
+ setTopCell(xPropertySet);
+ }
+ }
+
+ sal_Int32 nColumn;
+ sal_Int32 nRow;
+
+ // COLUMN HEADER
+
+ nColumn = 1;
+ for (auto const& rString : m_aXValues)
+ {
+ uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(nColumn, 0);
+ uno::Reference<beans::XPropertySet> xPropertySet(xCell, uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xCellTextRange(xCell, uno::UNO_QUERY);
+ if (xCellTextRange.is())
+ {
+ auto xText = xCellTextRange->getText();
+ xText->insertString(xText->getStart(), rString, false);
+ auto xTextPropertySet = getFirstParagraphProperties(xText);
+ if (!xTextPropertySet.is())
+ continue;
+
+ bool bLeft
+ = (bOutline && nColumn == 1) || (bVBorder && nColumn > 1 && nColumn < nColumnCount);
+ bool bRight = (bOutline && nColumn == nColumnCount)
+ || (bVBorder && nColumn > 1 && nColumn < nColumnCount);
+ setCellCharAndParagraphProperties(xTextPropertySet);
+ setCellProperties(xPropertySet, bLeft, bOutline, bRight, bOutline);
+ }
+ nColumn++;
+ }
+
+ // ROW HEADER
+ // Prepare keys (symbols)
+ sal_Int32 nMaxSymbolWidth = 0;
+ constexpr const sal_Int32 constSymbolMargin = 100; // 1mm
+ if (bKeys)
+ {
+ uno::Reference<beans::XPropertySet> xDataTableProperties(m_xDataTableModel);
+ float fFontHeight = 0.0;
+ xDataTableProperties->getPropertyValue("CharHeight") >>= fFontHeight;
+ fFontHeight = o3tl::convert(fFontHeight, o3tl::Length::pt, o3tl::Length::mm100);
+
+ sal_Int32 nSymbolHeight = sal_Int32(fFontHeight * 0.6);
+ sal_Int32 nSymbolWidth = nSymbolHeight;
+
+ for (VSeriesPlotter* pSeriesPlotter : m_pSeriesPlotterList)
+ {
+ if (pSeriesPlotter)
+ {
+ awt::Size aCurrentRatio = pSeriesPlotter->getPreferredLegendKeyAspectRatio();
+ sal_Int32 nCurrentWidth = aCurrentRatio.Width;
+ if (aCurrentRatio.Height > 0)
+ nCurrentWidth = nSymbolHeight * aCurrentRatio.Width / aCurrentRatio.Height;
+ nSymbolWidth = std::max(nSymbolWidth, nCurrentWidth);
+ }
+ }
+ nMaxSymbolWidth = nSymbolWidth;
+
+ for (VSeriesPlotter* pSeriesPlotter : m_pSeriesPlotterList)
+ {
+ if (pSeriesPlotter)
+ {
+ awt::Size aSize(nSymbolWidth, nSymbolHeight);
+ std::vector<ViewLegendSymbol> aNewEntries
+ = pSeriesPlotter->createSymbols(aSize, m_xTarget, m_xComponentContext);
+
+ for (auto const& rSymbol : aNewEntries)
+ aSymbols.push_back(rSymbol);
+ }
+ }
+ }
+
+ nRow = 1;
+ for (auto const& rSeriesName : m_aDataSeriesNames)
+ {
+ uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(0, nRow);
+ uno::Reference<beans::XPropertySet> xCellPropertySet(xCell, uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xCellTextRange(xCell, uno::UNO_QUERY);
+ if (xCellTextRange.is())
+ {
+ bool bTop = (bOutline && nRow == 1) || (bHBorder && nRow > 1 && nRow < nRowCount);
+ bool bBottom
+ = (bOutline && nRow == nRowCount) || (bHBorder && nRow > 1 && nRow < nRowCount);
+
+ auto xText = xCellTextRange->getText();
+ xText->insertString(xText->getStart(), rSeriesName, false);
+ auto xTextPropertySet = getFirstParagraphProperties(xText);
+ if (!xTextPropertySet.is())
+ continue;
+ setCellCharAndParagraphProperties(xTextPropertySet);
+ setCellProperties(xCellPropertySet, bOutline, bTop, bOutline, bBottom);
+
+ xCellPropertySet->setPropertyValue("ParaAdjust", uno::Any(style::ParagraphAdjust_LEFT));
+ if (bKeys)
+ {
+ xCellPropertySet->setPropertyValue(
+ "ParaLeftMargin", uno::Any(nMaxSymbolWidth + sal_Int32(2 * constSymbolMargin)));
+ }
+ }
+ nRow++;
+ }
+
+ // TABLE
+ nRow = 1;
+ for (auto const& rSeries : m_pDataSeriesValues)
+ {
+ nColumn = 1;
+ for (auto const& rValue : rSeries)
+ {
+ uno::Reference<table::XCell> xCell = m_xTable->getCellByPosition(nColumn, nRow);
+ uno::Reference<beans::XPropertySet> xCellPropertySet(xCell, uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xCellTextRange(xCell, uno::UNO_QUERY);
+ if (xCellTextRange.is())
+ {
+ auto xText = xCellTextRange->getText();
+ xText->insertString(xText->getStart(), rValue, false);
+ auto xTextPropertySet = getFirstParagraphProperties(xText);
+ if (!xTextPropertySet.is())
+ continue;
+
+ bool bLeft = false;
+ bool bTop = false;
+ bool bRight = false;
+ bool bBottom = false;
+
+ if (nColumn > 1 && bVBorder)
+ bLeft = true;
+
+ if (nRow > 1 && bHBorder)
+ bTop = true;
+
+ if (nRow == nRowCount && bOutline)
+ bBottom = true;
+
+ if (nColumn == nColumnCount && bOutline)
+ bRight = true;
+
+ setCellCharAndParagraphProperties(xTextPropertySet);
+ setCellProperties(xCellPropertySet, bLeft, bTop, bRight, bBottom);
+ }
+ nColumn++;
+ }
+ nRow++;
+ }
+
+ xBroadcaster->unlockBroadcasts();
+
+ // force recalculation of all cells in the table shape
+ pTableObject->DistributeColumns(0, nColumnCount, true, true);
+ pTableObject->DistributeRows(0, nRowCount, true, true);
+
+ xBroadcaster->lockBroadcasts();
+
+ // reposition the data table
+ changePosition(basegfx::fround(rStart.getX()), basegfx::fround(rStart.getY()));
+
+ sal_Int32 nTableX = m_xTableShape->getPosition().X;
+ sal_Int32 nTableY = m_xTableShape->getPosition().Y;
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xTableColumns->getByIndex(0), uno::UNO_QUERY);
+
+ for (sal_Int32 i = 1; i < xTableColumns->getCount(); ++i)
+ {
+ xPropertySet.set(xTableColumns->getByIndex(i), uno::UNO_QUERY);
+ xPropertySet->setPropertyValue("Width", uno::Any(nColumnWidth));
+ }
+
+ if (bKeys)
+ {
+ sal_Int32 nTotalHeight = 0;
+ for (sal_Int32 i = 0; i < xTableRows->getCount(); i++)
+ {
+ sal_Int32 nSymbolIndex = i - 1;
+ if (nSymbolIndex < sal_Int32(aSymbols.size()))
+ {
+ xPropertySet.set(xTableRows->getByIndex(i), uno::UNO_QUERY);
+ sal_Int32 nHeight = 0;
+ xPropertySet->getPropertyValue("Height") >>= nHeight;
+ if (i > 0)
+ {
+ auto& rSymbol = aSymbols[nSymbolIndex].xSymbol;
+ sal_Int32 nSymbolHeight = rSymbol->getSize().Height;
+ sal_Int32 nSymbolY
+ = basegfx::fround(double(nHeight) / 2.0 - double(nSymbolHeight) / 2.0);
+ rSymbol->setPosition(
+ { nTableX + constSymbolMargin, nTableY + nTotalHeight + nSymbolY });
+ }
+ nTotalHeight += nHeight;
+ }
+ }
+ }
+ xBroadcaster->unlockBroadcasts();
+}
+
+void DataTableView::changePosition(sal_Int32 x, sal_Int32 y)
+{
+ if (!m_xTable.is())
+ return;
+
+ uno::Reference<table::XTableColumns> xTableColumns = m_xTable->getColumns();
+ uno::Reference<beans::XPropertySet> xPropertySet(xTableColumns->getByIndex(0), uno::UNO_QUERY);
+
+ sal_Int32 nWidth = 0;
+ xPropertySet->getPropertyValue("Width") >>= nWidth;
+
+ m_xTarget->setPosition({ x - nWidth, y });
+}
+
+void DataTableView::initializeShapes(const rtl::Reference<SvxShapeGroupAnyD>& xTarget)
+{
+ m_xTarget = xTarget;
+}
+
+void DataTableView::initializeValues(
+ std::vector<std::unique_ptr<VSeriesPlotter>>& rSeriesPlotterList)
+{
+ for (auto& rSeriesPlotter : rSeriesPlotterList)
+ {
+ m_pSeriesPlotterList.push_back(rSeriesPlotter.get());
+
+ for (auto const& rCategory :
+ rSeriesPlotter->getExplicitCategoriesProvider()->getSimpleCategories())
+ {
+ m_aXValues.push_back(rCategory);
+ }
+
+ for (auto const& rString : rSeriesPlotter->getAllSeriesNames())
+ {
+ m_aDataSeriesNames.push_back(rString);
+ }
+
+ for (VDataSeries* pSeries : rSeriesPlotter->getAllSeries())
+ {
+ auto& rValues = m_pDataSeriesValues.emplace_back();
+ for (int i = 0; i < pSeries->getTotalPointCount(); i++)
+ {
+ double nValue = pSeries->getYValue(i);
+ rValues.push_back(rSeriesPlotter->getLabelTextForValue(*pSeries, i, nValue, false));
+ }
+ }
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/DrawModelWrapper.cxx b/chart2/source/view/main/DrawModelWrapper.cxx
new file mode 100644
index 0000000000..5593c9b599
--- /dev/null
+++ b/chart2/source/view/main/DrawModelWrapper.cxx
@@ -0,0 +1,330 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <chartview/DrawModelWrapper.hxx>
+#include <ShapeFactory.hxx>
+#include "ChartItemPool.hxx"
+#include <ObjectIdentifier.hxx>
+#include <svx/unomodel.hxx>
+#include <svl/itempool.hxx>
+#include <svx/objfac3d.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svx3ditems.hxx>
+#include <svx/xtable.hxx>
+#include <svx/svdoutl.hxx>
+#include <editeng/unolingu.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
+#include <libxml/xmlwriter.h>
+#include <osl/diagnose.h>
+
+namespace com::sun::star::linguistic2 { class XHyphenator; }
+namespace com::sun::star::linguistic2 { class XSpellChecker1; }
+
+using namespace ::com::sun::star;
+
+
+namespace chart
+{
+
+DrawModelWrapper::DrawModelWrapper()
+: SdrModel()
+{
+ m_xChartItemPool = ChartItemPool::CreateChartItemPool();
+
+ SetDefaultFontHeight(423); // 12pt
+
+ SfxItemPool* pMasterPool = &GetItemPool();
+ pMasterPool->SetDefaultMetric(MapUnit::Map100thMM);
+ pMasterPool->SetPoolDefaultItem(SfxBoolItem(EE_PARA_HYPHENATE, true) );
+ pMasterPool->SetPoolDefaultItem(makeSvx3DPercentDiagonalItem (5));
+
+ // append chart pool to end of pool chain
+ pMasterPool->GetLastPoolInChain()->SetSecondaryPool(m_xChartItemPool.get());
+ pMasterPool->FreezeIdRanges();
+ SetTextDefaults();
+
+ //this factory needs to be created before first use of 3D scenes once upon an office runtime
+ //@todo in future this should be done by drawing engine itself on demand
+ static bool b3dFactoryInitialized = false;
+ if(!b3dFactoryInitialized)
+ {
+ E3dObjFactory aObjFactory;
+ b3dFactoryInitialized = true;
+ }
+
+ //Hyphenation and spellchecking
+ SdrOutliner& rOutliner = GetDrawOutliner();
+ try
+ {
+ uno::Reference< linguistic2::XHyphenator > xHyphenator( LinguMgr::GetHyphenator() );
+ if( xHyphenator.is() )
+ rOutliner.SetHyphenator( xHyphenator );
+
+ uno::Reference< linguistic2::XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() );
+ if ( xSpellChecker.is() )
+ rOutliner.SetSpeller( xSpellChecker );
+ }
+ catch(...)
+ {
+ OSL_FAIL("Can't get Hyphenator or SpellChecker for chart");
+ }
+
+ //ref device for font rendering
+ OutputDevice* pDefaultDevice = rOutliner.GetRefDevice();
+ if( !pDefaultDevice )
+ pDefaultDevice = Application::GetDefaultDevice();
+ m_pRefDevice.disposeAndClear();
+ m_pRefDevice = VclPtr<VirtualDevice>::Create(*pDefaultDevice);
+ MapMode aMapMode = m_pRefDevice->GetMapMode();
+ aMapMode.SetMapUnit(MapUnit::Map100thMM);
+ m_pRefDevice->SetMapMode(aMapMode);
+ SetRefDevice(m_pRefDevice.get());
+ rOutliner.SetRefDevice(m_pRefDevice.get());
+}
+
+DrawModelWrapper::~DrawModelWrapper()
+{
+ // normally call from ~SdrModel, but do it here explicitly before we clear m_xChartItemPool
+ implDtorClearModel();
+
+ //remove m_pChartItemPool from pool chain
+ if (m_xChartItemPool)
+ {
+ SfxItemPool* pPool = &GetItemPool();
+ for (;;)
+ {
+ SfxItemPool* pSecondary = pPool->GetSecondaryPool();
+ if(pSecondary == m_xChartItemPool.get())
+ {
+ pPool->SetSecondaryPool (nullptr);
+ break;
+ }
+ pPool = pSecondary;
+ }
+ m_xChartItemPool.clear();
+ }
+ m_pRefDevice.disposeAndClear();
+}
+
+uno::Reference< frame::XModel > DrawModelWrapper::createUnoModel()
+{
+ return new SvxUnoDrawingModel( this ); //tell Andreas Schluens if SvxUnoDrawingModel is not needed anymore -> remove export from svx to avoid link problems in writer
+}
+
+uno::Reference< frame::XModel > DrawModelWrapper::getUnoModel()
+{
+ return SdrModel::getUnoModel();
+}
+
+SdrModel& DrawModelWrapper::getSdrModel()
+{
+ return *this;
+}
+
+uno::Reference< lang::XMultiServiceFactory > DrawModelWrapper::getShapeFactory()
+{
+ uno::Reference< lang::XMultiServiceFactory > xShapeFactory( getUnoModel(), uno::UNO_QUERY );
+ return xShapeFactory;
+}
+
+const rtl::Reference<SvxDrawPage> & DrawModelWrapper::getMainDrawPage()
+{
+ if (m_xMainDrawPage.is())
+ return m_xMainDrawPage;
+
+ // Create draw page.
+ uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSuplier(getUnoModel(), uno::UNO_QUERY);
+ if (!xDrawPagesSuplier.is())
+ return m_xMainDrawPage;
+
+ uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSuplier->getDrawPages();
+ if (xDrawPages->getCount() > 1)
+ {
+ // Take the first page in case of multiple pages.
+ uno::Any aPage = xDrawPages->getByIndex(0);
+ uno::Reference<drawing::XDrawPage> xTmp;
+ aPage >>= xTmp;
+ m_xMainDrawPage = dynamic_cast<SvxDrawPage*>(xTmp.get());
+ assert(m_xMainDrawPage);
+ }
+
+ if (!m_xMainDrawPage.is())
+ {
+ m_xMainDrawPage = dynamic_cast<SvxDrawPage*>(xDrawPages->insertNewByIndex(0).get());
+ assert(m_xMainDrawPage);
+ }
+
+ //ensure that additional shapes are in front of the chart objects so create the chart root before
+ // let us disable this call for now
+ // TODO:moggi
+ // ShapeFactory::getOrCreateShapeFactory(getShapeFactory())->getOrCreateChartRootShape( m_xMainDrawPage );
+ return m_xMainDrawPage;
+}
+
+const rtl::Reference<SvxDrawPage> & DrawModelWrapper::getHiddenDrawPage()
+{
+ if( !m_xHiddenDrawPage.is() )
+ {
+ uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSuplier( getUnoModel(), uno::UNO_QUERY );
+ if( xDrawPagesSuplier.is() )
+ {
+ uno::Reference< drawing::XDrawPages > xDrawPages( xDrawPagesSuplier->getDrawPages () );
+ if( xDrawPages->getCount()>1 )
+ {
+ uno::Any aPage = xDrawPages->getByIndex( 1 ) ;
+ uno::Reference<drawing::XDrawPage> xTmp;
+ aPage >>= xTmp;
+ m_xHiddenDrawPage = dynamic_cast<SvxDrawPage*>(xTmp.get());
+ assert(m_xHiddenDrawPage);
+ }
+
+ if(!m_xHiddenDrawPage.is())
+ {
+ if( xDrawPages->getCount()==0 )
+ {
+ m_xMainDrawPage = dynamic_cast<SvxDrawPage*>(xDrawPages->insertNewByIndex( 0 ).get());
+ assert(m_xMainDrawPage);
+ }
+ m_xHiddenDrawPage = dynamic_cast<SvxDrawPage*>(xDrawPages->insertNewByIndex( 1 ).get());
+ assert(m_xHiddenDrawPage);
+ }
+ }
+ }
+ return m_xHiddenDrawPage;
+}
+void DrawModelWrapper::clearMainDrawPage()
+{
+ //uno::Reference<drawing::XShapes> xChartRoot( m_xMainDrawPage, uno::UNO_QUERY );
+ rtl::Reference<SvxShapeGroupAnyD> xChartRoot( ShapeFactory::getChartRootShape( m_xMainDrawPage ) );
+ if( xChartRoot.is() )
+ {
+ sal_Int32 nSubCount = xChartRoot->getCount();
+ uno::Reference< drawing::XShape > xShape;
+ for( sal_Int32 nS = nSubCount; nS--; )
+ {
+ if( xChartRoot->getByIndex( nS ) >>= xShape )
+ xChartRoot->remove( xShape );
+ }
+ }
+}
+
+rtl::Reference<SvxShapeGroupAnyD> DrawModelWrapper::getChartRootShape( const rtl::Reference<SvxDrawPage>& xDrawPage )
+{
+ return ShapeFactory::getChartRootShape( xDrawPage );
+}
+
+void DrawModelWrapper::lockControllers()
+{
+ uno::Reference< frame::XModel > xDrawModel( getUnoModel() );
+ if( xDrawModel.is())
+ xDrawModel->lockControllers();
+}
+void DrawModelWrapper::unlockControllers()
+{
+ uno::Reference< frame::XModel > xDrawModel( getUnoModel() );
+ if( xDrawModel.is())
+ xDrawModel->unlockControllers();
+}
+
+OutputDevice* DrawModelWrapper::getReferenceDevice() const
+{
+ return SdrModel::GetRefDevice();
+}
+
+SfxItemPool& DrawModelWrapper::GetItemPool()
+{
+ return SdrModel::GetItemPool();
+}
+XColorListRef DrawModelWrapper::GetColorList() const
+{
+ return SdrModel::GetColorList();
+}
+XDashListRef DrawModelWrapper::GetDashList() const
+{
+ return SdrModel::GetDashList();
+}
+XLineEndListRef DrawModelWrapper::GetLineEndList() const
+{
+ return SdrModel::GetLineEndList();
+}
+XGradientListRef DrawModelWrapper::GetGradientList() const
+{
+ return SdrModel::GetGradientList();
+}
+XHatchListRef DrawModelWrapper::GetHatchList() const
+{
+ return SdrModel::GetHatchList();
+}
+XBitmapListRef DrawModelWrapper::GetBitmapList() const
+{
+ return SdrModel::GetBitmapList();
+}
+
+XPatternListRef DrawModelWrapper::GetPatternList() const
+{
+ return SdrModel::GetPatternList();
+}
+
+SdrObject* DrawModelWrapper::getNamedSdrObject( const OUString& rName )
+{
+ if( rName.isEmpty() )
+ return nullptr;
+ return getNamedSdrObject( rName, GetPage(0) );
+}
+
+SdrObject* DrawModelWrapper::getNamedSdrObject( const OUString& rObjectCID, SdrObjList const * pSearchList )
+{
+ if(!pSearchList || rObjectCID.isEmpty())
+ return nullptr;
+ for (const rtl::Reference<SdrObject>& pObj : *pSearchList)
+ {
+ if( ObjectIdentifier::areIdenticalObjects( rObjectCID, pObj->GetName() ) )
+ return pObj.get();
+ SdrObject* pNamedObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, pObj->GetSubList() );
+ if(pNamedObj)
+ return pNamedObj;
+ }
+ return nullptr;
+}
+
+bool DrawModelWrapper::removeShape( const rtl::Reference<SvxShape>& xShape )
+{
+ uno::Reference<drawing::XShapes> xShapes( xShape->getParent(), uno::UNO_QUERY );
+ if( xShapes.is() )
+ {
+ xShapes->remove(xShape);
+ return true;
+ }
+ return false;
+}
+
+void DrawModelWrapper::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("DrawModelWrapper"));
+ (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
+
+ SdrModel::dumpAsXml(pWriter);
+
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/ExplicitValueProvider.cxx b/chart2/source/view/main/ExplicitValueProvider.cxx
new file mode 100644
index 0000000000..52f259d341
--- /dev/null
+++ b/chart2/source/view/main/ExplicitValueProvider.cxx
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <chartview/ExplicitValueProvider.hxx>
+#include <AxisHelper.hxx>
+#include <ChartModel.hxx>
+#include <Diagram.hxx>
+#include <DiagramHelper.hxx>
+#include <unonames.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include <TitleHelper.hxx>
+#include <ObjectIdentifier.hxx>
+
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+constexpr sal_Int32 constDiagramTitleSpace = 200; //=0,2 cm spacing
+
+bool lcl_getPropertySwapXAndYAxis(const rtl::Reference<Diagram>& xDiagram)
+{
+ bool bSwapXAndY = false;
+
+ if (xDiagram.is())
+ {
+ const std::vector<rtl::Reference<BaseCoordinateSystem>>& aCooSysList(
+ xDiagram->getBaseCoordinateSystems());
+ if (!aCooSysList.empty())
+ {
+ try
+ {
+ aCooSysList[0]->getPropertyValue("SwapXAndYAxis") >>= bSwapXAndY;
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ }
+ }
+ return bSwapXAndY;
+}
+
+} // end anonymous namespace
+
+sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
+ const rtl::Reference<::chart::Axis>& xAxis,
+ const rtl::Reference<::chart::BaseCoordinateSystem>& xCorrespondingCoordinateSystem,
+ const rtl::Reference<::chart::ChartModel>& xChartDoc)
+{
+ return AxisHelper::getExplicitNumberFormatKeyForAxis(
+ xAxis, xCorrespondingCoordinateSystem, xChartDoc,
+ true /*bSearchForParallelAxisIfNothingIsFound*/);
+}
+
+sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
+ const uno::Reference<beans::XPropertySet>& xSeriesOrPointProp)
+{
+ sal_Int32 nFormat = 0;
+ if (!xSeriesOrPointProp.is())
+ return nFormat;
+
+ try
+ {
+ xSeriesOrPointProp->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nFormat;
+ }
+ catch (const beans::UnknownPropertyException&)
+ {
+ }
+
+ if (nFormat < 0)
+ nFormat = 0;
+ return nFormat;
+}
+
+sal_Int32 ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
+ const uno::Reference<beans::XPropertySet>& xSeriesOrPointProp,
+ const uno::Reference<util::XNumberFormatsSupplier>& xNumberFormatsSupplier)
+{
+ sal_Int32 nFormat = 0;
+ if (!xSeriesOrPointProp.is())
+ return nFormat;
+ if (!(xSeriesOrPointProp->getPropertyValue("PercentageNumberFormat") >>= nFormat))
+ {
+ nFormat = DiagramHelper::getPercentNumberFormat(xNumberFormatsSupplier);
+ }
+ if (nFormat < 0)
+ nFormat = 0;
+ return nFormat;
+}
+
+awt::Rectangle ExplicitValueProvider::AddSubtractAxisTitleSizes(
+ ChartModel& rModel, ExplicitValueProvider* pChartView, const awt::Rectangle& rPositionAndSize,
+ bool bSubtract)
+{
+ awt::Rectangle aRet(rPositionAndSize);
+
+ //add axis title sizes to the diagram size
+ rtl::Reference<::chart::Title> xTitle_Height(
+ TitleHelper::getTitle(TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, rModel));
+ rtl::Reference<::chart::Title> xTitle_Width(
+ TitleHelper::getTitle(TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, rModel));
+ rtl::Reference<::chart::Title> xSecondTitle_Height(
+ TitleHelper::getTitle(TitleHelper::SECONDARY_X_AXIS_TITLE, rModel));
+ rtl::Reference<::chart::Title> xSecondTitle_Width(
+ TitleHelper::getTitle(TitleHelper::SECONDARY_Y_AXIS_TITLE, rModel));
+ if (xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is()
+ || xSecondTitle_Width.is())
+ {
+ ExplicitValueProvider* pExplicitValueProvider = pChartView;
+ if (pExplicitValueProvider)
+ {
+ //detect whether x axis points into x direction or not
+ if (lcl_getPropertySwapXAndYAxis(rModel.getFirstChartDiagram()))
+ {
+ std::swap(xTitle_Height, xTitle_Width);
+ std::swap(xSecondTitle_Height, xSecondTitle_Width);
+ }
+
+ sal_Int32 nTitleSpaceWidth = 0;
+ sal_Int32 nTitleSpaceHeight = 0;
+ sal_Int32 nSecondTitleSpaceWidth = 0;
+ sal_Int32 nSecondTitleSpaceHeight = 0;
+
+ if (xTitle_Height.is())
+ {
+ OUString aCID_X(
+ ObjectIdentifier::createClassifiedIdentifierForObject(xTitle_Height, &rModel));
+ nTitleSpaceHeight
+ = pExplicitValueProvider->getRectangleOfObject(aCID_X, true).Height;
+ if (nTitleSpaceHeight)
+ nTitleSpaceHeight += constDiagramTitleSpace;
+ }
+ if (xTitle_Width.is())
+ {
+ OUString aCID_Y(
+ ObjectIdentifier::createClassifiedIdentifierForObject(xTitle_Width, &rModel));
+ nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject(aCID_Y, true).Width;
+ if (nTitleSpaceWidth)
+ nTitleSpaceWidth += constDiagramTitleSpace;
+ }
+ if (xSecondTitle_Height.is())
+ {
+ OUString aCID_X(ObjectIdentifier::createClassifiedIdentifierForObject(
+ xSecondTitle_Height, &rModel));
+ nSecondTitleSpaceHeight
+ = pExplicitValueProvider->getRectangleOfObject(aCID_X, true).Height;
+ if (nSecondTitleSpaceHeight)
+ nSecondTitleSpaceHeight += constDiagramTitleSpace;
+ }
+ if (xSecondTitle_Width.is())
+ {
+ OUString aCID_Y(ObjectIdentifier::createClassifiedIdentifierForObject(
+ xSecondTitle_Width, &rModel));
+ nSecondTitleSpaceWidth
+ += pExplicitValueProvider->getRectangleOfObject(aCID_Y, true).Width;
+ if (nSecondTitleSpaceWidth)
+ nSecondTitleSpaceWidth += constDiagramTitleSpace;
+ }
+ if (bSubtract)
+ {
+ aRet.X += nTitleSpaceWidth;
+ aRet.Y += nSecondTitleSpaceHeight;
+ aRet.Width -= (nTitleSpaceWidth + nSecondTitleSpaceWidth);
+ aRet.Height -= (nTitleSpaceHeight + nSecondTitleSpaceHeight);
+ }
+ else
+ {
+ aRet.X -= nTitleSpaceWidth;
+ aRet.Y -= nSecondTitleSpaceHeight;
+ aRet.Width += nTitleSpaceWidth + nSecondTitleSpaceWidth;
+ aRet.Height += nTitleSpaceHeight + nSecondTitleSpaceHeight;
+ }
+ }
+ }
+ return aRet;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/LabelPositionHelper.cxx b/chart2/source/view/main/LabelPositionHelper.cxx
new file mode 100644
index 0000000000..449c5776e4
--- /dev/null
+++ b/chart2/source/view/main/LabelPositionHelper.cxx
@@ -0,0 +1,468 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <LabelPositionHelper.hxx>
+#include <PlottingPositionHelper.hxx>
+#include <PropertyMapper.hxx>
+#include <RelativeSizeHelper.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+
+#include <cmath>
+#include <utility>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+LabelPositionHelper::LabelPositionHelper(
+ sal_Int32 nDimensionCount
+ , rtl::Reference<SvxShapeGroupAnyD> xLogicTarget)
+ : m_nDimensionCount(nDimensionCount)
+ , m_xLogicTarget(std::move(xLogicTarget))
+{
+}
+
+LabelPositionHelper::~LabelPositionHelper()
+{
+}
+
+awt::Point LabelPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D ) const
+{
+ return PlottingPositionHelper::transformSceneToScreenPosition(
+ rScenePosition3D, m_xLogicTarget, m_nDimensionCount );
+}
+
+void LabelPositionHelper::changeTextAdjustment( tAnySequence& rPropValues, const tNameSequence& rPropNames, LabelAlignment eAlignment)
+{
+ //HorizontalAdjustment
+ {
+ drawing::TextHorizontalAdjust eHorizontalAdjust = drawing::TextHorizontalAdjust_CENTER;
+ if( eAlignment==LABEL_ALIGN_RIGHT || eAlignment==LABEL_ALIGN_RIGHT_TOP || eAlignment==LABEL_ALIGN_RIGHT_BOTTOM )
+ eHorizontalAdjust = drawing::TextHorizontalAdjust_LEFT;
+ else if( eAlignment==LABEL_ALIGN_LEFT || eAlignment==LABEL_ALIGN_LEFT_TOP || eAlignment==LABEL_ALIGN_LEFT_BOTTOM )
+ eHorizontalAdjust = drawing::TextHorizontalAdjust_RIGHT;
+ uno::Any* pHorizontalAdjustAny = PropertyMapper::getValuePointer(rPropValues,rPropNames,u"TextHorizontalAdjust");
+ if(pHorizontalAdjustAny)
+ *pHorizontalAdjustAny <<= eHorizontalAdjust;
+ }
+
+ //VerticalAdjustment
+ {
+ drawing::TextVerticalAdjust eVerticalAdjust = drawing::TextVerticalAdjust_CENTER;
+ if( eAlignment==LABEL_ALIGN_TOP || eAlignment==LABEL_ALIGN_RIGHT_TOP || eAlignment==LABEL_ALIGN_LEFT_TOP )
+ eVerticalAdjust = drawing::TextVerticalAdjust_BOTTOM;
+ else if( eAlignment==LABEL_ALIGN_BOTTOM || eAlignment==LABEL_ALIGN_RIGHT_BOTTOM || eAlignment==LABEL_ALIGN_LEFT_BOTTOM )
+ eVerticalAdjust = drawing::TextVerticalAdjust_TOP;
+ uno::Any* pVerticalAdjustAny = PropertyMapper::getValuePointer(rPropValues,rPropNames,u"TextVerticalAdjust");
+ if(pVerticalAdjustAny)
+ *pVerticalAdjustAny <<= eVerticalAdjust;
+ }
+}
+
+static void lcl_doDynamicFontResize( uno::Any* pAOldAndNewFontHeightAny
+ , const awt::Size& rOldReferenceSize
+ , const awt::Size& rNewReferenceSize )
+{
+ double fOldFontHeight = 0;
+ if( pAOldAndNewFontHeightAny && ( *pAOldAndNewFontHeightAny >>= fOldFontHeight ) )
+ {
+ double fNewFontHeight = RelativeSizeHelper::calculate( fOldFontHeight, rOldReferenceSize, rNewReferenceSize );
+ *pAOldAndNewFontHeightAny <<= fNewFontHeight;
+ }
+}
+
+void LabelPositionHelper::doDynamicFontResize( tAnySequence& rPropValues
+ , const tNameSequence& rPropNames
+ , const uno::Reference< beans::XPropertySet >& xAxisModelProps
+ , const awt::Size& rNewReferenceSize
+ )
+{
+ //handle dynamic font resize:
+ awt::Size aOldReferenceSize;
+ if( xAxisModelProps->getPropertyValue( "ReferencePageSize") >>= aOldReferenceSize )
+ {
+ uno::Any* pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, u"CharHeight" );
+ lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize );
+ pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, u"CharHeightAsian" );
+ lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize );
+ pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, u"CharHeightComplex" );
+ lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize );
+ }
+}
+
+namespace
+{
+
+void lcl_correctRotation_Left( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
+{
+ //correct label positions for labels on a left side of something with a right centered alignment
+ double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = -aSize.Height*std::sin( fAnglePi )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = -aSize.Width*std::sin( fAnglePi )/2.0;
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-M_PI_2;
+ rfXCorrection = -aSize.Width *std::sin( beta )
+ -aSize.Height *std::cos( beta )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = -aSize.Width *std::cos( beta )/2.0;
+ else
+ rfYCorrection = -aSize.Width *std::cos( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = fAnglePi - M_PI;
+ rfXCorrection = -aSize.Width *std::cos( beta )
+ -aSize.Height*std::sin( beta )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = aSize.Width *std::sin( beta )/2.0;
+ else
+ rfYCorrection = aSize.Width *std::sin( beta );
+ }
+ else
+ {
+ double beta = 2*M_PI - fAnglePi;
+ rfXCorrection = -aSize.Height*std::sin( beta )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = aSize.Width*std::sin( beta )/2.0;
+ }
+}
+
+void lcl_correctRotation_Right( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
+{
+ //correct label positions for labels on a right side of something with a left centered alignment
+ double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
+ if( fAnglePositiveDegree== 0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = aSize.Height*std::sin( fAnglePi )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = aSize.Width*std::sin( fAnglePi )/2.0;
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = M_PI - fAnglePi;
+ rfXCorrection = aSize.Width *std::cos( beta )
+ + aSize.Height*std::sin( beta )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = aSize.Width *std::sin( beta )/2.0;
+ else
+ rfYCorrection = aSize.Width *std::sin( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*M_PI_2 - fAnglePi;
+ rfXCorrection = aSize.Width *std::sin( beta )
+ +aSize.Height*std::cos( beta )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = -aSize.Width *std::cos( beta )/2.0;
+ else
+ rfYCorrection = -aSize.Width *std::cos( beta );
+ }
+ else
+ {
+ rfXCorrection = aSize.Height*std::sin( 2*M_PI - fAnglePi )/2.0;
+ if( bRotateAroundCenter )
+ rfYCorrection = -aSize.Width*std::sin( 2*M_PI - fAnglePi )/2.0;
+ }
+}
+
+void lcl_correctRotation_Top( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
+{
+ //correct label positions for labels on top of something with a bottom centered alignment
+ double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
+ if( fAnglePositiveDegree== 0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = aSize.Height*std::sin( fAnglePi )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection += aSize.Width*std::cos( fAnglePi )/2.0;
+ rfYCorrection = -aSize.Width*std::sin( fAnglePi )/2.0;
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi - M_PI_2;
+ rfXCorrection = aSize.Height*std::cos( beta )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection -= aSize.Width*std::sin( beta )/2.0;
+ rfYCorrection = -aSize.Width*std::cos( beta )/2.0
+ - aSize.Height*std::sin( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = fAnglePi - M_PI;
+ rfXCorrection = -aSize.Height *std::sin( beta )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection += aSize.Width *std::cos( beta )/2.0;
+ rfYCorrection = -aSize.Width *std::sin( beta )/2.0
+ -aSize.Height *std::cos( beta );
+ }
+ else
+ {
+ rfXCorrection = aSize.Height*std::sin( fAnglePi )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection -= aSize.Width*std::cos( fAnglePi )/2.0;
+ rfYCorrection = aSize.Width*std::sin( fAnglePi )/2.0;
+ }
+}
+
+void lcl_correctRotation_Bottom( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
+{
+ //correct label positions for labels below something with a top centered alignment
+ double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = -aSize.Height*std::sin( fAnglePi )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection -= aSize.Width *std::cos( fAnglePi )/2.0;
+ rfYCorrection = aSize.Width*std::sin( fAnglePi )/2.0;
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-M_PI_2;
+ rfXCorrection = -aSize.Height*std::cos( beta )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection += aSize.Width *std::sin( beta )/2.0;
+ rfYCorrection = aSize.Width *std::cos( beta )/2.0
+ +aSize.Height*std::sin( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*M_PI_2 - fAnglePi;
+ rfXCorrection = aSize.Height*std::cos( beta )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection -= aSize.Width *std::sin( beta )/2.0;
+ rfYCorrection = aSize.Height*std::sin( beta )
+ +aSize.Width*std::cos( beta )/2.0;
+ }
+ else
+ {
+ double beta = 2*M_PI - fAnglePi;
+ rfXCorrection = aSize.Height*std::sin( beta )/2.0;
+ if( !bRotateAroundCenter )
+ rfXCorrection += aSize.Width*std::cos( beta )/2.0;
+ rfYCorrection = aSize.Width*std::sin( beta )/2.0;
+ }
+}
+
+void lcl_correctRotation_Left_Top( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize )
+{
+ //correct position for labels at the left top corner of something with a bottom right alignment
+ double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfYCorrection = -aSize.Width*std::sin( fAnglePi );
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-M_PI_2;
+ rfXCorrection = -aSize.Width*std::sin( beta );
+ rfYCorrection = -aSize.Height*std::sin( beta )
+ -aSize.Width*std::cos( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*M_PI_2 - fAnglePi;
+ rfXCorrection = -aSize.Height*std::cos( beta )
+ -aSize.Width*std::sin( beta );
+ rfYCorrection = -aSize.Height*std::sin( beta );
+ }
+ else
+ {
+ rfXCorrection = aSize.Height*std::sin( fAnglePi );
+ }
+}
+
+void lcl_correctRotation_Left_Bottom( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize )
+{
+ //correct position for labels at the left bottom corner of something with a top right alignment
+ double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = -aSize.Height*std::sin( fAnglePi );
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-M_PI_2;
+ rfXCorrection = -aSize.Width*std::sin( beta )
+ -aSize.Height*std::cos( beta );
+ rfYCorrection = aSize.Height*std::sin( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*M_PI_2 - fAnglePi;
+ rfXCorrection = -aSize.Width*std::sin( beta );
+ rfYCorrection = aSize.Width*std::cos( beta )
+ +aSize.Height*std::sin( beta );
+ }
+ else
+ {
+ rfYCorrection = -aSize.Width*std::sin( fAnglePi );
+ }
+}
+
+void lcl_correctRotation_Right_Top( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize )
+{
+ //correct position for labels at the right top corner of something with a bottom left alignment
+ double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfXCorrection = aSize.Height*std::sin( fAnglePi );
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-M_PI_2;
+ rfXCorrection = aSize.Width*std::sin( beta )
+ +aSize.Height*std::cos( beta );
+ rfYCorrection = -aSize.Height*std::sin( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*M_PI_2 - fAnglePi;
+ rfXCorrection = aSize.Width*std::sin( beta );
+ rfYCorrection = -aSize.Width*std::cos( beta )
+ -aSize.Height*std::sin( beta );
+ }
+ else
+ {
+ rfYCorrection = aSize.Width*std::sin( fAnglePi );
+ }
+}
+
+void lcl_correctRotation_Right_Bottom( double& rfXCorrection, double& rfYCorrection
+ , double fAnglePositiveDegree, const awt::Size& aSize )
+{
+ //correct position for labels at the right bottom corner of something with a top left alignment
+ double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
+ if( fAnglePositiveDegree==0.0 )
+ {
+ }
+ else if( fAnglePositiveDegree<= 90.0 )
+ {
+ rfYCorrection = aSize.Width*std::sin( fAnglePi );
+ }
+ else if( fAnglePositiveDegree<= 180.0 )
+ {
+ double beta = fAnglePi-M_PI_2;
+ rfXCorrection = aSize.Width*std::sin( beta );
+ rfYCorrection = aSize.Height*std::sin( beta )
+ +aSize.Width*std::cos( beta );
+ }
+ else if( fAnglePositiveDegree<= 270.0 )
+ {
+ double beta = 3*M_PI_2 - fAnglePi;
+ rfXCorrection = aSize.Height*std::cos( beta )
+ +aSize.Width*std::sin( beta );
+ rfYCorrection = aSize.Height*std::sin( beta );
+ }
+ else
+ {
+ rfXCorrection = -aSize.Height*std::sin( fAnglePi );
+ }
+}
+
+}//end anonymous namespace
+
+void LabelPositionHelper::correctPositionForRotation( const rtl::Reference<SvxShapeText>& xShape2DText
+ , LabelAlignment eLabelAlignment, const double fRotationAngle, bool bRotateAroundCenter )
+{
+ if( !xShape2DText.is() )
+ return;
+
+ awt::Point aOldPos = xShape2DText->getPosition();
+ awt::Size aSize = xShape2DText->getSize();
+
+ double fYCorrection = 0.0;
+ double fXCorrection = 0.0;
+
+ double fAnglePositiveDegree = fRotationAngle;
+ while(fAnglePositiveDegree<0.0)
+ fAnglePositiveDegree+=360.0;
+
+ switch(eLabelAlignment)
+ {
+ case LABEL_ALIGN_LEFT:
+ lcl_correctRotation_Left( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
+ break;
+ case LABEL_ALIGN_RIGHT:
+ lcl_correctRotation_Right( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
+ break;
+ case LABEL_ALIGN_TOP:
+ lcl_correctRotation_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
+ break;
+ case LABEL_ALIGN_BOTTOM:
+ lcl_correctRotation_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
+ break;
+ case LABEL_ALIGN_LEFT_TOP:
+ lcl_correctRotation_Left_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
+ break;
+ case LABEL_ALIGN_LEFT_BOTTOM:
+ lcl_correctRotation_Left_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
+ break;
+ case LABEL_ALIGN_RIGHT_TOP:
+ lcl_correctRotation_Right_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
+ break;
+ case LABEL_ALIGN_RIGHT_BOTTOM:
+ lcl_correctRotation_Right_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
+ break;
+ default: //LABEL_ALIGN_CENTER
+ break;
+ }
+
+ xShape2DText->setPosition( awt::Point(
+ static_cast<sal_Int32>(aOldPos.X + fXCorrection )
+ , static_cast<sal_Int32>(aOldPos.Y + fYCorrection ) ) );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/Linear3DTransformation.cxx b/chart2/source/view/main/Linear3DTransformation.cxx
new file mode 100644
index 0000000000..0d723ef345
--- /dev/null
+++ b/chart2/source/view/main/Linear3DTransformation.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <Linear3DTransformation.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+ Linear3DTransformation::Linear3DTransformation( const drawing::HomogenMatrix& rHomMatrix, bool bSwapXAndY )
+ : m_Matrix(rHomMatrix)
+ , m_bSwapXAndY(bSwapXAndY)
+{}
+
+Linear3DTransformation::~Linear3DTransformation()
+{}
+
+// ____ XTransformation2 ____
+css::drawing::Position3D Linear3DTransformation::transform(
+ const Sequence< double >& rSourceValues ) const
+{
+ double fX = rSourceValues[0];
+ double fY = rSourceValues[1];
+ double fZ = rSourceValues[2];
+ if(m_bSwapXAndY)
+ std::swap(fX,fY);
+ css::drawing::Position3D aNewVec;
+ double fZwi;
+
+ fZwi = m_Matrix.Line1.Column1 * fX
+ + m_Matrix.Line1.Column2 * fY
+ + m_Matrix.Line1.Column3 * fZ
+ + m_Matrix.Line1.Column4;
+ aNewVec.PositionX = fZwi;
+
+ fZwi = m_Matrix.Line2.Column1 * fX
+ + m_Matrix.Line2.Column2 * fY
+ + m_Matrix.Line2.Column3 * fZ
+ + m_Matrix.Line2.Column4;
+ aNewVec.PositionY = fZwi;
+
+ fZwi = m_Matrix.Line3.Column1 * fX
+ + m_Matrix.Line3.Column2 * fY
+ + m_Matrix.Line3.Column3 * fZ
+ + m_Matrix.Line3.Column4;
+ aNewVec.PositionZ = fZwi;
+
+ fZwi = m_Matrix.Line4.Column1 * fX
+ + m_Matrix.Line4.Column2 * fY
+ + m_Matrix.Line4.Column3 * fZ
+ + m_Matrix.Line4.Column4;
+ if(fZwi != 1.0 && fZwi != 0.0)
+ {
+ aNewVec.PositionX /= fZwi;
+ aNewVec.PositionY /= fZwi;
+ aNewVec.PositionZ /= fZwi;
+ }
+ return aNewVec;
+}
+
+css::drawing::Position3D Linear3DTransformation::transform(
+ const css::drawing::Position3D& rSourceValues ) const
+{
+ double fX = rSourceValues.PositionX;
+ double fY = rSourceValues.PositionY;
+ double fZ = rSourceValues.PositionZ;
+ if(m_bSwapXAndY)
+ std::swap(fX,fY);
+ css::drawing::Position3D aNewVec;
+ double fZwi;
+
+ fZwi = m_Matrix.Line1.Column1 * fX
+ + m_Matrix.Line1.Column2 * fY
+ + m_Matrix.Line1.Column3 * fZ
+ + m_Matrix.Line1.Column4;
+ aNewVec.PositionX = fZwi;
+
+ fZwi = m_Matrix.Line2.Column1 * fX
+ + m_Matrix.Line2.Column2 * fY
+ + m_Matrix.Line2.Column3 * fZ
+ + m_Matrix.Line2.Column4;
+ aNewVec.PositionY = fZwi;
+
+ fZwi = m_Matrix.Line3.Column1 * fX
+ + m_Matrix.Line3.Column2 * fY
+ + m_Matrix.Line3.Column3 * fZ
+ + m_Matrix.Line3.Column4;
+ aNewVec.PositionZ = fZwi;
+
+ fZwi = m_Matrix.Line4.Column1 * fX
+ + m_Matrix.Line4.Column2 * fY
+ + m_Matrix.Line4.Column3 * fZ
+ + m_Matrix.Line4.Column4;
+ if(fZwi != 1.0 && fZwi != 0.0)
+ {
+ aNewVec.PositionX /= fZwi;
+ aNewVec.PositionY /= fZwi;
+ aNewVec.PositionZ /= fZwi;
+ }
+ return aNewVec;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/PlotterBase.cxx b/chart2/source/view/main/PlotterBase.cxx
new file mode 100644
index 0000000000..a706f1600f
--- /dev/null
+++ b/chart2/source/view/main/PlotterBase.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PlotterBase.hxx>
+#include <PlottingPositionHelper.hxx>
+#include <ShapeFactory.hxx>
+#include <osl/diagnose.h>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+PlotterBase::PlotterBase( sal_Int32 nDimensionCount )
+ : m_nDimension(nDimensionCount)
+ , m_pPosHelper(nullptr)
+{
+}
+
+void PlotterBase::initPlotter( const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget
+ , const rtl::Reference<SvxShapeGroupAnyD>& xFinalTarget
+ , const OUString& rCID )
+{
+ OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is(),"no proper initialization parameters");
+ //is only allowed to be called once
+ m_xLogicTarget = xLogicTarget;
+ m_xFinalTarget = xFinalTarget;
+ m_aCID = rCID;
+}
+
+PlotterBase::~PlotterBase()
+{
+}
+
+void PlotterBase::setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis )
+{
+ if (!m_pPosHelper)
+ return;
+
+ OSL_PRECOND(m_nDimension<=static_cast<sal_Int32>(rScales.size()),"Dimension of Plotter does not fit two dimension of given scale sequence");
+ m_pPosHelper->setScales( std::move(rScales), bSwapXAndYAxis );
+}
+
+void PlotterBase::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix)
+{
+ if (!m_pPosHelper)
+ return;
+
+ OSL_PRECOND(m_nDimension==2,"Set this transformation only in case of 2D");
+ if(m_nDimension!=2)
+ return;
+ m_pPosHelper->setTransformationSceneToScreen( rMatrix );
+}
+
+rtl::Reference<SvxShapeGroupAnyD> PlotterBase::createGroupShape(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const OUString& rName )
+{
+ if(m_nDimension==2)
+ {
+ //create and add to target
+ return ShapeFactory::createGroup2D( xTarget, rName );
+ }
+ else
+ {
+ //create and added to target
+ return ShapeFactory::createGroup3D( xTarget, rName );
+ }
+}
+
+bool PlotterBase::isValidPosition( const drawing::Position3D& rPos )
+{
+ if( std::isnan(rPos.PositionX) )
+ return false;
+ if( std::isnan(rPos.PositionY) )
+ return false;
+ if( std::isnan(rPos.PositionZ) )
+ return false;
+ if( std::isinf(rPos.PositionX) )
+ return false;
+ if( std::isinf(rPos.PositionY) )
+ return false;
+ if( std::isinf(rPos.PositionZ) )
+ return false;
+ return true;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/PlottingPositionHelper.cxx b/chart2/source/view/main/PlottingPositionHelper.cxx
new file mode 100644
index 0000000000..dfbf38bbd9
--- /dev/null
+++ b/chart2/source/view/main/PlottingPositionHelper.cxx
@@ -0,0 +1,704 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PlottingPositionHelper.hxx>
+#include <CommonConverters.hxx>
+#include <Linear3DTransformation.hxx>
+#include <VPolarTransformation.hxx>
+#include <ShapeFactory.hxx>
+#include <PropertyMapper.hxx>
+#include <defines.hxx>
+
+#include <com/sun/star/chart/TimeUnit.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+
+#include <rtl/math.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+XTransformation2::~XTransformation2() {}
+
+PlottingPositionHelper::PlottingPositionHelper()
+ : m_bSwapXAndY( false )
+ , m_nXResolution( 1000 )
+ , m_nYResolution( 1000 )
+ , m_nZResolution( 1000 )
+ , m_bMaySkipPointsInRegressionCalculation( true )
+ , m_bDateAxis(false)
+ , m_nTimeResolution( css::chart::TimeUnit::DAY )
+ , m_aNullDate(30,12,1899)
+ , m_fScaledCategoryWidth(1.0)
+ , m_bAllowShiftXAxisPos(false)
+ , m_bAllowShiftZAxisPos(false)
+{
+}
+PlottingPositionHelper::PlottingPositionHelper( const PlottingPositionHelper& rSource )
+ : m_aScales( rSource.m_aScales )
+ , m_aMatrixScreenToScene( rSource.m_aMatrixScreenToScene )
+ // m_xTransformationLogicToScene( nullptr ) //should be recalculated
+ , m_bSwapXAndY( rSource.m_bSwapXAndY )
+ , m_nXResolution( rSource.m_nXResolution )
+ , m_nYResolution( rSource.m_nYResolution )
+ , m_nZResolution( rSource.m_nZResolution )
+ , m_bMaySkipPointsInRegressionCalculation( rSource.m_bMaySkipPointsInRegressionCalculation )
+ , m_bDateAxis( rSource.m_bDateAxis )
+ , m_nTimeResolution( rSource.m_nTimeResolution )
+ , m_aNullDate( rSource.m_aNullDate )
+ , m_fScaledCategoryWidth( rSource.m_fScaledCategoryWidth )
+ , m_bAllowShiftXAxisPos( rSource.m_bAllowShiftXAxisPos )
+ , m_bAllowShiftZAxisPos( rSource.m_bAllowShiftZAxisPos )
+{
+}
+
+PlottingPositionHelper::~PlottingPositionHelper()
+{
+
+}
+
+std::unique_ptr<PlottingPositionHelper> PlottingPositionHelper::clone() const
+{
+ return std::make_unique<PlottingPositionHelper>(*this);
+}
+
+std::unique_ptr<PlottingPositionHelper> PlottingPositionHelper::createSecondaryPosHelper( const ExplicitScaleData& rSecondaryScale )
+{
+ auto pRet = clone();
+ pRet->m_aScales[1]=rSecondaryScale;
+ return pRet;
+}
+
+void PlottingPositionHelper::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix)
+{
+ m_aMatrixScreenToScene = HomogenMatrixToB3DHomMatrix(rMatrix);
+ m_xTransformationLogicToScene = nullptr;
+}
+
+void PlottingPositionHelper::setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis )
+{
+ m_aScales = std::move(rScales);
+ m_bSwapXAndY = bSwapXAndYAxis;
+ m_xTransformationLogicToScene = nullptr;
+}
+
+::chart::XTransformation2* PlottingPositionHelper::getTransformationScaledLogicToScene() const
+{
+ //this is a standard transformation for a cartesian coordinate system
+
+ //transformation from 2) to 4) //@todo 2) and 4) need an ink to a document
+
+ //we need to apply this transformation to each geometric object because of a bug/problem
+ //of the old drawing layer (the UNO_NAME_3D_EXTRUDE_DEPTH is an integer value instead of a double )
+ if(!m_xTransformationLogicToScene)
+ {
+ ::basegfx::B3DHomMatrix aMatrix;
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MinZ = getLogicMinZ();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MaxZ = getLogicMaxZ();
+
+ AxisOrientation nXAxisOrientation = m_aScales[0].Orientation;
+ AxisOrientation nYAxisOrientation = m_aScales[1].Orientation;
+ AxisOrientation nZAxisOrientation = m_aScales[2].Orientation;
+
+ //apply scaling
+ doUnshiftedLogicScaling( &MinX, &MinY, &MinZ );
+ doUnshiftedLogicScaling( &MaxX, &MaxY, &MaxZ);
+
+ if(m_bSwapXAndY)
+ {
+ std::swap(MinX,MinY);
+ std::swap(MaxX,MaxY);
+ std::swap(nXAxisOrientation,nYAxisOrientation);
+ }
+
+ double fWidthX = MaxX - MinX;
+ double fWidthY = MaxY - MinY;
+ double fWidthZ = MaxZ - MinZ;
+
+ double fScaleDirectionX = nXAxisOrientation==AxisOrientation_MATHEMATICAL ? 1.0 : -1.0;
+ double fScaleDirectionY = nYAxisOrientation==AxisOrientation_MATHEMATICAL ? 1.0 : -1.0;
+ double fScaleDirectionZ = nZAxisOrientation==AxisOrientation_MATHEMATICAL ? -1.0 : 1.0;
+
+ double fScaleX = fScaleDirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthX;
+ double fScaleY = fScaleDirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthY;
+ double fScaleZ = fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ;
+
+ aMatrix.scale(fScaleX, fScaleY, fScaleZ);
+
+ if( nXAxisOrientation==AxisOrientation_MATHEMATICAL )
+ aMatrix.translate(-MinX*fScaleX, 0.0, 0.0);
+ else
+ aMatrix.translate(-MaxX*fScaleX, 0.0, 0.0);
+ if( nYAxisOrientation==AxisOrientation_MATHEMATICAL )
+ aMatrix.translate(0.0, -MinY*fScaleY, 0.0);
+ else
+ aMatrix.translate(0.0, -MaxY*fScaleY, 0.0);
+ if( nZAxisOrientation==AxisOrientation_MATHEMATICAL )
+ aMatrix.translate(0.0, 0.0, -MaxZ*fScaleZ);//z direction in draw is reverse mathematical direction
+ else
+ aMatrix.translate(0.0, 0.0, -MinZ*fScaleZ);
+
+ aMatrix = m_aMatrixScreenToScene*aMatrix;
+
+ m_xTransformationLogicToScene.reset(new Linear3DTransformation(B3DHomMatrixToHomogenMatrix( aMatrix ), m_bSwapXAndY));
+ }
+ return m_xTransformationLogicToScene.get();
+}
+
+drawing::Position3D PlottingPositionHelper::transformLogicToScene(
+ double fX, double fY, double fZ, bool bClip ) const
+{
+ doLogicScaling( &fX,&fY,&fZ );
+ if(bClip)
+ clipScaledLogicValues( &fX,&fY,&fZ );
+
+ return transformScaledLogicToScene( fX, fY, fZ, false );
+}
+
+drawing::Position3D PlottingPositionHelper::transformScaledLogicToScene(
+ double fX, double fY, double fZ, bool bClip ) const
+{
+ if( bClip )
+ clipScaledLogicValues( &fX,&fY,&fZ );
+
+ drawing::Position3D aPos( fX, fY, fZ);
+
+ ::chart::XTransformation2* pTransformation =
+ getTransformationScaledLogicToScene();
+ return pTransformation->transform( aPos );
+}
+
+awt::Point PlottingPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D
+ , const rtl::Reference<SvxShapeGroupAnyD>& xSceneTarget
+ , sal_Int32 nDimensionCount )
+{
+ //@todo would like to have a cheaper method to do this transformation
+ awt::Point aScreenPoint( static_cast<sal_Int32>(rScenePosition3D.PositionX), static_cast<sal_Int32>(rScenePosition3D.PositionY) );
+
+ //transformation from scene to screen (only necessary for 3D):
+ if(nDimensionCount==3)
+ {
+ //create 3D anchor shape
+ tPropertyNameMap aDummyPropertyNameMap;
+ rtl::Reference<Svx3DExtrudeObject> xShape3DAnchor = ShapeFactory::createCube( xSceneTarget
+ , rScenePosition3D,drawing::Direction3D(1,1,1)
+ , 0, nullptr, aDummyPropertyNameMap);
+ //get 2D position from xShape3DAnchor
+ aScreenPoint = xShape3DAnchor->getPosition();
+ xSceneTarget->remove(xShape3DAnchor);
+ }
+ return aScreenPoint;
+}
+
+void PlottingPositionHelper::transformScaledLogicToScene( drawing::PolyPolygonShape3D& rPolygon ) const
+{
+ drawing::Position3D aScenePosition;
+ auto SequenceXRange = asNonConstRange(rPolygon.SequenceX);
+ auto SequenceYRange = asNonConstRange(rPolygon.SequenceY);
+ auto SequenceZRange = asNonConstRange(rPolygon.SequenceZ);
+ for( sal_Int32 nS = rPolygon.SequenceX.getLength(); nS--;)
+ {
+ auto xValuesRange = asNonConstRange(SequenceXRange[nS]);
+ auto yValuesRange = asNonConstRange(SequenceYRange[nS]);
+ auto zValuesRange = asNonConstRange(SequenceZRange[nS]);
+ for( sal_Int32 nP = SequenceXRange[nS].getLength(); nP--; )
+ {
+ double& fX = xValuesRange[nP];
+ double& fY = yValuesRange[nP];
+ double& fZ = zValuesRange[nP];
+ aScenePosition = transformScaledLogicToScene( fX,fY,fZ,true );
+ fX = aScenePosition.PositionX;
+ fY = aScenePosition.PositionY;
+ fZ = aScenePosition.PositionZ;
+ }
+ }
+}
+
+void PlottingPositionHelper::transformScaledLogicToScene( std::vector<std::vector<css::drawing::Position3D>>& rPolygon ) const
+{
+ drawing::Position3D aScenePosition;
+ for( sal_Int32 nS = static_cast<sal_Int32>(rPolygon.size()); nS--;)
+ {
+ auto valuesRange = rPolygon[nS].data();
+ for( sal_Int32 nP = rPolygon[nS].size(); nP--; )
+ {
+ double& fX = valuesRange[nP].PositionX;
+ double& fY = valuesRange[nP].PositionY;
+ double& fZ = valuesRange[nP].PositionZ;
+ aScenePosition = transformScaledLogicToScene( fX,fY,fZ,true );
+ fX = aScenePosition.PositionX;
+ fY = aScenePosition.PositionY;
+ fZ = aScenePosition.PositionZ;
+ }
+ }
+}
+
+void PlottingPositionHelper::clipScaledLogicValues( double* pX, double* pY, double* pZ ) const
+{
+ //get logic clip values:
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MinZ = getLogicMinZ();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MaxZ = getLogicMaxZ();
+
+ //apply scaling
+ doUnshiftedLogicScaling( &MinX, &MinY, &MinZ );
+ doUnshiftedLogicScaling( &MaxX, &MaxY, &MaxZ);
+
+ if(pX)
+ {
+ if( *pX < MinX )
+ *pX = MinX;
+ else if( *pX > MaxX )
+ *pX = MaxX;
+ }
+ if(pY)
+ {
+ if( *pY < MinY )
+ *pY = MinY;
+ else if( *pY > MaxY )
+ *pY = MaxY;
+ }
+ if(pZ)
+ {
+ if( *pZ < MinZ )
+ *pZ = MinZ;
+ else if( *pZ > MaxZ )
+ *pZ = MaxZ;
+ }
+}
+
+basegfx::B2DRectangle PlottingPositionHelper::getScaledLogicClipDoubleRect() const
+{
+ //get logic clip values:
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MinZ = getLogicMinZ();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MaxZ = getLogicMaxZ();
+
+ //apply scaling
+ doUnshiftedLogicScaling( &MinX, &MinY, &MinZ );
+ doUnshiftedLogicScaling( &MaxX, &MaxY, &MaxZ);
+
+ basegfx::B2DRectangle aRet( MinX, MaxY, MaxX, MinY );
+ return aRet;
+}
+
+drawing::Direction3D PlottingPositionHelper::getScaledLogicWidth() const
+{
+ drawing::Direction3D aRet;
+
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MinZ = getLogicMinZ();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MaxZ = getLogicMaxZ();
+
+ doLogicScaling( &MinX, &MinY, &MinZ );
+ doLogicScaling( &MaxX, &MaxY, &MaxZ);
+
+ aRet.DirectionX = MaxX - MinX;
+ aRet.DirectionY = MaxY - MinY;
+ aRet.DirectionZ = MaxZ - MinZ;
+ return aRet;
+}
+
+PolarPlottingPositionHelper::PolarPlottingPositionHelper()
+ : m_fRadiusOffset(0.0)
+ , m_fAngleDegreeOffset(90.0)
+{
+ m_bMaySkipPointsInRegressionCalculation = false;
+}
+
+PolarPlottingPositionHelper::PolarPlottingPositionHelper( const PolarPlottingPositionHelper& rSource )
+ : PlottingPositionHelper(rSource)
+ , m_fRadiusOffset( rSource.m_fRadiusOffset )
+ , m_fAngleDegreeOffset( rSource.m_fAngleDegreeOffset )
+ , m_aUnitCartesianToScene( rSource.m_aUnitCartesianToScene )
+{
+}
+
+PolarPlottingPositionHelper::~PolarPlottingPositionHelper()
+{
+}
+
+std::unique_ptr<PlottingPositionHelper> PolarPlottingPositionHelper::clone() const
+{
+ return std::make_unique<PolarPlottingPositionHelper>(*this);
+}
+
+void PolarPlottingPositionHelper::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix)
+{
+ PlottingPositionHelper::setTransformationSceneToScreen( rMatrix);
+ m_aUnitCartesianToScene =impl_calculateMatrixUnitCartesianToScene( m_aMatrixScreenToScene );
+}
+void PolarPlottingPositionHelper::setScales( std::vector< ExplicitScaleData >&& rScales, bool bSwapXAndYAxis )
+{
+ PlottingPositionHelper::setScales( std::move(rScales), bSwapXAndYAxis );
+ m_aUnitCartesianToScene =impl_calculateMatrixUnitCartesianToScene( m_aMatrixScreenToScene );
+}
+
+::basegfx::B3DHomMatrix PolarPlottingPositionHelper::impl_calculateMatrixUnitCartesianToScene( const ::basegfx::B3DHomMatrix& rMatrixScreenToScene ) const
+{
+ ::basegfx::B3DHomMatrix aRet;
+
+ if( m_aScales.empty() )
+ return aRet;
+
+ double fTranslate =1.0;
+ double fScale =FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0;
+
+ double fTranslateLogicZ;
+ double fScaleLogicZ;
+ {
+ double fScaleDirectionZ = m_aScales[2].Orientation==AxisOrientation_MATHEMATICAL ? 1.0 : -1.0;
+ double MinZ = getLogicMinZ();
+ double MaxZ = getLogicMaxZ();
+ doLogicScaling( nullptr, nullptr, &MinZ );
+ doLogicScaling( nullptr, nullptr, &MaxZ );
+ double fWidthZ = MaxZ - MinZ;
+
+ if( m_aScales[2].Orientation==AxisOrientation_MATHEMATICAL )
+ fTranslateLogicZ=MinZ;
+ else
+ fTranslateLogicZ=MaxZ;
+ fScaleLogicZ = fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ;
+ }
+
+ double fTranslateX = fTranslate;
+ double fTranslateY = fTranslate;
+ double fTranslateZ = fTranslateLogicZ;
+
+ double fScaleX = fScale;
+ double fScaleY = fScale;
+ double fScaleZ = fScaleLogicZ;
+
+ aRet.translate(fTranslateX, fTranslateY, fTranslateZ);//x first
+ aRet.scale(fScaleX, fScaleY, fScaleZ);//x first
+
+ aRet = rMatrixScreenToScene * aRet;
+ return aRet;
+}
+
+::chart::XTransformation2* PolarPlottingPositionHelper::getTransformationScaledLogicToScene() const
+{
+ if( !m_xTransformationLogicToScene )
+ m_xTransformationLogicToScene.reset(new VPolarTransformation(*this));
+ return m_xTransformationLogicToScene.get();
+}
+
+double PolarPlottingPositionHelper::getWidthAngleDegree( double& fStartLogicValueOnAngleAxis, double& fEndLogicValueOnAngleAxis ) const
+{
+ const ExplicitScaleData& rAngleScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[0];
+ if( rAngleScale.Orientation != AxisOrientation_MATHEMATICAL )
+ std::swap( fStartLogicValueOnAngleAxis, fEndLogicValueOnAngleAxis );
+
+ double fStartAngleDegree = transformToAngleDegree( fStartLogicValueOnAngleAxis );
+ double fEndAngleDegree = transformToAngleDegree( fEndLogicValueOnAngleAxis );
+ double fWidthAngleDegree = fEndAngleDegree - fStartAngleDegree;
+
+ if( ::rtl::math::approxEqual( fStartAngleDegree, fEndAngleDegree )
+ && !::rtl::math::approxEqual( fStartLogicValueOnAngleAxis, fEndLogicValueOnAngleAxis ) )
+ fWidthAngleDegree = 360.0;
+
+ // tdf#123504: both 0 and 360 are valid and different values here!
+ while (fWidthAngleDegree < 0.0)
+ fWidthAngleDegree += 360.0;
+ while (fWidthAngleDegree > 360.0)
+ fWidthAngleDegree -= 360.0;
+
+ return fWidthAngleDegree;
+}
+
+//This method does a lot of computation for understanding which scale to
+//utilize and if reverse orientation should be used. Indeed, for a pie or donut,
+//the final result is as simple as multiplying by 360 and adding
+//`m_fAngleDegreeOffset`.
+double PolarPlottingPositionHelper::transformToAngleDegree( double fLogicValueOnAngleAxis, bool bDoScaling ) const
+{
+ double fRet=0.0;
+
+ double fAxisAngleScaleDirection = 1.0;
+ {
+ const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[0];
+ if(rScale.Orientation != AxisOrientation_MATHEMATICAL)
+ fAxisAngleScaleDirection *= -1.0;
+ }
+
+ double MinAngleValue = 0.0;
+ double MaxAngleValue = 0.0;
+ {
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ double MinZ = getLogicMinZ();
+ double MaxZ = getLogicMaxZ();
+
+ doLogicScaling( &MinX, &MinY, &MinZ );
+ doLogicScaling( &MaxX, &MaxY, &MaxZ);
+
+ MinAngleValue = m_bSwapXAndY ? MinY : MinX;
+ MaxAngleValue = m_bSwapXAndY ? MaxY : MaxX;
+ }
+
+ double fScaledLogicAngleValue = 0.0;
+ if(bDoScaling)
+ {
+ double fX = m_bSwapXAndY ? getLogicMaxX() : fLogicValueOnAngleAxis;
+ double fY = m_bSwapXAndY ? fLogicValueOnAngleAxis : getLogicMaxY();
+ double fZ = getLogicMaxZ();
+ clipLogicValues( &fX, &fY, &fZ );
+ doLogicScaling( &fX, &fY, &fZ );
+ fScaledLogicAngleValue = m_bSwapXAndY ? fY : fX;
+ }
+ else
+ fScaledLogicAngleValue = fLogicValueOnAngleAxis;
+
+ fRet = m_fAngleDegreeOffset
+ + fAxisAngleScaleDirection*(fScaledLogicAngleValue-MinAngleValue)*360.0
+ /fabs(MaxAngleValue-MinAngleValue);
+ // tdf#123504: both 0 and 360 are valid and different values here!
+ while (fRet > 360.0)
+ fRet -= 360.0;
+ while (fRet < 0)
+ fRet += 360.0;
+ return fRet;
+}
+
+/**
+ * Given a value in the radius axis scale range, it returns, in the simplest
+ * case (that is when `m_fRadiusOffset` is zero), the normalized value; when
+ * `m_fRadiusOffset` is not zero (e.g. as in the case of a donut), the interval
+ * used for normalization is extended by `m_fRadiusOffset`: if the axis
+ * orientation is not reversed the new interval becomes
+ * [scale.Minimum - m_fRadiusOffset, scale.Maximum] else it becomes
+ * [scale.Minimum, scale.Maximum + m_fRadiusOffset].
+ * Pay attention here! For the latter case, since the axis orientation is
+ * reversed, the normalization is reversed too. Indeed, we have
+ * `transformToRadius(scale.Maximum + m_fRadiusOffset) = 0` and
+ * `transformToRadius(scale.Minimum) = 1`.
+ *
+ * For a pie chart the radius axis scale range is initialized by the
+ * `getMinimum` and `getMaximum` methods of the `PieChart` object (see notes
+ * for `VCoordinateSystem::prepareAutomaticAxisScaling`).
+ * So we have scale.Minimum = 0.5 (always constant!) and
+ * scale.Maximum = 0.5 + number_of_rings + max_offset
+ * (see notes for `PieChart::getMaxOffset`).
+ * Hence we get the following general formulas for computing normalized inner
+ * and outer radius:
+ *
+ * 1- transformToRadius(inner_radius) =
+ * (number_of_rings - (ring_index + 1) + m_fRadiusOffset)
+ * / (number_of_rings + max_offset + m_fRadiusOffset)
+ *
+ * 2- transformToRadius(outer_radius) =
+ * (1 + number_of_rings - (ring_index + 1) + m_fRadiusOffset)
+ * / (number_of_rings + max_offset + m_fRadiusOffset).
+ *
+ * Here you have to take into account that values for inner and outer radius
+ * are swapped since the radius axis is reversed (See notes for
+ * `PiePositionHelper::getInnerAndOuterRadius`). So indeed inner_radius is
+ * the outer and outer_radius is the inner. Anyway still because of the reverse
+ * orientation, the normalization performed by `transformToRadius` is reversed
+ * too, as we have seen above. Hence `transformToRadius(inner_radius)` is
+ * really the normalized inner radius and `transformToRadius(outer_radius)` is
+ * really the normalized outer radius.
+ *
+ * Some basic examples where we apply the above formulas:
+ * 1- For a non-exploded pie chart we have:
+ * `transformToRadius(inner_radius) = 0`,
+ * `transformToRadius(outer_radius) = 1`.
+ * 2- For a non-exploded donut with a single ring we have:
+ * `transformToRadius(inner_radius) =
+ * m_fRadiusOffset/(1 + m_fRadiusOffset)`,
+ * `transformToRadius(outer_radius) =
+ * (1 + m_fRadiusOffset)/(1 + m_fRadiusOffset) = 1`.
+ * 3- For an exploded pie chart we have:
+ * `transformToRadius(inner_radius) = 0/(1 + max_offset) = 0`,
+ * `transformToRadius(outer_radius) = 1/(1 + max_offset)`.
+ *
+ * The third example needs some remark. Both the logical inner and outer
+ * radius passed to `transformToRadius` are offset by `max_offset`.
+ * However the returned normalized values do not contain any (normalized)
+ * offset term at all, otherwise the returned values would be
+ * `max_offset/(1 + max_offset)` and `1`. Hence, for exploded pie/donut,
+ * `transformToRadius` returns the normalized value of radii without any
+ * offset term. These values are smaller than in the non-exploded case by an
+ * amount equals to the value of the normalized maximum offset
+ * (`max_offset/(1 + max_offset)` in the example above). That is due to the
+ * fact that the normalization keeps into account the space needed for the
+ * offset. This is the correct behavior, in fact the offset for the current
+ * slice could be different from the maximum offset.
+ * These remarks should clarify why the `PieChart::createDataPoint` and
+ * `PieChart::createTextLabelShape` methods add the normalized offset (for the
+ * current slice) to the normalized radii in order to achieve the correct
+ * placement of slice and text shapes.
+ */
+double PolarPlottingPositionHelper::transformToRadius( double fLogicValueOnRadiusAxis, bool bDoScaling ) const
+{
+ double fNormalRadius = 0.0;
+ {
+ double fScaledLogicRadiusValue = 0.0;
+ double fX = m_bSwapXAndY ? fLogicValueOnRadiusAxis: getLogicMaxX();
+ double fY = m_bSwapXAndY ? getLogicMaxY() : fLogicValueOnRadiusAxis;
+ if(bDoScaling)
+ doLogicScaling( &fX, &fY, nullptr );
+
+ fScaledLogicRadiusValue = m_bSwapXAndY ? fX : fY;
+
+ bool bMinIsInnerRadius = true;
+ const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
+ if(rScale.Orientation != AxisOrientation_MATHEMATICAL)
+ bMinIsInnerRadius = false;
+
+ double fInnerScaledLogicRadius=0.0;
+ double fOuterScaledLogicRadius=0.0;
+ {
+ double MinX = getLogicMinX();
+ double MinY = getLogicMinY();
+ doLogicScaling( &MinX, &MinY, nullptr );
+ double MaxX = getLogicMaxX();
+ double MaxY = getLogicMaxY();
+ doLogicScaling( &MaxX, &MaxY, nullptr );
+
+ double fMin = m_bSwapXAndY ? MinX : MinY;
+ double fMax = m_bSwapXAndY ? MaxX : MaxY;
+
+ fInnerScaledLogicRadius = bMinIsInnerRadius ? fMin : fMax;
+ fOuterScaledLogicRadius = bMinIsInnerRadius ? fMax : fMin;
+ }
+
+ if( bMinIsInnerRadius )
+ fInnerScaledLogicRadius -= fabs(m_fRadiusOffset);
+ else
+ fInnerScaledLogicRadius += fabs(m_fRadiusOffset);
+ fNormalRadius = (fScaledLogicRadiusValue-fInnerScaledLogicRadius)/(fOuterScaledLogicRadius-fInnerScaledLogicRadius);
+ }
+ return fNormalRadius;
+}
+
+drawing::Position3D PolarPlottingPositionHelper::transformLogicToScene( double fX, double fY, double fZ, bool bClip ) const
+{
+ if(bClip)
+ clipLogicValues( &fX,&fY,&fZ );
+ double fLogicValueOnAngleAxis = m_bSwapXAndY ? fY : fX;
+ double fLogicValueOnRadiusAxis = m_bSwapXAndY ? fX : fY;
+ return transformAngleRadiusToScene( fLogicValueOnAngleAxis, fLogicValueOnRadiusAxis, fZ );
+}
+
+drawing::Position3D PolarPlottingPositionHelper::transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const
+{
+ if(bClip)
+ clipScaledLogicValues( &fX,&fY,&fZ );
+ double fLogicValueOnAngleAxis = m_bSwapXAndY ? fY : fX;
+ double fLogicValueOnRadiusAxis = m_bSwapXAndY ? fX : fY;
+ return transformAngleRadiusToScene( fLogicValueOnAngleAxis, fLogicValueOnRadiusAxis, fZ, false );
+}
+drawing::Position3D PolarPlottingPositionHelper::transformUnitCircleToScene( double fUnitAngleDegree, double fUnitRadius
+ , double fLogicZ ) const
+{
+ double fAnglePi = basegfx::deg2rad(fUnitAngleDegree);
+
+ double fX=fUnitRadius*std::cos(fAnglePi);
+ double fY=fUnitRadius*std::sin(fAnglePi);
+ double fZ=fLogicZ;
+
+ //!! applying matrix to vector does ignore translation, so it is important to use a B3DPoint here instead of B3DVector
+ ::basegfx::B3DPoint aPoint(fX,fY,fZ);
+ ::basegfx::B3DPoint aRet = m_aUnitCartesianToScene * aPoint;
+ return B3DPointToPosition3D(aRet);
+}
+
+drawing::Position3D PolarPlottingPositionHelper::transformAngleRadiusToScene( double fLogicValueOnAngleAxis, double fLogicValueOnRadiusAxis, double fLogicZ, bool bDoScaling ) const
+{
+ double fUnitAngleDegree = transformToAngleDegree(fLogicValueOnAngleAxis,bDoScaling);
+ double fUnitRadius = transformToRadius(fLogicValueOnRadiusAxis,bDoScaling);
+
+ return transformUnitCircleToScene( fUnitAngleDegree, fUnitRadius, fLogicZ );
+}
+
+double PolarPlottingPositionHelper::getOuterLogicRadius() const
+{
+ const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
+ if( rScale.Orientation==AxisOrientation_MATHEMATICAL )
+ return rScale.Maximum;
+ else
+ return rScale.Minimum;
+}
+
+bool PlottingPositionHelper::isPercentY() const
+{
+ return m_aScales[1].AxisType==AxisType::PERCENT;
+}
+
+double PlottingPositionHelper::getBaseValueY() const
+{
+ return m_aScales[1].Origin;
+}
+
+void PlottingPositionHelper::setTimeResolution( tools::Long nTimeResolution, const Date& rNullDate )
+{
+ m_nTimeResolution = nTimeResolution;
+ m_aNullDate = rNullDate;
+
+ //adapt category width
+ double fCategoryWidth = 1.0;
+ if( !m_aScales.empty() )
+ {
+ if( m_aScales[0].AxisType == css::chart2::AxisType::DATE )
+ {
+ m_bDateAxis = true;
+ if( nTimeResolution == css::chart::TimeUnit::YEAR )
+ {
+ const double fMonthCount = 12.0;//todo: this depends on the DateScaling and must be adjusted in case we use more generic calendars in future
+ fCategoryWidth = fMonthCount;
+ }
+ }
+ }
+ setScaledCategoryWidth(fCategoryWidth);
+}
+
+void PlottingPositionHelper::setScaledCategoryWidth( double fScaledCategoryWidth )
+{
+ m_fScaledCategoryWidth = fScaledCategoryWidth;
+}
+void PlottingPositionHelper::AllowShiftXAxisPos( bool bAllowShift )
+{
+ m_bAllowShiftXAxisPos = bAllowShift;
+}
+void PlottingPositionHelper::AllowShiftZAxisPos( bool bAllowShift )
+{
+ m_bAllowShiftZAxisPos = bAllowShift;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/PolarLabelPositionHelper.cxx b/chart2/source/view/main/PolarLabelPositionHelper.cxx
new file mode 100644
index 0000000000..d5c819954a
--- /dev/null
+++ b/chart2/source/view/main/PolarLabelPositionHelper.cxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PolarLabelPositionHelper.hxx>
+#include <PlottingPositionHelper.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+PolarLabelPositionHelper::PolarLabelPositionHelper(
+ PolarPlottingPositionHelper* pPosHelper
+ , sal_Int32 nDimensionCount
+ , const rtl::Reference<SvxShapeGroupAnyD>& xLogicTarget )
+ : LabelPositionHelper( nDimensionCount, xLogicTarget )
+ , m_pPosHelper(pPosHelper)
+{
+}
+
+PolarLabelPositionHelper::~PolarLabelPositionHelper()
+{
+}
+
+awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForLogicValues(
+ LabelAlignment& rAlignment
+ , double fLogicValueOnAngleAxis
+ , double fLogicValueOnRadiusAxis
+ , double fLogicZ
+ , sal_Int32 nScreenValueOffsetInRadiusDirection ) const
+{
+ double fUnitCircleAngleDegree = m_pPosHelper->transformToAngleDegree( fLogicValueOnAngleAxis );
+ double fUnitCircleRadius = m_pPosHelper->transformToRadius( fLogicValueOnRadiusAxis );
+
+ return getLabelScreenPositionAndAlignmentForUnitCircleValues(
+ rAlignment, css::chart::DataLabelPlacement::OUTSIDE
+ , fUnitCircleAngleDegree, 0.0
+ , fUnitCircleRadius, fUnitCircleRadius, fLogicZ, nScreenValueOffsetInRadiusDirection );
+}
+
+awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCircleValues(
+ LabelAlignment& rAlignment, sal_Int32 nLabelPlacement
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , double fLogicZ
+ , sal_Int32 nScreenValueOffsetInRadiusDirection ) const
+{
+ bool bCenter = (nLabelPlacement != css::chart::DataLabelPlacement::OUTSIDE)
+ && (nLabelPlacement != css::chart::DataLabelPlacement::INSIDE);
+
+ double fAngleDegree = fUnitCircleStartAngleDegree + fUnitCircleWidthAngleDegree/2.0;
+ double fRadius = 0.0;
+ if( !bCenter ) //e.g. for pure pie chart(one ring only) or for angle axis of polar coordinate system
+ fRadius = fUnitCircleOuterRadius;
+ else
+ fRadius = fUnitCircleInnerRadius + (fUnitCircleOuterRadius-fUnitCircleInnerRadius)/2.0 ;
+
+ awt::Point aRet( transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, fLogicZ+0.5 ) ) );
+
+ if(m_nDimensionCount==3 && nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE)
+ {
+ //check whether the upper or the downer edge is more distant from the center
+ //take the farthest point to put the label to
+
+ awt::Point aP0( transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene( 0, 0, fLogicZ ) ) );
+ awt::Point aP1(aRet);
+ awt::Point aP2( transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, fLogicZ-0.5 ) ) );
+
+ ::basegfx::B2DVector aV0( aP0.X, aP0.Y );
+ ::basegfx::B2DVector aV1( aP1.X, aP1.Y );
+ ::basegfx::B2DVector aV2( aP2.X, aP2.Y );
+
+ double fL1 = ::basegfx::B2DVector(aV1-aV0).getLength();
+ double fL2 = ::basegfx::B2DVector(aV2-aV0).getLength();
+
+ if(fL2>fL1)
+ aRet = aP2;
+
+ //calculate new angle for alignment
+ double fDX = aRet.X-aP0.X;
+ double fDY = aRet.Y-aP0.Y;
+ fDY*=-1.0;//drawing layer has inverse y values
+
+ fAngleDegree = basegfx::rad2deg(atan2(fDY,fDX));
+ }
+ //set LabelAlignment
+ if( !bCenter )
+ {
+ // tdf#123504: both 0 and 360 are valid and different values here!
+ while (fAngleDegree > 360.0)
+ fAngleDegree -= 360.0;
+ while (fAngleDegree < 0.0)
+ fAngleDegree += 360.0;
+
+ bool bOutside = nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE;
+
+ if (fAngleDegree <= 5 || fAngleDegree >= 355)
+ rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
+ else if (fAngleDegree < 85)
+ rAlignment = bOutside ? LABEL_ALIGN_RIGHT_TOP : LABEL_ALIGN_LEFT_BOTTOM;
+ else if (fAngleDegree <= 95)
+ rAlignment = bOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
+ else if (fAngleDegree < 175)
+ rAlignment = bOutside ? LABEL_ALIGN_LEFT_TOP : LABEL_ALIGN_RIGHT_BOTTOM;
+ else if (fAngleDegree <= 185)
+ rAlignment = bOutside ? LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
+ else if (fAngleDegree < 265)
+ rAlignment = bOutside ? LABEL_ALIGN_LEFT_BOTTOM : LABEL_ALIGN_RIGHT_TOP;
+ else if (fAngleDegree <= 275)
+ rAlignment = bOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
+ else
+ rAlignment = bOutside ? LABEL_ALIGN_RIGHT_BOTTOM : LABEL_ALIGN_LEFT_TOP;
+ }
+ else
+ {
+ rAlignment = LABEL_ALIGN_CENTER;
+ }
+
+ //add a scaling independent Offset if requested
+ if( nScreenValueOffsetInRadiusDirection != 0)
+ {
+ awt::Point aOrigin( transformSceneToScreenPosition(
+ m_pPosHelper->transformUnitCircleToScene( 0.0, 0.0, fLogicZ+0.5 ) ) );
+ basegfx::B2IVector aDirection( aRet.X- aOrigin.X, aRet.Y- aOrigin.Y );
+ aDirection.setLength(nScreenValueOffsetInRadiusDirection);
+ aRet.X += aDirection.getX();
+ aRet.Y += aDirection.getY();
+ }
+
+ return aRet;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/PropertyMapper.cxx b/chart2/source/view/main/PropertyMapper.cxx
new file mode 100644
index 0000000000..c324104905
--- /dev/null
+++ b/chart2/source/view/main/PropertyMapper.cxx
@@ -0,0 +1,561 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <PropertyMapper.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <svx/unoshape.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+void PropertyMapper::setMappedProperties(
+ SvxShape& xTarget
+ , const uno::Reference< beans::XPropertySet >& xSource
+ , const tPropertyNameMap& rMap )
+{
+ if( !xSource.is() )
+ return;
+
+ sal_Int32 nPropertyCount = rMap.size();
+ tNameSequence aNames(nPropertyCount);
+ tAnySequence aValues(nPropertyCount);
+ auto pNames = aNames.getArray();
+ auto pValues = aValues.getArray();
+ sal_Int32 nN=0;
+
+ for (auto const& elem : rMap)
+ {
+ const OUString & rTarget = elem.first;
+ const OUString & rSource = elem.second;
+ try
+ {
+ uno::Any aAny( xSource->getPropertyValue(rSource) );
+ if( aAny.hasValue() )
+ {
+ //do not set empty anys because of performance (otherwise SdrAttrObj::ItemChange will take much longer)
+ pNames[nN] = rTarget;
+ pValues[nN] = std::move(aAny);
+ ++nN;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ if (nN == 0)
+ return;
+ //reduce to real property count
+ aNames.realloc(nN);
+ aValues.realloc(nN);
+
+ uno::Reference< beans::XMultiPropertySet > xShapeMultiProp( xTarget, uno::UNO_QUERY_THROW );
+ try
+ {
+ xShapeMultiProp->setPropertyValues( aNames, aValues );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" ); //if this occurs more often think of removing the XMultiPropertySet completely for better performance
+ }
+}
+
+void PropertyMapper::setMappedProperties(
+ const uno::Reference< beans::XPropertySet >& xTarget
+ , const uno::Reference< beans::XPropertySet >& xSource
+ , const tPropertyNameMap& rMap )
+{
+ if( !xTarget.is() || !xSource.is() )
+ return;
+
+ tNameSequence aNames;
+ tAnySequence aValues;
+ sal_Int32 nN=0;
+ sal_Int32 nPropertyCount = rMap.size();
+ aNames.realloc(nPropertyCount);
+ auto pNames = aNames.getArray();
+ aValues.realloc(nPropertyCount);
+ auto pValues = aValues.getArray();
+
+ for (auto const& elem : rMap)
+ {
+ const OUString & rTarget = elem.first;
+ const OUString & rSource = elem.second;
+ try
+ {
+ uno::Any aAny( xSource->getPropertyValue(rSource) );
+ if( aAny.hasValue() )
+ {
+ //do not set empty anys because of performance (otherwise SdrAttrObj::ItemChange will take much longer)
+ pNames[nN] = rTarget;
+ pValues[nN] = aAny;
+ ++nN;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "exception mapping property from " << rSource << " to " << rTarget);
+ }
+ }
+ if (nN == 0)
+ return;
+
+ uno::Reference< beans::XMultiPropertySet > xShapeMultiProp( xTarget, uno::UNO_QUERY );
+ if (xShapeMultiProp)
+ try
+ {
+ //reduce to real property count
+ aNames.realloc(nN);
+ aValues.realloc(nN);
+ xShapeMultiProp->setPropertyValues( aNames, aValues );
+ return; // successful
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" ); //if this occurs more often think of removing the XMultiPropertySet completely for better performance
+ }
+
+ // fall back to one at a time
+ try
+ {
+ for( sal_Int32 i = 0; i < nN; i++ )
+ {
+ try
+ {
+ xTarget->setPropertyValue( aNames[i], aValues[i] );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+void PropertyMapper::getValueMap(
+ tPropertyNameValueMap& rValueMap
+ , const tPropertyNameMap& rNameMap
+ , const uno::Reference< beans::XPropertySet >& xSourceProp
+ )
+{
+ uno::Reference< beans::XMultiPropertySet > xMultiPropSet(xSourceProp, uno::UNO_QUERY);
+ if((false) && xMultiPropSet.is())
+ {
+ uno::Sequence< OUString > aPropSourceNames(rNameMap.size());
+ auto aPropSourceNamesRange = asNonConstRange(aPropSourceNames);
+ uno::Sequence< OUString > aPropTargetNames(rNameMap.size());
+ auto aPropTargetNamesRange = asNonConstRange(aPropTargetNames);
+ sal_Int32 i = 0;
+ for (auto const& elem : rNameMap)
+ {
+ aPropTargetNamesRange[i] = elem.first;
+ aPropSourceNamesRange[i] = elem.second;
+ ++i;
+ }
+
+ uno::Sequence< uno::Any > xValues = xMultiPropSet->getPropertyValues(aPropSourceNames);
+ sal_Int32 n = rNameMap.size();
+ for(i = 0;i < n; ++i)
+ {
+ if( xValues[i].hasValue() )
+ rValueMap.emplace( aPropTargetNames[i], xValues[i] );
+ }
+ }
+ else
+ {
+ for (auto const& elem : rNameMap)
+ {
+ const OUString & rTarget = elem.first;
+ const OUString & rSource = elem.second;
+ try
+ {
+ uno::Any aAny( xSourceProp->getPropertyValue(rSource) );
+ if( aAny.hasValue() )
+ rValueMap.emplace( rTarget, aAny );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ }
+}
+
+void PropertyMapper::getMultiPropertyListsFromValueMap(
+ tNameSequence& rNames
+ , tAnySequence& rValues
+ , const tPropertyNameValueMap& rValueMap
+ )
+{
+ sal_Int32 nPropertyCount = rValueMap.size();
+ rNames.realloc(nPropertyCount);
+ auto pNames = rNames.getArray();
+ rValues.realloc(nPropertyCount);
+ auto pValues = rValues.getArray();
+
+ //fill sequences
+ sal_Int32 nN=0;
+ for (auto const& elem : rValueMap)
+ {
+ const uno::Any& rAny = elem.second;
+ if( rAny.hasValue() )
+ {
+ //do not set empty anys because of performance (otherwise SdrAttrObj::ItemChange will take much longer)
+ pNames[nN] = elem.first;
+ pValues[nN] = rAny;
+ ++nN;
+ }
+ }
+ //reduce to real property count
+ rNames.realloc(nN);
+ rValues.realloc(nN);
+}
+
+uno::Any* PropertyMapper::getValuePointer( tAnySequence& rPropValues
+ , const tNameSequence& rPropNames
+ , std::u16string_view rPropName )
+{
+ sal_Int32 nCount = rPropNames.getLength();
+ for( sal_Int32 nN = 0; nN < nCount; nN++ )
+ {
+ if(rPropNames[nN] == rPropName)
+ return &rPropValues.getArray()[nN];
+ }
+ return nullptr;
+}
+
+uno::Any* PropertyMapper::getValuePointerForLimitedSpace( tAnySequence& rPropValues
+ , const tNameSequence& rPropNames
+ , bool bLimitedHeight)
+{
+ return PropertyMapper::getValuePointer( rPropValues, rPropNames
+ , bLimitedHeight ? OUString("TextMaximumFrameHeight") : OUString("TextMaximumFrameWidth") );
+}
+
+const tPropertyNameMap& PropertyMapper::getPropertyNameMapForCharacterProperties()
+{
+ //shape property -- chart model object property
+ static tPropertyNameMap s_aShapePropertyMapForCharacterProperties{
+ {"CharColor", "CharColor"},
+ {"CharContoured", "CharContoured"},
+ {"CharEmphasis", "CharEmphasis"},//the service style::CharacterProperties describes a property called 'CharEmphasize' which is nowhere implemented
+
+ {"CharFontFamily", "CharFontFamily"},
+ {"CharFontFamilyAsian", "CharFontFamilyAsian"},
+ {"CharFontFamilyComplex", "CharFontFamilyComplex"},
+ {"CharFontCharSet", "CharFontCharSet"},
+ {"CharFontCharSetAsian", "CharFontCharSetAsian"},
+ {"CharFontCharSetComplex", "CharFontCharSetComplex"},
+ {"CharFontName", "CharFontName"},
+ {"CharFontNameAsian", "CharFontNameAsian"},
+ {"CharFontNameComplex", "CharFontNameComplex"},
+ {"CharFontPitch", "CharFontPitch"},
+ {"CharFontPitchAsian", "CharFontPitchAsian"},
+ {"CharFontPitchComplex", "CharFontPitchComplex"},
+ {"CharFontStyleName", "CharFontStyleName"},
+ {"CharFontStyleNameAsian", "CharFontStyleNameAsian"},
+ {"CharFontStyleNameComplex", "CharFontStyleNameComplex"},
+
+ {"CharHeight", "CharHeight"},
+ {"CharHeightAsian", "CharHeightAsian"},
+ {"CharHeightComplex", "CharHeightComplex"},
+ {"CharKerning", "CharKerning"},
+ {"CharLocale", "CharLocale"},
+ {"CharLocaleAsian", "CharLocaleAsian"},
+ {"CharLocaleComplex", "CharLocaleComplex"},
+ {"CharPosture", "CharPosture"},
+ {"CharPostureAsian", "CharPostureAsian"},
+ {"CharPostureComplex", "CharPostureComplex"},
+ {"CharRelief", "CharRelief"},
+ {"CharShadowed", "CharShadowed"},
+ {"CharStrikeout", "CharStrikeout"},
+ {"CharUnderline", "CharUnderline"},
+ {"CharUnderlineColor", "CharUnderlineColor"},
+ {"CharUnderlineHasColor", "CharUnderlineHasColor"},
+ {"CharOverline", "CharOverline"},
+ {"CharOverlineColor", "CharOverlineColor"},
+ {"CharOverlineHasColor", "CharOverlineHasColor"},
+ {"CharWeight", "CharWeight"},
+ {"CharWeightAsian", "CharWeightAsian"},
+ {"CharWeightComplex", "CharWeightComplex"},
+ {"CharWordMode", "CharWordMode"},
+
+ {"WritingMode", "WritingMode"},
+
+ {"ParaIsCharacterDistance", "ParaIsCharacterDistance"}};
+
+ return s_aShapePropertyMapForCharacterProperties;
+}
+
+const tPropertyNameMap& PropertyMapper::getPropertyNameMapForParagraphProperties()
+{
+ //shape property -- chart model object property
+ static tPropertyNameMap s_aShapePropertyMapForParagraphProperties{
+ {"ParaAdjust", "ParaAdjust"},
+ {"ParaBottomMargin", "ParaBottomMargin"},
+ {"ParaIsHyphenation", "ParaIsHyphenation"},
+ {"ParaLastLineAdjust", "ParaLastLineAdjust"},
+ {"ParaLeftMargin", "ParaLeftMargin"},
+ {"ParaRightMargin", "ParaRightMargin"},
+ {"ParaTopMargin", "ParaTopMargin"}};
+ return s_aShapePropertyMapForParagraphProperties;
+}
+
+const tPropertyNameMap& PropertyMapper::getPropertyNameMapForFillProperties()
+{
+ //shape property -- chart model object property
+ static tPropertyNameMap s_aShapePropertyMapForFillProperties{
+ {"FillBackground", "FillBackground"},
+ {"FillBitmapName", "FillBitmapName"},
+ {"FillColor", "FillColor"},
+ {"FillGradientName", "FillGradientName"},
+ {"FillGradientStepCount", "FillGradientStepCount"},
+ {"FillHatchName", "FillHatchName"},
+ {"FillStyle", "FillStyle"},
+ {"FillTransparence", "FillTransparence"},
+ {"FillTransparenceGradientName", "FillTransparenceGradientName"},
+ //bitmap properties
+ {"FillBitmapMode", "FillBitmapMode"},
+ {"FillBitmapSizeX", "FillBitmapSizeX"},
+ {"FillBitmapSizeY", "FillBitmapSizeY"},
+ {"FillBitmapLogicalSize", "FillBitmapLogicalSize"},
+ {"FillBitmapOffsetX", "FillBitmapOffsetX"},
+ {"FillBitmapOffsetY", "FillBitmapOffsetY"},
+ {"FillBitmapRectanglePoint", "FillBitmapRectanglePoint"},
+ {"FillBitmapPositionOffsetX", "FillBitmapPositionOffsetX"},
+ {"FillBitmapPositionOffsetY", "FillBitmapPositionOffsetY"}};
+ return s_aShapePropertyMapForFillProperties;
+}
+
+const tPropertyNameMap& PropertyMapper::getPropertyNameMapForLineProperties()
+{
+ //shape property -- chart model object property
+ static tPropertyNameMap s_aShapePropertyMapForLineProperties{
+ {"LineColor", "LineColor"},
+ {"LineDashName", "LineDashName"},
+ {"LineJoint", "LineJoint"},
+ {"LineStyle", "LineStyle"},
+ {"LineTransparence", "LineTransparence"},
+ {"LineWidth", "LineWidth"},
+ {"LineCap", "LineCap"}};
+ return s_aShapePropertyMapForLineProperties;
+}
+
+namespace {
+ tPropertyNameMap getPropertyNameMapForFillAndLineProperties_() {
+ auto map = PropertyMapper::getPropertyNameMapForFillProperties();
+ auto const & add
+ = PropertyMapper::getPropertyNameMapForLineProperties();
+ map.insert(add.begin(), add.end());
+ return map;
+ }
+}
+const tPropertyNameMap& PropertyMapper::getPropertyNameMapForFillAndLineProperties()
+{
+ static tPropertyNameMap s_aShapePropertyMapForFillAndLineProperties
+ = getPropertyNameMapForFillAndLineProperties_();
+ return s_aShapePropertyMapForFillAndLineProperties;
+}
+
+namespace {
+ tPropertyNameMap getPropertyNameMapForTextShapeProperties_() {
+ auto map = PropertyMapper::getPropertyNameMapForCharacterProperties();
+ auto const & add1
+ = PropertyMapper::getPropertyNameMapForFillProperties();
+ map.insert(add1.begin(), add1.end());
+ auto const & add2
+ = PropertyMapper::getPropertyNameMapForLineProperties();
+ map.insert(add2.begin(), add2.end());
+ return map;
+ }
+}
+const tPropertyNameMap& PropertyMapper::getPropertyNameMapForTextShapeProperties()
+{
+ static tPropertyNameMap s_aShapePropertyMapForTextShapeProperties
+ = getPropertyNameMapForTextShapeProperties_();
+ return s_aShapePropertyMapForTextShapeProperties;
+}
+
+const tPropertyNameMap& PropertyMapper::getPropertyNameMapForLineSeriesProperties()
+{
+ //shape property -- chart model object property
+ static tPropertyNameMap s_aShapePropertyMapForLineSeriesProperties{
+ {"LineColor", "Color"},
+ {"LineDashName", "LineDashName"},
+ {"LineStyle", "LineStyle"},
+ {"LineTransparence", "Transparency"},
+ {"LineWidth", "LineWidth"},
+ {"LineCap", "LineCap"}};
+ return s_aShapePropertyMapForLineSeriesProperties;
+}
+
+namespace {
+ tPropertyNameMap getPropertyNameMapForTextLabelProperties_() {
+ auto map = PropertyMapper::getPropertyNameMapForCharacterProperties();
+ map.insert({
+ {"LineStyle", CHART_UNONAME_LABEL_BORDER_STYLE},
+ {"LineWidth", CHART_UNONAME_LABEL_BORDER_WIDTH},
+ {"LineColor", CHART_UNONAME_LABEL_BORDER_COLOR},
+ {"LineTransparence", CHART_UNONAME_LABEL_BORDER_TRANS},
+ {"FillStyle", CHART_UNONAME_LABEL_FILL_STYLE},
+ {"FillColor", CHART_UNONAME_LABEL_FILL_COLOR},
+ {"FillBackground", CHART_UNONAME_LABEL_FILL_BACKGROUND},
+ {"FillHatchName", CHART_UNONAME_LABEL_FILL_HATCH_NAME}
+ });
+ // fix the spelling!
+ return map;
+ }
+}
+const tPropertyNameMap& PropertyMapper::getPropertyNameMapForTextLabelProperties()
+{
+ // target name (drawing layer) : source name (chart model)
+ static tPropertyNameMap aMap = getPropertyNameMapForTextLabelProperties_();
+ return aMap;
+}
+
+const tPropertyNameMap& PropertyMapper::getPropertyNameMapForFilledSeriesProperties()
+{
+ //shape property -- chart model object property
+ static tPropertyNameMap s_aShapePropertyMapForFilledSeriesProperties{
+ {"FillBackground", "FillBackground"},
+ {"FillBitmapName", "FillBitmapName"},
+ {"FillColor", "Color"},
+ {"FillGradientName", "GradientName"},
+ {"FillGradientStepCount", "GradientStepCount"},
+ {"FillHatchName", "HatchName"},
+ {"FillStyle", "FillStyle"},
+ {"FillTransparence", "Transparency"},
+ {"FillTransparenceGradientName", "TransparencyGradientName"},
+ //bitmap properties
+ {"FillBitmapMode", "FillBitmapMode"},
+ {"FillBitmapSizeX", "FillBitmapSizeX"},
+ {"FillBitmapSizeY", "FillBitmapSizeY"},
+ {"FillBitmapLogicalSize", "FillBitmapLogicalSize"},
+ {"FillBitmapOffsetX", "FillBitmapOffsetX"},
+ {"FillBitmapOffsetY", "FillBitmapOffsetY"},
+ {"FillBitmapRectanglePoint", "FillBitmapRectanglePoint"},
+ {"FillBitmapPositionOffsetX", "FillBitmapPositionOffsetX"},
+ {"FillBitmapPositionOffsetY", "FillBitmapPositionOffsetY"},
+ //line properties
+ {"LineColor", "BorderColor"},
+ {"LineDashName", "BorderDashName"},
+ {"LineStyle", "BorderStyle"},
+ {"LineTransparence", "BorderTransparency"},
+ {"LineWidth", "BorderWidth"},
+ {"LineCap", "LineCap"}};
+ return s_aShapePropertyMapForFilledSeriesProperties;
+}
+
+void PropertyMapper::setMultiProperties(
+ const tNameSequence& rNames
+ , const tAnySequence& rValues
+ , SvxShape& xTarget )
+{
+ try
+ {
+ xTarget.setPropertyValues( rNames, rValues );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" ); //if this occurs more often think of removing the XMultiPropertySet completely for better performance
+ }
+}
+
+void PropertyMapper::getTextLabelMultiPropertyLists(
+ const uno::Reference< beans::XPropertySet >& xSourceProp
+ , tNameSequence& rPropNames, tAnySequence& rPropValues
+ , bool bName
+ , sal_Int32 nLimitedSpace
+ , bool bLimitedHeight
+ , bool bSupportsLabelBorder)
+{
+ //fill character properties into the ValueMap
+ tPropertyNameValueMap aValueMap;
+ tPropertyNameMap const & aNameMap = bSupportsLabelBorder ? PropertyMapper::getPropertyNameMapForTextLabelProperties() : getPropertyNameMapForCharacterProperties();
+
+ PropertyMapper::getValueMap(aValueMap, aNameMap, xSourceProp);
+
+ //some more shape properties apart from character properties, position-matrix and label string
+ aValueMap.emplace( "TextHorizontalAdjust", uno::Any(drawing::TextHorizontalAdjust_CENTER) ); // drawing::TextHorizontalAdjust - needs to be overwritten
+ aValueMap.emplace( "TextVerticalAdjust", uno::Any(drawing::TextVerticalAdjust_CENTER) ); //drawing::TextVerticalAdjust - needs to be overwritten
+ aValueMap.emplace( "TextAutoGrowHeight", uno::Any(true) ); // sal_Bool
+ aValueMap.emplace( "TextAutoGrowWidth", uno::Any(true) ); // sal_Bool
+ aValueMap.emplace( "ParaAdjust", uno::Any(style::ParagraphAdjust_CENTER) ); // style::ParagraphAdjust_CENTER - needs to be overwritten
+ if( bName )
+ aValueMap.emplace( "Name", uno::Any( OUString() ) ); //CID OUString - needs to be overwritten for each point
+
+ if( nLimitedSpace > 0 )
+ {
+ if(bLimitedHeight)
+ aValueMap.emplace( "TextMaximumFrameHeight", uno::Any(nLimitedSpace) ); //sal_Int32
+ else
+ aValueMap.emplace( "TextMaximumFrameWidth", uno::Any(nLimitedSpace) ); //sal_Int32
+ aValueMap.emplace( "ParaIsHyphenation", uno::Any(true) );
+ }
+
+ PropertyMapper::getMultiPropertyListsFromValueMap( rPropNames, rPropValues, aValueMap );
+}
+
+void PropertyMapper::getPreparedTextShapePropertyLists(
+ const uno::Reference< beans::XPropertySet >& xSourceProp
+ , tNameSequence& rPropNames, tAnySequence& rPropValues )
+{
+ //fill character, line and fill properties into the ValueMap
+ tPropertyNameValueMap aValueMap;
+ PropertyMapper::getValueMap( aValueMap
+ , PropertyMapper::getPropertyNameMapForTextShapeProperties()
+ , xSourceProp );
+
+ // auto-grow makes sure the shape has the correct size after setting text
+ aValueMap.emplace( "TextHorizontalAdjust", uno::Any( drawing::TextHorizontalAdjust_CENTER ));
+ aValueMap.emplace( "TextVerticalAdjust", uno::Any( drawing::TextVerticalAdjust_CENTER ));
+ aValueMap.emplace( "TextAutoGrowHeight", uno::Any( true ));
+ aValueMap.emplace( "TextAutoGrowWidth", uno::Any( true ));
+
+ // set some distance to the border, in case it is shown
+ const sal_Int32 nWidthDist = 250;
+ const sal_Int32 nHeightDist = 125;
+ aValueMap.emplace( "TextLeftDistance", uno::Any( nWidthDist ));
+ aValueMap.emplace( "TextRightDistance", uno::Any( nWidthDist ));
+ aValueMap.emplace( "TextUpperDistance", uno::Any( nHeightDist ));
+ aValueMap.emplace( "TextLowerDistance", uno::Any( nHeightDist ));
+
+ // use a line-joint showing the border of thick lines like two rectangles
+ // filled in between.
+ aValueMap["LineJoint"] <<= drawing::LineJoint_ROUND;
+
+ PropertyMapper::getMultiPropertyListsFromValueMap( rPropNames, rPropValues, aValueMap );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/SeriesPlotterContainer.cxx b/chart2/source/view/main/SeriesPlotterContainer.cxx
new file mode 100644
index 0000000000..bcc5b0f482
--- /dev/null
+++ b/chart2/source/view/main/SeriesPlotterContainer.cxx
@@ -0,0 +1,746 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cstddef>
+
+#include "SeriesPlotterContainer.hxx"
+
+#include <ChartView.hxx>
+#include <Diagram.hxx>
+#include <ChartType.hxx>
+#include <DataSeries.hxx>
+#include <ChartModel.hxx>
+#include <ChartTypeHelper.hxx>
+#include <ObjectIdentifier.hxx>
+#include <DiagramHelper.hxx>
+#include <Axis.hxx>
+#include <AxisIndexDefines.hxx>
+#include <DataSeriesHelper.hxx>
+#include <ExplicitCategoriesProvider.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart2/AxisType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include <comphelper/classids.hxx>
+#include <servicenames_charttypes.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::css;
+using namespace ::css::chart2;
+
+using ::css::uno::Reference;
+using ::css::uno::Sequence;
+using ::css::uno::Any;
+
+SeriesPlotterContainer::SeriesPlotterContainer(
+ std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList)
+ : m_rVCooSysList(rVCooSysList)
+ , m_nMaxAxisIndex(0)
+ , m_bChartTypeUsesShiftedCategoryPositionPerDefault(false)
+ , m_nDefaultDateNumberFormat(0)
+{
+}
+
+SeriesPlotterContainer::~SeriesPlotterContainer()
+{
+ // - remove plotter from coordinatesystems
+ for (auto& nC : m_rVCooSysList)
+ nC->clearMinimumAndMaximumSupplierList();
+}
+
+std::vector<LegendEntryProvider*> SeriesPlotterContainer::getLegendEntryProviderList()
+{
+ std::vector<LegendEntryProvider*> aRet(m_aSeriesPlotterList.size());
+ sal_Int32 nN = 0;
+ for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList)
+ aRet[nN++] = aPlotter.get();
+ return aRet;
+}
+
+VCoordinateSystem* SeriesPlotterContainer::findInCooSysList(
+ const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
+ const rtl::Reference<BaseCoordinateSystem>& xCooSys)
+{
+ for (auto& pVCooSys : rVCooSysList)
+ {
+ if (pVCooSys->getModel() == xCooSys)
+ return pVCooSys.get();
+ }
+ return nullptr;
+}
+
+VCoordinateSystem* SeriesPlotterContainer::getCooSysForPlotter(
+ const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
+ MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier)
+{
+ if (!pMinimumAndMaximumSupplier)
+ return nullptr;
+ for (auto& pVCooSys : rVCooSysList)
+ {
+ if (pVCooSys->hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier))
+ return pVCooSys.get();
+ }
+ return nullptr;
+}
+
+VCoordinateSystem* SeriesPlotterContainer::addCooSysToList(
+ std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
+ const rtl::Reference<BaseCoordinateSystem>& xCooSys, ChartModel& rChartModel)
+{
+ VCoordinateSystem* pExistingVCooSys
+ = SeriesPlotterContainer::findInCooSysList(rVCooSysList, xCooSys);
+ if (pExistingVCooSys)
+ return pExistingVCooSys;
+
+ std::unique_ptr<VCoordinateSystem> pVCooSys
+ = VCoordinateSystem::createCoordinateSystem(xCooSys);
+ if (!pVCooSys)
+ return nullptr;
+
+ OUString aCooSysParticle(
+ ObjectIdentifier::createParticleForCoordinateSystem(xCooSys, &rChartModel));
+ pVCooSys->setParticle(aCooSysParticle);
+
+ pVCooSys->setExplicitCategoriesProvider(new ExplicitCategoriesProvider(xCooSys, rChartModel));
+ rVCooSysList.push_back(std::move(pVCooSys));
+ return rVCooSysList.back().get();
+}
+
+void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(ChartModel& rChartModel)
+{
+ rtl::Reference<Diagram> xDiagram = rChartModel.getFirstChartDiagram();
+ if (!xDiagram.is())
+ return;
+
+ uno::Reference<util::XNumberFormatsSupplier> xNumberFormatsSupplier(&rChartModel);
+ if (rChartModel.hasInternalDataProvider() && xDiagram->isSupportingDateAxis())
+ m_nDefaultDateNumberFormat = DiagramHelper::getDateNumberFormat(xNumberFormatsSupplier);
+
+ sal_Int32 nDimensionCount = xDiagram->getDimension();
+ if (!nDimensionCount)
+ {
+ //@todo handle mixed dimension
+ nDimensionCount = 2;
+ }
+
+ bool bSortByXValues = false;
+ bool bConnectBars = false;
+ bool bGroupBarsPerAxis = true;
+ bool bIncludeHiddenCells = true;
+ bool bSecondaryYaxisVisible = true;
+ sal_Int32 nStartingAngle = 90;
+ sal_Int32 n3DRelativeHeight = 100;
+ try
+ {
+ xDiagram->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= bSortByXValues;
+ xDiagram->getPropertyValue("ConnectBars") >>= bConnectBars;
+ xDiagram->getPropertyValue("GroupBarsPerAxis") >>= bGroupBarsPerAxis;
+ xDiagram->getPropertyValue("IncludeHiddenCells") >>= bIncludeHiddenCells;
+ xDiagram->getPropertyValue("StartingAngle") >>= nStartingAngle;
+
+ if (nDimensionCount == 3)
+ {
+ xDiagram->getPropertyValue("3DRelativeHeight") >>= n3DRelativeHeight;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ if (xDiagram->getDataTable().is())
+ m_bForceShiftPosition = true;
+
+ //prepare for autoscaling and shape creation
+ // - create plotter for charttypes (for each first scale group at each plotter, as they are independent)
+ // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling)
+ // - add plotter to coordinate systems
+
+ //iterate through all coordinate systems
+ uno::Reference<XColorScheme> xColorScheme(xDiagram->getDefaultColorScheme());
+ auto aCooSysList = xDiagram->getBaseCoordinateSystems();
+ sal_Int32 nGlobalSeriesIndex = 0; //for automatic symbols
+ for (std::size_t nCS = 0; nCS < aCooSysList.size(); ++nCS)
+ {
+ rtl::Reference<BaseCoordinateSystem> xCooSys(aCooSysList[nCS]);
+ VCoordinateSystem* pVCooSys
+ = SeriesPlotterContainer::addCooSysToList(m_rVCooSysList, xCooSys, rChartModel);
+ // Let's check whether the secondary Y axis is visible
+ try
+ {
+ if (xCooSys->getMaximumAxisIndexByDimension(1) > 0)
+ {
+ rtl::Reference<Axis> xAxisProp = xCooSys->getAxisByDimension2(1, 1);
+ xAxisProp->getPropertyValue("Show") >>= bSecondaryYaxisVisible;
+ }
+ }
+ catch (const lang::IndexOutOfBoundsException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ //iterate through all chart types in the current coordinate system
+ std::vector<rtl::Reference<ChartType>> aChartTypeList(xCooSys->getChartTypes2());
+ for (std::size_t nT = 0; nT < aChartTypeList.size(); ++nT)
+ {
+ rtl::Reference<ChartType> xChartType(aChartTypeList[nT]);
+ if (nDimensionCount == 3
+ && xChartType->getChartType().equalsIgnoreAsciiCase(
+ CHART2_SERVICE_NAME_CHARTTYPE_PIE))
+ {
+ try
+ {
+ sal_Int32 n3DRelativeHeightOldValue(100);
+ uno::Any aAny = xChartType->getFastPropertyValue(
+ PROP_PIECHARTTYPE_3DRELATIVEHEIGHT); // "3DRelativeHeight"
+ aAny >>= n3DRelativeHeightOldValue;
+ if (n3DRelativeHeightOldValue != n3DRelativeHeight)
+ xChartType->setFastPropertyValue(
+ PROP_PIECHARTTYPE_3DRELATIVEHEIGHT, // "3DRelativeHeight"
+ uno::Any(n3DRelativeHeight));
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+
+ if (nT == 0)
+ m_bChartTypeUsesShiftedCategoryPositionPerDefault
+ = ChartTypeHelper::shiftCategoryPosAtXAxisPerDefault(xChartType);
+
+ bool bExcludingPositioning
+ = xDiagram->getDiagramPositioningMode() == DiagramPositioningMode::Excluding;
+ VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter(
+ xChartType, nDimensionCount, bExcludingPositioning);
+ if (!pPlotter)
+ continue;
+
+ m_aSeriesPlotterList.push_back(std::unique_ptr<VSeriesPlotter>(pPlotter));
+ pPlotter->setNumberFormatsSupplier(xNumberFormatsSupplier);
+ pPlotter->setColorScheme(xColorScheme);
+ if (pVCooSys)
+ pPlotter->setExplicitCategoriesProvider(pVCooSys->getExplicitCategoriesProvider());
+ sal_Int32 nMissingValueTreatment
+ = xDiagram->getCorrectedMissingValueTreatment(xChartType);
+
+ if (pVCooSys)
+ pVCooSys->addMinimumAndMaximumSupplier(pPlotter);
+
+ sal_Int32 zSlot = -1;
+ sal_Int32 xSlot = -1;
+ sal_Int32 ySlot = -1;
+ const std::vector<rtl::Reference<DataSeries>>& aSeriesList
+ = xChartType->getDataSeries2();
+ for (std::size_t nS = 0; nS < aSeriesList.size(); ++nS)
+ {
+ rtl::Reference<DataSeries> const& xDataSeries = aSeriesList[nS];
+ if (!bIncludeHiddenCells && !xDataSeries->hasUnhiddenData())
+ continue;
+
+ std::unique_ptr<VDataSeries> pSeries(new VDataSeries(xDataSeries));
+
+ pSeries->setGlobalSeriesIndex(nGlobalSeriesIndex);
+ nGlobalSeriesIndex++;
+
+ if (bSortByXValues)
+ pSeries->doSortByXValues();
+
+ pSeries->setConnectBars(bConnectBars);
+ pSeries->setGroupBarsPerAxis(bGroupBarsPerAxis);
+ pSeries->setStartingAngle(nStartingAngle);
+
+ pSeries->setMissingValueTreatment(nMissingValueTreatment);
+
+ OUString aSeriesParticle(ObjectIdentifier::createParticleForSeries(0, nCS, nT, nS));
+ pSeries->setParticle(aSeriesParticle);
+
+ OUString aRole(ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection(
+ xChartType));
+ pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole);
+
+ //ignore secondary axis for charttypes that do not support them
+ if (pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX
+ && (!ChartTypeHelper::isSupportingSecondaryAxis(xChartType, nDimensionCount)
+ || !bSecondaryYaxisVisible))
+ {
+ pSeries->setAttachedAxisIndex(MAIN_AXIS_INDEX);
+ }
+
+ StackingDirection eDirection = pSeries->getStackingDirection();
+ switch (eDirection)
+ {
+ case StackingDirection_NO_STACKING:
+ xSlot++;
+ ySlot = -1;
+ if (zSlot < 0)
+ zSlot = 0;
+ break;
+ case StackingDirection_Y_STACKING:
+ ySlot++;
+ if (xSlot < 0)
+ xSlot = 0;
+ if (zSlot < 0)
+ zSlot = 0;
+ break;
+ case StackingDirection_Z_STACKING:
+ zSlot++;
+ xSlot = -1;
+ ySlot = -1;
+ break;
+ default:
+ // UNO enums have one additional auto-generated case
+ break;
+ }
+ pPlotter->addSeries(std::move(pSeries), zSlot, xSlot, ySlot);
+ }
+ }
+ }
+
+ //transport seriesnames to the coordinatesystems if needed
+ if (m_aSeriesPlotterList.empty())
+ return;
+
+ uno::Sequence<OUString> aSeriesNames;
+ bool bSeriesNamesInitialized = false;
+ for (auto& pVCooSys : m_rVCooSysList)
+ {
+ if (pVCooSys->needSeriesNamesForAxis())
+ {
+ if (!bSeriesNamesInitialized)
+ {
+ aSeriesNames = m_aSeriesPlotterList[0]->getSeriesNames();
+ bSeriesNamesInitialized = true;
+ }
+ pVCooSys->setSeriesNamesForAxis(aSeriesNames);
+ }
+ }
+}
+
+bool SeriesPlotterContainer::isCategoryPositionShifted(const chart2::ScaleData& rSourceScale,
+ bool bHasComplexCategories)
+{
+ if (m_bForceShiftPosition)
+ return true;
+
+ if (rSourceScale.AxisType == AxisType::CATEGORY)
+ return bHasComplexCategories || rSourceScale.ShiftedCategoryPosition
+ || m_bChartTypeUsesShiftedCategoryPositionPerDefault;
+
+ if (rSourceScale.AxisType == AxisType::DATE)
+ return rSourceScale.ShiftedCategoryPosition;
+
+ return rSourceScale.AxisType == AxisType::SERIES;
+}
+
+void SeriesPlotterContainer::initAxisUsageList(const Date& rNullDate)
+{
+ m_aAxisUsageList.clear();
+
+ // Loop through coordinate systems in the diagram (though for now
+ // there should only be one coordinate system per diagram).
+ for (auto& pVCooSys : m_rVCooSysList)
+ {
+ rtl::Reference<BaseCoordinateSystem> xCooSys = pVCooSys->getModel();
+ sal_Int32 nDimCount = xCooSys->getDimension();
+ bool bComplexCategoryAllowed = ChartTypeHelper::isSupportingComplexCategory(
+ AxisHelper::getChartTypeByIndex(xCooSys, 0));
+
+ for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
+ {
+ bool bDateAxisAllowed = ChartTypeHelper::isSupportingDateAxis(
+ AxisHelper::getChartTypeByIndex(xCooSys, 0), nDimIndex);
+
+ // Each dimension may have primary and secondary axes.
+ const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimIndex);
+ for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaxAxisIndex; ++nAxisIndex)
+ {
+ rtl::Reference<Axis> xAxis = xCooSys->getAxisByDimension2(nDimIndex, nAxisIndex);
+
+ if (!xAxis.is())
+ continue;
+
+ if (m_aAxisUsageList.find(xAxis) == m_aAxisUsageList.end())
+ {
+ // Create axis usage object for this axis.
+
+ chart2::ScaleData aSourceScale = xAxis->getScaleData();
+ ExplicitCategoriesProvider* pCatProvider
+ = pVCooSys->getExplicitCategoriesProvider();
+ if (nDimIndex == 0)
+ AxisHelper::checkDateAxis(aSourceScale, pCatProvider, bDateAxisAllowed);
+
+ bool bHasComplexCat = pCatProvider && pCatProvider->hasComplexCategories()
+ && bComplexCategoryAllowed;
+ aSourceScale.ShiftedCategoryPosition
+ = isCategoryPositionShifted(aSourceScale, bHasComplexCat);
+
+ m_aAxisUsageList[xAxis].aAutoScaling = ScaleAutomatism(aSourceScale, rNullDate);
+ }
+
+ AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis];
+ rAxisUsage.addCoordinateSystem(pVCooSys.get(), nDimIndex, nAxisIndex);
+ }
+ }
+ }
+
+ // Determine the highest axis index of all dimensions.
+ m_nMaxAxisIndex = 0;
+ for (const auto& pVCooSys : m_rVCooSysList)
+ {
+ uno::Reference<XCoordinateSystem> xCooSys = pVCooSys->getModel();
+ sal_Int32 nDimCount = xCooSys->getDimension();
+
+ for (sal_Int32 nDimIndex = 0; nDimIndex < nDimCount; ++nDimIndex)
+ {
+ for (auto& axisUsage : m_aAxisUsageList)
+ {
+ sal_Int32 nLocalMax = axisUsage.second.getMaxAxisIndexForDimension(nDimIndex);
+ if (m_nMaxAxisIndex < nLocalMax)
+ m_nMaxAxisIndex = nLocalMax;
+ }
+ }
+ }
+}
+
+void SeriesPlotterContainer::setScalesFromCooSysToPlotter()
+{
+ //set scales to plotter to enable them to provide the preferred scene AspectRatio
+ for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList)
+ {
+ VSeriesPlotter* pSeriesPlotter = aPlotter.get();
+ VCoordinateSystem* pVCooSys
+ = SeriesPlotterContainer::getCooSysForPlotter(m_rVCooSysList, pSeriesPlotter);
+ if (pVCooSys)
+ {
+ pSeriesPlotter->setScales(pVCooSys->getExplicitScales(0, 0),
+ pVCooSys->getPropertySwapXAndYAxis());
+ sal_Int32 nMaxAxisIndex = pVCooSys->getMaximumAxisIndexByDimension(
+ 1); //only additional value axis are relevant for series plotter
+ for (sal_Int32 nI = 1; nI <= nMaxAxisIndex; nI++)
+ pSeriesPlotter->addSecondaryValueScale(pVCooSys->getExplicitScale(1, nI), nI);
+ }
+ }
+}
+
+void SeriesPlotterContainer::setNumberFormatsFromAxes()
+{
+ //set numberformats to plotter to enable them to display the data labels in the numberformat of the axis
+ for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList)
+ {
+ VSeriesPlotter* pSeriesPlotter = aPlotter.get();
+ VCoordinateSystem* pVCooSys
+ = SeriesPlotterContainer::getCooSysForPlotter(m_rVCooSysList, pSeriesPlotter);
+ if (pVCooSys)
+ {
+ AxesNumberFormats aAxesNumberFormats;
+ const rtl::Reference<BaseCoordinateSystem>& xCooSys = pVCooSys->getModel();
+ sal_Int32 nDimensionCount = xCooSys->getDimension();
+ for (sal_Int32 nDimensionIndex = 0; nDimensionIndex < nDimensionCount;
+ ++nDimensionIndex)
+ {
+ const sal_Int32 nMaximumAxisIndex
+ = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for (sal_Int32 nAxisIndex = 0; nAxisIndex <= nMaximumAxisIndex; ++nAxisIndex)
+ {
+ try
+ {
+ rtl::Reference<Axis> xAxisProp
+ = xCooSys->getAxisByDimension2(nDimensionIndex, nAxisIndex);
+ if (xAxisProp.is())
+ {
+ sal_Int32 nNumberFormatKey(0);
+ if (xAxisProp->getPropertyValue(CHART_UNONAME_NUMFMT)
+ >>= nNumberFormatKey)
+ {
+ aAxesNumberFormats.setFormat(nNumberFormatKey, nDimensionIndex,
+ nAxisIndex);
+ }
+ else if (nDimensionIndex == 0)
+ {
+ //provide a default date format for date axis with own data
+ aAxesNumberFormats.setFormat(m_nDefaultDateNumberFormat,
+ nDimensionIndex, nAxisIndex);
+ }
+ }
+ }
+ catch (const lang::IndexOutOfBoundsException&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ }
+ }
+ }
+ }
+}
+
+void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes()
+{
+ for (auto& nC : m_rVCooSysList)
+ nC->updateScalesAndIncrementsOnAxes();
+}
+
+void SeriesPlotterContainer::doAutoScaling(ChartModel& rChartModel)
+{
+ if (m_aSeriesPlotterList.empty() || m_aAxisUsageList.empty())
+ // We need these two containers populated to do auto-scaling. Bail out.
+ return;
+
+ //iterate over the main scales first than secondary axis
+ for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; ++nAxisIndex)
+ {
+ // - first do autoscale for all x and z scales (because they are treated independent)
+ for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
+ {
+ (void)rAxis;
+ rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 0, nAxisIndex);
+ rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 2, nAxisIndex);
+
+ ExplicitScaleData aExplicitScale;
+ ExplicitIncrementData aExplicitIncrement;
+ rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement(aExplicitScale,
+ aExplicitIncrement);
+
+ rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, aExplicitScale,
+ aExplicitIncrement);
+ rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, aExplicitScale,
+ aExplicitIncrement);
+ }
+
+ // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already )
+ for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
+ {
+ (void)rAxis;
+ rAxisUsage.prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, nAxisIndex);
+
+ ExplicitScaleData aExplicitScale;
+ ExplicitIncrementData aExplicitIncrement;
+ rAxisUsage.aAutoScaling.calculateExplicitScaleAndIncrement(aExplicitScale,
+ aExplicitIncrement);
+
+ rAxisUsage.setExplicitScaleAndIncrement(0, nAxisIndex, aExplicitScale,
+ aExplicitIncrement);
+ rAxisUsage.setExplicitScaleAndIncrement(1, nAxisIndex, aExplicitScale,
+ aExplicitIncrement);
+ rAxisUsage.setExplicitScaleAndIncrement(2, nAxisIndex, aExplicitScale,
+ aExplicitIncrement);
+ }
+ }
+ AdaptScaleOfYAxisWithoutAttachedSeries(rChartModel);
+}
+
+void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries(ChartModel& rModel)
+{
+ //issue #i80518#
+ for (sal_Int32 nAxisIndex = 0; nAxisIndex <= m_nMaxAxisIndex; nAxisIndex++)
+ {
+ for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
+ {
+ (void)rAxis;
+ std::vector<VCoordinateSystem*> aVCooSysList_Y
+ = rAxisUsage.getCoordinateSystems(1, nAxisIndex);
+ if (aVCooSysList_Y.empty())
+ continue;
+
+ rtl::Reference<Diagram> xDiagram(rModel.getFirstChartDiagram());
+ if (!xDiagram.is())
+ continue;
+
+ bool bSeriesAttachedToThisAxis = false;
+ sal_Int32 nAttachedAxisIndex = -1;
+ {
+ std::vector<rtl::Reference<DataSeries>> aSeriesVector = xDiagram->getDataSeries();
+ for (auto const& series : aSeriesVector)
+ {
+ sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex(series);
+ if (nAxisIndex == nCurrentIndex)
+ {
+ bSeriesAttachedToThisAxis = true;
+ break;
+ }
+ else if (nAttachedAxisIndex < 0 || nAttachedAxisIndex > nCurrentIndex)
+ nAttachedAxisIndex = nCurrentIndex;
+ }
+ }
+
+ if (bSeriesAttachedToThisAxis || nAttachedAxisIndex < 0)
+ continue;
+
+ for (VCoordinateSystem* nC : aVCooSysList_Y)
+ {
+ nC->prepareAutomaticAxisScaling(rAxisUsage.aAutoScaling, 1, nAttachedAxisIndex);
+
+ ExplicitScaleData aExplicitScaleSource
+ = nC->getExplicitScale(1, nAttachedAxisIndex);
+ ExplicitIncrementData aExplicitIncrementSource
+ = nC->getExplicitIncrement(1, nAttachedAxisIndex);
+
+ ExplicitScaleData aExplicitScaleDest = nC->getExplicitScale(1, nAxisIndex);
+ ExplicitIncrementData aExplicitIncrementDest
+ = nC->getExplicitIncrement(1, nAxisIndex);
+
+ aExplicitScaleDest.Orientation = aExplicitScaleSource.Orientation;
+ aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling;
+ aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType;
+
+ aExplicitIncrementDest.BaseValue = aExplicitIncrementSource.BaseValue;
+
+ ScaleData aScale(rAxisUsage.aAutoScaling.getScale());
+ if (!aScale.Minimum.hasValue())
+ {
+ bool bNewMinOK = true;
+ double fMax = 0.0;
+ if (aScale.Maximum >>= fMax)
+ bNewMinOK = (aExplicitScaleSource.Minimum <= fMax);
+ if (bNewMinOK)
+ aExplicitScaleDest.Minimum = aExplicitScaleSource.Minimum;
+ }
+ else
+ aExplicitIncrementDest.BaseValue = aExplicitScaleDest.Minimum;
+
+ if (!aScale.Maximum.hasValue())
+ {
+ bool bNewMaxOK = true;
+ double fMin = 0.0;
+ if (aScale.Minimum >>= fMin)
+ bNewMaxOK = (fMin <= aExplicitScaleSource.Maximum);
+ if (bNewMaxOK)
+ aExplicitScaleDest.Maximum = aExplicitScaleSource.Maximum;
+ }
+ if (!aScale.Origin.hasValue())
+ aExplicitScaleDest.Origin = aExplicitScaleSource.Origin;
+
+ if (!aScale.IncrementData.Distance.hasValue())
+ aExplicitIncrementDest.Distance = aExplicitIncrementSource.Distance;
+
+ bool bAutoMinorInterval = true;
+ if (aScale.IncrementData.SubIncrements.hasElements())
+ bAutoMinorInterval
+ = !(aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue());
+ if (bAutoMinorInterval)
+ {
+ if (!aExplicitIncrementDest.SubIncrements.empty()
+ && !aExplicitIncrementSource.SubIncrements.empty())
+ aExplicitIncrementDest.SubIncrements[0].IntervalCount
+ = aExplicitIncrementSource.SubIncrements[0].IntervalCount;
+ }
+
+ nC->setExplicitScaleAndIncrement(1, nAxisIndex, aExplicitScaleDest,
+ aExplicitIncrementDest);
+ }
+ }
+ }
+
+ if (!AxisHelper::isAxisPositioningEnabled())
+ return;
+
+ //correct origin for y main axis (the origin is where the other main axis crosses)
+ sal_Int32 nAxisIndex = 0;
+ sal_Int32 nDimensionIndex = 1;
+ for (auto & [ rAxis, rAxisUsage ] : m_aAxisUsageList)
+ {
+ (void)rAxis;
+ std::vector<VCoordinateSystem*> aVCooSysList
+ = rAxisUsage.getCoordinateSystems(nDimensionIndex, nAxisIndex);
+ size_t nC;
+ for (nC = 0; nC < aVCooSysList.size(); nC++)
+ {
+ ExplicitScaleData aExplicitScale(
+ aVCooSysList[nC]->getExplicitScale(nDimensionIndex, nAxisIndex));
+ ExplicitIncrementData aExplicitIncrement(
+ aVCooSysList[nC]->getExplicitIncrement(nDimensionIndex, nAxisIndex));
+
+ rtl::Reference<BaseCoordinateSystem> xCooSys(aVCooSysList[nC]->getModel());
+ rtl::Reference<Axis> xAxis = xCooSys->getAxisByDimension2(nDimensionIndex, nAxisIndex);
+ rtl::Reference<Axis> xCrossingMainAxis
+ = AxisHelper::getCrossingMainAxis(xAxis, xCooSys);
+
+ if (xCrossingMainAxis.is())
+ {
+ css::chart::ChartAxisPosition eCrossingMainAxisPos(
+ css::chart::ChartAxisPosition_ZERO);
+ xCrossingMainAxis->getPropertyValue("CrossoverPosition") >>= eCrossingMainAxisPos;
+ if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_VALUE)
+ {
+ double fValue = 0.0;
+ xCrossingMainAxis->getPropertyValue("CrossoverValue") >>= fValue;
+ aExplicitScale.Origin = fValue;
+ }
+ else if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_ZERO)
+ aExplicitScale.Origin = 0.0;
+ else if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_START)
+ aExplicitScale.Origin = aExplicitScale.Minimum;
+ else if (eCrossingMainAxisPos == css::chart::ChartAxisPosition_END)
+ aExplicitScale.Origin = aExplicitScale.Maximum;
+ }
+
+ aVCooSysList[nC]->setExplicitScaleAndIncrement(nDimensionIndex, nAxisIndex,
+ aExplicitScale, aExplicitIncrement);
+ }
+ }
+}
+
+drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio()
+{
+ drawing::Direction3D aPreferredAspectRatio(1.0, 1.0, 1.0);
+
+ //get a list of all preferred aspect ratios and combine them
+ //first with special demands wins (less or equal zero <-> arbitrary)
+ double fx, fy, fz;
+ fx = fy = fz = -1.0;
+ for (const std::unique_ptr<VSeriesPlotter>& aPlotter : m_aSeriesPlotterList)
+ {
+ drawing::Direction3D aSingleRatio(aPlotter->getPreferredDiagramAspectRatio());
+ if (fx < 0 && aSingleRatio.DirectionX > 0)
+ fx = aSingleRatio.DirectionX;
+
+ if (fy < 0 && aSingleRatio.DirectionY > 0)
+ {
+ if (fx > 0 && aSingleRatio.DirectionX > 0)
+ fy = fx * aSingleRatio.DirectionY / aSingleRatio.DirectionX;
+ else if (fz > 0 && aSingleRatio.DirectionZ > 0)
+ fy = fz * aSingleRatio.DirectionY / aSingleRatio.DirectionZ;
+ else
+ fy = aSingleRatio.DirectionY;
+ }
+
+ if (fz < 0 && aSingleRatio.DirectionZ > 0)
+ {
+ if (fx > 0 && aSingleRatio.DirectionX > 0)
+ fz = fx * aSingleRatio.DirectionZ / aSingleRatio.DirectionX;
+ else if (fy > 0 && aSingleRatio.DirectionY > 0)
+ fz = fy * aSingleRatio.DirectionZ / aSingleRatio.DirectionY;
+ else
+ fz = aSingleRatio.DirectionZ;
+ }
+
+ if (fx > 0 && fy > 0 && fz > 0)
+ break;
+ }
+ aPreferredAspectRatio = drawing::Direction3D(fx, fy, fz);
+ return aPreferredAspectRatio;
+}
+
+} //end chart2 namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/SeriesPlotterContainer.hxx b/chart2/source/view/main/SeriesPlotterContainer.hxx
new file mode 100644
index 0000000000..578f2ba276
--- /dev/null
+++ b/chart2/source/view/main/SeriesPlotterContainer.hxx
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_feature_desktop.h>
+#include <VSeriesPlotter.hxx>
+#include <BaseCoordinateSystem.hxx>
+#include "AxisUsage.hxx"
+
+namespace chart
+{
+/** This class is a container of `SeriesPlotter` objects (such as `PieChart`
+ * instances). It is used for initializing coordinate systems, axes and scales
+ * of all series plotters which belongs to the container.
+ */
+class SeriesPlotterContainer
+{
+public:
+ explicit SeriesPlotterContainer(std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList);
+ ~SeriesPlotterContainer();
+
+ /** It is used to set coordinate systems (`m_rVCooSysList`), this method
+ * is invoked by `ChartView::createShapes2D` before of
+ * `ChartView::impl_createDiagramAndContent`.
+ * Coordinate systems are retrieved through the `XCoordinateSystemContainer`
+ * interface implemented by a diagram object which is provided by the
+ * `ChartModel` object passed to the method (`rChartModel.getFirstDiagram()`).
+ *
+ * It is used for creating series plotters and appending them
+ * to `m_aSeriesPlotterList`. The created series plotters are initialized
+ * through data (number formats supplier, color scheme, data series),
+ * extracted from the chart model or the diagram objects. An exception is
+ * the explicit category provider that is retrieved through the
+ * `VCoordinateSystem` object used by the series plotter.
+ *
+ * It sets the minimum-maximum supplier for a coordinate system:
+ * this supplier is the series plotter itself which utilizes the given
+ * coordinate system. In fact `VSeriesPlotter` has `MinimumMaximumSupplier`
+ * as one of its base classes.
+ * Hence, for instance, a `PieChart`, which is a series plotter, is
+ * a `MinimumMaximumSupplier`, too.
+ */
+ void initializeCooSysAndSeriesPlotter(ChartModel& rModel);
+
+ /** This method is invoked by `ChartView::impl_createDiagramAndContent`.
+ * It iterates on every axis of every coordinate systems, and if the axis
+ * is not yet present in `m_aAxisUsageList` it creates a new `AxisUsage`
+ * object and initialize its `aAutoScaling` member to the `ScaleData`
+ * object of the current axis.
+ */
+ void initAxisUsageList(const Date& rNullDate);
+
+ /**
+ * Perform automatic axis scaling and determine the amount and spacing of
+ * increments. It assumes that the caller has determined the size of the
+ * largest axis label text object prior to calling this method.
+ *
+ * The new axis scaling data will be stored in the VCoordinateSystem
+ * objects. The label alignment direction for each axis will also get
+ * determined during this process, and stored in VAxis.
+ *
+ * This method is invoked by `ChartView::impl_createDiagramAndContent`
+ * soon after `initAxisUsageList`.
+ * It initializes explicit scale and increment objects for all coordinate
+ * systems in `m_rVCooSysList`.
+ * This action is achieved by iterating on the `m_aAxisUsageList` container,
+ * and performing 3 steps:
+ * 1- call `VCoordinateSystem::prepareAutomaticAxisScaling` for setting
+ * scaling parameters of the `aAutoScaling` member (a `ScaleAutomatism`
+ * object) for the current `AxisUsage` instance
+ * (see `VCoordinateSystem::prepareAutomaticAxisScaling`);
+ * 2- calculate the explicit scale and increment objects
+ * (see ScaleAutomatism::calculateExplicitScaleAndIncrement);
+ * 3- set the explicit scale and increment objects for each coordinate
+ * system.
+ */
+ void doAutoScaling(ChartModel& rModel);
+
+ /**
+ * After auto-scaling is performed, call this method to set the explicit
+ * scaling and increment data to all relevant VAxis objects.
+ */
+ void updateScalesAndIncrementsOnAxes();
+
+ /**
+ * After auto-scaling is performed, call this method to set the explicit
+ * scaling data to all the plotters.
+ */
+ void setScalesFromCooSysToPlotter();
+
+ void setNumberFormatsFromAxes();
+ css::drawing::Direction3D getPreferredAspectRatio();
+
+ std::vector<std::unique_ptr<VSeriesPlotter>>& getSeriesPlotterList()
+ {
+ return m_aSeriesPlotterList;
+ }
+ std::vector<std::unique_ptr<VCoordinateSystem>>& getCooSysList() { return m_rVCooSysList; }
+ std::vector<LegendEntryProvider*> getLegendEntryProviderList();
+
+ void AdaptScaleOfYAxisWithoutAttachedSeries(ChartModel& rModel);
+
+ bool isCategoryPositionShifted(const css::chart2::ScaleData& rSourceScale,
+ bool bHasComplexCategories);
+
+ static VCoordinateSystem*
+ getCooSysForPlotter(const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
+ MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier);
+ static VCoordinateSystem*
+ addCooSysToList(std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
+ const rtl::Reference<BaseCoordinateSystem>& xCooSys, ChartModel& rChartModel);
+ static VCoordinateSystem*
+ findInCooSysList(const std::vector<std::unique_ptr<VCoordinateSystem>>& rVCooSysList,
+ const rtl::Reference<BaseCoordinateSystem>& xCooSys);
+
+private:
+ /** A vector of series plotters.
+ */
+ std::vector<std::unique_ptr<VSeriesPlotter>> m_aSeriesPlotterList;
+
+ /** A vector of coordinate systems.
+ */
+ std::vector<std::unique_ptr<VCoordinateSystem>>& m_rVCooSysList;
+
+ /** A map whose key is a `XAxis` interface and the related value is
+ * an object of `AxisUsage` type.
+ */
+ std::map<rtl::Reference<Axis>, AxisUsage> m_aAxisUsageList;
+
+ /**
+ * Max axis index of all dimensions. Currently this can be either 0 or 1
+ * since we only support primary and secondary axes per dimension. The
+ * value of 0 means all dimensions have only primary axis, while 1 means
+ * at least one dimension has a secondary axis.
+ */
+ sal_Int32 m_nMaxAxisIndex;
+
+ bool m_bChartTypeUsesShiftedCategoryPositionPerDefault;
+ bool m_bForceShiftPosition = false;
+ sal_Int32 m_nDefaultDateNumberFormat;
+};
+
+} //end chart2 namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/ShapeFactory.cxx b/chart2/source/view/main/ShapeFactory.cxx
new file mode 100644
index 0000000000..f9efceb676
--- /dev/null
+++ b/chart2/source/view/main/ShapeFactory.cxx
@@ -0,0 +1,2554 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ShapeFactory.hxx>
+#include <BaseGFXHelper.hxx>
+#include <ViewDefines.hxx>
+#include <Stripe.hxx>
+#include <CommonConverters.hxx>
+#include <RelativeSizeHelper.hxx>
+#include <PropertyMapper.hxx>
+#include <VLineProperties.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/chart2/XFormattedString.hpp>
+#include <com/sun/star/drawing/CircleKind.hpp>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+#include <com/sun/star/drawing/FlagSequence.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/NormalsKind.hpp>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/TextureProjectionMode.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/XShapes2.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+#include <editeng/unoprnms.hxx>
+#include <rtl/math.hxx>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdopath.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/helpers.hxx>
+#include <tools/UnitConversion.hxx>
+#include <sal/log.hxx>
+
+#include <algorithm>
+#include <cmath>
+#include <cstddef>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+
+namespace chart
+{
+
+namespace
+{
+
+void lcl_addProperty(uno::Sequence<OUString> & rPropertyNames, uno::Sequence<uno::Any> & rPropertyValues,
+ OUString const & rName, uno::Any const & rAny)
+{
+ rPropertyNames.realloc(rPropertyNames.getLength() + 1);
+ rPropertyNames.getArray()[rPropertyNames.getLength() - 1] = rName;
+
+ rPropertyValues.realloc(rPropertyValues.getLength() + 1);
+ rPropertyValues.getArray()[rPropertyValues.getLength() - 1] = rAny;
+}
+
+css::drawing::PolyPolygonShape3D toPolyPolygonShape3D(const std::vector<std::vector<css::drawing::Position3D>>& rPoints)
+{
+ css::drawing::PolyPolygonShape3D aUnoPoly;
+ aUnoPoly.SequenceX.realloc(rPoints.size());
+ aUnoPoly.SequenceY.realloc(rPoints.size());
+ aUnoPoly.SequenceZ.realloc(rPoints.size());
+ for (std::size_t nPolygonIndex=0; nPolygonIndex<rPoints.size(); ++nPolygonIndex)
+ {
+ drawing::DoubleSequence* pOuterSequenceX = &aUnoPoly.SequenceX.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceY = &aUnoPoly.SequenceY.getArray()[nPolygonIndex];
+ drawing::DoubleSequence* pOuterSequenceZ = &aUnoPoly.SequenceZ.getArray()[nPolygonIndex];
+ pOuterSequenceX->realloc(rPoints[nPolygonIndex].size());
+ pOuterSequenceY->realloc(rPoints[nPolygonIndex].size());
+ pOuterSequenceZ->realloc(rPoints[nPolygonIndex].size());
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+ for (std::size_t nPointIndex=0; nPointIndex<rPoints[nPolygonIndex].size(); ++nPointIndex)
+ {
+ auto& rPos = rPoints[nPolygonIndex][nPointIndex];
+ pInnerSequenceX[nPointIndex] = rPos.PositionX;
+ pInnerSequenceY[nPointIndex] = rPos.PositionY;
+ pInnerSequenceZ[nPointIndex] = rPos.PositionZ;
+ }
+ }
+ return aUnoPoly;
+}
+
+} // end anonymous namespace
+
+rtl::Reference<SvxShapeGroupAnyD> ShapeFactory::getOrCreateChartRootShape(
+ const rtl::Reference<SvxDrawPage>& xDrawPage )
+{
+ rtl::Reference<SvxShapeGroupAnyD> xRet = ShapeFactory::getChartRootShape(xDrawPage);
+ if (xRet.is())
+ return xRet;
+
+ // Create a new root shape and set it to the bottom of the page. The root
+ // shape is identified by having the name com.sun.star.chart2.shapes.
+ rtl::Reference<SvxShapeGroup> xShapeGroup = new SvxShapeGroup(nullptr, nullptr);
+ xShapeGroup->setShapeKind(SdrObjKind::Group);
+ // cast to resolve ambiguity in converting to XShape
+ xDrawPage->addBottom(static_cast<SvxShape*>(xShapeGroup.get()));
+
+ setShapeName(xShapeGroup, "com.sun.star.chart2.shapes");
+ xShapeGroup->setSize(awt::Size(0,0));
+
+ return xShapeGroup;
+}
+
+void ShapeFactory::setPageSize(const rtl::Reference<SvxShapeGroupAnyD>&, const awt::Size&) {}
+
+// diverse tools::PolyPolygon create methods
+
+static uno::Any createPolyPolygon_Cube(
+ const drawing::Direction3D& rSize, double fRoundedEdge, bool bRounded )
+{
+ OSL_PRECOND(fRoundedEdge>=0, "fRoundedEdge needs to be >= 0");
+
+ // always use extra points, so set percent diagonal to 0.4 which is 0% in the UI (old Chart comment)
+ if( fRoundedEdge == 0.0 && bRounded)
+ fRoundedEdge = 0.4 / 200.0;
+ else if(!bRounded)
+ fRoundedEdge = 0.0;
+
+ //fWidthH stands for Half Width
+ const double fWidthH = rSize.DirectionX >=0.0? rSize.DirectionX/2.0 : -rSize.DirectionX/2.0;
+ const double fHeight = rSize.DirectionY;
+
+ const double fHeightSign = fHeight >= 0.0 ? 1.0 : -1.0;
+
+ const double fOffset = (fWidthH * fRoundedEdge) * 1.05; // increase by 5% for safety
+ const bool bRoundEdges = fRoundedEdge && fOffset < fWidthH && 2.0 * fOffset < fHeightSign*fHeight;
+ const sal_Int32 nPointCount = bRoundEdges ? 13 : 5;
+
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(1);
+ aPP.SequenceY.realloc(1);
+ aPP.SequenceZ.realloc(1);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(nPointCount);
+ pOuterSequenceY->realloc(nPointCount);
+ pOuterSequenceZ->realloc(nPointCount);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ for(sal_Int32 nN = nPointCount; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ if(nPointCount == 5)
+ {
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = 0.0;
+
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = -fWidthH;
+ }
+ else
+ {
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = fHeightSign*fOffset;
+ *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = fHeight;
+ *pInnerSequenceY++ = fHeight - fHeightSign*fOffset;
+ *pInnerSequenceY++ = fHeightSign*fOffset;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+
+ *pInnerSequenceX++ = -fWidthH + fOffset;
+ *pInnerSequenceX++ = fWidthH - fOffset;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = fWidthH;
+ *pInnerSequenceX++ = fWidthH - fOffset;
+ *pInnerSequenceX++ = -fWidthH + fOffset;
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = -fWidthH;
+ *pInnerSequenceX++ = -fWidthH + fOffset;
+ }
+ return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
+}
+
+static uno::Any createPolyPolygon_Cylinder(
+ double fHeight
+ , double fRadius
+ , sal_Int32& nVerticalSegmentCount )
+{
+ //fHeight may be negative
+ OSL_PRECOND(fRadius>0, "The radius of a cylinder needs to be > 0");
+
+ drawing::PolyPolygonShape3D aPP;
+
+ nVerticalSegmentCount=1;
+
+ aPP.SequenceX.realloc(3);
+ aPP.SequenceY.realloc(3);
+ aPP.SequenceZ.realloc(3);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(2);
+ pOuterSequenceY->realloc(2);
+ pOuterSequenceZ->realloc(2);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ double fY1 = 0.0;
+ double fY2 = fHeight;
+
+ if( fHeight<0.0 )
+ std::swap(fY1,fY2);
+
+ for(sal_Int32 nN = 2; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = fY1;
+
+ *pInnerSequenceX++ = fRadius;
+ *pInnerSequenceY++ = fY1;
+
+ pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
+ pOuterSequenceX->realloc(2);
+ pOuterSequenceY->realloc(2);
+ pOuterSequenceZ->realloc(2);
+
+ pInnerSequenceX = pOuterSequenceX->getArray();
+ pInnerSequenceY = pOuterSequenceY->getArray();
+ pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ for(sal_Int32 nN = 2; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = fRadius;
+ *pInnerSequenceY++ = fY1;
+
+ *pInnerSequenceX++ = fRadius;
+ *pInnerSequenceY++ = fY2;
+
+ pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
+ pOuterSequenceX->realloc(2);
+ pOuterSequenceY->realloc(2);
+ pOuterSequenceZ->realloc(2);
+
+ pInnerSequenceX = pOuterSequenceX->getArray();
+ pInnerSequenceY = pOuterSequenceY->getArray();
+ pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ for(sal_Int32 nN = 2; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = fRadius;
+ *pInnerSequenceY++ = fY2;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = fY2;
+
+ return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
+}
+
+static uno::Any createPolyPolygon_Cone( double fHeight, double fRadius, double fTopHeight
+ , sal_Int32& nVerticalSegmentCount )
+{
+ OSL_PRECOND(fRadius>0, "The radius of a cone needs to be > 0");
+
+ //for stacked charts we need cones without top -> fTopHeight != 0 resp. bTopless == true
+ //fTopHeight indicates the high of the cutted top only (not the full height)
+ bool bTopless = !::rtl::math::approxEqual( fHeight, fHeight + fTopHeight );
+
+ double r1= 0.0, r2 = fRadius;
+ if(bTopless)
+ // #i63212# fHeight may be negative, fTopHeight is always positive -> use fabs(fHeight)
+ r1 = fRadius * fTopHeight/(fabs(fHeight)+fTopHeight);
+
+ nVerticalSegmentCount=1;
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(2);
+ aPP.SequenceY.realloc(2);
+ aPP.SequenceZ.realloc(2);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(2);
+ pOuterSequenceY->realloc(2);
+ pOuterSequenceZ->realloc(2);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ double fX1 = 0.0;
+ double fX2 = r2;
+ double fX3 = r1;
+
+ double fY1 = 0.0;
+ double fY2 = 0.0;
+ double fY3 = fHeight;
+
+ if( fHeight<0.0 )
+ {
+ std::swap(fX1,fX3);
+ std::swap(fY1,fY3);
+ }
+
+ for(sal_Int32 nN = 2; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceY++ = fY1;
+ *pInnerSequenceX++ = fX1;
+
+ *pInnerSequenceY++ = fY2;
+ *pInnerSequenceX++ = fX2;
+
+ pOuterSequenceX++;pOuterSequenceY++;pOuterSequenceZ++;
+ pOuterSequenceX->realloc(2);
+ pOuterSequenceY->realloc(2);
+ pOuterSequenceZ->realloc(2);
+
+ pInnerSequenceX = pOuterSequenceX->getArray();
+ pInnerSequenceY = pOuterSequenceY->getArray();
+ pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ for(sal_Int32 nN = 2; nN--;)
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceY++ = fY2;
+ *pInnerSequenceX++ = fX2;
+
+ *pInnerSequenceY++ = fY3;
+ *pInnerSequenceX++ = fX3;
+
+ return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
+}
+
+// methods for 3D shape creation
+
+rtl::Reference<Svx3DExtrudeObject>
+ ShapeFactory::createCube(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , sal_Int32 nRotateZAngleHundredthDegree
+ , const uno::Reference< beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap
+ , bool bRounded )
+{
+ if( !xTarget.is() )
+ return nullptr;
+ if( bRounded )
+ {
+ try
+ {
+ if( xSourceProp.is() )
+ {
+ drawing::LineStyle aLineStyle;
+ xSourceProp->getPropertyValue( "BorderStyle" ) >>= aLineStyle;
+ if( aLineStyle == drawing::LineStyle_SOLID )
+ bRounded = false;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ rtl::Reference<Svx3DExtrudeObject> xShape = impl_createCube( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree, bRounded );
+ if( xSourceProp.is())
+ PropertyMapper::setMappedProperties( *xShape, xSourceProp, rPropertyNameMap );
+ return xShape;
+}
+
+rtl::Reference<Svx3DExtrudeObject>
+ ShapeFactory::impl_createCube(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , sal_Int32 nRotateZAngleHundredthDegree
+ , bool bRounded )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ //create shape
+ rtl::Reference<Svx3DExtrudeObject> xShape = new Svx3DExtrudeObject(nullptr);
+ xShape->setShapeKind(SdrObjKind::E3D_Extrusion);
+ xTarget->addShape(*xShape);
+
+ //set properties
+ try
+ {
+ //depth
+ double fDepth = rSize.DirectionZ;
+ if (fDepth<0)
+ fDepth*=-1.0;
+
+ //PercentDiagonal
+ sal_Int16 nPercentDiagonal = bRounded ? 3 : 0;
+
+ //Matrix for position
+ basegfx::B3DHomMatrix aHomMatrix;
+ if (nRotateZAngleHundredthDegree != 0)
+ aHomMatrix.rotate(0.0, 0.0, -basegfx::deg2rad<100>(nRotateZAngleHundredthDegree));
+ aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY,
+ rPosition.PositionZ - (fDepth / 2.0));
+
+ uno::Sequence<OUString> aPropertyNames {
+ UNO_NAME_3D_EXTRUDE_DEPTH,
+ UNO_NAME_3D_PERCENT_DIAGONAL,
+ UNO_NAME_3D_POLYPOLYGON3D,
+ UNO_NAME_3D_TRANSFORM_MATRIX,
+ };
+
+ uno::Sequence<uno::Any> aPropertyValues {
+ uno::Any(sal_Int32(fDepth)), // Depth
+ uno::Any(nPercentDiagonal), // PercentDiagonal
+ createPolyPolygon_Cube(rSize, double(nPercentDiagonal) / 200.0, bRounded),
+ uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix))
+ };
+
+ xShape->setPropertyValues(aPropertyNames, aPropertyValues);
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<Svx3DLatheObject>
+ ShapeFactory::createCylinder(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , sal_Int32 nRotateZAngleHundredthDegree )
+{
+ return impl_createConeOrCylinder(
+ xTarget, rPosition, rSize, 0.0, nRotateZAngleHundredthDegree, true );
+}
+
+rtl::Reference<Svx3DSceneObject>
+ ShapeFactory::createPyramid(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , double fTopHeight, bool bRotateZ
+ , const uno::Reference< beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ rtl::Reference<Svx3DSceneObject> xGroup( ShapeFactory::createGroup3D( xTarget ) );
+
+ bool bDoubleSided = false;
+ short nRotatedTexture = 0;
+
+ const double fWidth = rSize.DirectionX;
+ const double fDepth = rSize.DirectionZ;
+ const double fHeight = rSize.DirectionY;
+
+ drawing::Position3D aBottomP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth/2.0 );
+ if(bRotateZ)
+ aBottomP1.PositionY -= fWidth/2.0;
+ else
+ aBottomP1.PositionX -= fWidth/2.0;
+ drawing::Position3D aBottomP2( aBottomP1 );
+ if(bRotateZ)
+ aBottomP2.PositionY += fWidth;
+ else
+ aBottomP2.PositionX += fWidth;
+ drawing::Position3D aBottomP3( aBottomP2 );
+ drawing::Position3D aBottomP4( aBottomP1 );
+ aBottomP3.PositionZ += fDepth;
+ aBottomP4.PositionZ += fDepth;
+
+ const double fTopFactor = fTopHeight/(fabs(fHeight)+fTopHeight);
+ drawing::Position3D aTopP1( rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ - fDepth*fTopFactor/2.0 );
+ if(bRotateZ)
+ {
+ aTopP1.PositionY -= fWidth*fTopFactor/2.0;
+ aTopP1.PositionX += fHeight;
+ }
+ else
+ {
+ aTopP1.PositionX -= fWidth*fTopFactor/2.0;
+ aTopP1.PositionY += fHeight;
+ }
+ drawing::Position3D aTopP2( aTopP1 );
+ if(bRotateZ)
+ aTopP2.PositionY += fWidth*fTopFactor;
+ else
+ aTopP2.PositionX += fWidth*fTopFactor;
+ drawing::Position3D aTopP3( aTopP2 );
+ drawing::Position3D aTopP4( aTopP1 );
+ aTopP3.PositionZ += fDepth*fTopFactor;
+ aTopP4.PositionZ += fDepth*fTopFactor;
+
+ Stripe aStripeBottom( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
+
+ drawing::Position3D aNormalsBottomP1( aBottomP1 );
+ drawing::Position3D aNormalsBottomP2( aBottomP2 );
+ drawing::Position3D aNormalsBottomP3( aBottomP3 );
+ drawing::Position3D aNormalsBottomP4( aBottomP4 );
+ drawing::Position3D aNormalsTopP1( aBottomP1 );
+ drawing::Position3D aNormalsTopP2( aBottomP2 );
+ drawing::Position3D aNormalsTopP3( aBottomP3 );
+ drawing::Position3D aNormalsTopP4( aBottomP4 );
+ if( bRotateZ )
+ {
+ aNormalsTopP1.PositionX += fHeight;
+ aNormalsTopP2.PositionX += fHeight;
+ aNormalsTopP3.PositionX += fHeight;
+ aNormalsTopP4.PositionX += fHeight;
+ }
+ else
+ {
+ aNormalsTopP1.PositionY += fHeight;
+ aNormalsTopP2.PositionY += fHeight;
+ aNormalsTopP3.PositionY += fHeight;
+ aNormalsTopP4.PositionY += fHeight;
+ }
+
+ bool bInvertPolygon = false;
+ bool bInvertNormals = false;
+
+ if(bRotateZ)
+ {
+ //bars
+ if(fHeight>=0.0)
+ {
+ nRotatedTexture = 2;
+ bInvertNormals = true;
+ aStripeBottom = Stripe( aBottomP1, aBottomP4, aBottomP3, aBottomP2 );
+ }
+ else
+ {
+ bInvertPolygon = true;
+ nRotatedTexture = 1;
+ aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
+ }
+ }
+ else
+ {
+ //columns
+ if(fHeight>=0.0)
+ {
+ bInvertPolygon = true;
+ nRotatedTexture = 2;
+ aStripeBottom = Stripe( aBottomP2, aBottomP3, aBottomP4, aBottomP1 );
+ }
+ else
+ {
+ nRotatedTexture = 3;
+ bInvertNormals = true;
+ aStripeBottom = Stripe( aBottomP4, aBottomP3, aBottomP2, aBottomP1 );
+ }
+ }
+ aStripeBottom.InvertNormal(true);
+
+ Stripe aStripe1( aTopP2, aTopP1, aBottomP1, aBottomP2 );
+ Stripe aStripe2( aTopP3, aTopP2, aBottomP2, aBottomP3 );
+ Stripe aStripe3( aTopP4, aTopP3, aBottomP3, aBottomP4 );
+ Stripe aStripe4( aTopP1, aTopP4, aBottomP4, aBottomP1 );
+
+ if( bInvertPolygon )
+ {
+ aStripe1 = Stripe( aBottomP1, aTopP1, aTopP2, aBottomP2 );
+ aStripe2 = Stripe( aBottomP2, aTopP2, aTopP3, aBottomP3 );
+ aStripe3 = Stripe( aBottomP3, aTopP3, aTopP4, aBottomP4 );
+ aStripe4 = Stripe( aBottomP4, aTopP4, aTopP1, aBottomP1 );
+ }
+
+ Stripe aNormalsStripe1( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP2, aNormalsTopP2 );
+ Stripe aNormalsStripe2( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP3, aNormalsTopP3 );
+ Stripe aNormalsStripe3( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP4, aNormalsTopP4 );
+ Stripe aNormalsStripe4( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP1, aNormalsTopP1 );
+
+ if( bInvertNormals )
+ {
+ aNormalsStripe1 = Stripe( aNormalsTopP2, aNormalsBottomP2, aNormalsBottomP1, aNormalsTopP1 );
+ aNormalsStripe2 = Stripe( aNormalsTopP3, aNormalsBottomP3, aNormalsBottomP2, aNormalsTopP2 );
+ aNormalsStripe3 = Stripe( aNormalsTopP4, aNormalsBottomP4, aNormalsBottomP3, aNormalsTopP3 );
+ aNormalsStripe4 = Stripe( aNormalsTopP1, aNormalsBottomP1, aNormalsBottomP4, aNormalsTopP4 );
+ }
+
+ aStripe1.SetManualNormal( aNormalsStripe1.getNormal() );
+ aStripe2.SetManualNormal( aNormalsStripe2.getNormal() );
+ aStripe3.SetManualNormal( aNormalsStripe3.getNormal() );
+ aStripe4.SetManualNormal( aNormalsStripe4.getNormal() );
+
+ const bool bFlatNormals = false;
+ ShapeFactory::createStripe( xGroup, aStripe1, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
+ ShapeFactory::createStripe( xGroup, aStripe2, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
+ ShapeFactory::createStripe( xGroup, aStripe3, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
+ ShapeFactory::createStripe( xGroup, aStripe4, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
+ ShapeFactory::createStripe( xGroup, aStripeBottom, xSourceProp, rPropertyNameMap, bDoubleSided, nRotatedTexture, bFlatNormals );
+
+ return xGroup;
+}
+
+rtl::Reference<Svx3DLatheObject>
+ ShapeFactory::createCone(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree )
+{
+ return impl_createConeOrCylinder( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree, false );
+}
+
+rtl::Reference<Svx3DLatheObject>
+ ShapeFactory::impl_createConeOrCylinder(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
+ , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
+ , bool bCylinder )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ //create shape
+ rtl::Reference<Svx3DLatheObject> xShape = new Svx3DLatheObject(nullptr);
+ xShape->setShapeKind(SdrObjKind::E3D_Lathe);
+ xTarget->addShape(*xShape);
+
+ double fWidth = rSize.DirectionX/2.0; //The depth will be corrected within Matrix
+ double fRadius = fWidth; //!!!!!!!! problem in drawing layer: rotation object calculates wrong needed size -> wrong camera (it's a problem with bounding boxes)
+ double fHeight = rSize.DirectionY;
+
+ //set properties
+ try
+ {
+ //Polygon
+ sal_Int32 nVerticalSegmentCount = 0;
+ uno::Any aPPolygon = bCylinder
+ ? createPolyPolygon_Cylinder(fHeight, fRadius, nVerticalSegmentCount)
+ : createPolyPolygon_Cone(fHeight, fRadius, fTopHeight, nVerticalSegmentCount);
+
+ //Matrix for position
+ basegfx::B3DHomMatrix aHomMatrix;
+ if (nRotateZAngleHundredthDegree != 0)
+ aHomMatrix.rotate(0.0,0.0,-basegfx::deg2rad<100>(nRotateZAngleHundredthDegree));
+ //stretch the symmetric objects to given depth
+ aHomMatrix.scale(1.0,1.0,rSize.DirectionZ/rSize.DirectionX);
+ aHomMatrix.translate(rPosition.PositionX, rPosition.PositionY, rPosition.PositionZ);
+
+ uno::Sequence<OUString> aPropertyNames{
+ UNO_NAME_3D_PERCENT_DIAGONAL,
+ UNO_NAME_3D_POLYPOLYGON3D,
+ UNO_NAME_3D_TRANSFORM_MATRIX,
+ UNO_NAME_3D_HORZ_SEGS,
+ UNO_NAME_3D_VERT_SEGS,
+ UNO_NAME_3D_REDUCED_LINE_GEOMETRY
+ };
+
+ uno::Sequence<uno::Any> aPropertyValues {
+ uno::Any(sal_Int16(5)), // PercentDiagonal
+ aPPolygon, // Polygon
+ uno::Any(B3DHomMatrixToHomogenMatrix(aHomMatrix)), // Matrix
+ uno::Any(CHART_3DOBJECT_SEGMENTCOUNT), // Horizontal Segments
+ uno::Any(nVerticalSegmentCount), // Vertical Segments
+ uno::Any(true) // Reduced lines
+ };
+
+ xShape->setPropertyValues(aPropertyNames, aPropertyValues);
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+static void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rReturn, const drawing::PolyPolygonBezierCoords& rAdd, bool bAppendInverse )
+{
+ if(!rAdd.Coordinates.hasElements())
+ return;
+ sal_Int32 nAddCount = rAdd.Coordinates[0].getLength();
+ if(!nAddCount)
+ return;
+
+ sal_Int32 nOldCount = rReturn.Coordinates[0].getLength();
+
+ auto pCoordinates = rReturn.Coordinates.getArray();
+ pCoordinates[0].realloc(nOldCount + nAddCount + 1);
+ auto pCoordinates0 = pCoordinates[0].getArray();
+ auto pFlags = rReturn.Flags.getArray();
+ pFlags[0].realloc(nOldCount+nAddCount+1);
+ auto pFlags0 = pFlags[0].getArray();
+
+ for(sal_Int32 nN=0;nN<nAddCount; nN++ )
+ {
+ sal_Int32 nAdd = bAppendInverse ? (nAddCount-1-nN) : nN;
+ pCoordinates0[nOldCount+nN] = rAdd.Coordinates[0][nAdd];
+ pFlags0[nOldCount+nN] = rAdd.Flags[0][nAdd];
+ }
+
+ //close
+ pCoordinates0[nOldCount+nAddCount] = rReturn.Coordinates[0][0];
+ pFlags0[nOldCount+nAddCount] = rReturn.Flags[0][0];
+}
+
+static drawing::PolyPolygonBezierCoords getCircularArcBezierCoords(
+ double fStartAngleRadian, double fWidthAngleRadian, double fUnitRadius
+ , const ::basegfx::B2DHomMatrix& rTransformationFromUnitCircle
+ , const double fAngleSubdivisionRadian )
+{
+ //at least one polygon is created using two normal and two control points
+ //if the angle is larger it is separated into multiple sub angles
+
+ drawing::PolyPolygonBezierCoords aReturn;
+ sal_Int32 nSegmentCount = static_cast< sal_Int32 >( fWidthAngleRadian/fAngleSubdivisionRadian );
+ if( fWidthAngleRadian > fAngleSubdivisionRadian*nSegmentCount )
+ nSegmentCount++;
+
+ double fFirstSegmentAngle = fAngleSubdivisionRadian;
+ double fLastSegmentAngle = fAngleSubdivisionRadian;
+ if(nSegmentCount==1)
+ {
+ fFirstSegmentAngle = fWidthAngleRadian;
+ fLastSegmentAngle = 0.0;
+ }
+ else
+ {
+ double fFirstAngleOnSubDivision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian;
+ if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDivision ) )
+ fFirstSegmentAngle = fFirstAngleOnSubDivision-fStartAngleRadian;
+
+ if(nSegmentCount>1)
+ {
+ fLastSegmentAngle = fWidthAngleRadian-fFirstSegmentAngle-fAngleSubdivisionRadian*(nSegmentCount-2);
+ if( fLastSegmentAngle<0 )
+ nSegmentCount--;
+ if( fLastSegmentAngle>fAngleSubdivisionRadian )
+ {
+ fLastSegmentAngle-=fAngleSubdivisionRadian;
+ nSegmentCount++;
+ }
+ }
+ }
+
+ sal_Int32 nPointCount = 1 + 3*nSegmentCount; //first point of next segment equals last point of former segment
+
+ drawing::PointSequence aPoints(nPointCount);
+ auto pPoints = aPoints.getArray();
+ drawing::FlagSequence aFlags(nPointCount);
+ auto pFlags = aFlags.getArray();
+
+ //!! applying matrix to vector does ignore translation, so it is important to use a B2DPoint here instead of B2DVector
+ ::basegfx::B2DPoint P0,P1,P2,P3;
+
+ sal_Int32 nPoint=0;
+ double fCurrentRotateAngle = fStartAngleRadian;
+ for(sal_Int32 nSegment=0; nSegment<nSegmentCount; nSegment++)
+ {
+ double fCurrentSegmentAngle = fAngleSubdivisionRadian;
+ if(nSegment==0)//first segment gets only a smaller peace until the next subdivision
+ fCurrentSegmentAngle = fFirstSegmentAngle;
+ else if(nSegment==(nSegmentCount-1)) //the last segment gets the rest angle that does not fit into equal pieces
+ fCurrentSegmentAngle = fLastSegmentAngle;
+
+ //first create untransformed points for a unit circle arc:
+ const double fCos = cos(fCurrentSegmentAngle/2.0);
+ const double fSin = sin(fCurrentSegmentAngle/2.0);
+ P0.setX(fCos);
+ P3.setX(fCos);
+ P0.setY(-fSin);
+ P3.setY(-P0.getY());
+
+ P1.setX((4.0-fCos)/3.0);
+ P2.setX(P1.getX());
+ P1.setY((1.0-fCos)*(fCos-3.0)/(3.0*fSin));
+ P2.setY(-P1.getY());
+ //transform thus startangle equals NULL
+ ::basegfx::B2DHomMatrix aStart;
+ aStart.rotate(fCurrentSegmentAngle/2.0 + fCurrentRotateAngle );
+ fCurrentRotateAngle+=fCurrentSegmentAngle;
+
+ aStart.scale( fUnitRadius, fUnitRadius );
+
+ //apply given transformation to get final points
+ P0 = rTransformationFromUnitCircle*(aStart*P0);
+ P1 = rTransformationFromUnitCircle*(aStart*P1);
+ P2 = rTransformationFromUnitCircle*(aStart*P2);
+ P3 = rTransformationFromUnitCircle*(aStart*P3);
+
+ pPoints[nPoint].X = static_cast< sal_Int32 >( P0.getX());
+ pPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY());
+ pFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
+
+ pPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX());
+ pPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY());
+ pFlags[nPoint++] = drawing::PolygonFlags_CONTROL;
+
+ pPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX());
+ pPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY());
+ pFlags [nPoint++] = drawing::PolygonFlags_CONTROL;
+
+ if(nSegment==(nSegmentCount-1))
+ {
+ pPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX());
+ pPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY());
+ pFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
+ }
+ }
+
+ aReturn.Coordinates = { aPoints };
+ aReturn.Flags = { aFlags };
+
+ return aReturn;
+}
+
+static drawing::PolyPolygonBezierCoords getRingBezierCoords(
+ double fUnitCircleInnerRadius
+ , double fUnitCircleOuterRadius
+ , double fStartAngleRadian, double fWidthAngleRadian
+ , const ::basegfx::B2DHomMatrix& aTransformationFromUnitCircle
+ , const double fAngleSubdivisionRadian )
+{
+ drawing::PolyPolygonBezierCoords aReturn;
+
+ drawing::PolyPolygonBezierCoords aOuterArc = getCircularArcBezierCoords(
+ fStartAngleRadian, fWidthAngleRadian, fUnitCircleOuterRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
+ aReturn.Coordinates = { aOuterArc.Coordinates[0] };
+ aReturn.Flags = { aOuterArc.Flags[0] };
+
+ drawing::PolyPolygonBezierCoords aInnerArc = getCircularArcBezierCoords(
+ fStartAngleRadian, fWidthAngleRadian, fUnitCircleInnerRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
+ appendAndCloseBezierCoords( aReturn, aInnerArc, true );
+
+ return aReturn;
+}
+
+rtl::Reference<SvxShapePolyPolygon>
+ ShapeFactory::createPieSegment2D(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , const drawing::Direction3D& rOffset
+ , const drawing::HomogenMatrix& rUnitCircleToScene )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ // tdf#123504: both 0 and 360 are valid and different values here!
+ while (fUnitCircleWidthAngleDegree > 360)
+ fUnitCircleWidthAngleDegree -= 360.0;
+ while (fUnitCircleWidthAngleDegree < 0)
+ fUnitCircleWidthAngleDegree += 360.0;
+
+ //create shape
+ rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
+ xShape->setShapeKind(SdrObjKind::PathFill); // aka ClosedBezierShape
+ xTarget->addShape(*xShape); //need to add the shape before setting of properties
+
+ //set properties
+ try
+ {
+ ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
+ aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
+
+ const double fAngleSubdivisionRadian = M_PI/10.0;
+
+ drawing::PolyPolygonBezierCoords aCoords
+ = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius,
+ basegfx::deg2rad(fUnitCircleStartAngleDegree),
+ basegfx::deg2rad(fUnitCircleWidthAngleDegree),
+ aTransformationFromUnitCircle, fAngleSubdivisionRadian);
+
+ xShape->SvxShape::setPropertyValue( "PolyPolygonBezier", uno::Any( aCoords ) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ return xShape;
+}
+
+rtl::Reference<Svx3DExtrudeObject>
+ ShapeFactory::createPieSegment(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
+ , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
+ , const drawing::Direction3D& rOffset
+ , const drawing::HomogenMatrix& rUnitCircleToScene
+ , double fDepth )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ // tdf#123504: both 0 and 360 are valid and different values here!
+ while (fUnitCircleWidthAngleDegree > 360)
+ fUnitCircleWidthAngleDegree -= 360.0;
+ while (fUnitCircleWidthAngleDegree < 0)
+ fUnitCircleWidthAngleDegree += 360.0;
+
+ //create shape
+ rtl::Reference<Svx3DExtrudeObject> xShape = new Svx3DExtrudeObject(nullptr);
+ xShape->setShapeKind(SdrObjKind::E3D_Extrusion);
+ xTarget->addShape(*xShape); //need to add the shape before setting of properties
+
+ //set properties
+ try
+ {
+ ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(rUnitCircleToScene) ) );
+ aTransformationFromUnitCircle.translate(rOffset.DirectionX,rOffset.DirectionY);
+
+ const double fAngleSubdivisionRadian = M_PI/32.0;
+
+ drawing::PolyPolygonBezierCoords aCoords
+ = getRingBezierCoords(fUnitCircleInnerRadius, fUnitCircleOuterRadius,
+ basegfx::deg2rad(fUnitCircleStartAngleDegree),
+ basegfx::deg2rad(fUnitCircleWidthAngleDegree),
+ aTransformationFromUnitCircle, fAngleSubdivisionRadian);
+
+ //depth
+ xShape->setPropertyValue( UNO_NAME_3D_EXTRUDE_DEPTH
+ , uno::Any(static_cast<sal_Int32>(fDepth)) );
+
+ //PercentDiagonal
+ xShape->setPropertyValue( UNO_NAME_3D_PERCENT_DIAGONAL
+ , uno::Any( sal_Int16(0) ) );
+
+ //Polygon
+ drawing::PolyPolygonShape3D aPoly( BezierToPoly(aCoords) );
+ ShapeFactory::closePolygon( aPoly );
+ xShape->setPropertyValue( UNO_NAME_3D_POLYPOLYGON3D
+ , uno::Any( aPoly ) );
+
+ //DoubleSided
+ xShape->setPropertyValue( UNO_NAME_3D_DOUBLE_SIDED
+ , uno::Any( true ) );
+
+ //Reduced lines
+ xShape->setPropertyValue( UNO_NAME_3D_REDUCED_LINE_GEOMETRY
+ , uno::Any( true ) );
+
+ //TextureProjectionMode
+ xShape->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y
+ , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
+
+ //TextureProjectionMode
+ xShape->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_X
+ , uno::Any( drawing::TextureProjectionMode_PARALLEL ) );
+ xShape->setPropertyValue( UNO_NAME_3D_TEXTURE_PROJ_Y
+ , uno::Any( drawing::TextureProjectionMode_OBJECTSPECIFIC ) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<Svx3DPolygonObject>
+ ShapeFactory::createStripe( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const Stripe& rStripe
+ , const uno::Reference< beans::XPropertySet >& xSourceProp
+ , const tPropertyNameMap& rPropertyNameMap
+ , bool bDoubleSided
+ , short nRotatedTexture
+ , bool bFlatNormals )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ //create shape
+ rtl::Reference<Svx3DPolygonObject> xShape = new Svx3DPolygonObject(nullptr);
+ xShape->setShapeKind(SdrObjKind::E3D_Polygon);
+ xTarget->addShape(*xShape);
+
+ //set properties
+ try
+ {
+ uno::Sequence<OUString> aPropertyNames{
+ UNO_NAME_3D_POLYPOLYGON3D,
+ UNO_NAME_3D_TEXTUREPOLYGON3D,
+ UNO_NAME_3D_NORMALSPOLYGON3D,
+ UNO_NAME_3D_LINEONLY,
+ UNO_NAME_3D_DOUBLE_SIDED
+ };
+
+ uno::Sequence<uno::Any> aPropertyValues {
+ rStripe.getPolyPolygonShape3D(), // Polygon
+ Stripe::getTexturePolygon(nRotatedTexture), // TexturePolygon
+ rStripe.getNormalsPolygon(), // Normals Polygon
+ uno::Any(false), // LineOnly
+ uno::Any(bDoubleSided) // DoubleSided
+ };
+
+ //NormalsKind
+ if (bFlatNormals)
+ lcl_addProperty(aPropertyNames, aPropertyValues,
+ UNO_NAME_3D_NORMALS_KIND, uno::Any(drawing::NormalsKind_FLAT));
+
+ xShape->setPropertyValues(aPropertyNames, aPropertyValues);
+
+ if (xSourceProp)
+ {
+ PropertyMapper::setMappedProperties(*xShape, xSourceProp, rPropertyNameMap);
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<Svx3DExtrudeObject>
+ ShapeFactory::createArea3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon
+ , double fDepth )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ if( rPolyPolygon.empty() )
+ return nullptr;
+
+ //create shape
+ rtl::Reference<Svx3DExtrudeObject> xShape = new Svx3DExtrudeObject(nullptr);
+ xShape->setShapeKind(SdrObjKind::E3D_Extrusion);
+ xTarget->addShape(*xShape);
+
+ css::drawing::PolyPolygonShape3D aUnoPolyPolygon = toPolyPolygonShape3D(rPolyPolygon);
+
+ //set properties
+ try
+ {
+ uno::Sequence<OUString> aPropertyNames{
+ UNO_NAME_3D_EXTRUDE_DEPTH,
+ UNO_NAME_3D_PERCENT_DIAGONAL,
+ UNO_NAME_3D_POLYPOLYGON3D,
+ UNO_NAME_3D_DOUBLE_SIDED,
+ };
+
+ uno::Sequence<uno::Any> aPropertyValues {
+ uno::Any(sal_Int32(fDepth)), // depth
+ uno::Any(sal_Int16(0)), // PercentDiagonal
+ uno::Any(aUnoPolyPolygon), // Polygon
+ uno::Any(true) // DoubleSided
+ };
+
+ //the z component of the polygon is now ignored by the drawing layer,
+ //so we need to translate the object via transformation matrix
+
+ //Matrix for position
+ if (!rPolyPolygon.empty() && !rPolyPolygon[0].empty())
+ {
+ basegfx::B3DHomMatrix aM;
+ aM.translate(0, 0, rPolyPolygon[0][0].PositionZ);
+ drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
+ lcl_addProperty(aPropertyNames, aPropertyValues, UNO_NAME_3D_TRANSFORM_MATRIX, uno::Any(aHM));
+ }
+ xShape->setPropertyValues(aPropertyNames, aPropertyValues);
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<SvxShapePolyPolygon>
+ ShapeFactory::createArea2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ //create shape
+ rtl::Reference<SdrPathObj> pPath = new SdrPathObj(xTarget->GetSdrObject()->getSdrModelFromSdrObject(), SdrObjKind::Polygon);
+ xTarget->GetSdrObject()->GetSubList()->InsertObject(pPath.get());
+
+ //set properties
+ try
+ {
+ // Polygon
+ basegfx::B2DPolyPolygon aNewPolyPolygon( PolyToB2DPolyPolygon(rPolyPolygon) );
+ // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
+ pPath->ForceMetricToItemPoolMetric(aNewPolyPolygon);
+ pPath->SetPathPoly(aNewPolyPolygon);
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return static_cast<SvxShapePolyPolygon*>(pPath->getUnoShape().get());
+}
+
+static drawing::PointSequenceSequence createPolyPolygon_Symbol( const drawing::Position3D& rPos
+ , const drawing::Direction3D& rSize
+ , sal_Int32 nStandardSymbol )
+{
+ if(nStandardSymbol<0)
+ nStandardSymbol*=-1;
+ nStandardSymbol = nStandardSymbol%ShapeFactory::getSymbolCount();
+ SymbolEnum eSymbolType=static_cast<SymbolEnum>(nStandardSymbol);
+
+ const double& fX = rPos.PositionX;
+ const double& fY = rPos.PositionY;
+
+ const double fWidthH = rSize.DirectionX/2.0; //fWidthH stands for Half Width
+ const double fHeightH = rSize.DirectionY/2.0; //fHeightH stands for Half Height
+
+ const sal_Int32 nQuarterCount = 35; // points inside a quadrant, used in case circle
+
+ sal_Int32 nPointCount = 4; //all arrow symbols only need 4 points
+ switch( eSymbolType )
+ {
+ case Symbol_Square:
+ case Symbol_Diamond:
+ case Symbol_Bowtie:
+ case Symbol_Sandglass:
+ case Symbol_HorizontalBar:
+ case Symbol_VerticalBar:
+ nPointCount = 5;
+ break;
+ case Symbol_X:
+ nPointCount = 13;
+ break;
+ case Symbol_Plus:
+ nPointCount = 13;
+ break;
+ case Symbol_Star:
+ nPointCount = 9;
+ break;
+ case Symbol_Asterisk:
+ nPointCount = 19;
+ break;
+ case Symbol_Circle:
+ nPointCount = 5 + 4 * nQuarterCount;
+ break;
+ default:
+ break;
+ }
+
+ drawing::PointSequenceSequence aPP;
+
+ aPP.realloc(1);
+
+ uno::Sequence<awt::Point>* pOuterSequence = aPP.getArray();
+
+ pOuterSequence->realloc(nPointCount);
+
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+
+ auto toPoint = [](double x, double y) -> awt::Point
+ {
+ return { static_cast<sal_Int32>(x), static_cast<sal_Int32>(y) };
+ };
+ switch(eSymbolType)
+ {
+ case Symbol_Square:
+ {
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+ break;
+ }
+ case Symbol_UpArrow:
+ {
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
+ break;
+ }
+ case Symbol_DownArrow:
+ {
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+ break;
+ }
+ case Symbol_RightArrow:
+ {
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+ break;
+ }
+ case Symbol_LeftArrow:
+ {
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY );
+ break;
+ }
+ case Symbol_Bowtie:
+ {
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+ break;
+ }
+ case Symbol_Sandglass:
+ {
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
+ break;
+ }
+ case Symbol_Diamond:
+ {
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY );
+
+ *pInnerSequence++ = toPoint( fX, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY );
+
+ *pInnerSequence++ = toPoint( fX, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY );
+ break;
+ }
+ case Symbol_HorizontalBar:
+ {
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-0.2*fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY-0.2*fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY+0.2*fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+0.2*fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-0.2*fHeightH );
+ break;
+ }
+ case Symbol_VerticalBar:
+ {
+ *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY-fHeightH );
+
+ break;
+ }
+ case Symbol_Circle:
+ {
+ double fOmega = M_PI_2 / (nQuarterCount + 1.0);
+ // one point in the middle of each edge to get full size bounding rectangle
+ *pInnerSequence++ = toPoint( fX + fWidthH, fY );
+ // 0 to PI/2
+ for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
+ {
+ *pInnerSequence++ = toPoint( fX + fWidthH * cos( i * fOmega ), fY - fHeightH * sin( i * fOmega ) );
+ }
+ // PI/2 to PI
+ *pInnerSequence++ = toPoint( fX, fY - fHeightH );
+ for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
+ {
+ *pInnerSequence++ = toPoint( fX - fWidthH * sin( i * fOmega), fY - fHeightH * cos( i * fOmega) );
+ }
+ // PI to 3/2*PI
+ *pInnerSequence++ = toPoint( fX - fWidthH, fY );
+ for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
+ {
+ *pInnerSequence++ = toPoint( fX - fWidthH * cos( i * fOmega), fY + fHeightH * sin( i * fOmega) );
+ }
+ // 3/2*PI to 2*PI
+ *pInnerSequence++ = toPoint( fX, fY + fHeightH );
+ for (sal_Int32 i = 1; i <= nQuarterCount; ++i)
+ {
+ *pInnerSequence++ = toPoint( fX + fWidthH * sin(i * fOmega), fY + fHeightH * cos(i * fOmega) );
+ }
+ // close polygon
+ *pInnerSequence++ = toPoint( fX + fWidthH, fY );
+ break;
+ }
+ case Symbol_Star:
+ {
+ *pInnerSequence++ = toPoint( fX, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY-0.2*fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY );
+
+ *pInnerSequence++ = toPoint( fX+0.2*fWidthH, fY+0.2*fHeightH );
+
+ *pInnerSequence++ = toPoint( fX, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY+0.2*fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY );
+
+ *pInnerSequence++ = toPoint( fX-0.2*fWidthH, fY-0.2*fHeightH );
+
+ *pInnerSequence++ = toPoint( fX, fY-fHeightH );
+ break;
+ }
+ case Symbol_X:
+ {
+ const double fScaleX = fWidthH / 128.0;
+ const double fScaleY = fHeightH / 128.0;
+ const double fSmall = sqrt(200.0);
+ const double fLarge = 128.0 - fSmall;
+
+ *pInnerSequence++ = toPoint( fX, fY - fScaleY * fSmall );
+
+ *pInnerSequence++ = toPoint( fX - fScaleX * fLarge, fY - fHeightH );
+
+ *pInnerSequence++ = toPoint( fX - fWidthH, fY - fScaleY * fLarge );
+
+ *pInnerSequence++ = toPoint( fX - fScaleX * fSmall, fY );
+
+ *pInnerSequence++ = toPoint( fX - fWidthH, fY + fScaleY * fLarge );
+
+ *pInnerSequence++ = toPoint( fX - fScaleX * fLarge, fY + fHeightH );
+
+ *pInnerSequence++ = toPoint( fX, fY + fScaleY * fSmall );
+
+ *pInnerSequence++ = toPoint( fX + fScaleX * fLarge, fY + fHeightH );
+
+ *pInnerSequence++ = toPoint( fX + fWidthH, fY + fScaleY * fLarge );
+
+ *pInnerSequence++ = toPoint( fX + fScaleX * fSmall, fY );
+
+ *pInnerSequence++ = toPoint( fX + fWidthH, fY - fScaleY * fLarge );
+
+ *pInnerSequence++ = toPoint( fX + fScaleX * fLarge, fY - fHeightH );
+
+ *pInnerSequence++ = toPoint( fX, fY - fScaleY * fSmall );
+ break;
+
+ }
+ case Symbol_Plus:
+ {
+ const double fScaleX = fWidthH / 128.0;
+ const double fScaleY = fHeightH / 128.0;
+ const double fHalf = 10.0; //half line width on 256 size square
+ const double fdX = fScaleX * fHalf;
+ const double fdY = fScaleY * fHalf;
+
+ *pInnerSequence++ = toPoint( fX-fdX, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fdX, fY-fdY );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fdY );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+fdY );
+
+ *pInnerSequence++ = toPoint( fX-fdX, fY+fdY );
+
+ *pInnerSequence++ = toPoint( fX-fdX, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fdX, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fdX, fY+fdY );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY+fdY );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY-fdY );
+
+ *pInnerSequence++ = toPoint( fX+fdX, fY-fdY );
+
+ *pInnerSequence++ = toPoint( fX+fdY, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fdX, fY-fHeightH );
+ break;
+
+ }
+ case Symbol_Asterisk:
+ {
+ const double fHalf = 10.0; // half line width on 256 size square
+ const double fTwoY = fHalf * sqrt(3.0);
+ const double fFourY = (128.0 - 2.0 * fHalf ) / sqrt(3.0);
+ const double fThreeX = 128.0 - fHalf;
+ const double fThreeY = fHalf * sqrt(3.0) + fFourY;
+ const double fFiveX = 2.0 * fHalf;
+
+ const double fScaleX = fWidthH / 128.0;
+ const double fScaleY = fHeightH / 128.0;
+
+ //1
+ *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY-fHeightH );
+ //2
+ *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY-fScaleY * fTwoY );
+ //3
+ *pInnerSequence++ = toPoint( fX-fScaleX * fThreeX, fY-fScaleY * fThreeY );
+ //4
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fScaleY * fFourY );
+ //5
+ *pInnerSequence++ = toPoint( fX-fScaleX * fFiveX, fY );
+ //6 as 4
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+fScaleY * fFourY );
+ //7 as 3
+ *pInnerSequence++ = toPoint( fX-fScaleX * fThreeX, fY+fScaleY * fThreeY );
+ //8 as 2
+ *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY+fScaleY * fTwoY );
+ //9 as 1
+ *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY+fHeightH );
+ //10 as 1
+ *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY+fHeightH );
+ //11 as 2
+ *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY+fScaleY * fTwoY );
+ //12 as 3
+ *pInnerSequence++ = toPoint( fX+fScaleX * fThreeX, fY+fScaleY * fThreeY );
+ //13 as 4
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY+fScaleY * fFourY );
+ //14 as 5
+ *pInnerSequence++ = toPoint( fX+fScaleX * fFiveX, fY );
+ //15 as 4
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY-fScaleY * fFourY );
+ //16 as 3
+ *pInnerSequence++ = toPoint( fX+fScaleX * fThreeX, fY-fScaleY * fThreeY );
+ //17 as 2
+ *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY-fScaleY * fTwoY );
+ // 18 as 1
+ *pInnerSequence++ = toPoint( fX+fScaleX * fHalf, fY-fHeightH );
+ // 19 = 1, closing
+ *pInnerSequence++ = toPoint( fX-fScaleX * fHalf, fY-fHeightH );
+ break;
+ }
+ default: //case Symbol_Square:
+ {
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY+fHeightH );
+
+ *pInnerSequence++ = toPoint( fX+fWidthH, fY-fHeightH );
+
+ *pInnerSequence++ = toPoint( fX-fWidthH, fY-fHeightH );
+ break;
+ }
+ }
+
+ return aPP;
+}
+
+rtl::Reference<SvxShapePolyPolygon>
+ ShapeFactory::createSymbol2D(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rPosition
+ , const drawing::Direction3D& rSize
+ , sal_Int32 nStandardSymbol
+ , sal_Int32 nBorderColor
+ , sal_Int32 nFillColor )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ //create shape
+ rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
+ xShape->setShapeKind(SdrObjKind::Polygon);
+ xTarget->addShape(*xShape);
+
+ //set properties
+ try
+ {
+ drawing::PointSequenceSequence aPoints =
+ createPolyPolygon_Symbol( rPosition, rSize, nStandardSymbol );
+
+ //Polygon
+ xShape->SvxShape::setPropertyValue( UNO_NAME_POLYPOLYGON
+ , uno::Any( aPoints ) );
+
+ //LineColor
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINECOLOR
+ , uno::Any( nBorderColor ) );
+
+ //FillColor
+ xShape->SvxShape::setPropertyValue( UNO_NAME_FILLCOLOR
+ , uno::Any( nFillColor ) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<SvxGraphicObject>
+ ShapeFactory::createGraphic2D(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rPosition
+ , const drawing::Direction3D& rSize
+ , const uno::Reference< graphic::XGraphic >& xGraphic )
+{
+ if( !xTarget.is() || !xGraphic.is() )
+ return nullptr;
+
+ // @todo: change this to a rectangle shape with a fill bitmap for
+ // performance reasons (ask AW, said CL)
+
+ //create shape
+ rtl::Reference<SvxGraphicObject> xShape = new SvxGraphicObject(nullptr);
+ xShape->setShapeKind(SdrObjKind::Graphic);
+ xTarget->addShape(*xShape);
+
+ try
+ {
+ // assume position is upper left corner. Transform to center.
+ drawing::Position3D aCenterPosition(
+ rPosition.PositionX - (rSize.DirectionX / 2.0),
+ rPosition.PositionY - (rSize.DirectionY / 2.0),
+ rPosition.PositionZ );
+ xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
+ xShape->setSize( Direction3DToAWTSize( rSize ));
+ }
+ catch( const uno::Exception & )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ try
+ {
+ xShape->SvxShape::setPropertyValue( "Graphic", uno::Any( xGraphic ));
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference< SvxShapeGroup >
+ ShapeFactory::createGroup2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const OUString& aName )
+{
+ if( !xTarget.is() )
+ return nullptr;
+ try
+ {
+ //create and add to target
+ rtl::Reference<SvxShapeGroup> xShapeGroup = new SvxShapeGroup(nullptr, nullptr);
+ xShapeGroup->setShapeKind(SdrObjKind::Group);
+ // cast to resolve ambiguity in converting to XShape
+ xTarget->addShape(*xShapeGroup);
+
+ //set name
+ if(!aName.isEmpty())
+ setShapeName( xShapeGroup, aName );
+
+ {//workaround
+ //need this null size as otherwise empty group shapes where painted with a gray border
+ xShapeGroup->setSize(awt::Size(0,0));
+ }
+
+ return xShapeGroup;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return nullptr;
+}
+
+rtl::Reference< SvxShapeGroup >
+ ShapeFactory::createGroup2D( const rtl::Reference<SvxDrawPage>& xTarget
+ , const OUString& aName )
+{
+ if( !xTarget.is() )
+ return nullptr;
+ try
+ {
+ //create and add to target
+ rtl::Reference<SvxShapeGroup> xShapeGroup = new SvxShapeGroup(nullptr, nullptr);
+ xShapeGroup->setShapeKind(SdrObjKind::Group);
+ // cast to resolve ambiguity in converting to XShape
+ xTarget->add(static_cast<SvxShape*>(xShapeGroup.get()));
+
+ //set name
+ if(!aName.isEmpty())
+ setShapeName( xShapeGroup, aName );
+
+ {//workaround
+ //need this null size as otherwise empty group shapes where painted with a gray border
+ xShapeGroup->setSize(awt::Size(0,0));
+ }
+
+ return xShapeGroup;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return nullptr;
+}
+
+rtl::Reference<Svx3DSceneObject>
+ ShapeFactory::createGroup3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const OUString& aName )
+{
+ if( !xTarget.is() )
+ return nullptr;
+ try
+ {
+ //create shape
+ rtl::Reference<Svx3DSceneObject> xShape = new Svx3DSceneObject(nullptr, nullptr);
+ xShape->setShapeKind(SdrObjKind::E3D_Scene);
+ xTarget->addShape(*xShape);
+
+ //it is necessary to set the transform matrix to initialize the scene properly
+ //otherwise all objects which are placed into this Group will not be visible
+ //the following should be unnecessary after the bug is fixed
+ //set properties
+ try
+ {
+ ::basegfx::B3DHomMatrix aM;
+ xShape->SvxShape::setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
+ , uno::Any(B3DHomMatrixToHomogenMatrix(aM)) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ //set name
+ if(!aName.isEmpty())
+ setShapeName( xShape , aName );
+
+ //return
+ return xShape;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return nullptr;
+}
+
+rtl::Reference<SvxShapeCircle>
+ ShapeFactory::createCircle2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::Position3D& rPosition
+ , const drawing::Direction3D& rSize )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ //create shape
+ rtl::Reference<SvxShapeCircle> xShape = new SvxShapeCircle(nullptr);
+ xShape->setShapeKind(SdrObjKind::CircleOrEllipse);
+ xTarget->addShape(*xShape);
+
+ try
+ {
+ drawing::Position3D aCenterPosition(
+ rPosition.PositionX - (rSize.DirectionX / 2.0),
+ rPosition.PositionY - (rSize.DirectionY / 2.0),
+ rPosition.PositionZ );
+ xShape->setPosition( Position3DToAWTPoint( aCenterPosition ));
+ xShape->setSize( Direction3DToAWTSize( rSize ));
+ }
+ catch( const uno::Exception & )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ //set properties
+ try
+ {
+ xShape->SvxShape::setPropertyValue( UNO_NAME_CIRCKIND, uno::Any( drawing::CircleKind_FULL ) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<SvxShapeCircle>
+ ShapeFactory::createCircle( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const awt::Size& rSize
+ , const awt::Point& rPosition )
+{
+ rtl::Reference<SvxShapeCircle> xShape = new SvxShapeCircle(nullptr);
+ xShape->setShapeKind(SdrObjKind::CircleOrEllipse);
+ xTarget->addShape(*xShape);
+ xShape->setSize( rSize );
+ xShape->setPosition( rPosition );
+
+ return xShape;
+}
+
+rtl::Reference<Svx3DPolygonObject>
+ ShapeFactory::createLine3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const std::vector<std::vector<css::drawing::Position3D>>& rPoints
+ , const VLineProperties& rLineProperties )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ if(rPoints.empty())
+ return nullptr;
+
+ //create shape
+ rtl::Reference<Svx3DPolygonObject> xShape = new Svx3DPolygonObject(nullptr);
+ xShape->setShapeKind(SdrObjKind::E3D_Polygon);
+ xTarget->addShape(*xShape);
+
+ css::drawing::PolyPolygonShape3D aUnoPoly = toPolyPolygonShape3D(rPoints);
+
+ //set properties
+ try
+ {
+ uno::Sequence<OUString> aPropertyNames {
+ UNO_NAME_3D_POLYPOLYGON3D,
+ UNO_NAME_3D_LINEONLY
+ };
+
+ uno::Sequence<uno::Any> aPropertyValues {
+ uno::Any(aUnoPoly), // Polygon
+ uno::Any(true) // LineOnly
+ };
+
+ //Transparency
+ if(rLineProperties.Transparence.hasValue())
+ {
+ lcl_addProperty(aPropertyNames, aPropertyValues,
+ UNO_NAME_LINETRANSPARENCE,
+ rLineProperties.Transparence);
+ }
+
+ //LineStyle
+ if(rLineProperties.LineStyle.hasValue())
+ {
+ lcl_addProperty(aPropertyNames, aPropertyValues,
+ UNO_NAME_LINESTYLE,
+ rLineProperties.LineStyle);
+ }
+
+ //LineWidth
+ if(rLineProperties.Width.hasValue())
+ {
+ lcl_addProperty(aPropertyNames, aPropertyValues,
+ UNO_NAME_LINEWIDTH,
+ rLineProperties.Width);
+ }
+
+ //LineColor
+ if(rLineProperties.Color.hasValue())
+ {
+ lcl_addProperty(aPropertyNames, aPropertyValues,
+ UNO_NAME_LINECOLOR,
+ rLineProperties.Color);
+ }
+ xShape->setPropertyValues(aPropertyNames, aPropertyValues);
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<SvxShapePolyPolygon>
+ ShapeFactory::createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const drawing::PointSequenceSequence& rPoints
+ , const VLineProperties* pLineProperties )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ if(!rPoints.hasElements())
+ return nullptr;
+
+ //create shape
+ rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
+ xShape->setShapeKind(SdrObjKind::PolyLine);
+ xTarget->addShape(*xShape);
+
+ //set properties
+ try
+ {
+ //Polygon
+ xShape->SvxShape::setPropertyValue( UNO_NAME_POLYPOLYGON
+ , uno::Any( rPoints ) );
+
+ if(pLineProperties)
+ {
+ //Transparency
+ if(pLineProperties->Transparence.hasValue())
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINETRANSPARENCE
+ , pLineProperties->Transparence );
+
+ //LineStyle
+ if(pLineProperties->LineStyle.hasValue())
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINESTYLE
+ , pLineProperties->LineStyle );
+
+ //LineWidth
+ if(pLineProperties->Width.hasValue())
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINEWIDTH
+ , pLineProperties->Width );
+
+ //LineColor
+ if(pLineProperties->Color.hasValue())
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINECOLOR
+ , pLineProperties->Color );
+
+ //LineDashName
+ if(pLineProperties->DashName.hasValue())
+ xShape->SvxShape::setPropertyValue( "LineDashName"
+ , pLineProperties->DashName );
+
+ //LineCap
+ if(pLineProperties->LineCap.hasValue())
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINECAP
+ , pLineProperties->LineCap );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<SvxShapePolyPolygon>
+ ShapeFactory::createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const std::vector<std::vector<css::drawing::Position3D>>& rPoints
+ , const VLineProperties* pLineProperties )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ if(rPoints.empty())
+ return nullptr;
+
+ //create shape
+ rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
+ xShape->setShapeKind(SdrObjKind::PolyLine);
+ xTarget->addShape(*xShape);
+
+ drawing::PointSequenceSequence aAnyPoints = PolyToPointSequence(rPoints);
+
+ //set properties
+ try
+ {
+ //Polygon
+ xShape->SvxShape::setPropertyValue( UNO_NAME_POLYPOLYGON
+ , uno::Any( aAnyPoints ) );
+
+ if(pLineProperties)
+ {
+ //Transparency
+ if(pLineProperties->Transparence.hasValue())
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINETRANSPARENCE
+ , pLineProperties->Transparence );
+
+ //LineStyle
+ if(pLineProperties->LineStyle.hasValue())
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINESTYLE
+ , pLineProperties->LineStyle );
+
+ //LineWidth
+ if(pLineProperties->Width.hasValue())
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINEWIDTH
+ , pLineProperties->Width );
+
+ //LineColor
+ if(pLineProperties->Color.hasValue())
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINECOLOR
+ , pLineProperties->Color );
+
+ //LineDashName
+ if(pLineProperties->DashName.hasValue())
+ xShape->SvxShape::setPropertyValue( "LineDashName"
+ , pLineProperties->DashName );
+
+ //LineCap
+ if(pLineProperties->LineCap.hasValue())
+ xShape->SvxShape::setPropertyValue( UNO_NAME_LINECAP
+ , pLineProperties->LineCap );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<SvxShapePolyPolygon>
+ ShapeFactory::createLine ( const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const awt::Size& rSize, const awt::Point& rPosition )
+{
+ //create shape
+ rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
+ xShape->setShapeKind(SdrObjKind::Line);
+ xTarget->addShape(*xShape);
+ xShape->setSize( rSize );
+ xShape->setPosition( rPosition );
+
+ return xShape;
+}
+
+rtl::Reference<SvxShapeRect> ShapeFactory::createInvisibleRectangle(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const awt::Size& rSize )
+{
+ try
+ {
+ if(!xTarget.is())
+ return nullptr;
+
+ rtl::Reference<SvxShapeRect> xShape = new SvxShapeRect(nullptr);
+ xShape->setShapeKind(SdrObjKind::Rectangle);
+ xTarget->addShape( *xShape );
+ ShapeFactory::makeShapeInvisible( xShape );
+ xShape->setSize( rSize );
+ return xShape;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return nullptr;
+}
+
+rtl::Reference<SvxShapeRect> ShapeFactory::createRectangle(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const awt::Size& rSize,
+ const awt::Point& rPosition,
+ const tNameSequence& rPropNames,
+ const tAnySequence& rPropValues,
+ StackPosition ePos )
+{
+ rtl::Reference<SvxShapeRect> xShape = new SvxShapeRect(nullptr);
+ xShape->setShapeKind(SdrObjKind::Rectangle);
+ if (ePos == StackPosition::Bottom)
+ {
+ uno::Reference<drawing::XShapes2> xTarget2(static_cast<cppu::OWeakObject*>(xTarget.get()), uno::UNO_QUERY);
+ assert(xTarget2);
+ if (xTarget2.is())
+ xTarget2->addBottom(xShape);
+ }
+ else
+ xTarget->addShape(*xShape);
+
+ xShape->setPosition( rPosition );
+ xShape->setSize( rSize );
+ PropertyMapper::setMultiProperties( rPropNames, rPropValues, *xShape );
+
+ return xShape;
+}
+
+rtl::Reference<SvxShapeRect>
+ ShapeFactory::createRectangle(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
+{
+ rtl::Reference<SvxShapeRect> xShape = new SvxShapeRect(nullptr);
+ xShape->setShapeKind(SdrObjKind::Rectangle);
+ xTarget->addShape( *xShape );
+
+ return xShape;
+}
+
+rtl::Reference<SvxShapeText>
+ ShapeFactory::createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const OUString& rText
+ , const tNameSequence& rPropNames
+ , const tAnySequence& rPropValues
+ , const uno::Any& rATransformation )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ if(rText.isEmpty())
+ return nullptr;
+
+ //create shape and add to page
+ rtl::Reference<SvxShapeText> xShape = new SvxShapeText(nullptr);
+ xShape->setShapeKind(SdrObjKind::Text);
+ xTarget->addShape(*xShape);
+
+ //set text
+ xShape->setString( rText );
+
+ //set properties
+ PropertyMapper::setMultiProperties( rPropNames, rPropValues, *xShape );
+
+ //set position matrix
+ //the matrix needs to be set at the end behind autogrow and such position influencing properties
+ try
+ {
+ if (rATransformation.hasValue())
+ xShape->SvxShape::setPropertyValue( "Transformation", rATransformation );
+ else
+ SAL_INFO("chart2", "No rATransformation value is given to ShapeFactory::createText()");
+
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<SvxShapeText>
+ ShapeFactory::createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+ , const uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString
+ , const tNameSequence& rPropNames
+ , const tAnySequence& rPropValues
+ , const uno::Any& rATransformation )
+{
+ if( !xTarget.is() )
+ return nullptr;
+
+ if( !xFormattedString.hasElements() )
+ return nullptr;
+
+ sal_Int32 nNumberOfParagraphs = xFormattedString.getLength();
+
+ bool bNotEmpty = false;
+ for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
+ {
+ if( !xFormattedString[nN]->getString().isEmpty() )
+ {
+ bNotEmpty = true;
+ break;
+ }
+ }
+ if( !bNotEmpty )
+ return nullptr;
+
+ //create shape and add to page
+ rtl::Reference<SvxShapeText> xShape = new SvxShapeText(nullptr);
+ xShape->setShapeKind(SdrObjKind::Text);
+ xTarget->addShape(*xShape);
+
+ //set paragraph properties
+ bNotEmpty = false;
+ // the first cursor is used for appending the next paragraph,
+ // after a new string has been inserted the cursor is moved at the end
+ // of the inserted string
+ // the second cursor is used for selecting the paragraph and apply the
+ // passed text properties
+ Reference< text::XTextCursor > xInsertCursor = xShape->createTextCursor();
+ Reference< text::XTextCursor > xSelectionCursor = xShape->createTextCursor();
+ if( xInsertCursor.is() && xSelectionCursor.is() )
+ {
+ uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY );
+ if( xSelectionProp.is() )
+ {
+ for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
+ {
+ if( !xFormattedString[nN]->getString().isEmpty() )
+ {
+ xInsertCursor->gotoEnd( false );
+ xSelectionCursor->gotoEnd( false );
+ xShape->insertString( xInsertCursor, xFormattedString[nN]->getString(), false );
+ bNotEmpty = true;
+ xSelectionCursor->gotoEnd( true ); // select current paragraph
+ uno::Reference< beans::XPropertySet > xStringProperties( xFormattedString[nN], uno::UNO_QUERY );
+ PropertyMapper::setMappedProperties( xSelectionProp, xStringProperties,
+ PropertyMapper::getPropertyNameMapForTextShapeProperties() );
+ }
+ }
+ }
+ }
+
+ if( !bNotEmpty )
+ return nullptr;
+
+ //set whole text shape properties
+ PropertyMapper::setMultiProperties( rPropNames, rPropValues, *xShape );
+
+ if( rATransformation.hasValue() )
+ {
+ //set position matrix
+ //the matrix needs to be set at the end behind autogrow and such position influencing properties
+ try
+ {
+ xShape->SvxShape::setPropertyValue( "Transformation", rATransformation );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ return xShape;
+}
+
+rtl::Reference<SvxShapeText>
+ ShapeFactory::createText( const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
+ const awt::Size& rSize,
+ const awt::Point& rPos,
+ uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString,
+ const uno::Reference<
+ beans::XPropertySet > & xTextProperties,
+ double nRotation, const OUString& aName, sal_Int32 nTextMaxWidth )
+{
+ //create shape and add to page
+ rtl::Reference<SvxShapeText> xShape = new SvxShapeText(nullptr);
+ xShape->setShapeKind(SdrObjKind::Text);
+ try
+ {
+ xTarget->addShape(*xShape);
+
+ //set text and text properties
+ uno::Reference< text::XTextCursor > xTextCursor( xShape->createTextCursor() );
+ if( !xTextCursor.is() )
+ return xShape;
+
+ tPropertyNameValueMap aValueMap;
+ //fill line-, fill- and paragraph-properties into the ValueMap
+ {
+ tPropertyNameMap aNameMap = PropertyMapper::getPropertyNameMapForParagraphProperties();
+ auto const & add = PropertyMapper::getPropertyNameMapForFillAndLineProperties();
+ aNameMap.insert(add.begin(), add.end());
+
+ PropertyMapper::getValueMap( aValueMap, aNameMap, xTextProperties );
+ }
+
+ //fill some more shape properties into the ValueMap
+ {
+ aValueMap.insert( { "TextHorizontalAdjust", uno::Any(drawing::TextHorizontalAdjust_CENTER) } ); // drawing::TextHorizontalAdjust
+ aValueMap.insert( { "TextVerticalAdjust", uno::Any(drawing::TextVerticalAdjust_CENTER) } ); //drawing::TextVerticalAdjust
+ aValueMap.insert( { "TextAutoGrowHeight", uno::Any(true) } ); // sal_Bool
+ aValueMap.insert( { "TextAutoGrowWidth", uno::Any(true) } ); // sal_Bool
+ aValueMap.insert( { "TextMaximumFrameWidth", uno::Any(nTextMaxWidth) } ); // sal_Int32
+
+ //set name/classified ObjectID (CID)
+ if( !aName.isEmpty() )
+ aValueMap.emplace( "Name", uno::Any( aName ) ); //CID OUString
+ }
+
+ //set global title properties
+ {
+ tNameSequence aPropNames;
+ tAnySequence aPropValues;
+ PropertyMapper::getMultiPropertyListsFromValueMap( aPropNames, aPropValues, aValueMap );
+ PropertyMapper::setMultiProperties( aPropNames, aPropValues, *xShape );
+ }
+
+ bool bStackCharacters(false);
+ try
+ {
+ xTextProperties->getPropertyValue( "StackCharacters" ) >>= bStackCharacters;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ if(bStackCharacters)
+ {
+ //if the characters should be stacked we use only the first character properties for code simplicity
+ if( xFormattedString.hasElements() )
+ {
+ OUString aLabel;
+ for( const auto & i : std::as_const(xFormattedString) )
+ aLabel += i->getString();
+ aLabel = ShapeFactory::getStackedString( aLabel, bStackCharacters );
+
+ xTextCursor->gotoEnd(false);
+ xShape->insertString( xTextCursor, aLabel, false );
+ xTextCursor->gotoEnd(true);
+ uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY );
+
+ PropertyMapper::setMappedProperties( *xShape, xSourceProps
+ , PropertyMapper::getPropertyNameMapForCharacterProperties() );
+
+ // adapt font size according to page size
+ awt::Size aOldRefSize;
+ if( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize )
+ {
+ RelativeSizeHelper::adaptFontSizes( *xShape, aOldRefSize, rSize );
+ }
+ }
+ }
+ else
+ {
+ for( const uno::Reference< chart2::XFormattedString >& rxFS : std::as_const(xFormattedString) )
+ {
+ xTextCursor->gotoEnd(false);
+ xShape->insertString( xTextCursor, rxFS->getString(), false );
+ xTextCursor->gotoEnd(true);
+ }
+ awt::Size aOldRefSize;
+ bool bHasRefPageSize =
+ ( xTextProperties->getPropertyValue( "ReferencePageSize") >>= aOldRefSize );
+
+ if( xFormattedString.hasElements() )
+ {
+ uno::Reference< beans::XPropertySet > xSourceProps( xFormattedString[0], uno::UNO_QUERY );
+ PropertyMapper::setMappedProperties( *xShape, xSourceProps, PropertyMapper::getPropertyNameMapForCharacterProperties() );
+
+ // adapt font size according to page size
+ if( bHasRefPageSize )
+ {
+ RelativeSizeHelper::adaptFontSizes( *xShape, aOldRefSize, rSize );
+ }
+ }
+ }
+
+ // #i109336# Improve auto positioning in chart
+ float fFontHeight = 0.0;
+ if ( xShape->SvxShape::getPropertyValue( "CharHeight" ) >>= fFontHeight )
+ {
+ fFontHeight = convertPointToMm100(fFontHeight);
+ sal_Int32 nXDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * 0.18f ) );
+ sal_Int32 nYDistance = static_cast< sal_Int32 >( ::rtl::math::round( fFontHeight * 0.30f ) );
+ xShape->SvxShape::setPropertyValue( "TextLeftDistance", uno::Any( nXDistance ) );
+ xShape->SvxShape::setPropertyValue( "TextRightDistance", uno::Any( nXDistance ) );
+ xShape->SvxShape::setPropertyValue( "TextUpperDistance", uno::Any( nYDistance ) );
+ xShape->SvxShape::setPropertyValue( "TextLowerDistance", uno::Any( nYDistance ) );
+ }
+ sal_Int32 nXPos = rPos.X;
+ sal_Int32 nYPos = rPos.Y;
+
+ //set position matrix
+ //the matrix needs to be set at the end behind autogrow and such position influencing properties
+ ::basegfx::B2DHomMatrix aM;
+ aM.rotate( -basegfx::deg2rad(nRotation) );//#i78696#->#i80521#
+ aM.translate( nXPos, nYPos );
+ xShape->SvxShape::setPropertyValue( "Transformation", uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ) );
+
+ xShape->SvxShape::setPropertyValue( "ParaAdjust", uno::Any( style::ParagraphAdjust_CENTER ) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return xShape;
+}
+
+rtl::Reference<SvxShapeGroupAnyD> ShapeFactory::getChartRootShape(
+ const rtl::Reference<SvxDrawPage>& xDrawPage )
+{
+ rtl::Reference<SvxShapeGroupAnyD> xRet;
+ const uno::Reference< drawing::XShapes > xShapes = xDrawPage;
+ if( xShapes.is() )
+ {
+ sal_Int32 nCount = xShapes->getCount();
+ uno::Reference< drawing::XShape > xShape;
+ for( sal_Int32 nN = nCount; nN--; )
+ {
+ if( xShapes->getByIndex( nN ) >>= xShape )
+ {
+ if( ShapeFactory::getShapeName( xShape ) == "com.sun.star.chart2.shapes" )
+ {
+ xRet = dynamic_cast<SvxShapeGroupAnyD*>(xShape.get());
+ assert(xRet);
+ break;
+ }
+ }
+ }
+ }
+ return xRet;
+}
+
+void ShapeFactory::makeShapeInvisible( const rtl::Reference< SvxShape >& xShape )
+{
+ try
+ {
+ xShape->setPropertyValue( "LineStyle", uno::Any( drawing::LineStyle_NONE ));
+ xShape->setPropertyValue( "FillStyle", uno::Any( drawing::FillStyle_NONE ));
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+// set a name/CID at a shape (is used for selection handling)
+
+void ShapeFactory::setShapeName( const rtl::Reference< SvxShape >& xShape
+ , const OUString& rName )
+{
+ if(!xShape.is())
+ return;
+ try
+ {
+ xShape->setPropertyValue( UNO_NAME_MISC_OBJ_NAME
+ , uno::Any( rName ) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+OUString ShapeFactory::getShapeName( const uno::Reference< drawing::XShape >& xShape )
+{
+ OUString aRet;
+
+ uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+ OSL_ENSURE(xProp.is(), "shape offers no XPropertySet");
+ if( xProp.is())
+ {
+ try
+ {
+ xProp->getPropertyValue( UNO_NAME_MISC_OBJ_NAME ) >>= aRet;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+
+ return aRet;
+}
+
+uno::Any ShapeFactory::makeTransformation( const awt::Point& rScreenPosition2D, double fRotationAnglePi )
+{
+ ::basegfx::B2DHomMatrix aM;
+ //As autogrow is active the rectangle is automatically expanded to that side
+ //to which the text is not adjusted.
+ // aM.scale( 1, 1 ); Oops? A scale with this parameters is neutral, line commented out
+ aM.rotate( fRotationAnglePi );
+ aM.translate( rScreenPosition2D.X, rScreenPosition2D.Y );
+ uno::Any aATransformation( B2DHomMatrixToHomogenMatrix3(aM) );
+ return aATransformation;
+}
+
+OUString ShapeFactory::getStackedString( const OUString& rString, bool bStacked )
+{
+ sal_Int32 nLen = rString.getLength();
+ if(!bStacked || !nLen)
+ return rString;
+
+ OUStringBuffer aStackStr;
+
+ //add a newline after each letter
+ //as we do not no letters here add a newline after each char
+ for( sal_Int32 nPosSrc=0; nPosSrc < nLen; nPosSrc++ )
+ {
+ if( nPosSrc )
+ aStackStr.append( '\r' );
+ aStackStr.append(rString[nPosSrc]);
+ }
+ return aStackStr.makeStringAndClear();
+}
+
+bool ShapeFactory::hasPolygonAnyLines( const std::vector<std::vector<css::drawing::Position3D>>& rPoly)
+{
+ // #i67757# check all contained polygons, if at least one polygon contains 2 or more points, return true
+ for( auto const & i : rPoly )
+ if( i.size() > 1 )
+ return true;
+ return false;
+}
+
+bool ShapeFactory::isPolygonEmptyOrSinglePoint( const drawing::PolyPolygonShape3D& rPoly)
+{
+ // true, if empty polypolygon or one polygon with one point
+ return !rPoly.SequenceX.hasElements() ||
+ ((rPoly.SequenceX.getLength() == 1) && (rPoly.SequenceX[0].getLength() <= 1));
+}
+
+bool ShapeFactory::isPolygonEmptyOrSinglePoint( const std::vector<std::vector<css::drawing::Position3D>>& rPoly)
+{
+ // true, if empty polypolygon or one polygon with one point
+ return rPoly.empty() || ((rPoly.size() == 1) && (rPoly[0].size() <= 1));
+}
+
+void ShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly)
+{
+ OSL_ENSURE( rPoly.SequenceX.getLength() <= 1, "ShapeFactory::closePolygon - single polygon expected" );
+ //add a last point == first point
+ if(isPolygonEmptyOrSinglePoint(rPoly))
+ return;
+ drawing::Position3D aFirst(rPoly.SequenceX[0][0],rPoly.SequenceY[0][0],rPoly.SequenceZ[0][0]);
+ AddPointToPoly( rPoly, aFirst );
+}
+
+void ShapeFactory::closePolygon( std::vector<std::vector<css::drawing::Position3D>>& rPoly)
+{
+ OSL_ENSURE( rPoly.size() <= 1, "ShapeFactory::closePolygon - single polygon expected" );
+ //add a last point == first point
+ if(isPolygonEmptyOrSinglePoint(rPoly))
+ return;
+ drawing::Position3D aFirst(rPoly[0][0]);
+ AddPointToPoly( rPoly, aFirst );
+}
+
+awt::Size ShapeFactory::calculateNewSizeRespectingAspectRatio(
+ const awt::Size& rTargetSize
+ , const awt::Size& rSourceSizeWithCorrectAspectRatio )
+{
+ awt::Size aNewSize;
+
+ double fFactorWidth = double(rTargetSize.Width)/double(rSourceSizeWithCorrectAspectRatio.Width);
+ double fFactorHeight = double(rTargetSize.Height)/double(rSourceSizeWithCorrectAspectRatio.Height);
+ double fFactor = std::min(fFactorWidth,fFactorHeight);
+ aNewSize.Width=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Width);
+ aNewSize.Height=static_cast<sal_Int32>(fFactor*rSourceSizeWithCorrectAspectRatio.Height);
+
+ return aNewSize;
+}
+
+awt::Point ShapeFactory::calculateTopLeftPositionToCenterObject(
+ const awt::Point& rTargetAreaPosition
+ , const awt::Size& rTargetAreaSize
+ , const awt::Size& rObjectSize )
+{
+ awt::Point aNewPosition(rTargetAreaPosition);
+ aNewPosition.X += static_cast<sal_Int32>(double(rTargetAreaSize.Width-rObjectSize.Width)/2.0);
+ aNewPosition.Y += static_cast<sal_Int32>(double(rTargetAreaSize.Height-rObjectSize.Height)/2.0);
+ return aNewPosition;
+}
+
+::basegfx::B2IRectangle ShapeFactory::getRectangleOfShape( SvxShape& rShape )
+{
+ ::basegfx::B2IRectangle aRet;
+
+ awt::Point aPos = rShape.getPosition();
+ awt::Size aSize = rShape.getSize();
+ aRet = BaseGFXHelper::makeRectangle(aPos,aSize);
+
+ return aRet;
+}
+
+awt::Size ShapeFactory::getSizeAfterRotation(
+ SvxShape& rShape, double fRotationAngleDegree )
+{
+ awt::Size aRet(0,0);
+ const awt::Size aSize( rShape.getSize() );
+
+ if( fRotationAngleDegree == 0.0 )
+ aRet = aSize;
+ else
+ {
+ fRotationAngleDegree = NormAngle360(fRotationAngleDegree);
+ if(fRotationAngleDegree>270.0)
+ fRotationAngleDegree=360.0-fRotationAngleDegree;
+ else if(fRotationAngleDegree>180.0)
+ fRotationAngleDegree=fRotationAngleDegree-180.0;
+ else if(fRotationAngleDegree>90.0)
+ fRotationAngleDegree=180.0-fRotationAngleDegree;
+
+ const double fAnglePi = basegfx::deg2rad(fRotationAngleDegree);
+
+ aRet.Height = static_cast<sal_Int32>(
+ aSize.Width*std::sin( fAnglePi )
+ + aSize.Height*std::cos( fAnglePi ));
+ aRet.Width = static_cast<sal_Int32>(
+ aSize.Width*std::cos( fAnglePi )
+ + aSize.Height*std::sin( fAnglePi ));
+ }
+ return aRet;
+}
+
+void ShapeFactory::removeSubShapes( const rtl::Reference<SvxShapeGroupAnyD>& xShapes )
+{
+ if( xShapes.is() )
+ {
+ sal_Int32 nSubCount = xShapes->getCount();
+ uno::Reference< drawing::XShape > xShape;
+ for( sal_Int32 nS = nSubCount; nS--; )
+ {
+ if( xShapes->getByIndex( nS ) >>= xShape )
+ xShapes->remove( xShape );
+ }
+ }
+}
+
+rtl::Reference<SvxTableShape>
+ShapeFactory::createTable(rtl::Reference<SvxShapeGroupAnyD> const& xTarget, OUString const& rName)
+{
+ if (!xTarget.is())
+ return nullptr;
+
+ //create table shape
+ rtl::Reference<SvxTableShape> xShape = new SvxTableShape(nullptr);
+ xShape->setShapeKind(SdrObjKind::Table);
+ xTarget->addShape(*xShape);
+ if (!rName.isEmpty())
+ setShapeName(xShape, rName);
+ return xShape;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/Stripe.cxx b/chart2/source/view/main/Stripe.cxx
new file mode 100644
index 0000000000..74c8ad0468
--- /dev/null
+++ b/chart2/source/view/main/Stripe.cxx
@@ -0,0 +1,347 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <Stripe.hxx>
+#include <CommonConverters.hxx>
+#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
+#include <basegfx/polygon/b3dpolygon.hxx>
+
+using namespace ::com::sun::star;
+
+namespace chart
+{
+
+Stripe::Stripe( const drawing::Position3D& rPoint1
+ , const drawing::Direction3D& rDirectionToPoint2
+ , const drawing::Direction3D& rDirectionToPoint4 )
+ : m_aPoint1(rPoint1)
+ , m_aPoint2(rPoint1+rDirectionToPoint2)
+ , m_aPoint3(m_aPoint2+rDirectionToPoint4)
+ , m_aPoint4(rPoint1+rDirectionToPoint4)
+ , m_bInvertNormal(false)
+ , m_bManualNormalSet(false)
+{
+}
+
+Stripe::Stripe( const drawing::Position3D& rPoint1
+ , const drawing::Position3D& rPoint2
+ , double fDepth )
+ : m_aPoint1(rPoint1)
+ , m_aPoint2(rPoint2)
+ , m_aPoint3(rPoint2)
+ , m_aPoint4(rPoint1)
+ , m_bInvertNormal(false)
+ , m_bManualNormalSet(false)
+{
+ m_aPoint3.PositionZ += fDepth;
+ m_aPoint4.PositionZ += fDepth;
+}
+
+Stripe::Stripe( const drawing::Position3D& rPoint1
+ , const drawing::Position3D& rPoint2
+ , const drawing::Position3D& rPoint3
+ , const drawing::Position3D& rPoint4 )
+ : m_aPoint1(rPoint1)
+ , m_aPoint2(rPoint2)
+ , m_aPoint3(rPoint3)
+ , m_aPoint4(rPoint4)
+ , m_bInvertNormal(false)
+ , m_bManualNormalSet(false)
+{
+}
+
+void Stripe::SetManualNormal( const drawing::Direction3D& rNormal )
+{
+ m_aManualNormal = rNormal;
+ m_bManualNormalSet = true;
+}
+
+void Stripe::InvertNormal( bool bInvertNormal )
+{
+ m_bInvertNormal = bInvertNormal;
+}
+
+uno::Any Stripe::getPolyPolygonShape3D() const
+{
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(1);
+ aPP.SequenceY.realloc(1);
+ aPP.SequenceZ.realloc(1);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(4);
+ pOuterSequenceY->realloc(4);
+ pOuterSequenceZ->realloc(4);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ *pInnerSequenceX++ = m_aPoint1.PositionX;
+ *pInnerSequenceY++ = m_aPoint1.PositionY;
+ *pInnerSequenceZ++ = m_aPoint1.PositionZ;
+
+ *pInnerSequenceX++ = m_aPoint2.PositionX;
+ *pInnerSequenceY++ = m_aPoint2.PositionY;
+ *pInnerSequenceZ++ = m_aPoint2.PositionZ;
+
+ *pInnerSequenceX++ = m_aPoint3.PositionX;
+ *pInnerSequenceY++ = m_aPoint3.PositionY;
+ *pInnerSequenceZ++ = m_aPoint3.PositionZ;
+
+ *pInnerSequenceX++ = m_aPoint4.PositionX;
+ *pInnerSequenceY++ = m_aPoint4.PositionY;
+ *pInnerSequenceZ++ = m_aPoint4.PositionZ;
+
+ return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
+}
+
+drawing::Direction3D Stripe::getNormal() const
+{
+ drawing::Direction3D aRet(1.0,0.0,0.0);
+
+ if( m_bManualNormalSet )
+ aRet = m_aManualNormal;
+ else
+ {
+ ::basegfx::B3DPolygon aPolygon3D;
+ aPolygon3D.append(Position3DToB3DPoint( m_aPoint1 ));
+ aPolygon3D.append(Position3DToB3DPoint( m_aPoint2 ));
+ aPolygon3D.append(Position3DToB3DPoint( m_aPoint3 ));
+ aPolygon3D.append(Position3DToB3DPoint( m_aPoint4 ));
+ ::basegfx::B3DVector aNormal(aPolygon3D.getNormal());
+ aRet = B3DVectorToDirection3D(aNormal);
+ }
+
+ if( m_bInvertNormal )
+ {
+ aRet.DirectionX *= -1.0;
+ aRet.DirectionY *= -1.0;
+ aRet.DirectionZ *= -1.0;
+ }
+ return aRet;
+}
+
+uno::Any Stripe::getNormalsPolygon() const
+{
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(1);
+ aPP.SequenceY.realloc(1);
+ aPP.SequenceZ.realloc(1);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(4);
+ pOuterSequenceY->realloc(4);
+ pOuterSequenceZ->realloc(4);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ drawing::Direction3D aNormal( getNormal() );
+
+ for(sal_Int32 nN=4; --nN; )
+ {
+ *pInnerSequenceX++ = aNormal.DirectionX;
+ *pInnerSequenceY++ = aNormal.DirectionY;
+ *pInnerSequenceZ++ = aNormal.DirectionZ;
+ }
+ return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
+}
+
+uno::Any Stripe::getTexturePolygon( short nRotatedTexture )
+{
+ drawing::PolyPolygonShape3D aPP;
+
+ aPP.SequenceX.realloc(1);
+ aPP.SequenceY.realloc(1);
+ aPP.SequenceZ.realloc(1);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPP.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPP.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPP.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(4);
+ pOuterSequenceY->realloc(4);
+ pOuterSequenceZ->realloc(4);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ if( nRotatedTexture==0 )
+ {
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==1 )
+ {
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==2 )
+ {
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==3 )
+ {
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==4 )
+ {
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==5 )
+ {
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==6 )
+ {
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+ else if( nRotatedTexture==7 )
+ {
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 1.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 0.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+
+ *pInnerSequenceX++ = 1.0;
+ *pInnerSequenceY++ = 0.0;
+ *pInnerSequenceZ++ = 0.0;
+ }
+
+ return uno::Any( &aPP, cppu::UnoType<drawing::PolyPolygonShape3D>::get());
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/VButton.cxx b/chart2/source/view/main/VButton.cxx
new file mode 100644
index 0000000000..25a770fb04
--- /dev/null
+++ b/chart2/source/view/main/VButton.cxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "VButton.hxx"
+
+#include <ShapeFactory.hxx>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+
+#include <CommonConverters.hxx>
+#include <editeng/unoprnms.hxx>
+
+namespace chart
+{
+using namespace css;
+
+VButton::VButton()
+ : m_bShowArrow(true)
+ , m_nArrowColor(0x00000000)
+ , m_nBGColor(0x00E6E6E6)
+{
+}
+
+void VButton::init(const rtl::Reference<SvxShapeGroupAnyD>& xTargetPage)
+{
+ m_xTarget = xTargetPage;
+}
+
+rtl::Reference<SvxShapePolyPolygon> VButton::createTriangle(awt::Size aSize)
+{
+ rtl::Reference<SvxShapePolyPolygon> xShape = new SvxShapePolyPolygon(nullptr);
+ xShape->setShapeKind(SdrObjKind::Polygon);
+
+ drawing::PolyPolygonShape3D aPolyPolygon;
+ aPolyPolygon.SequenceX.realloc(1);
+ aPolyPolygon.SequenceY.realloc(1);
+ aPolyPolygon.SequenceZ.realloc(1);
+
+ drawing::DoubleSequence* pOuterSequenceX = aPolyPolygon.SequenceX.getArray();
+ drawing::DoubleSequence* pOuterSequenceY = aPolyPolygon.SequenceY.getArray();
+ drawing::DoubleSequence* pOuterSequenceZ = aPolyPolygon.SequenceZ.getArray();
+
+ pOuterSequenceX->realloc(3);
+ pOuterSequenceY->realloc(3);
+ pOuterSequenceZ->realloc(3);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ pInnerSequenceX[0] = 0.0;
+ pInnerSequenceY[0] = 0.0;
+ pInnerSequenceZ[0] = 0.0;
+
+ pInnerSequenceX[1] = aSize.Width / 2.0;
+ pInnerSequenceY[1] = aSize.Height;
+ pInnerSequenceZ[1] = 0.0;
+
+ pInnerSequenceX[2] = aSize.Width;
+ pInnerSequenceY[2] = 0.0;
+ pInnerSequenceZ[2] = 0.0;
+
+ xShape->SvxShape::setPropertyValue("Name", uno::Any(m_sCID));
+ xShape->SvxShape::setPropertyValue(UNO_NAME_POLYPOLYGON,
+ uno::Any(PolyToPointSequence(aPolyPolygon)));
+ xShape->SvxShape::setPropertyValue("LineStyle", uno::Any(drawing::LineStyle_NONE));
+ xShape->SvxShape::setPropertyValue("FillColor", uno::Any(m_nArrowColor));
+
+ return xShape;
+}
+
+void VButton::createShapes(const uno::Reference<beans::XPropertySet>& xTextProp)
+{
+ tNameSequence aPropNames;
+ tAnySequence aPropValues;
+
+ PropertyMapper::getTextLabelMultiPropertyLists(xTextProp, aPropNames, aPropValues);
+
+ m_xShape = ShapeFactory::createGroup2D(m_xTarget, m_sCID);
+ m_xShape->setPosition(m_aPosition);
+ m_xShape->setSize(m_aSize);
+
+ rtl::Reference<SvxShapeGroupAnyD> xContainer = m_xShape;
+
+ tPropertyNameValueMap aTextValueMap;
+ aTextValueMap["CharHeight"] <<= 10.0f;
+ aTextValueMap["CharHeightAsian"] <<= 10.0f;
+ aTextValueMap["CharHeightComplex"] <<= 10.0f;
+ aTextValueMap["FillColor"] <<= m_nBGColor;
+ aTextValueMap["FillStyle"] <<= drawing::FillStyle_SOLID;
+ aTextValueMap["LineColor"] <<= sal_Int32(0xcccccc);
+ aTextValueMap["LineStyle"] <<= drawing::LineStyle_SOLID;
+ aTextValueMap["ParaAdjust"] <<= style::ParagraphAdjust_CENTER;
+ aTextValueMap["TextHorizontalAdjust"] <<= drawing::TextHorizontalAdjust_LEFT;
+ aTextValueMap["TextVerticalAdjust"] <<= drawing::TextVerticalAdjust_CENTER;
+ aTextValueMap["ParaLeftMargin"] <<= sal_Int32(100);
+ aTextValueMap["ParaRightMargin"] <<= sal_Int32(600);
+
+ aTextValueMap["Name"] <<= m_sCID; //CID OUString
+
+ PropertyMapper::getMultiPropertyListsFromValueMap(aPropNames, aPropValues, aTextValueMap);
+
+ rtl::Reference<SvxShapeText> xEntry
+ = ShapeFactory::createText(xContainer, m_sLabel, aPropNames, aPropValues, uno::Any());
+
+ if (xEntry.is())
+ {
+ xEntry->setPosition(m_aPosition);
+ xEntry->setSize(m_aSize);
+ }
+
+ if (!m_bShowArrow)
+ return;
+
+ awt::Size aPolySize{ 280, 180 };
+
+ rtl::Reference<SvxShapePolyPolygon> xPoly = createTriangle(aPolySize);
+ xPoly->setSize(aPolySize);
+ xPoly->setPosition(
+ { sal_Int32(m_aPosition.X + m_aSize.Width - aPolySize.Width - 100),
+ sal_Int32(m_aPosition.Y + (m_aSize.Height / 2.0) - (aPolySize.Height / 2.0)) });
+ xContainer->add(xPoly);
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/VButton.hxx b/chart2/source/view/main/VButton.hxx
new file mode 100644
index 0000000000..87017f3690
--- /dev/null
+++ b/chart2/source/view/main/VButton.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <tools/color.hxx>
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::drawing { class XShape; }
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+
+namespace chart
+{
+
+class VButton final
+{
+private:
+ rtl::Reference<SvxShapeGroupAnyD> m_xTarget;
+ rtl::Reference<SvxShapeGroup> m_xShape;
+ OUString m_sLabel;
+ OUString m_sCID;
+ css::awt::Point m_aPosition;
+ css::awt::Size m_aSize;
+ bool m_bShowArrow;
+ Color m_nArrowColor;
+ Color m_nBGColor;
+
+ rtl::Reference<SvxShapePolyPolygon>
+ createTriangle(css::awt::Size aSize);
+
+public:
+ VButton();
+
+ void init(const rtl::Reference<SvxShapeGroupAnyD>& xTargetPage);
+
+ void createShapes(const css::uno::Reference<css::beans::XPropertySet>& xTextProp);
+
+ void showArrow(bool bShowArrow)
+ {
+ m_bShowArrow = bShowArrow;
+ }
+ void setArrowColor(Color nArrowColor)
+ {
+ m_nArrowColor = nArrowColor;
+ }
+ void setBGColor(Color nBGColor)
+ {
+ m_nBGColor = nBGColor;
+ }
+ void setLabel(OUString const & rLabel)
+ {
+ m_sLabel = rLabel;
+ }
+ void setCID(OUString const & rCID)
+ {
+ m_sCID = rCID;
+ }
+ void setPosition(css::awt::Point const & rPosition)
+ {
+ m_aPosition = rPosition;
+ }
+ css::awt::Size const & getSize() const
+ {
+ return m_aSize;
+ }
+ void setSize(css::awt::Size const & rSize)
+ {
+ m_aSize = rSize;
+ }
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/VDataSeries.cxx b/chart2/source/view/main/VDataSeries.cxx
new file mode 100644
index 0000000000..abfc7766d7
--- /dev/null
+++ b/chart2/source/view/main/VDataSeries.cxx
@@ -0,0 +1,1122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <limits>
+#include <memory>
+#include <VDataSeries.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesProperties.hxx>
+#include <ObjectIdentifier.hxx>
+#include <CommonConverters.hxx>
+#include <LabelPositionHelper.hxx>
+#include <ChartType.hxx>
+#include <ChartTypeHelper.hxx>
+#include <RegressionCurveCalculator.hxx>
+#include <RegressionCurveHelper.hxx>
+#include <unonames.hxx>
+
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/chart2/XRegressionCurveCalculator.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+
+#include <osl/diagnose.h>
+#include <tools/color.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+
+namespace chart {
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using namespace ::chart::DataSeriesProperties;
+
+void VDataSequence::init( const uno::Reference< data::XDataSequence >& xModel )
+{
+ m_xModel = xModel;
+ m_aValues = DataSequenceToDoubleSequence( xModel );
+}
+
+bool VDataSequence::is() const
+{
+ return m_xModel.is();
+}
+void VDataSequence::clear()
+{
+ m_xModel = nullptr;
+ m_aValues.realloc(0);
+}
+
+double VDataSequence::getValue( sal_Int32 index ) const
+{
+ if( 0<=index && index<m_aValues.getLength() )
+ return m_aValues[index];
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+sal_Int32 VDataSequence::detectNumberFormatKey( sal_Int32 index ) const
+{
+ sal_Int32 nNumberFormatKey = -1;
+
+ // -1 is allowed and means a key for the whole sequence
+ if( -1<=index && index<m_aValues.getLength() && m_xModel.is())
+ {
+ nNumberFormatKey = m_xModel->getNumberFormatKeyByIndex( index );
+ }
+
+ return nNumberFormatKey;
+}
+
+sal_Int32 VDataSequence::getLength() const
+{
+ return m_aValues.getLength();
+}
+
+namespace
+{
+struct lcl_LessXOfPoint
+{
+ bool operator() ( const std::vector< double >& first,
+ const std::vector< double >& second )
+ {
+ if( !first.empty() && !second.empty() )
+ {
+ return first[0]<second[0];
+ }
+ return false;
+ }
+};
+
+void lcl_clearIfNoValuesButTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence )
+{
+ //#i71686#, #i101968#, #i102428#
+ sal_Int32 nCount = rData.m_aValues.getLength();
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ if( !std::isnan( rData.m_aValues[i] ) )
+ return;
+ }
+ //no double value is contained
+ //is there any text?
+ uno::Sequence< OUString > aStrings( DataSequenceToStringSequence( xDataSequence ) );
+ sal_Int32 nTextCount = aStrings.getLength();
+ for( sal_Int32 j = 0; j < nTextCount; ++j )
+ {
+ if( !aStrings[j].isEmpty() )
+ {
+ rData.clear();
+ return;
+ }
+ }
+ //no content at all
+}
+
+void lcl_maybeReplaceNanWithZero( double& rfValue, sal_Int32 nMissingValueTreatment )
+{
+ if( nMissingValueTreatment == css::chart::MissingValueTreatment::USE_ZERO
+ && (std::isnan(rfValue) || std::isinf(rfValue)) )
+ rfValue = 0.0;
+}
+
+}
+
+VDataSeries::VDataSeries( const rtl::Reference< DataSeries >& xDataSeries )
+ : m_nPolygonIndex(0)
+ , m_fLogicMinX(0.0)
+ , m_fLogicMaxX(0.0)
+ , m_fLogicZPos(0.0)
+ , m_xDataSeries(xDataSeries)
+ , m_nPointCount(0)
+ , m_pValueSequenceForDataLabelNumberFormatDetection(&m_aValues_Y)
+ , m_fXMeanValue(std::numeric_limits<double>::quiet_NaN())
+ , m_fYMeanValue(std::numeric_limits<double>::quiet_NaN())
+ , m_eStackingDirection(StackingDirection_NO_STACKING)
+ , m_nAxisIndex(0)
+ , m_bConnectBars(false)
+ , m_bGroupBarsPerAxis(true)
+ , m_nStartingAngle(90)
+ , m_nGlobalSeriesIndex(0)
+ , m_nCurrentAttributedPoint(-1)
+ , m_nMissingValueTreatment(css::chart::MissingValueTreatment::LEAVE_GAP)
+ , m_bAllowPercentValueInDataLabel(false)
+ , mpOldSeries(nullptr)
+ , mnPercent(0.0)
+{
+ m_xDataSeriesProps = m_xDataSeries;
+
+ const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aDataSequences =
+ m_xDataSeries->getDataSequences2();
+
+ for(sal_Int32 nN = aDataSequences.size();nN--;)
+ {
+ uno::Reference<data::XDataSequence> xDataSequence( aDataSequences[nN]->getValues());
+ uno::Reference<beans::XPropertySet> xProp(xDataSequence, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ try
+ {
+ uno::Any aARole = xProp->getPropertyValue("Role");
+ OUString aRole;
+ aARole >>= aRole;
+
+ if (aRole == "values-x")
+ {
+ m_aValues_X.init( xDataSequence );
+ lcl_clearIfNoValuesButTextIsContained( m_aValues_X, xDataSequence );
+ }
+ else if (aRole =="values-y")
+ m_aValues_Y.init( xDataSequence );
+ else if (aRole == "values-min")
+ m_aValues_Y_Min.init( xDataSequence );
+ else if (aRole == "values-max")
+ m_aValues_Y_Max.init( xDataSequence );
+ else if (aRole == "values-first")
+ m_aValues_Y_First.init( xDataSequence );
+ else if (aRole == "values-last")
+ m_aValues_Y_Last.init( xDataSequence );
+ else if (aRole == "values-size")
+ m_aValues_Bubble_Size.init( xDataSequence );
+ else
+ {
+ VDataSequence aSequence;
+ aSequence.init(xDataSequence);
+ m_PropertyMap.insert(std::make_pair(aRole, aSequence));
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ }
+ }
+
+ //determine the point count
+ m_nPointCount = m_aValues_Y.getLength();
+ {
+ if( m_nPointCount < m_aValues_Bubble_Size.getLength() )
+ m_nPointCount = m_aValues_Bubble_Size.getLength();
+ if( m_nPointCount < m_aValues_Y_Min.getLength() )
+ m_nPointCount = m_aValues_Y_Min.getLength();
+ if( m_nPointCount < m_aValues_Y_Max.getLength() )
+ m_nPointCount = m_aValues_Y_Max.getLength();
+ if( m_nPointCount < m_aValues_Y_First.getLength() )
+ m_nPointCount = m_aValues_Y_First.getLength();
+ if( m_nPointCount < m_aValues_Y_Last.getLength() )
+ m_nPointCount = m_aValues_Y_Last.getLength();
+ }
+
+ if( !xDataSeries.is())
+ return;
+
+ try
+ {
+ // "AttributedDataPoints"
+ xDataSeries->getFastPropertyValue(PROP_DATASERIES_ATTRIBUTED_DATA_POINTS) >>= m_aAttributedDataPointIndexList;
+
+ xDataSeries->getFastPropertyValue(PROP_DATASERIES_STACKING_DIRECTION) >>= m_eStackingDirection; // "StackingDirection"
+
+ xDataSeries->getFastPropertyValue(PROP_DATASERIES_ATTACHED_AXIS_INDEX) >>= m_nAxisIndex; // "AttachedAxisIndex"
+ if(m_nAxisIndex<0)
+ m_nAxisIndex=0;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+VDataSeries::~VDataSeries()
+{
+}
+
+void VDataSeries::doSortByXValues()
+{
+ if( !(m_aValues_X.is() && m_aValues_X.m_aValues.hasElements()) )
+ return;
+
+ //prepare a vector for sorting
+ std::vector< std::vector< double > > aTmp;//outer vector are points, inner vector are the different values of the point
+ sal_Int32 nPointIndex = 0;
+ for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ )
+ {
+ aTmp.push_back(
+ { ((nPointIndex < m_aValues_X.m_aValues.getLength()) ? m_aValues_X.m_aValues[nPointIndex]
+ : std::numeric_limits<double>::quiet_NaN()),
+ ((nPointIndex < m_aValues_Y.m_aValues.getLength()) ? m_aValues_Y.m_aValues[nPointIndex]
+ : std::numeric_limits<double>::quiet_NaN())
+ }
+ );
+ }
+
+ //do sort
+ std::stable_sort( aTmp.begin(), aTmp.end(), lcl_LessXOfPoint() );
+
+ //fill the sorted points back to the members
+ m_aValues_X.m_aValues.realloc( m_nPointCount );
+ auto pDoublesX = m_aValues_X.m_aValues.getArray();
+ m_aValues_Y.m_aValues.realloc( m_nPointCount );
+ auto pDoublesY = m_aValues_Y.m_aValues.getArray();
+
+ for( nPointIndex=0; nPointIndex < m_nPointCount; nPointIndex++ )
+ {
+ pDoublesX[nPointIndex]=aTmp[nPointIndex][0];
+ pDoublesY[nPointIndex]=aTmp[nPointIndex][1];
+ }
+}
+
+void VDataSeries::releaseShapes()
+{
+ m_xGroupShape.clear();
+ m_xLabelsGroupShape.clear();
+ m_xErrorXBarsGroupShape.clear();
+ m_xErrorYBarsGroupShape.clear();
+ m_xFrontSubGroupShape.clear();
+ m_xBackSubGroupShape.clear();
+
+ m_aPolyPolygonShape3D.clear();
+ m_nPolygonIndex = 0;
+}
+
+const rtl::Reference<::chart::DataSeries>& VDataSeries::getModel() const
+{
+ return m_xDataSeries;
+}
+
+void VDataSeries::setCategoryXAxis()
+{
+ m_aValues_X.clear();
+ m_bAllowPercentValueInDataLabel = true;
+}
+
+void VDataSeries::setXValues( const Reference< chart2::data::XDataSequence >& xValues )
+{
+ m_aValues_X.clear();
+ m_aValues_X.init( xValues );
+ m_bAllowPercentValueInDataLabel = true;
+}
+
+void VDataSeries::setXValuesIfNone( const Reference< chart2::data::XDataSequence >& xValues )
+{
+ if( m_aValues_X.is() )
+ return;
+
+ m_aValues_X.init( xValues );
+ lcl_clearIfNoValuesButTextIsContained( m_aValues_X, xValues );
+}
+
+void VDataSeries::setGlobalSeriesIndex( sal_Int32 nGlobalSeriesIndex )
+{
+ m_nGlobalSeriesIndex = nGlobalSeriesIndex;
+}
+
+void VDataSeries::setParticle( const OUString& rSeriesParticle )
+{
+ m_aSeriesParticle = rSeriesParticle;
+
+ //get CID
+ m_aCID = ObjectIdentifier::createClassifiedIdentifierForParticle( m_aSeriesParticle );
+ m_aPointCID_Stub = ObjectIdentifier::createSeriesSubObjectStub( OBJECTTYPE_DATA_POINT, m_aSeriesParticle );
+
+ m_aLabelCID_Stub = ObjectIdentifier::createClassifiedIdentifierWithParent(
+ OBJECTTYPE_DATA_LABEL, u"", getLabelsCID() );
+}
+OUString VDataSeries::getErrorBarsCID(bool bYError) const
+{
+ OUString aChildParticle( ObjectIdentifier::getStringForType(
+ bYError ? OBJECTTYPE_DATA_ERRORS_Y : OBJECTTYPE_DATA_ERRORS_X )
+ + "=" );
+
+ return ObjectIdentifier::createClassifiedIdentifierForParticles(
+ m_aSeriesParticle, aChildParticle );
+}
+OUString VDataSeries::getLabelsCID() const
+{
+ OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) + "=" );
+
+ return ObjectIdentifier::createClassifiedIdentifierForParticles(
+ m_aSeriesParticle, aChildParticle );
+}
+OUString VDataSeries::getDataCurveCID( sal_Int32 nCurveIndex, bool bAverageLine ) const
+{
+ return ObjectIdentifier::createDataCurveCID( m_aSeriesParticle, nCurveIndex, bAverageLine );
+}
+
+OUString VDataSeries::getDataCurveEquationCID( sal_Int32 nCurveIndex ) const
+{
+ return ObjectIdentifier::createDataCurveEquationCID( m_aSeriesParticle, nCurveIndex );
+}
+void VDataSeries::setPageReferenceSize( const awt::Size & rPageRefSize )
+{
+ m_aReferenceSize = rPageRefSize;
+}
+
+void VDataSeries::setConnectBars( bool bConnectBars )
+{
+ m_bConnectBars = bConnectBars;
+}
+
+bool VDataSeries::getConnectBars() const
+{
+ return m_bConnectBars;
+}
+
+void VDataSeries::setGroupBarsPerAxis( bool bGroupBarsPerAxis )
+{
+ m_bGroupBarsPerAxis = bGroupBarsPerAxis;
+}
+
+bool VDataSeries::getGroupBarsPerAxis() const
+{
+ return m_bGroupBarsPerAxis;
+}
+
+void VDataSeries::setStartingAngle( sal_Int32 nStartingAngle )
+{
+ m_nStartingAngle = nStartingAngle;
+}
+
+sal_Int32 VDataSeries::getStartingAngle() const
+{
+ return m_nStartingAngle;
+}
+
+chart2::StackingDirection VDataSeries::getStackingDirection() const
+{
+ return m_eStackingDirection;
+}
+
+sal_Int32 VDataSeries::getAttachedAxisIndex() const
+{
+ return m_nAxisIndex;
+}
+
+void VDataSeries::setAttachedAxisIndex( sal_Int32 nAttachedAxisIndex )
+{
+ if( nAttachedAxisIndex < 0 )
+ nAttachedAxisIndex = 0;
+ m_nAxisIndex = nAttachedAxisIndex;
+}
+
+double VDataSeries::getXValue( sal_Int32 index ) const
+{
+ double fRet = std::numeric_limits<double>::quiet_NaN();
+ if(m_aValues_X.is())
+ {
+ if( 0<=index && index<m_aValues_X.getLength() )
+ {
+ fRet = m_aValues_X.m_aValues[index];
+ if(mpOldSeries && index < mpOldSeries->m_aValues_X.getLength())
+ {
+ double nOldVal = mpOldSeries->m_aValues_X.m_aValues[index];
+ fRet = nOldVal + (fRet - nOldVal) * mnPercent;
+ }
+ }
+ }
+ else
+ {
+ // #i70133# always return correct X position - needed for short data series
+ if( 0<=index /*&& index < m_nPointCount*/ )
+ fRet = index+1;//first category (index 0) matches with real number 1.0
+ }
+ lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() );
+ return fRet;
+}
+
+double VDataSeries::getYValue( sal_Int32 index ) const
+{
+ double fRet = std::numeric_limits<double>::quiet_NaN();
+ if(m_aValues_Y.is())
+ {
+ if( 0<=index && index<m_aValues_Y.getLength() )
+ {
+ fRet = m_aValues_Y.m_aValues[index];
+ if(mpOldSeries && index < mpOldSeries->m_aValues_Y.getLength())
+ {
+ double nOldVal = mpOldSeries->m_aValues_Y.m_aValues[index];
+ fRet = nOldVal + (fRet - nOldVal) * mnPercent;
+ }
+ }
+ }
+ else
+ {
+ // #i70133# always return correct X position - needed for short data series
+ if( 0<=index /*&& index < m_nPointCount*/ )
+ fRet = index+1;//first category (index 0) matches with real number 1.0
+ }
+ lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() );
+ return fRet;
+}
+
+void VDataSeries::getMinMaxXValue(double& fMin, double& fMax) const
+{
+ fMax = std::numeric_limits<double>::quiet_NaN();
+ fMin = std::numeric_limits<double>::quiet_NaN();
+
+ uno::Sequence< double > aValuesX = getAllX();
+
+ if(!aValuesX.hasElements())
+ return;
+
+ sal_Int32 i = 0;
+ while ( i < aValuesX.getLength() && std::isnan(aValuesX[i]) )
+ i++;
+ if ( i < aValuesX.getLength() )
+ fMax = fMin = aValuesX[i++];
+
+ for ( ; i < aValuesX.getLength(); i++)
+ {
+ const double aValue = aValuesX[i];
+ if ( aValue > fMax)
+ {
+ fMax = aValue;
+ }
+ else if ( aValue < fMin)
+ {
+ fMin = aValue;
+ }
+ }
+}
+double VDataSeries::getY_Min( sal_Int32 index ) const
+{
+ return m_aValues_Y_Min.getValue( index );
+}
+double VDataSeries::getY_Max( sal_Int32 index ) const
+{
+ return m_aValues_Y_Max.getValue( index );
+}
+double VDataSeries::getY_First( sal_Int32 index ) const
+{
+ return m_aValues_Y_First.getValue( index );
+}
+double VDataSeries::getY_Last( sal_Int32 index ) const
+{
+ return m_aValues_Y_Last.getValue( index );
+}
+double VDataSeries::getBubble_Size( sal_Int32 index ) const
+{
+ double nNewVal = m_aValues_Bubble_Size.getValue( index );
+ if(mpOldSeries && index < mpOldSeries->m_aValues_Bubble_Size.getLength())
+ {
+ double nOldVal = mpOldSeries->m_aValues_Bubble_Size.getValue( index );
+ nNewVal = nOldVal + (nNewVal - nOldVal) * mnPercent;
+ }
+
+ return nNewVal;
+}
+
+bool VDataSeries::hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const
+{
+ OUString aPropName = bForPercentage ? OUString("PercentageNumberFormat") : CHART_UNONAME_NUMFMT;
+ bool bHasNumberFormat = false;
+ bool bLinkToSource = true;
+ uno::Reference< beans::XPropertySet > xPointProp( getPropertiesOfPoint( nPointIndex ));
+ if( xPointProp.is() && (xPointProp->getPropertyValue(CHART_UNONAME_LINK_TO_SRC_NUMFMT) >>= bLinkToSource))
+ {
+ sal_Int32 nNumberFormat = -1;
+ if( !bLinkToSource && (xPointProp->getPropertyValue(aPropName) >>= nNumberFormat))
+ bHasNumberFormat = true;
+ }
+ return bHasNumberFormat;
+}
+sal_Int32 VDataSeries::getExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const
+{
+ OUString aPropName = bForPercentage ? OUString("PercentageNumberFormat") : CHART_UNONAME_NUMFMT;
+ sal_Int32 nNumberFormat = -1;
+ uno::Reference< beans::XPropertySet > xPointProp( getPropertiesOfPoint( nPointIndex ));
+ if( xPointProp.is() )
+ xPointProp->getPropertyValue(aPropName) >>= nNumberFormat;
+ return nNumberFormat;
+}
+void VDataSeries::setRoleOfSequenceForDataLabelNumberFormatDetection( std::u16string_view rRole )
+{
+ if (rRole == u"values-y")
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y;
+ else if (rRole == u"values-size")
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Bubble_Size;
+ else if (rRole == u"values-min")
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Min;
+ else if (rRole == u"values-max")
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Max;
+ else if (rRole == u"values-first")
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_First;
+ else if (rRole == u"values-last")
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Last;
+ else if (rRole == u"values-x")
+ m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_X;
+}
+sal_Int32 VDataSeries::detectNumberFormatKey( sal_Int32 index ) const
+{
+ sal_Int32 nRet = 0;
+ if( m_pValueSequenceForDataLabelNumberFormatDetection )
+ nRet = m_pValueSequenceForDataLabelNumberFormatDetection->detectNumberFormatKey( index );
+ return nRet;
+}
+
+sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const rtl::Reference< ChartType >& xChartType, bool bSwapXAndY ) const
+{
+ sal_Int32 nLabelPlacement=0;
+ try
+ {
+ uno::Reference< beans::XPropertySet > xPointProps( getPropertiesOfPoint( nPointIndex ) );
+ if( xPointProps.is() )
+ xPointProps->getPropertyValue("LabelPlacement") >>= nLabelPlacement;
+
+ const uno::Sequence < sal_Int32 > aAvailablePlacements( ChartTypeHelper::getSupportedLabelPlacements(
+ xChartType, bSwapXAndY, m_xDataSeries ) );
+
+ for( sal_Int32 n : aAvailablePlacements )
+ if( n == nLabelPlacement )
+ return nLabelPlacement; //ok
+
+ //otherwise use the first supported one
+ if( aAvailablePlacements.hasElements() )
+ {
+ nLabelPlacement = aAvailablePlacements[0];
+ if( xPointProps.is() )
+ xPointProps->setPropertyValue("LabelPlacement", uno::Any(nLabelPlacement));
+ return nLabelPlacement;
+ }
+
+ OSL_FAIL("no label placement supported");
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return nLabelPlacement;
+}
+
+awt::Point VDataSeries::getLabelPosition( awt::Point aTextShapePos, sal_Int32 nPointIndex ) const
+{
+ awt::Point aPos(-1, -1);
+ try
+ {
+ RelativePosition aCustomLabelPosition;
+ uno::Reference< beans::XPropertySet > xPointProps(getPropertiesOfPoint(nPointIndex));
+ if( xPointProps.is() && (xPointProps->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition))
+ {
+ aPos.X = static_cast<sal_Int32>(aCustomLabelPosition.Primary * m_aReferenceSize.Width) + aTextShapePos.X;
+ aPos.Y = static_cast<sal_Int32>(aCustomLabelPosition.Secondary * m_aReferenceSize.Height) + aTextShapePos.Y;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ return aPos;
+}
+
+bool VDataSeries::isLabelCustomPos(sal_Int32 nPointIndex) const
+{
+ bool bCustom = false;
+ try
+ {
+ if( isAttributedDataPoint(nPointIndex) )
+ {
+ uno::Reference< beans::XPropertySet > xPointProps(m_xDataSeries->getDataPointByIndex(nPointIndex));
+ RelativePosition aCustomLabelPosition;
+ if( xPointProps.is() && (xPointProps->getPropertyValue("CustomLabelPosition") >>= aCustomLabelPosition) )
+ bCustom = true;
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ return bCustom;
+}
+
+double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const
+{
+ double fMin = std::numeric_limits<double>::infinity();
+
+ if( !m_aValues_Y.is() &&
+ (m_aValues_Y_Min.is() || m_aValues_Y_Max.is()
+ || m_aValues_Y_First.is() || m_aValues_Y_Last.is() ) )
+ {
+ double fY_Min = getY_Min( index );
+ double fY_Max = getY_Max( index );
+ double fY_First = getY_First( index );
+ double fY_Last = getY_Last( index );
+
+ if(fMin>fY_First)
+ fMin=fY_First;
+ if(fMin>fY_Last)
+ fMin=fY_Last;
+ if(fMin>fY_Min)
+ fMin=fY_Min;
+ if(fMin>fY_Max)
+ fMin=fY_Max;
+ }
+ else
+ {
+ double fY = getYValue( index );
+ if(fMin>fY)
+ fMin=fY;
+ }
+
+ if( std::isinf(fMin) )
+ return std::numeric_limits<double>::quiet_NaN();
+
+ return fMin;
+}
+
+double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const
+{
+ double fMax = -std::numeric_limits<double>::infinity();
+
+ if( !m_aValues_Y.is() &&
+ (m_aValues_Y_Min.is() || m_aValues_Y_Max.is()
+ || m_aValues_Y_First.is() || m_aValues_Y_Last.is() ) )
+ {
+ double fY_Min = getY_Min( index );
+ double fY_Max = getY_Max( index );
+ double fY_First = getY_First( index );
+ double fY_Last = getY_Last( index );
+
+ if(fMax<fY_First)
+ fMax=fY_First;
+ if(fMax<fY_Last)
+ fMax=fY_Last;
+ if(fMax<fY_Min)
+ fMax=fY_Min;
+ if(fMax<fY_Max)
+ fMax=fY_Max;
+ }
+ else
+ {
+ double fY = getYValue( index );
+ if(fMax<fY)
+ fMax=fY;
+ }
+
+ if( std::isinf(fMax) )
+ return std::numeric_limits<double>::quiet_NaN();
+
+ return fMax;
+}
+
+uno::Sequence< double > const & VDataSeries::getAllX() const
+{
+ if(!m_aValues_X.is() && !m_aValues_X.getLength() && m_nPointCount)
+ {
+ //init x values from category indexes
+ //first category (index 0) matches with real number 1.0
+ m_aValues_X.m_aValues.realloc( m_nPointCount );
+ auto pDoubles = m_aValues_X.m_aValues.getArray();
+ for(sal_Int32 nN=m_aValues_X.getLength();nN--;)
+ pDoubles[nN] = nN+1;
+ }
+ return m_aValues_X.m_aValues;
+}
+
+uno::Sequence< double > const & VDataSeries::getAllY() const
+{
+ if(!m_aValues_Y.is() && !m_aValues_Y.getLength() && m_nPointCount)
+ {
+ //init y values from indexes
+ //first y-value (index 0) matches with real number 1.0
+ m_aValues_Y.m_aValues.realloc( m_nPointCount );
+ auto pDoubles = m_aValues_Y.m_aValues.getArray();
+ for(sal_Int32 nN=m_aValues_Y.getLength();nN--;)
+ pDoubles[nN] = nN+1;
+ }
+ return m_aValues_Y.m_aValues;
+}
+
+double VDataSeries::getXMeanValue() const
+{
+ if( std::isnan( m_fXMeanValue ) )
+ {
+ rtl::Reference< RegressionCurveCalculator > xCalculator( RegressionCurveHelper::createRegressionCurveCalculatorByServiceName( u"com.sun.star.chart2.MeanValueRegressionCurve" ) );
+ uno::Sequence< double > aXValuesDummy;
+ xCalculator->recalculateRegression( aXValuesDummy, getAllX() );
+ m_fXMeanValue = xCalculator->getCurveValue( 1.0 );
+ }
+ return m_fXMeanValue;
+}
+
+double VDataSeries::getYMeanValue() const
+{
+ if( std::isnan( m_fYMeanValue ) )
+ {
+ rtl::Reference< RegressionCurveCalculator > xCalculator(
+ RegressionCurveHelper::createRegressionCurveCalculatorByServiceName(u"com.sun.star.chart2.MeanValueRegressionCurve"));
+ uno::Sequence< double > aXValuesDummy;
+ xCalculator->recalculateRegression( aXValuesDummy, getAllY() );
+ m_fYMeanValue = xCalculator->getCurveValue( 1.0 );
+ }
+ return m_fYMeanValue;
+}
+
+static std::optional<Symbol> getSymbolPropertiesFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp )
+{
+ Symbol aSymbolProps;
+ try
+ {
+ if( xProp->getPropertyValue("Symbol") >>= aSymbolProps )
+ {
+ //use main color to fill symbols
+ xProp->getPropertyValue("Color") >>= aSymbolProps.FillColor;
+ // border of symbols always same as fill color
+ aSymbolProps.BorderColor = aSymbolProps.FillColor;
+ }
+ else
+ return std::nullopt;
+ }
+ catch(const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return aSymbolProps;
+}
+
+Symbol* VDataSeries::getSymbolProperties( sal_Int32 index ) const
+{
+ Symbol* pRet=nullptr;
+ if( isAttributedDataPoint( index ) )
+ {
+ adaptPointCache( index );
+ if (!m_oSymbolProperties_AttributedPoint)
+ m_oSymbolProperties_AttributedPoint
+ = getSymbolPropertiesFromPropertySet(getPropertiesOfPoint(index));
+ pRet = &*m_oSymbolProperties_AttributedPoint;
+ //if a single data point does not have symbols but the dataseries itself has symbols
+ //we create an invisible symbol shape to enable selection of that point
+ if( !pRet || pRet->Style == SymbolStyle_NONE )
+ {
+ if (!m_oSymbolProperties_Series)
+ m_oSymbolProperties_Series
+ = getSymbolPropertiesFromPropertySet(getPropertiesOfSeries());
+ if( m_oSymbolProperties_Series && m_oSymbolProperties_Series->Style != SymbolStyle_NONE )
+ {
+ if (!m_oSymbolProperties_InvisibleSymbolForSelection)
+ {
+ m_oSymbolProperties_InvisibleSymbolForSelection.emplace();
+ m_oSymbolProperties_InvisibleSymbolForSelection->Style = SymbolStyle_STANDARD;
+ m_oSymbolProperties_InvisibleSymbolForSelection->StandardSymbol = 0;//square
+ m_oSymbolProperties_InvisibleSymbolForSelection->Size = com::sun::star::awt::Size(0, 0);//tdf#126033
+ m_oSymbolProperties_InvisibleSymbolForSelection->BorderColor = 0xff000000;//invisible
+ m_oSymbolProperties_InvisibleSymbolForSelection->FillColor = 0xff000000;//invisible
+ }
+ pRet = &*m_oSymbolProperties_InvisibleSymbolForSelection;
+ }
+ }
+ }
+ else
+ {
+ if (!m_oSymbolProperties_Series)
+ m_oSymbolProperties_Series
+ = getSymbolPropertiesFromPropertySet(getPropertiesOfSeries());
+ pRet = &*m_oSymbolProperties_Series;
+ }
+
+ if( pRet && pRet->Style == SymbolStyle_AUTO )
+ {
+ pRet->Style = SymbolStyle_STANDARD;
+
+ sal_Int32 nIndex = m_nGlobalSeriesIndex;
+ if(m_aValues_X.is())
+ nIndex++;
+ pRet->StandardSymbol = nIndex;
+ }
+
+ return pRet;
+}
+
+uno::Reference< beans::XPropertySet > VDataSeries::getXErrorBarProperties( sal_Int32 index ) const
+{
+ uno::Reference< beans::XPropertySet > xErrorBarProp;
+
+ uno::Reference< beans::XPropertySet > xPointProp( getPropertiesOfPoint( index ));
+ if( xPointProp.is() )
+ xPointProp->getPropertyValue(CHART_UNONAME_ERRORBAR_X) >>= xErrorBarProp;
+ return xErrorBarProp;
+}
+
+uno::Reference< beans::XPropertySet > VDataSeries::getYErrorBarProperties( sal_Int32 index ) const
+{
+ uno::Reference< beans::XPropertySet > xErrorBarProp;
+
+ uno::Reference< beans::XPropertySet > xPointProp( getPropertiesOfPoint( index ));
+ if( xPointProp.is() )
+ xPointProp->getPropertyValue(CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarProp;
+ return xErrorBarProp;
+}
+
+bool VDataSeries::hasPointOwnColor( sal_Int32 index ) const
+{
+ if( !isAttributedDataPoint(index) )
+ return false;
+
+ try
+ {
+ uno::Reference< beans::XPropertyState > xPointState( getPropertiesOfPoint(index), uno::UNO_QUERY_THROW );
+ return (xPointState->getPropertyState("Color") != beans::PropertyState_DEFAULT_VALUE );
+ }
+ catch(const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return false;
+}
+
+bool VDataSeries::isAttributedDataPoint( sal_Int32 index ) const
+{
+ //returns true if the data point assigned by the given index has set its own properties
+ if( index>=m_nPointCount || m_nPointCount==0)
+ return false;
+ for(sal_Int32 n : m_aAttributedDataPointIndexList)
+ {
+ if(index == n)
+ return true;
+ }
+ return false;
+}
+
+bool VDataSeries::isVaryColorsByPoint() const
+{
+ bool bVaryColorsByPoint = false;
+ if( m_xDataSeries )
+ m_xDataSeries->getFastPropertyValue(PROP_DATASERIES_VARY_COLORS_BY_POINT) >>= bVaryColorsByPoint; // "VaryColorsByPoint"
+ return bVaryColorsByPoint;
+}
+
+uno::Reference< beans::XPropertySet > VDataSeries::getPropertiesOfPoint( sal_Int32 index ) const
+{
+ if( isAttributedDataPoint( index ) )
+ return m_xDataSeries->getDataPointByIndex(index);
+ return getPropertiesOfSeries();
+}
+
+const uno::Reference<beans::XPropertySet> & VDataSeries::getPropertiesOfSeries() const
+{
+ return m_xDataSeriesProps;
+}
+
+static std::optional<DataPointLabel> getDataPointLabelFromPropertySet( const uno::Reference< beans::XPropertySet >& xProp )
+{
+ std::optional< DataPointLabel > apLabel( std::in_place );
+ try
+ {
+ if( !(xProp->getPropertyValue(CHART_UNONAME_LABEL) >>= *apLabel) )
+ apLabel.reset();
+ }
+ catch(const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+ return apLabel;
+}
+
+void VDataSeries::adaptPointCache( sal_Int32 nNewPointIndex ) const
+{
+ if( m_nCurrentAttributedPoint != nNewPointIndex )
+ {
+ m_oLabel_AttributedPoint.reset();
+ m_apLabelPropNames_AttributedPoint.reset();
+ m_apLabelPropValues_AttributedPoint.reset();
+ m_oSymbolProperties_AttributedPoint.reset();
+ m_nCurrentAttributedPoint = nNewPointIndex;
+ }
+}
+
+DataPointLabel* VDataSeries::getDataPointLabel( sal_Int32 index ) const
+{
+ DataPointLabel* pRet = nullptr;
+ if( isAttributedDataPoint( index ) )
+ {
+ adaptPointCache( index );
+ if (!m_oLabel_AttributedPoint)
+ m_oLabel_AttributedPoint
+ = getDataPointLabelFromPropertySet(getPropertiesOfPoint(index));
+ if (m_oLabel_AttributedPoint)
+ pRet = &*m_oLabel_AttributedPoint;
+ }
+ else
+ {
+ if (!m_oLabel_Series)
+ m_oLabel_Series
+ = getDataPointLabelFromPropertySet(getPropertiesOfPoint(index));
+ if (m_oLabel_Series)
+ pRet = &*m_oLabel_Series;
+ }
+ if( !m_bAllowPercentValueInDataLabel )
+ {
+ if( pRet )
+ pRet->ShowNumberInPercent = false;
+ }
+ return pRet;
+}
+
+DataPointLabel* VDataSeries::getDataPointLabelIfLabel( sal_Int32 index ) const
+{
+ DataPointLabel* pLabel = getDataPointLabel( index );
+ if( !pLabel || (!pLabel->ShowNumber && !pLabel->ShowNumberInPercent
+ && !pLabel->ShowCategoryName && !pLabel->ShowCustomLabel && !pLabel->ShowSeriesName ) )
+ return nullptr;
+ return pLabel;
+}
+
+bool VDataSeries::getTextLabelMultiPropertyLists( sal_Int32 index
+ , tNameSequence*& pPropNames
+ , tAnySequence*& pPropValues ) const
+{
+ pPropNames = nullptr; pPropValues = nullptr;
+ uno::Reference< beans::XPropertySet > xTextProp;
+ bool bDoDynamicFontResize = false;
+ if( isAttributedDataPoint( index ) )
+ {
+ adaptPointCache( index );
+ if (!m_apLabelPropValues_AttributedPoint)
+ {
+ // Cache these properties for this point.
+ m_apLabelPropNames_AttributedPoint.reset(new tNameSequence);
+ m_apLabelPropValues_AttributedPoint.reset(new tAnySequence);
+ xTextProp.set( getPropertiesOfPoint( index ));
+ PropertyMapper::getTextLabelMultiPropertyLists(
+ xTextProp, *m_apLabelPropNames_AttributedPoint, *m_apLabelPropValues_AttributedPoint);
+ bDoDynamicFontResize = true;
+ }
+ pPropNames = m_apLabelPropNames_AttributedPoint.get();
+ pPropValues = m_apLabelPropValues_AttributedPoint.get();
+ }
+ else
+ {
+ if (!m_oLabelPropValues_Series)
+ {
+ // Cache these properties for the whole series.
+ m_oLabelPropNames_Series.emplace();
+ m_oLabelPropValues_Series.emplace();
+ xTextProp.set( getPropertiesOfPoint( index ));
+ PropertyMapper::getTextLabelMultiPropertyLists(
+ xTextProp, *m_oLabelPropNames_Series, *m_oLabelPropValues_Series);
+ bDoDynamicFontResize = true;
+ }
+ pPropNames = &*m_oLabelPropNames_Series;
+ pPropValues = &*m_oLabelPropValues_Series;
+ }
+
+ if( bDoDynamicFontResize &&
+ pPropNames && pPropValues &&
+ xTextProp.is())
+ {
+ LabelPositionHelper::doDynamicFontResize( *pPropValues, *pPropNames, xTextProp, m_aReferenceSize );
+ }
+
+ return (pPropNames && pPropValues);
+}
+
+void VDataSeries::setMissingValueTreatment( sal_Int32 nMissingValueTreatment )
+{
+ m_nMissingValueTreatment = nMissingValueTreatment;
+}
+
+sal_Int32 VDataSeries::getMissingValueTreatment() const
+{
+ return m_nMissingValueTreatment;
+}
+
+VDataSeries::VDataSeries()
+ : m_nPolygonIndex(0)
+ , m_fLogicMinX(0)
+ , m_fLogicMaxX(0)
+ , m_fLogicZPos(0)
+ , m_nPointCount(0)
+ , m_pValueSequenceForDataLabelNumberFormatDetection(nullptr)
+ , m_fXMeanValue(0)
+ , m_fYMeanValue(0)
+ , m_eStackingDirection(chart2::StackingDirection_NO_STACKING)
+ , m_nAxisIndex(0)
+ , m_bConnectBars(false)
+ , m_bGroupBarsPerAxis(false)
+ , m_nStartingAngle(0)
+ , m_nGlobalSeriesIndex(0)
+ , m_nCurrentAttributedPoint(0)
+ , m_nMissingValueTreatment(0)
+ , m_bAllowPercentValueInDataLabel(false)
+ , mpOldSeries(nullptr)
+ , mnPercent(0)
+{
+}
+
+void VDataSeries::setOldTimeBased( VDataSeries* pOldSeries, double nPercent )
+{
+ mnPercent = nPercent;
+ mpOldSeries = pOldSeries;
+ mpOldSeries->mpOldSeries = nullptr;
+}
+
+VDataSeries* VDataSeries::createCopyForTimeBased() const
+{
+ VDataSeries* pNew = new VDataSeries();
+ pNew->m_aValues_X = m_aValues_X;
+ pNew->m_aValues_Y = m_aValues_Y;
+ pNew->m_aValues_Z = m_aValues_Z;
+ pNew->m_aValues_Y_Min = m_aValues_Y_Min;
+ pNew->m_aValues_Y_Max = m_aValues_Y_Max;
+ pNew->m_aValues_Y_First = m_aValues_Y_First;
+ pNew->m_aValues_Y_Last = m_aValues_Y_Last;
+ pNew->m_aValues_Bubble_Size = m_aValues_Bubble_Size;
+ pNew->m_PropertyMap = m_PropertyMap;
+
+ pNew->m_nPointCount = m_nPointCount;
+
+ return pNew;
+}
+
+double VDataSeries::getValueByProperty( sal_Int32 nIndex, const OUString& rPropName ) const
+{
+ auto const itr = m_PropertyMap.find(rPropName);
+ if (itr == m_PropertyMap.end())
+ return std::numeric_limits<double>::quiet_NaN();
+
+ const VDataSequence* pData = &itr->second;
+ double fValue = pData->getValue(nIndex);
+ if(mpOldSeries && mpOldSeries->hasPropertyMapping(rPropName))
+ {
+ double fOldValue = mpOldSeries->getValueByProperty( nIndex, rPropName );
+ if(rPropName.endsWith("Color"))
+ {
+ //optimized interpolation for color values
+ Color aColor(ColorTransparency, static_cast<sal_uInt32>(fValue));
+ Color aOldColor(ColorTransparency, static_cast<sal_uInt32>(fOldValue));
+ sal_uInt8 r = aOldColor.GetRed() + (aColor.GetRed() - aOldColor.GetRed()) * mnPercent;
+ sal_uInt8 g = aOldColor.GetGreen() + (aColor.GetGreen() - aOldColor.GetGreen()) * mnPercent;
+ sal_uInt8 b = aOldColor.GetBlue() + (aColor.GetBlue() - aOldColor.GetBlue()) * mnPercent;
+ sal_uInt8 a = aOldColor.GetAlpha() + (aColor.GetAlpha() - aOldColor.GetAlpha()) * mnPercent;
+ Color aRet(ColorAlpha, a, r, g, b);
+ return sal_uInt32(aRet);
+ }
+ return fOldValue + (fValue - fOldValue) * mnPercent;
+ }
+ return fValue;
+}
+
+bool VDataSeries::hasPropertyMapping(const OUString& rPropName ) const
+{
+ return m_PropertyMap.find(rPropName) != m_PropertyMap.end();
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/VLegend.cxx b/chart2/source/view/main/VLegend.cxx
new file mode 100644
index 0000000000..8a4935e9b0
--- /dev/null
+++ b/chart2/source/view/main/VLegend.cxx
@@ -0,0 +1,1110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VLegend.hxx"
+#include "VButton.hxx"
+#include <Legend.hxx>
+#include <PropertyMapper.hxx>
+#include <ChartModel.hxx>
+#include <ObjectIdentifier.hxx>
+#include <FormattedString.hxx>
+#include <RelativePositionHelper.hxx>
+#include <ShapeFactory.hxx>
+#include <RelativeSizeHelper.hxx>
+#include <LegendEntryProvider.hxx>
+#include <chartview/DrawModelWrapper.hxx>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <com/sun/star/chart/ChartLegendExpansion.hpp>
+#include <com/sun/star/chart2/LegendPosition.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/chart2/XFormattedString2.hpp>
+#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
+#include <com/sun/star/chart2/data/PivotTableFieldEntry.hpp>
+#include <rtl/math.hxx>
+#include <svl/ctloptions.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/UnitConversion.hxx>
+
+#include <utility>
+#include <vector>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+namespace
+{
+
+typedef std::pair< ::chart::tNameSequence, ::chart::tAnySequence > tPropertyValues;
+
+double lcl_CalcViewFontSize(
+ const Reference< beans::XPropertySet > & xProp,
+ const awt::Size & rReferenceSize )
+{
+ double fResult = 10.0;
+
+ float fFontHeight( 0.0 );
+ if( xProp.is() && ( xProp->getPropertyValue( "CharHeight") >>= fFontHeight ))
+ {
+ fResult = fFontHeight;
+ try
+ {
+ awt::Size aPropRefSize;
+ if( (xProp->getPropertyValue( "ReferencePageSize") >>= aPropRefSize) &&
+ (aPropRefSize.Height > 0))
+ {
+ fResult = ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return convertPointToMm100(fResult);
+}
+
+void lcl_getProperties(
+ const Reference< beans::XPropertySet > & xLegendProp,
+ tPropertyValues & rOutLineFillProperties,
+ tPropertyValues & rOutTextProperties,
+ const awt::Size & rReferenceSize )
+{
+ // Get Line- and FillProperties from model legend
+ if( !xLegendProp.is())
+ return;
+
+ // set rOutLineFillProperties
+ ::chart::tPropertyNameValueMap aLineFillValueMap;
+ ::chart::PropertyMapper::getValueMap( aLineFillValueMap, ::chart::PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xLegendProp );
+
+ aLineFillValueMap[ "LineJoint" ] <<= drawing::LineJoint_ROUND;
+
+ ::chart::PropertyMapper::getMultiPropertyListsFromValueMap(
+ rOutLineFillProperties.first, rOutLineFillProperties.second, aLineFillValueMap );
+
+ // set rOutTextProperties
+ ::chart::tPropertyNameValueMap aTextValueMap;
+ ::chart::PropertyMapper::getValueMap( aTextValueMap, ::chart::PropertyMapper::getPropertyNameMapForCharacterProperties(), xLegendProp );
+
+ aTextValueMap[ "TextAutoGrowHeight" ] <<= true;
+ aTextValueMap[ "TextAutoGrowWidth" ] <<= true;
+ aTextValueMap[ "TextHorizontalAdjust" ] <<= drawing::TextHorizontalAdjust_LEFT;
+ aTextValueMap[ "TextMaximumFrameWidth" ] <<= rReferenceSize.Width; //needs to be overwritten by actual available space in the legend
+
+ // recalculate font size
+ awt::Size aPropRefSize;
+ float fFontHeight( 0.0 );
+ if( (xLegendProp->getPropertyValue( "ReferencePageSize") >>= aPropRefSize) &&
+ (aPropRefSize.Height > 0) &&
+ (aTextValueMap[ "CharHeight" ] >>= fFontHeight) )
+ {
+ aTextValueMap[ "CharHeight" ] <<=
+ static_cast< float >(
+ ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize ));
+
+ if( aTextValueMap[ "CharHeightAsian" ] >>= fFontHeight )
+ {
+ aTextValueMap[ "CharHeightAsian" ] <<=
+ static_cast< float >(
+ ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize ));
+ }
+ if( aTextValueMap[ "CharHeightComplex" ] >>= fFontHeight )
+ {
+ aTextValueMap[ "CharHeightComplex" ] <<=
+ static_cast< float >(
+ ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize ));
+ }
+ }
+
+ ::chart::PropertyMapper::getMultiPropertyListsFromValueMap(
+ rOutTextProperties.first, rOutTextProperties.second, aTextValueMap );
+}
+
+awt::Size lcl_createTextShapes(
+ const std::vector<ViewLegendEntry> & rEntries,
+ const rtl::Reference<SvxShapeGroupAnyD> & xTarget,
+ std::vector< rtl::Reference<SvxShapeText> > & rOutTextShapes,
+ const tPropertyValues & rTextProperties )
+{
+ awt::Size aResult;
+
+ for (ViewLegendEntry const & rEntry : rEntries)
+ {
+ try
+ {
+ OUString aLabelString;
+ if (rEntry.xLabel)
+ {
+ // tdf#150034 limit legend label text
+ if (rEntry.xLabel->getString().getLength() > 520)
+ {
+ sal_Int32 nIndex = rEntry.xLabel->getString().indexOf(' ', 500);
+ rEntry.xLabel->setString(
+ rEntry.xLabel->getString().copy(0, nIndex > 500 ? nIndex : 500));
+ }
+
+ aLabelString += rEntry.xLabel->getString();
+ // workaround for Issue #i67540#
+ if( aLabelString.isEmpty())
+ aLabelString = " ";
+ }
+
+ rtl::Reference<SvxShapeText> xEntry =
+ ShapeFactory::createText( xTarget, aLabelString,
+ rTextProperties.first, rTextProperties.second, uno::Any() );
+
+ // adapt max-extent
+ awt::Size aCurrSize( xEntry->getSize());
+ aResult.Width = std::max( aResult.Width, aCurrSize.Width );
+ aResult.Height = std::max( aResult.Height, aCurrSize.Height );
+
+ rOutTextShapes.push_back( xEntry );
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+
+ return aResult;
+}
+
+void lcl_collectColumnWidths( std::vector< sal_Int32 >& rColumnWidths, const sal_Int32 nNumberOfRows, const sal_Int32 nNumberOfColumns,
+ const std::vector< rtl::Reference<SvxShapeText> >& rTextShapes, sal_Int32 nSymbolPlusDistanceWidth )
+{
+ rColumnWidths.clear();
+ sal_Int32 nNumberOfEntries = rTextShapes.size();
+ for (sal_Int32 nRow = 0; nRow < nNumberOfRows; ++nRow )
+ {
+ for (sal_Int32 nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
+ {
+ sal_Int32 nEntry = nColumn + nRow * nNumberOfColumns;
+ if( nEntry < nNumberOfEntries )
+ {
+ awt::Size aTextSize( rTextShapes[ nEntry ]->getSize() );
+ sal_Int32 nWidth = nSymbolPlusDistanceWidth + aTextSize.Width;
+ if( nRow==0 )
+ rColumnWidths.push_back( nWidth );
+ else
+ rColumnWidths[nColumn] = std::max( nWidth, rColumnWidths[nColumn] );
+ }
+ }
+ }
+}
+
+void lcl_collectRowHeighs( std::vector< sal_Int32 >& rRowHeights, const sal_Int32 nNumberOfRows, const sal_Int32 nNumberOfColumns,
+ const std::vector< rtl::Reference<SvxShapeText> >& rTextShapes )
+{
+ // calculate maximum height for each row
+ // and collect column widths
+ rRowHeights.clear();
+ sal_Int32 nNumberOfEntries = rTextShapes.size();
+ for (sal_Int32 nRow = 0; nRow < nNumberOfRows; ++nRow)
+ {
+ sal_Int32 nCurrentRowHeight = 0;
+ for (sal_Int32 nColumn = 0; nColumn < nNumberOfColumns; ++nColumn)
+ {
+ sal_Int32 nEntry = nColumn + nRow * nNumberOfColumns;
+ if( nEntry < nNumberOfEntries )
+ {
+ awt::Size aTextSize( rTextShapes[ nEntry ]->getSize() );
+ nCurrentRowHeight = std::max( nCurrentRowHeight, aTextSize.Height );
+ }
+ }
+ rRowHeights.push_back( nCurrentRowHeight );
+ }
+}
+
+sal_Int32 lcl_getTextLineHeight( const std::vector< sal_Int32 >& aRowHeights, const sal_Int32 nNumberOfRows, double fViewFontSize )
+{
+ const sal_Int32 nFontHeight = static_cast< sal_Int32 >( fViewFontSize );
+ if (!nFontHeight)
+ return 0;
+ sal_Int32 nTextLineHeight = nFontHeight;
+ for (sal_Int32 nRow = 0; nRow < nNumberOfRows; ++nRow)
+ {
+ sal_Int32 nFullTextHeight = aRowHeights[nRow];
+ if( ( nFullTextHeight / nFontHeight ) <= 1 )
+ {
+ nTextLineHeight = nFullTextHeight;//found an entry with one line-> have real text height
+ break;
+ }
+ }
+ return nTextLineHeight;
+}
+
+//returns resulting legend size
+awt::Size lcl_placeLegendEntries(
+ std::vector<ViewLegendEntry> & rEntries,
+ css::chart::ChartLegendExpansion eExpansion,
+ bool bSymbolsLeftSide,
+ double fViewFontSize,
+ const awt::Size& rMaxSymbolExtent,
+ tPropertyValues & rTextProperties,
+ const rtl::Reference<SvxShapeGroupAnyD> & xTarget,
+ const awt::Size& rRemainingSpace,
+ sal_Int32 nYStartPosition,
+ const awt::Size& rPageSize,
+ bool bIsPivotChart,
+ awt::Size& rDefaultLegendSize)
+{
+ bool bIsCustomSize = (eExpansion == css::chart::ChartLegendExpansion_CUSTOM);
+ awt::Size aResultingLegendSize(0,0);
+ // For Pivot charts set the *minimum* legend size as a function of page size.
+ if ( bIsPivotChart )
+ aResultingLegendSize = awt::Size((rPageSize.Width * 13) / 80, (rPageSize.Height * 31) / 90);
+ if( bIsCustomSize )
+ aResultingLegendSize = awt::Size(rRemainingSpace.Width, rRemainingSpace.Height + nYStartPosition);
+
+ // #i109336# Improve auto positioning in chart
+ sal_Int32 nXPadding = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.33 ) );
+ sal_Int32 nXOffset = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.66 ) );
+ sal_Int32 nYPadding = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.2 ) );
+ sal_Int32 nYOffset = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.2 ) );
+
+ const sal_Int32 nSymbolToTextDistance = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.22 ) );//minimum 1mm
+ const sal_Int32 nSymbolPlusDistanceWidth = rMaxSymbolExtent.Width + nSymbolToTextDistance;
+ sal_Int32 nMaxTextWidth = rRemainingSpace.Width - nSymbolPlusDistanceWidth;
+ uno::Any* pFrameWidthAny = PropertyMapper::getValuePointer( rTextProperties.second, rTextProperties.first, u"TextMaximumFrameWidth");
+ if(pFrameWidthAny)
+ {
+ if( eExpansion == css::chart::ChartLegendExpansion_HIGH )
+ {
+ // limit the width of texts to 30% of the total available width
+ // #i109336# Improve auto positioning in chart
+ nMaxTextWidth = rRemainingSpace.Width * 3 / 10;
+ }
+ *pFrameWidthAny <<= nMaxTextWidth;
+ }
+
+ std::vector< rtl::Reference<SvxShapeText> > aTextShapes;
+ awt::Size aMaxEntryExtent = lcl_createTextShapes( rEntries, xTarget, aTextShapes, rTextProperties );
+ OSL_ASSERT( aTextShapes.size() == rEntries.size());
+
+ sal_Int32 nMaxEntryWidth = nXOffset + nSymbolPlusDistanceWidth + aMaxEntryExtent.Width;
+ sal_Int32 nMaxEntryHeight = nYOffset + aMaxEntryExtent.Height;
+ sal_Int32 nNumberOfEntries = rEntries.size();
+
+ rDefaultLegendSize.Width = nMaxEntryWidth;
+ rDefaultLegendSize.Height = nMaxEntryHeight + nYPadding;
+
+ sal_Int32 nNumberOfColumns = 0, nNumberOfRows = 0;
+ std::vector< sal_Int32 > aColumnWidths;
+ std::vector< sal_Int32 > aRowHeights;
+
+ sal_Int32 nTextLineHeight = static_cast< sal_Int32 >( fViewFontSize );
+
+ // determine layout depending on LegendExpansion
+ if( eExpansion == css::chart::ChartLegendExpansion_CUSTOM )
+ {
+ sal_Int32 nCurrentRow=0;
+ sal_Int32 nCurrentColumn=-1;
+ sal_Int32 nMaxColumnCount=-1;
+ for( sal_Int32 nN=0; nN<static_cast<sal_Int32>(aTextShapes.size()); nN++ )
+ {
+ rtl::Reference<SvxShapeText> xShape( aTextShapes[nN] );
+ if( !xShape.is() )
+ continue;
+ awt::Size aSize( xShape->getSize() );
+ sal_Int32 nNewWidth = aSize.Width + nSymbolPlusDistanceWidth;
+ sal_Int32 nCurrentColumnCount = aColumnWidths.size();
+
+ //are we allowed to add a new column?
+ if( nMaxColumnCount==-1 || (nCurrentColumn+1) < nMaxColumnCount )
+ {
+ //try add a new column
+ nCurrentColumn++;
+ if( nCurrentColumn < nCurrentColumnCount )
+ {
+ //check whether the current column width is sufficient for the new entry
+ if( aColumnWidths[nCurrentColumn]>=nNewWidth )
+ {
+ //all good proceed with next entry
+ continue;
+ }
+
+ aColumnWidths[nCurrentColumn] = std::max( nNewWidth, aColumnWidths[nCurrentColumn] );
+ } else
+ aColumnWidths.push_back(nNewWidth);
+
+ //do the columns still fit into the given size?
+ nCurrentColumnCount = aColumnWidths.size();//update count
+ sal_Int32 nSumWidth = 0;
+ for (sal_Int32 nColumn = 0; nColumn < nCurrentColumnCount; nColumn++)
+ nSumWidth += aColumnWidths[nColumn];
+
+ if( nSumWidth <= rRemainingSpace.Width || nCurrentColumnCount==1 )
+ {
+ //all good proceed with next entry
+ continue;
+ }
+ else
+ {
+ //not enough space for the current amount of columns
+ //try again with less columns
+ nMaxColumnCount = nCurrentColumnCount-1;
+ nN=-1;
+ nCurrentRow=0;
+ nCurrentColumn=-1;
+ aColumnWidths.clear();
+ }
+ }
+ else
+ {
+ //add a new row and try the same entry again
+ nCurrentRow++;
+ nCurrentColumn=-1;
+ nN--;
+ }
+ }
+ nNumberOfColumns = aColumnWidths.size();
+ nNumberOfRows = nCurrentRow+1;
+
+ //check if there is not enough space so that some entries must be removed
+ lcl_collectRowHeighs( aRowHeights, nNumberOfRows, nNumberOfColumns, aTextShapes );
+ nTextLineHeight = lcl_getTextLineHeight( aRowHeights, nNumberOfRows, fViewFontSize );
+ sal_Int32 nSumHeight = 0;
+ for (sal_Int32 nRow=0; nRow < nNumberOfRows; nRow++)
+ nSumHeight += aRowHeights[nRow];
+ sal_Int32 nRemainingSpace = rRemainingSpace.Height - nSumHeight;
+
+ if( nRemainingSpace < -100 ) // 1mm tolerance for OOXML interop tdf#90404
+ {
+ //remove entries that are too big
+ for (sal_Int32 nRow = nNumberOfRows; nRow--; )
+ {
+ for (sal_Int32 nColumn = nNumberOfColumns; nColumn--; )
+ {
+ sal_Int32 nEntry = nColumn + nRow * nNumberOfColumns;
+ if( nEntry < static_cast<sal_Int32>(aTextShapes.size()) )
+ {
+ DrawModelWrapper::removeShape( aTextShapes[nEntry] );
+ aTextShapes.pop_back();
+ }
+ if( nEntry < nNumberOfEntries && ( nEntry != 0 || nNumberOfColumns != 1 ) )
+ {
+ DrawModelWrapper::removeShape( rEntries[ nEntry ].xSymbol );
+ rEntries.pop_back();
+ nNumberOfEntries--;
+ }
+ }
+ if (nRow == 0 && nNumberOfColumns == 1)
+ {
+ try
+ {
+ OUString aLabelString = rEntries[0].xLabel->getString();
+ static constexpr OUString sDots = u"..."_ustr;
+ for (sal_Int32 nNewLen = aLabelString.getLength() - sDots.getLength(); nNewLen > 0; )
+ {
+ OUString aNewLabel = aLabelString.subView(0, nNewLen) + sDots;
+ rtl::Reference<SvxShapeText> xEntry = ShapeFactory::createText(
+ xTarget, aNewLabel, rTextProperties.first, rTextProperties.second, uno::Any());
+ nSumHeight = xEntry->getSize().Height;
+ nRemainingSpace = rRemainingSpace.Height - nSumHeight;
+ if (nRemainingSpace >= 0)
+ {
+ sal_Int32 nWidth = xEntry->getSize().Width + nSymbolPlusDistanceWidth;
+ if (rRemainingSpace.Width - nWidth >= 0)
+ {
+ aTextShapes.push_back(xEntry);
+ rEntries[0].xLabel->setString(aNewLabel);
+ aRowHeights[0] = nSumHeight;
+ aColumnWidths[0] = nWidth;
+ break;
+ }
+ }
+ DrawModelWrapper::removeShape(xEntry);
+ // The intention here is to make pathological cases with extremely large labels
+ // converge a little faster
+ if (nNewLen > 10 && std::abs(nRemainingSpace) > nSumHeight / 10)
+ nNewLen -= nNewLen / 10;
+ else
+ --nNewLen;
+ }
+ if (aTextShapes.size() == 0)
+ {
+ DrawModelWrapper::removeShape(rEntries[0].xSymbol);
+ rEntries.pop_back();
+ nNumberOfEntries--;
+ aRowHeights.pop_back();
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ }
+ else
+ {
+ nSumHeight -= aRowHeights[nRow];
+ aRowHeights.pop_back();
+ nRemainingSpace = rRemainingSpace.Height - nSumHeight;
+ if (nRemainingSpace >= 0)
+ break;
+ }
+ }
+ nNumberOfRows = static_cast<sal_Int32>(aRowHeights.size());
+ }
+ if( nRemainingSpace >= -100 ) // 1mm tolerance for OOXML interop tdf#90404
+ {
+ sal_Int32 nNormalSpacingHeight = 2*nYPadding+(nNumberOfRows-1)*nYOffset;
+ if( nRemainingSpace < nNormalSpacingHeight )
+ {
+ //reduce spacing between the entries
+ nYPadding = nYOffset = nRemainingSpace/(nNumberOfRows+1);
+ }
+ else
+ {
+ //we have some space left that should be spread equally between all rows
+ sal_Int32 nRemainingSingleSpace = (nRemainingSpace-nNormalSpacingHeight)/(nNumberOfRows+1);
+ nYPadding += nRemainingSingleSpace;
+ nYOffset += nRemainingSingleSpace;
+ }
+ }
+
+ //check spacing between columns
+ sal_Int32 nSumWidth = 0;
+ for (sal_Int32 nColumn = 0; nColumn < nNumberOfColumns; nColumn++)
+ nSumWidth += aColumnWidths[nColumn];
+ nRemainingSpace = rRemainingSpace.Width - nSumWidth;
+ if( nRemainingSpace>=0 )
+ {
+ sal_Int32 nNormalSpacingWidth = 2*nXPadding+(nNumberOfColumns-1)*nXOffset;
+ if( nRemainingSpace < nNormalSpacingWidth )
+ {
+ //reduce spacing between the entries
+ nXPadding = nXOffset = nRemainingSpace/(nNumberOfColumns+1);
+ }
+ else
+ {
+ //we have some space left that should be spread equally between all columns
+ sal_Int32 nRemainingSingleSpace = (nRemainingSpace-nNormalSpacingWidth)/(nNumberOfColumns+1);
+ nXPadding += nRemainingSingleSpace;
+ nXOffset += nRemainingSingleSpace;
+ }
+ }
+ }
+ else if( eExpansion == css::chart::ChartLegendExpansion_HIGH )
+ {
+ sal_Int32 nMaxNumberOfRows = nMaxEntryHeight
+ ? (rRemainingSpace.Height - 2*nYPadding ) / nMaxEntryHeight
+ : 0;
+
+ nNumberOfColumns = nMaxNumberOfRows
+ ? static_cast< sal_Int32 >(
+ ceil( static_cast< double >( nNumberOfEntries ) /
+ static_cast< double >( nMaxNumberOfRows ) ))
+ : 0;
+ nNumberOfRows = nNumberOfColumns
+ ? static_cast< sal_Int32 >(
+ ceil( static_cast< double >( nNumberOfEntries ) /
+ static_cast< double >( nNumberOfColumns ) ))
+ : 0;
+ }
+ else if( eExpansion == css::chart::ChartLegendExpansion_WIDE )
+ {
+ sal_Int32 nMaxNumberOfColumns = nMaxEntryWidth
+ ? (rRemainingSpace.Width - 2*nXPadding ) / nMaxEntryWidth
+ : 0;
+
+ nNumberOfRows = nMaxNumberOfColumns
+ ? static_cast< sal_Int32 >(
+ ceil( static_cast< double >( nNumberOfEntries ) /
+ static_cast< double >( nMaxNumberOfColumns ) ))
+ : 0;
+ nNumberOfColumns = nNumberOfRows
+ ? static_cast< sal_Int32 >(
+ ceil( static_cast< double >( nNumberOfEntries ) /
+ static_cast< double >( nNumberOfRows ) ))
+ : 0;
+ }
+ else // css::chart::ChartLegendExpansion_BALANCED
+ {
+ double fAspect = nMaxEntryHeight
+ ? static_cast< double >( nMaxEntryWidth ) / static_cast< double >( nMaxEntryHeight )
+ : 0.0;
+
+ nNumberOfRows = static_cast< sal_Int32 >(
+ ceil( sqrt( static_cast< double >( nNumberOfEntries ) * fAspect )));
+ nNumberOfColumns = nNumberOfRows
+ ? static_cast< sal_Int32 >(
+ ceil( static_cast< double >( nNumberOfEntries ) /
+ static_cast< double >( nNumberOfRows ) ))
+ : 0;
+ }
+
+ if(nNumberOfRows<=0)
+ return aResultingLegendSize;
+
+ if( eExpansion != css::chart::ChartLegendExpansion_CUSTOM )
+ {
+ lcl_collectColumnWidths( aColumnWidths, nNumberOfRows, nNumberOfColumns, aTextShapes, nSymbolPlusDistanceWidth );
+ lcl_collectRowHeighs( aRowHeights, nNumberOfRows, nNumberOfColumns, aTextShapes );
+ nTextLineHeight = lcl_getTextLineHeight( aRowHeights, nNumberOfRows, fViewFontSize );
+ }
+
+ sal_Int32 nCurrentXPos = bSymbolsLeftSide ? nXPadding : -nXPadding;
+
+ // place entries into column and rows
+ sal_Int32 nMaxYPos = 0;
+
+ for (sal_Int32 nColumn = 0; nColumn < nNumberOfColumns; ++nColumn)
+ {
+ sal_Int32 nCurrentYPos = nYPadding + nYStartPosition;
+ for (sal_Int32 nRow = 0; nRow < nNumberOfRows; ++nRow)
+ {
+ sal_Int32 nEntry = nColumn + nRow * nNumberOfColumns;
+ if( nEntry >= nNumberOfEntries )
+ break;
+
+ // text shape
+ rtl::Reference<SvxShapeText> xTextShape( aTextShapes[nEntry] );
+ if( xTextShape.is() )
+ {
+ awt::Size aTextSize( xTextShape->getSize() );
+ sal_Int32 nTextXPos = nCurrentXPos + nSymbolPlusDistanceWidth;
+ if( !bSymbolsLeftSide )
+ nTextXPos = nCurrentXPos - nSymbolPlusDistanceWidth - aTextSize.Width;
+ xTextShape->setPosition( awt::Point( nTextXPos, nCurrentYPos ));
+ }
+
+ // symbol
+ rtl::Reference<SvxShapeGroup> & xSymbol( rEntries[ nEntry ].xSymbol );
+ if( xSymbol.is() )
+ {
+ awt::Size aSymbolSize( rMaxSymbolExtent );
+ sal_Int32 nSymbolXPos = nCurrentXPos;
+ if( !bSymbolsLeftSide )
+ nSymbolXPos = nCurrentXPos - rMaxSymbolExtent.Width;
+ sal_Int32 nSymbolYPos = nCurrentYPos + ( ( nTextLineHeight - aSymbolSize.Height ) / 2 );
+ xSymbol->setPosition( awt::Point( nSymbolXPos, nSymbolYPos ) );
+ }
+
+ nCurrentYPos += aRowHeights[ nRow ];
+ if( nRow+1 < nNumberOfRows )
+ nCurrentYPos += nYOffset;
+ nMaxYPos = std::max( nMaxYPos, nCurrentYPos );
+ }
+ if( bSymbolsLeftSide )
+ {
+ nCurrentXPos += aColumnWidths[nColumn];
+ if( nColumn+1 < nNumberOfColumns )
+ nCurrentXPos += nXOffset;
+ }
+ else
+ {
+ nCurrentXPos -= aColumnWidths[nColumn];
+ if( nColumn+1 < nNumberOfColumns )
+ nCurrentXPos -= nXOffset;
+ }
+ }
+
+ if( !bIsCustomSize )
+ {
+ if( bSymbolsLeftSide )
+ aResultingLegendSize.Width = std::max( aResultingLegendSize.Width, nCurrentXPos + nXPadding );
+ else
+ {
+ sal_Int32 nLegendWidth = -(nCurrentXPos-nXPadding);
+ aResultingLegendSize.Width = std::max( aResultingLegendSize.Width, nLegendWidth );
+ }
+ aResultingLegendSize.Height = std::max( aResultingLegendSize.Height, nMaxYPos + nYPadding );
+ }
+
+ if( !bSymbolsLeftSide )
+ {
+ sal_Int32 nLegendWidth = aResultingLegendSize.Width;
+ awt::Point aPos(0,0);
+ for( sal_Int32 nEntry=0; nEntry<nNumberOfEntries; nEntry++ )
+ {
+ rtl::Reference<SvxShapeGroup> & xSymbol( rEntries[ nEntry ].xSymbol );
+ aPos = xSymbol->getPosition();
+ aPos.X += nLegendWidth;
+ xSymbol->setPosition( aPos );
+ rtl::Reference<SvxShapeText> & xText( aTextShapes[ nEntry ] );
+ aPos = xText->getPosition();
+ aPos.X += nLegendWidth;
+ xText->setPosition( aPos );
+ }
+ }
+
+ return aResultingLegendSize;
+}
+
+// #i109336# Improve auto positioning in chart
+sal_Int32 lcl_getLegendLeftRightMargin()
+{
+ return 210; // 1/100 mm
+}
+
+// #i109336# Improve auto positioning in chart
+sal_Int32 lcl_getLegendTopBottomMargin()
+{
+ return 185; // 1/100 mm
+}
+
+chart2::RelativePosition lcl_getDefaultPosition( LegendPosition ePos, const awt::Rectangle& rOutAvailableSpace, const awt::Size & rPageSize )
+{
+ chart2::RelativePosition aResult;
+
+ switch( ePos )
+ {
+ case LegendPosition_LINE_START:
+ {
+ // #i109336# Improve auto positioning in chart
+ const double fDefaultDistance = static_cast< double >( lcl_getLegendLeftRightMargin() ) /
+ static_cast< double >( rPageSize.Width );
+ aResult = chart2::RelativePosition(
+ fDefaultDistance, 0.5, drawing::Alignment_LEFT );
+ }
+ break;
+ case LegendPosition_LINE_END:
+ {
+ // #i109336# Improve auto positioning in chart
+ const double fDefaultDistance = static_cast< double >( lcl_getLegendLeftRightMargin() ) /
+ static_cast< double >( rPageSize.Width );
+ aResult = chart2::RelativePosition(
+ 1.0 - fDefaultDistance, 0.5, drawing::Alignment_RIGHT );
+ }
+ break;
+ case LegendPosition_PAGE_START:
+ {
+ // #i109336# Improve auto positioning in chart
+ const double fDefaultDistance = static_cast< double >( lcl_getLegendTopBottomMargin() ) /
+ static_cast< double >( rPageSize.Height );
+ double fDistance = (static_cast<double>(rOutAvailableSpace.Y)/static_cast<double>(rPageSize.Height)) + fDefaultDistance;
+ aResult = chart2::RelativePosition(
+ 0.5, fDistance, drawing::Alignment_TOP );
+ }
+ break;
+ case LegendPosition_PAGE_END:
+ {
+ // #i109336# Improve auto positioning in chart
+ const double fDefaultDistance = static_cast< double >( lcl_getLegendTopBottomMargin() ) /
+ static_cast< double >( rPageSize.Height );
+
+ double fDistance = double(rPageSize.Height - (rOutAvailableSpace.Y + rOutAvailableSpace.Height));
+ fDistance += fDefaultDistance;
+ fDistance /= double(rPageSize.Height);
+
+ aResult = chart2::RelativePosition(
+ 0.5, 1.0 - fDistance, drawing::Alignment_BOTTOM );
+ }
+ break;
+ case LegendPosition::LegendPosition_MAKE_FIXED_SIZE:
+ default:
+ // nothing to be set
+ break;
+ }
+
+ return aResult;
+}
+
+/** @return
+ a point relative to the upper left corner that can be used for
+ XShape::setPosition()
+*/
+awt::Point lcl_calculatePositionAndRemainingSpace(
+ awt::Rectangle & rRemainingSpace,
+ const awt::Size & rPageSize,
+ const chart2::RelativePosition& rRelPos,
+ LegendPosition ePos,
+ const awt::Size& aLegendSize,
+ bool bOverlay )
+{
+ // calculate position
+ awt::Point aResult(
+ static_cast< sal_Int32 >( rRelPos.Primary * rPageSize.Width ),
+ static_cast< sal_Int32 >( rRelPos.Secondary * rPageSize.Height ));
+
+ aResult = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
+ aResult, aLegendSize, rRelPos.Anchor );
+
+ // adapt rRemainingSpace if LegendPosition is not CUSTOM
+ // #i109336# Improve auto positioning in chart
+ sal_Int32 nXDistance = lcl_getLegendLeftRightMargin();
+ sal_Int32 nYDistance = lcl_getLegendTopBottomMargin();
+ if (!bOverlay) switch( ePos )
+ {
+ case LegendPosition_LINE_START:
+ {
+ sal_Int32 nExtent = aLegendSize.Width;
+ rRemainingSpace.Width -= ( nExtent + nXDistance );
+ rRemainingSpace.X += ( nExtent + nXDistance );
+ }
+ break;
+ case LegendPosition_LINE_END:
+ {
+ rRemainingSpace.Width -= ( aLegendSize.Width + nXDistance );
+ }
+ break;
+ case LegendPosition_PAGE_START:
+ {
+ sal_Int32 nExtent = aLegendSize.Height;
+ rRemainingSpace.Height -= ( nExtent + nYDistance );
+ rRemainingSpace.Y += ( nExtent + nYDistance );
+ }
+ break;
+ case LegendPosition_PAGE_END:
+ {
+ rRemainingSpace.Height -= ( aLegendSize.Height + nYDistance );
+ }
+ break;
+
+ default:
+ // nothing
+ break;
+ }
+
+ // adjust the legend position. Esp. for old files that had slightly smaller legends
+ const sal_Int32 nEdgeDistance( 30 );
+ if( aResult.X + aLegendSize.Width > rPageSize.Width )
+ {
+ sal_Int32 nNewX( (rPageSize.Width - aLegendSize.Width) - nEdgeDistance );
+ if( nNewX > rPageSize.Width / 4 )
+ aResult.X = nNewX;
+ }
+ if( aResult.Y + aLegendSize.Height > rPageSize.Height )
+ {
+ sal_Int32 nNewY( (rPageSize.Height - aLegendSize.Height) - nEdgeDistance );
+ if( nNewY > rPageSize.Height / 4 )
+ aResult.Y = nNewY;
+ }
+
+ return aResult;
+}
+
+bool lcl_shouldSymbolsBePlacedOnTheLeftSide( const Reference< beans::XPropertySet >& xLegendProp, sal_Int16 nDefaultWritingMode )
+{
+ bool bSymbolsLeftSide = true;
+ try
+ {
+ if( SvtCTLOptions::IsCTLFontEnabled() )
+ {
+ if(xLegendProp.is())
+ {
+ sal_Int16 nWritingMode=-1;
+ if( xLegendProp->getPropertyValue( "WritingMode" ) >>= nWritingMode )
+ {
+ if( nWritingMode == text::WritingMode2::PAGE )
+ nWritingMode = nDefaultWritingMode;
+ if( nWritingMode == text::WritingMode2::RL_TB )
+ bSymbolsLeftSide=false;
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return bSymbolsLeftSide;
+}
+
+std::vector<std::shared_ptr<VButton>> lcl_createButtons(
+ rtl::Reference<SvxShapeGroupAnyD> const & xLegendContainer,
+ ChartModel& rModel, bool bPlaceButtonsVertically, tools::Long & nUsedHeight)
+{
+ std::vector<std::shared_ptr<VButton>> aButtons;
+
+ uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(rModel.getDataProvider(), uno::UNO_QUERY);
+ if (!xPivotTableDataProvider.is())
+ return aButtons;
+
+ if (!xPivotTableDataProvider->getColumnFields().hasElements())
+ return aButtons;
+
+ awt::Size aSize(2000, 700);
+ int x = 100;
+ int y = 100;
+
+ const css::uno::Sequence<chart2::data::PivotTableFieldEntry> aPivotFieldEntries = xPivotTableDataProvider->getColumnFields();
+ for (chart2::data::PivotTableFieldEntry const & sColumnFieldEntry : aPivotFieldEntries)
+ {
+ auto pButton = std::make_shared<VButton>();
+ aButtons.push_back(pButton);
+ pButton->init(xLegendContainer);
+ awt::Point aNewPosition(x, y);
+ pButton->setLabel(sColumnFieldEntry.Name);
+ pButton->setCID("FieldButton.Column." + OUString::number(sColumnFieldEntry.DimensionIndex));
+ pButton->setPosition(aNewPosition);
+ pButton->setSize(aSize);
+ if (sColumnFieldEntry.Name == "Data")
+ {
+ pButton->showArrow(false);
+ pButton->setBGColor(Color(0x00F6F6F6));
+ }
+ if (sColumnFieldEntry.HasHiddenMembers)
+ pButton->setArrowColor(Color(0x0000FF));
+
+ if (bPlaceButtonsVertically)
+ y += aSize.Height + 100;
+ else
+ x += aSize.Width + 100;
+ }
+ if (bPlaceButtonsVertically)
+ nUsedHeight += y + 100;
+ else
+ nUsedHeight += aSize.Height + 100;
+
+ return aButtons;
+}
+
+} // anonymous namespace
+
+VLegend::VLegend(
+ rtl::Reference< Legend > xLegend,
+ const Reference< uno::XComponentContext > & xContext,
+ std::vector< LegendEntryProvider* >&& rLegendEntryProviderList,
+ rtl::Reference<SvxShapeGroupAnyD> xTargetPage,
+ ChartModel& rModel )
+ : m_xTarget(std::move(xTargetPage))
+ , m_xLegend(std::move(xLegend))
+ , mrModel(rModel)
+ , m_xContext(xContext)
+ , m_aLegendEntryProviderList(std::move(rLegendEntryProviderList))
+ , m_nDefaultWritingMode(text::WritingMode2::LR_TB)
+{
+}
+
+void VLegend::setDefaultWritingMode( sal_Int16 nDefaultWritingMode )
+{
+ m_nDefaultWritingMode = nDefaultWritingMode;
+}
+
+bool VLegend::isVisible( const rtl::Reference< Legend > & xLegend )
+{
+ if( ! xLegend.is())
+ return false;
+
+ bool bShow = false;
+ try
+ {
+ xLegend->getPropertyValue( "Show") >>= bShow;
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return bShow;
+}
+
+void VLegend::createShapes(
+ const awt::Size & rAvailableSpace,
+ const awt::Size & rPageSize,
+ awt::Size & rDefaultLegendSize )
+{
+ if(! (m_xLegend.is() && m_xTarget.is()))
+ return;
+
+ try
+ {
+ //create shape and add to page
+ OUString aLegendParticle( ObjectIdentifier::createParticleForLegend( &mrModel ) );
+ m_xShape = ShapeFactory::createGroup2D( m_xTarget,
+ ObjectIdentifier::createClassifiedIdentifierForParticle( aLegendParticle ) );
+
+ // create and insert sub-shapes
+ rtl::Reference<SvxShapeGroupAnyD> xLegendContainer = m_xShape;
+ if( xLegendContainer.is() )
+ {
+ // for quickly setting properties
+ tPropertyValues aLineFillProperties;
+ tPropertyValues aTextProperties;
+
+ css::chart::ChartLegendExpansion eExpansion = css::chart::ChartLegendExpansion_HIGH;
+ awt::Size aLegendSize( rAvailableSpace );
+
+ bool bCustom = false;
+ LegendPosition eLegendPosition = LegendPosition_LINE_END;
+ // get Expansion property
+ m_xLegend->getPropertyValue("Expansion") >>= eExpansion;
+ if( eExpansion == css::chart::ChartLegendExpansion_CUSTOM )
+ {
+ RelativeSize aRelativeSize;
+ if (m_xLegend->getPropertyValue("RelativeSize") >>= aRelativeSize)
+ {
+ aLegendSize.Width = static_cast<sal_Int32>(::rtl::math::approxCeil( aRelativeSize.Primary * rPageSize.Width ));
+ aLegendSize.Height = static_cast<sal_Int32>(::rtl::math::approxCeil( aRelativeSize.Secondary * rPageSize.Height ));
+ bCustom = true;
+ }
+ else
+ {
+ eExpansion = css::chart::ChartLegendExpansion_HIGH;
+ }
+ }
+ m_xLegend->getPropertyValue("AnchorPosition") >>= eLegendPosition;
+ lcl_getProperties( m_xLegend, aLineFillProperties, aTextProperties, rPageSize );
+
+ // create entries
+ double fViewFontSize = lcl_CalcViewFontSize( m_xLegend, rPageSize );//todo
+ // #i109336# Improve auto positioning in chart
+ sal_Int32 nSymbolHeight = static_cast< sal_Int32 >( fViewFontSize * 0.6 );
+ sal_Int32 nSymbolWidth = nSymbolHeight;
+
+ for (LegendEntryProvider* pLegendEntryProvider : m_aLegendEntryProviderList)
+ {
+ if (pLegendEntryProvider)
+ {
+ awt::Size aCurrentRatio = pLegendEntryProvider->getPreferredLegendKeyAspectRatio();
+ sal_Int32 nCurrentWidth = aCurrentRatio.Width;
+ if( aCurrentRatio.Height > 0 )
+ {
+ nCurrentWidth = nSymbolHeight* aCurrentRatio.Width/aCurrentRatio.Height;
+ }
+ nSymbolWidth = std::max( nSymbolWidth, nCurrentWidth );
+ }
+ }
+ awt::Size aMaxSymbolExtent( nSymbolWidth, nSymbolHeight );
+
+ std::vector<ViewLegendEntry> aViewEntries;
+ for(LegendEntryProvider* pLegendEntryProvider : m_aLegendEntryProviderList)
+ {
+ if (pLegendEntryProvider)
+ {
+ std::vector<ViewLegendEntry> aNewEntries = pLegendEntryProvider->createLegendEntries(
+ aMaxSymbolExtent, eLegendPosition, m_xLegend,
+ xLegendContainer, m_xContext, mrModel);
+ aViewEntries.insert( aViewEntries.end(), aNewEntries.begin(), aNewEntries.end() );
+ }
+ }
+
+ bool bSymbolsLeftSide = lcl_shouldSymbolsBePlacedOnTheLeftSide( m_xLegend, m_nDefaultWritingMode );
+
+ uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider( mrModel.getDataProvider(), uno::UNO_QUERY );
+ bool bIsPivotChart = xPivotTableDataProvider.is();
+
+ if ( !aViewEntries.empty() || bIsPivotChart )
+ {
+ // create buttons
+ tools::Long nUsedButtonHeight = 0;
+ bool bPlaceButtonsVertically = (eLegendPosition != LegendPosition_PAGE_START &&
+ eLegendPosition != LegendPosition_PAGE_END &&
+ eExpansion != css::chart::ChartLegendExpansion_WIDE);
+
+ std::vector<std::shared_ptr<VButton>> aButtons = lcl_createButtons(xLegendContainer, mrModel, bPlaceButtonsVertically, nUsedButtonHeight);
+
+ // A custom size includes the size we used for buttons already, so we need to
+ // subtract that from the size that is available for the legend
+ if (bCustom)
+ aLegendSize.Height -= nUsedButtonHeight;
+
+ // place the legend entries
+ aLegendSize = lcl_placeLegendEntries(aViewEntries, eExpansion, bSymbolsLeftSide, fViewFontSize,
+ aMaxSymbolExtent, aTextProperties, xLegendContainer,
+ aLegendSize, nUsedButtonHeight, rPageSize, bIsPivotChart, rDefaultLegendSize);
+
+ uno::Reference<beans::XPropertySet> xModelPage(mrModel.getPageBackground());
+
+ for (std::shared_ptr<VButton> const & pButton : aButtons)
+ {
+ // adjust the width of the buttons if we place them vertically
+ if (bPlaceButtonsVertically)
+ pButton->setSize({aLegendSize.Width - 200, pButton->getSize().Height});
+
+ // create the buttons
+ pButton->createShapes(xModelPage);
+ }
+
+ rtl::Reference<SvxShapeRect> xBorder = ShapeFactory::createRectangle(
+ xLegendContainer, aLegendSize, awt::Point(0, 0), aLineFillProperties.first,
+ aLineFillProperties.second, ShapeFactory::StackPosition::Bottom);
+
+ //because of this name this border will be used for marking the legend
+ ShapeFactory::setShapeName(xBorder, "MarkHandles");
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+}
+
+void VLegend::changePosition(
+ awt::Rectangle & rOutAvailableSpace,
+ const awt::Size & rPageSize,
+ const css::awt::Size & rDefaultLegendSize )
+{
+ if(! m_xShape.is())
+ return;
+
+ try
+ {
+ // determine position and alignment depending on default position
+ awt::Size aLegendSize = m_xShape->getSize();
+ chart2::RelativePosition aRelativePosition;
+
+ bool bDefaultLegendSize = rDefaultLegendSize.Width != 0 || rDefaultLegendSize.Height != 0;
+ bool bAutoPosition =
+ ! (m_xLegend->getPropertyValue( "RelativePosition") >>= aRelativePosition);
+
+ LegendPosition ePos = LegendPosition_LINE_END;
+ m_xLegend->getPropertyValue( "AnchorPosition") >>= ePos;
+
+ bool bOverlay = false;
+ m_xLegend->getPropertyValue("Overlay") >>= bOverlay;
+ //calculate position
+ if( bAutoPosition )
+ {
+ // auto position: relative to remaining space
+ aRelativePosition = lcl_getDefaultPosition( ePos, rOutAvailableSpace, rPageSize );
+ awt::Point aPos = lcl_calculatePositionAndRemainingSpace(
+ rOutAvailableSpace, rPageSize, aRelativePosition, ePos, aLegendSize, bOverlay );
+ m_xShape->setPosition( aPos );
+ }
+ else
+ {
+ // manual position: relative to whole page
+ awt::Rectangle aAvailableSpace( 0, 0, rPageSize.Width, rPageSize.Height );
+ awt::Point aPos = lcl_calculatePositionAndRemainingSpace(
+ aAvailableSpace, rPageSize, aRelativePosition, ePos, bDefaultLegendSize ? rDefaultLegendSize : aLegendSize, bOverlay );
+ m_xShape->setPosition( aPos );
+
+ if (!bOverlay)
+ {
+ // calculate remaining space as if having autoposition:
+ aRelativePosition = lcl_getDefaultPosition( ePos, rOutAvailableSpace, rPageSize );
+ lcl_calculatePositionAndRemainingSpace(
+ rOutAvailableSpace, rPageSize, aRelativePosition, ePos, bDefaultLegendSize ? rDefaultLegendSize : aLegendSize, bOverlay );
+ }
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2" );
+ }
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/VLegend.hxx b/chart2/source/view/main/VLegend.hxx
new file mode 100644
index 0000000000..b6b6a0074e
--- /dev/null
+++ b/chart2/source/view/main/VLegend.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <Legend.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <rtl/ref.hxx>
+#include <svx/unoshape.hxx>
+#include <vector>
+
+namespace chart { class ChartModel; }
+namespace com::sun::star::awt { struct Rectangle; }
+namespace com::sun::star::awt { struct Size; }
+namespace com::sun::star::chart2 { class XLegend; }
+namespace com::sun::star::drawing { class XShape; }
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace chart
+{
+
+class Legend;
+class LegendEntryProvider;
+
+class VLegend
+{
+public:
+ VLegend( rtl::Reference< ::chart::Legend > xLegend,
+ const css::uno::Reference< css::uno::XComponentContext > & xContext,
+ std::vector< LegendEntryProvider* >&& rLegendEntryProviderList,
+ rtl::Reference<SvxShapeGroupAnyD> xTargetPage,
+ ChartModel& rModel );
+
+ void setDefaultWritingMode( sal_Int16 nDefaultWritingMode );
+
+ void createShapes( const css::awt::Size & rAvailableSpace,
+ const css::awt::Size & rPageSize,
+ css::awt::Size & rDefaultLegendSize );
+
+ /** Sets the position according to its internal anchor.
+
+ @param rOutAvailableSpace
+ is modified by the method, if the legend is in a standard position,
+ such that the space allocated by the legend is removed from it.
+
+ @param rReferenceSize
+ is used to calculate the offset (default 2%) from the edge.
+ */
+ void changePosition(
+ css::awt::Rectangle & rOutAvailableSpace,
+ const css::awt::Size & rReferenceSize,
+ const css::awt::Size & rDefaultLegendSize );
+
+ static bool isVisible(
+ const rtl::Reference< ::chart::Legend > & xLegend );
+
+private:
+ rtl::Reference<SvxShapeGroupAnyD> m_xTarget;
+ rtl::Reference<::chart::Legend> m_xLegend;
+ rtl::Reference< SvxShapeGroup > m_xShape;
+
+ ChartModel& mrModel;
+
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+
+ std::vector< LegendEntryProvider* > m_aLegendEntryProviderList;
+
+ sal_Int16 m_nDefaultWritingMode;//to be used when writing mode is set to page
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/VLegendSymbolFactory.cxx b/chart2/source/view/main/VLegendSymbolFactory.cxx
new file mode 100644
index 0000000000..0b230ed07f
--- /dev/null
+++ b/chart2/source/view/main/VLegendSymbolFactory.cxx
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <VLegendSymbolFactory.hxx>
+#include <PropertyMapper.hxx>
+#include <ShapeFactory.hxx>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/chart2/Symbol.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Reference;
+
+namespace
+{
+
+void getPropNamesAndValues( const Reference< beans::XPropertySet >& xProp,
+ ::chart::tNameSequence& rNames,
+ ::chart::tAnySequence& rValues,
+ ::chart::VLegendSymbolFactory::PropertyType ePropertyType,
+ const awt::Size& aMaxSymbolExtent)
+{
+ const ::chart::tPropertyNameMap & aFilledSeriesNameMap( ::chart::PropertyMapper::getPropertyNameMapForFilledSeriesProperties());
+ const ::chart::tPropertyNameMap & aLineSeriesNameMap( ::chart::PropertyMapper::getPropertyNameMapForLineSeriesProperties());
+ const ::chart::tPropertyNameMap & aLineNameMap( ::chart::PropertyMapper::getPropertyNameMapForLineProperties());
+
+ ::chart::tPropertyNameValueMap aValueMap;
+ switch( ePropertyType )
+ {
+ case ::chart::VLegendSymbolFactory::PropertyType::FilledSeries:
+ ::chart::PropertyMapper::getValueMap( aValueMap, aFilledSeriesNameMap, xProp );
+ break;
+ case ::chart::VLegendSymbolFactory::PropertyType::LineSeries:
+ ::chart::PropertyMapper::getValueMap( aValueMap, aLineSeriesNameMap, xProp );
+ break;
+ case ::chart::VLegendSymbolFactory::PropertyType::Line:
+ ::chart::PropertyMapper::getValueMap( aValueMap, aLineNameMap, xProp );
+ break;
+ }
+
+ ::chart::PropertyMapper::getMultiPropertyListsFromValueMap( rNames, rValues, aValueMap );
+
+ uno::Any* pLineWidthAny = ::chart::PropertyMapper::getValuePointer(rValues,rNames,u"LineWidth");
+ sal_Int32 nLineWidth = 0;
+ if( pLineWidthAny && (*pLineWidthAny>>=nLineWidth) )
+ {
+ // use legend entry height as upper limit for line width
+ sal_Int32 nMaxLineWidthForLegend = aMaxSymbolExtent.Height;
+ if( nLineWidth>nMaxLineWidthForLegend )
+ *pLineWidthAny <<= nMaxLineWidthForLegend;
+ }
+}
+
+void lcl_setPropertiesToShape(
+ const Reference< beans::XPropertySet > & xProp,
+ const rtl::Reference< SvxShape > & xShape,
+ ::chart::VLegendSymbolFactory::PropertyType ePropertyType,
+ const awt::Size& aMaxSymbolExtent)
+{
+ ::chart::tNameSequence aPropNames;
+ ::chart::tAnySequence aPropValues;
+ getPropNamesAndValues( xProp, aPropNames, aPropValues,
+ ePropertyType, aMaxSymbolExtent );
+
+ ::chart::PropertyMapper::setMultiProperties( aPropNames, aPropValues, *xShape );
+}
+
+} // anonymous namespace
+
+namespace chart
+{
+
+rtl::Reference< SvxShapeGroup > VLegendSymbolFactory::createSymbol(
+ const awt::Size& rEntryKeyAspectRatio,
+ const rtl::Reference<SvxShapeGroupAnyD>& rSymbolContainer,
+ LegendSymbolStyle eStyle,
+ const Reference< beans::XPropertySet > & xLegendEntryProperties,
+ PropertyType ePropertyType, const uno::Any& rExplicitSymbol )
+{
+ rtl::Reference< SvxShapeGroup > xResult;
+
+ if( !rSymbolContainer)
+ return xResult;
+
+ xResult = ShapeFactory::createGroup2D( rSymbolContainer );
+ if( ! xResult)
+ return xResult;
+
+ rtl::Reference<SvxShapeGroupAnyD> xResultGroup = xResult;
+
+ // add an invisible square box to maintain aspect ratio
+ ShapeFactory::createInvisibleRectangle( xResultGroup, rEntryKeyAspectRatio );
+
+ // create symbol
+ try
+ {
+ if( eStyle == LegendSymbolStyle::Line )
+ {
+ rtl::Reference<SvxShapePolyPolygon> xLine =
+ ShapeFactory::createLine( xResultGroup, awt::Size( rEntryKeyAspectRatio.Width, 0 ),
+ awt::Point( 0, rEntryKeyAspectRatio.Height/2 ));
+ lcl_setPropertiesToShape( xLegendEntryProperties, xLine, ePropertyType, rEntryKeyAspectRatio );
+
+ const sal_Int32 nSize = std::min(rEntryKeyAspectRatio.Width,rEntryKeyAspectRatio.Height);
+ chart2::Symbol aSymbol;
+ if( rExplicitSymbol >>= aSymbol )
+ {
+ drawing::Direction3D aSymbolSize( nSize, nSize, 0 );
+ drawing::Position3D aPos( rEntryKeyAspectRatio.Width/2.0, rEntryKeyAspectRatio.Height/2.0, 0 );
+ if( aSymbol.Style == chart2::SymbolStyle_STANDARD )
+ {
+ // take series color as fill color
+ xLegendEntryProperties->getPropertyValue( "Color") >>= aSymbol.FillColor;
+ // border of symbols always same as fill color
+ aSymbol.BorderColor = aSymbol.FillColor;
+
+ ShapeFactory::createSymbol2D(
+ xResultGroup,
+ aPos,
+ aSymbolSize,
+ aSymbol.StandardSymbol,
+ aSymbol.BorderColor,
+ aSymbol.FillColor );
+ }
+ else if( aSymbol.Style == chart2::SymbolStyle_GRAPHIC )
+ {
+ ShapeFactory::createGraphic2D(
+ xResultGroup,
+ aPos,
+ aSymbolSize,
+ aSymbol.Graphic );
+ }
+ else if( aSymbol.Style == chart2::SymbolStyle_AUTO )
+ {
+ SAL_WARN("chart2", "the given parameter is not allowed to contain an automatic symbol style");
+ }
+ }
+ }
+ else if( eStyle == LegendSymbolStyle::Circle )
+ {
+ sal_Int32 nSize = std::min( rEntryKeyAspectRatio.Width, rEntryKeyAspectRatio.Height );
+ rtl::Reference<SvxShapeCircle> xShape =
+ ShapeFactory::createCircle( xResultGroup, awt::Size( nSize, nSize ),
+ awt::Point( rEntryKeyAspectRatio.Width/2-nSize/2, rEntryKeyAspectRatio.Height/2-nSize/2 ));
+ lcl_setPropertiesToShape( xLegendEntryProperties, xShape, ePropertyType, awt::Size(0,0) ); // PropertyType::FilledSeries );
+ }
+ else // eStyle == LegendSymbolStyle::Box
+ {
+ tNameSequence aPropNames;
+ tAnySequence aPropValues;
+
+ getPropNamesAndValues( xLegendEntryProperties, aPropNames, aPropValues,
+ ePropertyType, awt::Size(0,0) );// PropertyType::FilledSeries
+
+ ShapeFactory::createRectangle( xResultGroup,
+ rEntryKeyAspectRatio, awt::Point( 0, 0 ),
+ aPropNames, aPropValues );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+
+ return xResult;
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/VLineProperties.cxx b/chart2/source/view/main/VLineProperties.cxx
new file mode 100644
index 0000000000..81685337f7
--- /dev/null
+++ b/chart2/source/view/main/VLineProperties.cxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <VLineProperties.hxx>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/LineCap.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+
+// get line properties from a propertyset
+
+VLineProperties::VLineProperties()
+{
+ Color <<= sal_Int32(0x000000); //type sal_Int32 UNO_NAME_LINECOLOR
+ LineStyle
+ <<= drawing::LineStyle_SOLID; //type drawing::LineStyle for property UNO_NAME_LINESTYLE
+ Transparence <<= sal_Int16(0); //type sal_Int16 for property UNO_NAME_LINETRANSPARENCE
+ Width <<= sal_Int32(0); //type sal_Int32 for property UNO_NAME_LINEWIDTH
+ LineCap <<= drawing::LineCap_BUTT; //type drawing::LineCap for property UNO_NAME_LINECAP
+}
+
+void VLineProperties::initFromPropertySet(const uno::Reference<beans::XPropertySet>& xProp)
+{
+ if (xProp.is())
+ {
+ try
+ {
+ Color = xProp->getPropertyValue("LineColor");
+ LineStyle = xProp->getPropertyValue("LineStyle");
+ Transparence = xProp->getPropertyValue("LineTransparence");
+ Width = xProp->getPropertyValue("LineWidth");
+ DashName = xProp->getPropertyValue("LineDashName");
+ LineCap = xProp->getPropertyValue("LineCap");
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "");
+ }
+ }
+ else
+ LineStyle <<= drawing::LineStyle_NONE;
+}
+
+bool VLineProperties::isLineVisible() const
+{
+ bool bRet = false;
+
+ drawing::LineStyle aLineStyle(drawing::LineStyle_SOLID);
+ LineStyle >>= aLineStyle;
+ if (aLineStyle != drawing::LineStyle_NONE)
+ {
+ sal_Int16 nLineTransparence = 0;
+ Transparence >>= nLineTransparence;
+ if (nLineTransparence != 100)
+ {
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/VPolarTransformation.cxx b/chart2/source/view/main/VPolarTransformation.cxx
new file mode 100644
index 0000000000..9ec2eea3fc
--- /dev/null
+++ b/chart2/source/view/main/VPolarTransformation.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <VPolarTransformation.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Sequence;
+
+namespace chart
+{
+
+VPolarTransformation::VPolarTransformation( const PolarPlottingPositionHelper& rPositionHelper )
+ : m_aPositionHelper(rPositionHelper)
+ , m_aUnitCartesianToScene( rPositionHelper.getUnitCartesianToScene() )
+{
+}
+
+VPolarTransformation::~VPolarTransformation()
+{
+}
+
+// ____ XTransformation2 ____
+css::drawing::Position3D VPolarTransformation::transform(
+ const Sequence< double >& rSourceValues ) const
+{
+ double fScaledLogicAngle = rSourceValues[0];
+ double fScaledLogicRadius = rSourceValues[1];
+
+ if( m_aPositionHelper.isSwapXAndY() )
+ std::swap(fScaledLogicAngle,fScaledLogicRadius);
+
+ double fAngleDegree = m_aPositionHelper.transformToAngleDegree( fScaledLogicAngle, false );
+ double fAnglePi = basegfx::deg2rad(fAngleDegree);
+ double fRadius = m_aPositionHelper.transformToRadius( fScaledLogicRadius, false);
+
+ double fX=fRadius*cos(fAnglePi);
+ double fY=fRadius*sin(fAnglePi);
+ double fZ=rSourceValues[2];
+
+ //!! applying matrix to vector does ignore translation, so it is important to use a B3DPoint here instead of B3DVector
+ ::basegfx::B3DPoint aPoint(fX,fY,fZ);
+ ::basegfx::B3DPoint aRet = m_aUnitCartesianToScene * aPoint;
+ return css::drawing::Position3D(aRet.getX(), aRet.getY(), aRet.getZ());
+}
+
+css::drawing::Position3D VPolarTransformation::transform(
+ const css::drawing::Position3D& rSourceValues ) const
+{
+ double fScaledLogicAngle = rSourceValues.PositionX;
+ double fScaledLogicRadius = rSourceValues.PositionY;
+
+ if( m_aPositionHelper.isSwapXAndY() )
+ std::swap(fScaledLogicAngle,fScaledLogicRadius);
+
+ double fAngleDegree = m_aPositionHelper.transformToAngleDegree( fScaledLogicAngle, false );
+ double fAnglePi = basegfx::deg2rad(fAngleDegree);
+ double fRadius = m_aPositionHelper.transformToRadius( fScaledLogicRadius, false);
+
+ double fX=fRadius*cos(fAnglePi);
+ double fY=fRadius*sin(fAnglePi);
+ double fZ=rSourceValues.PositionZ;
+
+ //!! applying matrix to vector does ignore translation, so it is important to use a B3DPoint here instead of B3DVector
+ ::basegfx::B3DPoint aPoint(fX,fY,fZ);
+ ::basegfx::B3DPoint aRet = m_aUnitCartesianToScene * aPoint;
+ return css::drawing::Position3D(aRet.getX(), aRet.getY(), aRet.getZ());
+}
+
+} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/VTitle.cxx b/chart2/source/view/main/VTitle.cxx
new file mode 100644
index 0000000000..e251fe9597
--- /dev/null
+++ b/chart2/source/view/main/VTitle.cxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VTitle.hxx"
+#include <CommonConverters.hxx>
+#include <ShapeFactory.hxx>
+#include <Title.hxx>
+#include <com/sun/star/chart2/XTitle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <utility>
+#include <comphelper/diagnose_ex.hxx>
+
+namespace chart
+{
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+
+VTitle::VTitle( uno::Reference< XTitle > xTitle )
+ : m_xTitle(std::move(xTitle))
+ , m_fRotationAngleDegree(0.0)
+ , m_nXPos(0)
+ , m_nYPos(0)
+{
+}
+
+VTitle::~VTitle()
+{
+}
+
+void VTitle::init(
+ const rtl::Reference<SvxShapeGroupAnyD>& xTargetPage
+ , const OUString& rCID )
+{
+ m_xTarget = xTargetPage;
+ m_aCID = rCID;
+}
+
+double VTitle::getRotationAnglePi() const
+{
+ return basegfx::deg2rad(m_fRotationAngleDegree);
+}
+
+awt::Size VTitle::getUnrotatedSize() const //size before rotation
+{
+ awt::Size aRet;
+ if(m_xShape.is())
+ aRet = m_xShape->getSize();
+ return aRet;
+}
+
+awt::Size VTitle::getFinalSize() const //size after rotation
+{
+ return ShapeFactory::getSizeAfterRotation(
+ *m_xShape, m_fRotationAngleDegree );
+}
+
+void VTitle::changePosition( const awt::Point& rPos )
+{
+ if(!m_xShape.is())
+ return;
+ try
+ {
+ m_nXPos = rPos.X;
+ m_nYPos = rPos.Y;
+
+ //set position matrix
+ //the matrix needs to be set at the end behind autogrow and such position influencing properties
+ ::basegfx::B2DHomMatrix aM;
+ aM.rotate( basegfx::deg2rad(-m_fRotationAngleDegree) );//#i78696#->#i80521#
+ aM.translate( m_nXPos, m_nYPos);
+ m_xShape->SvxShape::setPropertyValue( "Transformation", uno::Any( B2DHomMatrixToHomogenMatrix3(aM) ) );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+}
+
+bool VTitle::isVisible(const rtl::Reference< Title >& xTitle) {
+ if (!xTitle.is()) {
+ return false;
+ }
+ bool bShow = true;
+ try {
+ xTitle->getPropertyValue("Visible") >>= bShow;
+ } catch (const uno::Exception &) {
+ DBG_UNHANDLED_EXCEPTION("chart2");
+ }
+ return bShow;
+}
+
+
+void VTitle::createShapes(
+ const awt::Point& rPos
+ , const awt::Size& rReferenceSize
+ , const awt::Size& rTextMaxWidth
+ , bool bYAxisTitle )
+{
+ if(!m_xTitle.is())
+ return;
+
+ uno::Sequence< uno::Reference< XFormattedString > > aStringList = m_xTitle->getText();
+ if(!aStringList.hasElements())
+ return;
+
+ m_nXPos = rPos.X;
+ m_nYPos = rPos.Y;
+
+ uno::Reference< beans::XPropertySet > xTitleProperties( m_xTitle, uno::UNO_QUERY );
+
+ try
+ {
+ double fAngleDegree = 0;
+ xTitleProperties->getPropertyValue( "TextRotation" ) >>= fAngleDegree;
+ m_fRotationAngleDegree += fAngleDegree;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("chart2", "" );
+ }
+
+ sal_Int32 nTextMaxWidth;
+ if (bYAxisTitle)
+ {
+ if (m_fRotationAngleDegree < 75.0 || m_fRotationAngleDegree > 285.0
+ || (m_fRotationAngleDegree > 105.0 && m_fRotationAngleDegree < 255.0))
+ nTextMaxWidth = rTextMaxWidth.Width;
+ else
+ nTextMaxWidth = rTextMaxWidth.Height;
+ }
+ else if (m_fRotationAngleDegree <= 15.0 || m_fRotationAngleDegree >= 345.0
+ || (m_fRotationAngleDegree >= 165.0 && m_fRotationAngleDegree <= 195.0))
+ nTextMaxWidth = rTextMaxWidth.Width;
+ else
+ nTextMaxWidth = rTextMaxWidth.Height;
+
+ m_xShape = ShapeFactory::createText( m_xTarget, rReferenceSize, rPos, aStringList, xTitleProperties,
+ m_fRotationAngleDegree, m_aCID, nTextMaxWidth );
+}
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/VTitle.hxx b/chart2/source/view/main/VTitle.hxx
new file mode 100644
index 0000000000..792d7f6a0a
--- /dev/null
+++ b/chart2/source/view/main/VTitle.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+#include <sal/types.h>
+#include <svx/unoshape.hxx>
+
+namespace com::sun::star::awt { struct Point; }
+namespace com::sun::star::chart2 { class XTitle; }
+namespace com::sun::star::drawing { class XShape; }
+namespace com::sun::star::drawing { class XShapes; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+class SvxShapeText;
+
+namespace chart
+{
+class Title;
+
+class VTitle final
+{
+public:
+ explicit VTitle( css::uno::Reference< css::chart2::XTitle > xTitle );
+ ~VTitle();
+
+ void init( const rtl::Reference<SvxShapeGroupAnyD>& xTargetPage
+ , const OUString& rCID );
+
+ void createShapes( const css::awt::Point& rPos
+ , const css::awt::Size& rReferenceSize
+ , const css::awt::Size& nTextMaxWidth
+ , bool bYAxisTitle );
+
+ double getRotationAnglePi() const;
+ css::awt::Size getUnrotatedSize() const;
+ css::awt::Size getFinalSize() const;
+ void changePosition( const css::awt::Point& rPos );
+ static bool isVisible(
+ const rtl::Reference< ::chart::Title > & xTitle);
+
+private:
+ rtl::Reference<SvxShapeGroupAnyD> m_xTarget;
+ css::uno::Reference< css::chart2::XTitle > m_xTitle;
+ rtl::Reference<SvxShapeText> m_xShape;
+ OUString m_aCID;
+
+ double m_fRotationAngleDegree;
+ sal_Int32 m_nXPos;
+ sal_Int32 m_nYPos;
+};
+
+} //namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/uiconfig/accelerator/en-US/default.xml b/chart2/uiconfig/accelerator/en-US/default.xml
new file mode 100644
index 0000000000..3965f4b8f3
--- /dev/null
+++ b/chart2/uiconfig/accelerator/en-US/default.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<accel:acceleratorlist xmlns:accel="http://openoffice.org/2001/accel" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <accel:item accel:code="KEY_Q" accel:mod1="true" xlink:href=".uno:Quit"/>
+ <accel:item accel:code="KEY_F4" accel:mod2="true" xlink:href=".uno:Quit"/>
+ <accel:item accel:code="KEY_N" accel:mod1="true" xlink:href=".uno:NewDoc"/>
+ <accel:item accel:code="KEY_O" accel:mod1="true" xlink:href=".uno:Open"/>
+ <accel:item accel:code="KEY_OPEN" xlink:href=".uno:Open"/>
+ <accel:item accel:code="KEY_P" accel:mod1="true" xlink:href=".uno:Print"/>
+ <accel:item accel:code="KEY_S" accel:mod1="true" xlink:href=".uno:Save"/>
+ <accel:item accel:code="KEY_W" accel:mod1="true" xlink:href=".uno:CloseWin"/>
+ <accel:item accel:code="KEY_F4" accel:mod1="true" xlink:href=".uno:CloseWin"/>
+ <accel:item accel:code="KEY_J" accel:shift="true" accel:mod1="true" xlink:href=".uno:FullScreen"/>
+ <accel:item accel:code="KEY_Z" accel:mod1="true" xlink:href=".uno:Undo"/>
+ <accel:item accel:code="KEY_BACKSPACE" accel:mod2="true" xlink:href=".uno:Undo"/>
+ <accel:item accel:code="KEY_UNDO" xlink:href=".uno:Undo"/>
+ <accel:item accel:code="KEY_Y" accel:mod1="true" xlink:href=".uno:Redo"/>
+ <accel:item accel:code="KEY_REPEAT" xlink:href=".uno:Repeat"/>
+ <accel:item accel:code="KEY_X" accel:mod1="true" xlink:href=".uno:Cut"/>
+ <accel:item accel:code="KEY_DELETE" accel:shift="true" xlink:href=".uno:Cut"/>
+ <accel:item accel:code="KEY_CUT" xlink:href=".uno:Cut"/>
+ <accel:item accel:code="KEY_C" accel:mod1="true" xlink:href=".uno:Copy"/>
+ <accel:item accel:code="KEY_INSERT" accel:mod1="true" xlink:href=".uno:Copy"/>
+ <accel:item accel:code="KEY_COPY" xlink:href=".uno:Copy"/>
+ <accel:item accel:code="KEY_V" accel:mod1="true" xlink:href=".uno:Paste"/>
+ <accel:item accel:code="KEY_INSERT" accel:shift="true" xlink:href=".uno:Paste"/>
+ <accel:item accel:code="KEY_PASTE" xlink:href=".uno:Paste"/>
+ <accel:item accel:code="KEY_DELETE" xlink:href=".uno:Delete"/>
+ <accel:item accel:code="KEY_F4" xlink:href=".uno:TransformDialog"/>
+</accel:acceleratorlist>
diff --git a/chart2/uiconfig/menubar/menubar.xml b/chart2/uiconfig/menubar/menubar.xml
new file mode 100644
index 0000000000..58c84d6cbc
--- /dev/null
+++ b/chart2/uiconfig/menubar/menubar.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<menu:menubar xmlns:menu="http://openoffice.org/2001/menu" menu:id="menubar">
+ <menu:menu menu:id=".uno:PickList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:AddDirect"/>
+ <menu:menuitem menu:id=".uno:CloseDoc"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Save"/>
+ <menu:menuitem menu:id=".uno:SaveAs"/>
+ <menu:menuitem menu:id=".uno:SaveAll" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SetDocumentProperties"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Quit"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:EditMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:Undo"/>
+ <menu:menuitem menu:id=".uno:Redo"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:Cut"/>
+ <menu:menuitem menu:id=".uno:Copy"/>
+ <menu:menuitem menu:id=".uno:Paste"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ViewMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:AvailableToolbars"/>
+ <menu:menuitem menu:id=".uno:StatusBarVisible"/>
+ <menu:menuitem menu:id=".uno:Sidebar" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DiagramData"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:InsertMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:InsertMenuTitles"/>
+ <menu:menuitem menu:id=".uno:InsertMenuLegend"/>
+ <menu:menuitem menu:id=".uno:InsertMenuAxes"/>
+ <menu:menuitem menu:id=".uno:InsertMenuGrids"/>
+ <menu:menuitem menu:id=".uno:InsertMenuDataTable"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:InsertMenuDataLabels"/>
+ <menu:menuitem menu:id=".uno:InsertMenuTrendlines"/>
+ <menu:menuitem menu:id=".uno:InsertMenuMeanValues"/>
+ <menu:menuitem menu:id=".uno:InsertMenuXErrorBars"/>
+ <menu:menuitem menu:id=".uno:InsertMenuYErrorBars"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:InsertSymbol"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:FormatMenu">
+ <menu:menupopup>
+ <menu:menu menu:id=".uno:ChartTitleMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:MainTitle"/>
+ <menu:menuitem menu:id=".uno:SubTitle"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:XTitle"/>
+ <menu:menuitem menu:id=".uno:YTitle"/>
+ <menu:menuitem menu:id=".uno:ZTitle"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SecondaryXTitle"/>
+ <menu:menuitem menu:id=".uno:SecondaryYTitle"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:AllTitles"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuitem menu:id=".uno:Legend"/>
+ <menu:menu menu:id=".uno:DiagramAxisMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DiagramAxisX"/>
+ <menu:menuitem menu:id=".uno:DiagramAxisY"/>
+ <menu:menuitem menu:id=".uno:DiagramAxisZ"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DiagramAxisA"/>
+ <menu:menuitem menu:id=".uno:DiagramAxisB"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DiagramAxisAll"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:DiagramGridMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:DiagramGridYMain"/>
+ <menu:menuitem menu:id=".uno:DiagramGridXMain"/>
+ <menu:menuitem menu:id=".uno:DiagramGridZMain"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DiagramGridYHelp"/>
+ <menu:menuitem menu:id=".uno:DiagramGridXHelp"/>
+ <menu:menuitem menu:id=".uno:DiagramGridZHelp"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DiagramGridAll"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DiagramWall" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:DiagramFloor" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:DiagramArea" menu:style="text"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:DiagramType"/>
+ <menu:menuitem menu:id=".uno:DataRanges"/>
+ <menu:menuitem menu:id=".uno:View3D"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:FormatSelection" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:TransformDialog" menu:style="text"/>
+ <menu:menu menu:id=".uno:ArrangeRow">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:Forward"/>
+ <menu:menuitem menu:id=".uno:Backward"/>
+ </menu:menupopup>
+ </menu:menu>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:ToolsMenu">
+ <menu:menupopup>
+ <menu:menu menu:id=".uno:MacrosMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:MacroRecorder"/>
+ <menu:menuitem menu:id=".uno:RunMacro"/>
+ <menu:menuitem menu:id=".uno:BasicIDEAppear"/>
+ <menu:menuitem menu:id=".uno:ScriptOrganizer"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:MacroSignature"/>
+ <menu:menuitem menu:id=".uno:MacroOrganizer?TabId:short=1"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuitem menu:id=".uno:OpenXMLFilterSettings"/>
+ <menu:menuitem menu:id="service:com.sun.star.deployment.ui.PackageManagerDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:ConfigureDialog" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:OptionsTreeDialog"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:WindowList">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:NewWindow"/>
+ <menu:menuitem menu:id=".uno:CloseWin"/>
+ <menu:menuseparator/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menu menu:id=".uno:HelpMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:HelpIndex"/>
+ <menu:menuitem menu:id=".uno:ExtendedHelp"/>
+ <menu:menuitem menu:id=".uno:Documentation"/>
+ <menu:menuitem menu:id=".uno:TipOfTheDay"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:QuestionAnswers"/>
+ <menu:menuitem menu:id=".uno:SendFeedback"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:SafeMode"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:GetInvolved"/>
+ <menu:menuitem menu:id=".uno:Donation"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:ShowLicense"/>
+ <menu:menuitem menu:id=".uno:About"/>
+ </menu:menupopup>
+ </menu:menu>
+</menu:menubar>
diff --git a/chart2/uiconfig/popupmenu/draw.xml b/chart2/uiconfig/popupmenu/draw.xml
new file mode 100644
index 0000000000..f7f762ea8b
--- /dev/null
+++ b/chart2/uiconfig/popupmenu/draw.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu">
+ <menu:menuitem menu:id=".uno:Cut"/>
+ <menu:menuitem menu:id=".uno:Copy"/>
+ <menu:menuitem menu:id=".uno:Paste"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:TransformDialog"/>
+ <menu:menuitem menu:id=".uno:FormatLine"/>
+ <menu:menuitem menu:id=".uno:FormatArea"/>
+ <menu:menuitem menu:id=".uno:TextAttributes"/>
+ <menu:menuseparator/>
+ <menu:menu menu:id=".uno:ArrangeRow">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:BringToFront"/>
+ <menu:menuitem menu:id=".uno:Forward"/>
+ <menu:menuitem menu:id=".uno:Backward"/>
+ <menu:menuitem menu:id=".uno:SendToBack"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:RenameObject"/>
+ <menu:menuitem menu:id=".uno:ObjectTitleDescription"/>
+</menu:menupopup>
diff --git a/chart2/uiconfig/popupmenu/drawtext.xml b/chart2/uiconfig/popupmenu/drawtext.xml
new file mode 100644
index 0000000000..e13990ca0a
--- /dev/null
+++ b/chart2/uiconfig/popupmenu/drawtext.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu">
+ <menu:menuitem menu:id=".uno:Cut"/>
+ <menu:menuitem menu:id=".uno:Copy"/>
+ <menu:menuitem menu:id=".uno:Paste"/>
+ <menu:menu menu:id=".uno:PasteSpecialMenu">
+ <menu:menupopup>
+ <menu:menuitem menu:id=".uno:PasteUnformatted"/>
+ <menu:menuitem menu:id=".uno:PasteSpecial"/>
+ </menu:menupopup>
+ </menu:menu>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:TextAttributes"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:FontDialog"/>
+ <menu:menuitem menu:id=".uno:ParagraphDialog"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:ThesaurusFromContext"/>
+ <menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:ResetAttributes"/>
+</menu:menupopup>
diff --git a/chart2/uiconfig/statusbar/statusbar.xml b/chart2/uiconfig/statusbar/statusbar.xml
new file mode 100644
index 0000000000..4f718b8d1d
--- /dev/null
+++ b/chart2/uiconfig/statusbar/statusbar.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE statusbar:statusbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "statusbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<statusbar:statusbar xmlns:statusbar="http://openoffice.org/2001/statusbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <statusbar:statusbaritem xlink:href=".uno:Context" statusbar:align="left" statusbar:autosize="true" statusbar:width="208"/>
+ <statusbar:statusbaritem xlink:href=".uno:ModifiedStatus" statusbar:align="center" statusbar:ownerdraw="true" statusbar:width="9"/>
+</statusbar:statusbar>
diff --git a/chart2/uiconfig/toolbar/arrowshapes.xml b/chart2/uiconfig/toolbar/arrowshapes.xml
new file mode 100644
index 0000000000..3f74148c7d
--- /dev/null
+++ b/chart2/uiconfig/toolbar/arrowshapes.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.right-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.left-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.down-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.up-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.left-right-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.up-down-arrow"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.circular-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.s-sharped-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.split-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.split-round-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.quad-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.corner-right-arrow"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.chevron"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.pentagon-right"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.striped-right-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.up-right-down-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.notched-right-arrow"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.up-right-arrow"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.right-arrow-callout"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.left-arrow-callout"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.down-arrow-callout"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.up-arrow-callout"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.left-right-arrow-callout"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.up-down-arrow-callout"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.quad-arrow-callout"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes.up-right-arrow-callout"/>
+</toolbar:toolbar>
diff --git a/chart2/uiconfig/toolbar/basicshapes.xml b/chart2/uiconfig/toolbar/basicshapes.xml
new file mode 100644
index 0000000000..148245f666
--- /dev/null
+++ b/chart2/uiconfig/toolbar/basicshapes.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.rectangle"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.round-rectangle"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.quadrat"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.round-quadrat"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.parallelogram"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.trapezoid"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.ellipse"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.circle"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.circle-pie"/>
+ <toolbar:toolbaritem xlink:href=".uno:CircleCut"/>
+ <toolbar:toolbaritem xlink:href=".uno:Arc"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.block-arc"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.isosceles-triangle"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.right-triangle"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.diamond"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.pentagon"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.hexagon"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.octagon"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.can"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.cube"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.paper"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.cross"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.frame"/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes.ring"/>
+</toolbar:toolbar>
diff --git a/chart2/uiconfig/toolbar/calloutshapes.xml b/chart2/uiconfig/toolbar/calloutshapes.xml
new file mode 100644
index 0000000000..04176302cc
--- /dev/null
+++ b/chart2/uiconfig/toolbar/calloutshapes.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:CalloutShapes.rectangular-callout"/>
+ <toolbar:toolbaritem xlink:href=".uno:CalloutShapes.round-rectangular-callout"/>
+ <toolbar:toolbaritem xlink:href=".uno:CalloutShapes.round-callout"/>
+ <toolbar:toolbaritem xlink:href=".uno:CalloutShapes.cloud-callout"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:CalloutShapes.line-callout-1"/>
+ <toolbar:toolbaritem xlink:href=".uno:CalloutShapes.line-callout-2"/>
+ <toolbar:toolbaritem xlink:href=".uno:CalloutShapes.line-callout-3"/>
+</toolbar:toolbar>
diff --git a/chart2/uiconfig/toolbar/drawbar.xml b/chart2/uiconfig/toolbar/drawbar.xml
new file mode 100644
index 0000000000..e6f48002a5
--- /dev/null
+++ b/chart2/uiconfig/toolbar/drawbar.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:SelectObject"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Line"/>
+ <toolbar:toolbaritem xlink:href=".uno:LineArrowEnd"/>
+ <toolbar:toolbaritem xlink:href=".uno:Rect"/>
+ <toolbar:toolbaritem xlink:href=".uno:Ellipse"/>
+ <toolbar:toolbaritem xlink:href=".uno:Freeline_Unfilled"/>
+ <toolbar:toolbaritem xlink:href=".uno:DrawText"/>
+ <toolbar:toolbaritem xlink:href=".uno:DrawCaption"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:BasicShapes"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes"/>
+ <toolbar:toolbaritem xlink:href=".uno:ArrowShapes"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes"/>
+ <toolbar:toolbaritem xlink:href=".uno:CalloutShapes"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes"/>
+</toolbar:toolbar>
diff --git a/chart2/uiconfig/toolbar/flowchartshapes.xml b/chart2/uiconfig/toolbar/flowchartshapes.xml
new file mode 100644
index 0000000000..019a908627
--- /dev/null
+++ b/chart2/uiconfig/toolbar/flowchartshapes.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-process"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-alternate-process"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-decision"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-data"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-predefined-process"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-internal-storage"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-document"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-multidocument"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-terminator"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-preparation"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-manual-input"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-manual-operation"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-connector"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-off-page-connector"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-card"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-punched-tape"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-summing-junction"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-or"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-collate"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-sort"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-extract"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-merge"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-stored-data"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-delay"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-sequential-access"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-magnetic-disk"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-direct-access-storage"/>
+ <toolbar:toolbaritem xlink:href=".uno:FlowChartShapes.flowchart-display"/>
+</toolbar:toolbar>
diff --git a/chart2/uiconfig/toolbar/standardbar.xml b/chart2/uiconfig/toolbar/standardbar.xml
new file mode 100644
index 0000000000..a4f3c21d3a
--- /dev/null
+++ b/chart2/uiconfig/toolbar/standardbar.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:AddDirect" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:NewDoc" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:Open" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:Save"/>
+ <toolbar:toolbaritem xlink:href=".uno:SaveAs" toolbar:visible="false"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:ExportDirectToPDF"/>
+ <toolbar:toolbaritem xlink:href=".uno:Print"/>
+ <toolbar:toolbaritem xlink:href=".uno:PrintDefault" toolbar:visible="false"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Cut" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:Copy" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:Paste" toolbar:visible="false"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:Undo"/>
+ <toolbar:toolbaritem xlink:href=".uno:Redo"/>
+</toolbar:toolbar>
diff --git a/chart2/uiconfig/toolbar/starshapes.xml b/chart2/uiconfig/toolbar/starshapes.xml
new file mode 100644
index 0000000000..cbc07fc70a
--- /dev/null
+++ b/chart2/uiconfig/toolbar/starshapes.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.star4"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.star5"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.star6"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.star8"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.star12"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.star24"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.bang"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.vertical-scroll"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.horizontal-scroll"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.signet"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.doorplate"/>
+ <toolbar:toolbaritem xlink:href=".uno:StarShapes.concave-star6"/>
+</toolbar:toolbar>
diff --git a/chart2/uiconfig/toolbar/symbolshapes.xml b/chart2/uiconfig/toolbar/symbolshapes.xml
new file mode 100644
index 0000000000..9ba9f22e0c
--- /dev/null
+++ b/chart2/uiconfig/toolbar/symbolshapes.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.smiley"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.heart"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.sun"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.moon"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.cloud"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.lightning"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.flower"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.forbidden"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.puzzle"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.quad-bevel"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.octagon-bevel"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.diamond-bevel"/>
+ <toolbar:toolbarbreak/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.bracket-pair"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.left-bracket"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.right-bracket"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.brace-pair"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.left-brace"/>
+ <toolbar:toolbaritem xlink:href=".uno:SymbolShapes.right-brace"/>
+</toolbar:toolbar>
diff --git a/chart2/uiconfig/toolbar/toolbar.xml b/chart2/uiconfig/toolbar/toolbar.xml
new file mode 100644
index 0000000000..809174ba20
--- /dev/null
+++ b/chart2/uiconfig/toolbar/toolbar.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE toolbar:toolbar PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "toolbar.dtd">
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<toolbar:toolbar xmlns:toolbar="http://openoffice.org/2001/toolbar" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <toolbar:toolbaritem xlink:href=".uno:ChartElementSelector"/>
+ <toolbar:toolbaritem xlink:href=".uno:FormatSelection"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DiagramType"/>
+ <toolbar:toolbaritem xlink:href=".uno:DiagramArea"/>
+ <toolbar:toolbaritem xlink:href=".uno:DiagramWall"/>
+ <toolbar:toolbaritem xlink:href=".uno:View3D"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DataRanges"/>
+ <toolbar:toolbaritem xlink:href=".uno:DiagramData"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:InsertMenuTitles"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:ToggleLegend"/>
+ <toolbar:toolbaritem xlink:href=".uno:Legend"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:ToggleGridHorizontal"/>
+ <toolbar:toolbaritem xlink:href=".uno:ToggleGridVertical"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:DiagramAxisX"/>
+ <toolbar:toolbaritem xlink:href=".uno:DiagramAxisY"/>
+ <toolbar:toolbaritem xlink:href=".uno:DiagramAxisZ"/>
+ <toolbar:toolbaritem xlink:href=".uno:DiagramAxisAll"/>
+ <toolbar:toolbarseparator/>
+ <toolbar:toolbaritem xlink:href=".uno:ScaleText" toolbar:visible="false"/>
+ <toolbar:toolbaritem xlink:href=".uno:NewArrangement" toolbar:visible="false"/>
+</toolbar:toolbar>
diff --git a/chart2/uiconfig/ui/3dviewdialog.ui b/chart2/uiconfig/ui/3dviewdialog.ui
new file mode 100644
index 0000000000..7225cf9595
--- /dev/null
+++ b/chart2/uiconfig/ui/3dviewdialog.ui
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="3DViewDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="3dviewdialog|3DViewDialog">3D View</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/attributedialog.ui b/chart2/uiconfig/ui/attributedialog.ui
new file mode 100644
index 0000000000..d99a2936bd
--- /dev/null
+++ b/chart2/uiconfig/ui/attributedialog.ui
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="AttributeDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes" context="stock">_Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="101">reset</action-widget>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/chardialog.ui b/chart2/uiconfig/ui/chardialog.ui
new file mode 100644
index 0000000000..ff84e760a4
--- /dev/null
+++ b/chart2/uiconfig/ui/chardialog.ui
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="CharDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="chardialog|CharDialog">Character</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes" context="stock">_Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="font">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="chardialog|font">Font</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="fonteffects">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="chardialog|fonteffects">Font Effects</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="position">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="chardialog|position">Position</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="101">reset</action-widget>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/chartdatadialog.ui b/chart2/uiconfig/ui/chartdatadialog.ui
new file mode 100644
index 0000000000..4c4b5bf5c8
--- /dev/null
+++ b/chart2/uiconfig/ui/chartdatadialog.ui
@@ -0,0 +1,361 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="ChartDataDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="chartdatadialog|ChartDataDialog">Data Table</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="close">
+ <property name="label" translatable="yes" context="stock">_Close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">12</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkToolButton" id="InsertRow">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="chartdatadialog|InsertRow">Insert Row</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">chart2/res/dataeditor_icon01.png</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="InsertRow-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="chartdatadialog|extended_tip|InsertRow">Inserts a new row below the current row.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="InsertColumn">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="chartdatadialog|InsertColumn">Insert Series</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">chart2/res/dataeditor_icon02.png</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="InsertColumn-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="chartdatadialog|extended_tip|InsertColumn">Inserts a new data series after the current column.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="InsertTextColumn">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="chartdatadialog|InsertTextColumn">Insert Text Column</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">chart2/res/dataeditor_icon07.png</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="InsertTextColumn-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="chartdatadialog|extended_tip|InsertTextColumn">Inserts a new text column after the current column for hierarchical axes descriptions.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="RemoveRow">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="chartdatadialog|RemoveRow">Delete Row</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">chart2/res/dataeditor_icon03.png</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RemoveRow-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="chartdatadialog|extended_tip|RemoveRow">Deletes the current row. It is not possible to delete the label row.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="RemoveColumn">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="chartdatadialog|RemoveColumn">Delete Series</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">chart2/res/dataeditor_icon04.png</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RemoveColumn-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="chartdatadialog|extended_tip|RemoveColumn">Deletes the current series or text column. It is not possible to delete the first text column.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparatorToolItem" id="toolbutton1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="MoveLeftColumn">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="chartdatadialog|MoveLeftColumn">Move Series Left</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">chart2/res/dataeditor_icon08.png</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MoveLeftColumn-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="chartdatadialog|extended_tip|MoveLeftColumn">Switches the current column with its neighbor at the left.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="MoveRightColumn">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="chartdatadialog|MoveRightColumn">Move Series Right</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">chart2/res/dataeditor_icon05.png</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MoveRightColumn-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="chartdatadialog|extended_tip|MoveRightColumn">Switches the current column with its neighbor at the right.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="MoveUpRow">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="chartdatadialog|MoveUpRow">Move Row Up</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">chart2/res/dataeditor_icon09.png</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MoveUpRow-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="chartdatadialog|extended_tip|MoveUpRow">Switches the current row with its neighbor above.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="MoveDownRow">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="chartdatadialog|MoveDownRow">Move Row Down</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">chart2/res/dataeditor_icon06.png</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MoveDownRow-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="chartdatadialog|extended_tip|MoveDownRow">Switches the current row with its neighbor below.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">external</property>
+ <property name="vscrollbar_policy">never</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="columns">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">external</property>
+ <property name="vscrollbar_policy">never</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="colorcolumns">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="datawindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-7">close</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ChartDataDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="chartdatadialog|extended_tip|ChartDataDialog">Opens the Data Table dialog where you can edit the chart data.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/charttypedialog.ui b/chart2/uiconfig/ui/charttypedialog.ui
new file mode 100644
index 0000000000..627a619d0b
--- /dev/null
+++ b/chart2/uiconfig/ui/charttypedialog.ui
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="ChartTypeDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="charttypedialog|ChartTypeDialog">Chart Type</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="content">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/columnfragment.ui b/chart2/uiconfig/ui/columnfragment.ui
new file mode 100644
index 0000000000..4f6be9d81d
--- /dev/null
+++ b/chart2/uiconfig/ui/columnfragment.ui
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="container">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry">
+ <property name="width_request">5</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="width_chars">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/combobox.ui b/chart2/uiconfig/ui/combobox.ui
new file mode 100644
index 0000000000..4cd0032993
--- /dev/null
+++ b/chart2/uiconfig/ui/combobox.ui
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="ComboBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin-end">6</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkComboBoxText" id="combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/datarangedialog.ui b/chart2/uiconfig/ui/datarangedialog.ui
new file mode 100644
index 0000000000..7817801dae
--- /dev/null
+++ b/chart2/uiconfig/ui/datarangedialog.ui
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="DataRangeDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="datarangedialog|DataRangeDialog">Data Ranges</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="range">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="datarangedialog|range">Data Range</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="series">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="datarangedialog|series">Data Series</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/dlg_DataLabel.ui b/chart2/uiconfig/ui/dlg_DataLabel.ui
new file mode 100644
index 0000000000..9c0df29325
--- /dev/null
+++ b/chart2/uiconfig/ui/dlg_DataLabel.ui
@@ -0,0 +1,676 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentDEGREE">
+ <property name="upper">359</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkDialog" id="dlg_DataLabels">
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="title" translatable="yes" context="dlg_DataLabel|dlg_DataLabels">Data Labels for all Data Series</property>
+ <property name="type-hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can-focus">False</property>
+ <property name="layout-style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="can-default">True</property>
+ <property name="has-default">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="dlg_DataLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="name">box_left</property>
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=2 n-rows=6 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <property name="row-homogeneous">True</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_VALUE_AS_NUMBER">
+ <property name="label" translatable="yes" context="dlg_DataLabel|CB_VALUE_AS_NUMBER">Value as _number</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_VALUE_AS_NUMBER-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|CB_VALUE_AS_NUMBER">Displays the absolute values of the data points.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_VALUE_AS_PERCENTAGE">
+ <property name="label" translatable="yes" context="dlg_DataLabel|CB_VALUE_AS_PERCENTAGE">Value as _percentage</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_VALUE_AS_PERCENTAGE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|CB_VALUE_AS_PERCENTAGE">Displays the percentage of the data points in each column.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_CATEGORY">
+ <property name="label" translatable="yes" context="dlg_DataLabel|CB_CATEGORY">_Category</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_CATEGORY-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|CB_CATEGORY">Shows the data point text labels.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_SYMBOL">
+ <property name="label" translatable="yes" context="dlg_DataLabel|CB_SYMBOL">_Legend key</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_SYMBOL-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|CB_SYMBOL">Displays the legend icons next to each data point label.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_WRAP_TEXT">
+ <property name="label" translatable="yes" context="dlg_DataLabel|CB_WRAP_TEXT">Auto text _wrap</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="PB_NUMBERFORMAT">
+ <property name="label" translatable="yes" context="dlg_DataLabel|PB_NUMBERFORMAT">Number _format...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="valign">center</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="PB_NUMBERFORMAT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|PB_NUMBERFORMAT">Opens a dialog to select the number format.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="PB_PERCENT_NUMBERFORMAT">
+ <property name="label" translatable="yes" context="dlg_DataLabel|PB_PERCENT_NUMBERFORMAT">Percentage f_ormat...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="valign">center</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="PB_PERCENT_NUMBERFORMAT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|PB_PERCENT_NUMBERFORMAT">Opens a dialog to select the percentage format.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="CT_LABEL_DIAL">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="label" translatable="yes" context="dlg_DataLabel|CT_LABEL_DIAL">ABCD</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="STR_DLG_NUMBERFORMAT_FOR_PERCENTAGE_VALUE">
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="dlg_DataLabel|STR_DLG_NUMBERFORMAT_FOR_PERCENTAGE_VALUE">Number Format for Percentage Value</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_DATA_SERIES_NAME">
+ <property name="label" translatable="yes" context="dlg_DataLabel|CB_DATA_SERIES_NAME">_Series name</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_DATA_SERIES_NAME-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|CB_DATA_SERIES_NAME">Shows the data series name in the label.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="dlg_DataLabel|label1">Text Attributes</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=2 n-rows=2 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <property name="row-homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="FT_LABEL_PLACEMENT">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="dlg_DataLabel|FT_LABEL_PLACEMENT">Place_ment</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">LB_LABEL_PLACEMENT</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_LABEL_PLACEMENT">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="valign">center</property>
+ <items>
+ <item id="0" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Best fit</item>
+ <item id="1" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Center</item>
+ <item id="2" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Above</item>
+ <item id="3" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Top left</item>
+ <item id="4" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Left</item>
+ <item id="5" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Bottom left</item>
+ <item id="6" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Below</item>
+ <item id="7" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Bottom right</item>
+ <item id="8" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Right</item>
+ <item id="9" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Top right</item>
+ <item id="10" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Inside</item>
+ <item id="11" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Outside</item>
+ <item id="12" translatable="yes" context="dlg_DataLabel|liststorePLACEMENT">Near origin</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_LABEL_PLACEMENT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|LB_LABEL_PLACEMENT">Selects the placement of data labels relative to the objects.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_TEXT_SEPARATOR">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="dlg_DataLabel|FT_TEXT_SEPARATOR">_Separator</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">LB_TEXT_SEPARATOR</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_TEXT_SEPARATOR">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="valign">center</property>
+ <items>
+ <item id="0" translatable="yes" context="dlg_DataLabel|liststoreSEPARATOR">Space</item>
+ <item id="1" translatable="yes" context="dlg_DataLabel|liststoreSEPARATOR">Comma</item>
+ <item id="2" translatable="yes" context="dlg_DataLabel|liststoreSEPARATOR">Semicolon</item>
+ <item id="3" translatable="yes" context="dlg_DataLabel|liststoreSEPARATOR">New line</item>
+ <item id="4" translatable="yes" context="dlg_DataLabel|liststoreSEPARATOR">Period</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_TEXT_SEPARATOR-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|LB_TEXT_SEPARATOR">Selects the separator between multiple text strings for the same object.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="dlg_DataLabel|label1">Attribute Options</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box_right">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="boxORIENTATION">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkDrawingArea" id="CT_DIAL">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CT_DIAL-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|CT_DIAL">Click in the dial to set the text orientation for the data labels.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="NF_LABEL_DEGREES">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="valign">center</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentDEGREE</property>
+ <property name="wrap">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="NF_LABEL_DEGREES-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|NF_LABEL_DEGREES">Enter the counterclockwise rotation angle for the data labels.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_LABEL_DEGREES">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="dlg_DataLabel|FT_LABEL_DEGREES">_Degrees</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="boxTXT_DIRECTION">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_LABEL_TEXTDIR">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="dlg_DataLabel|FT_LABEL_TEXTDIR">Te_xt direction</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">LB_LABEL_TEXTDIR</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_LABEL_TEXTDIR">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_LABEL_TEXTDIR-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|LB_LABEL_TEXTDIR">Specify the text direction for a paragraph that uses complex text layout (CTL). This feature is only available if complex text layout support is enabled.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="dlg_DataLabel|label2">Rotate Text</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_CUSTOM_LEADER_LINES">
+ <property name="label" translatable="yes" context="dlg_DataLabel|CB_CUSTOM_LEADER_LINES">_Connect displaced data labels to data points</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_CUSTOM_LEADER_LINES-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|CB_CUSTOM_LEADER_LINES">Draws a line connecting the data labels to the data points</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="dlg_DataLabel|label3">Leader Lines</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="dlg_DataLabel-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|dlg_DataLabel">Opens the Data Labels dialog, which enables you to set the data labels.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="dlg_DataLabels-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_DataLabel|extended_tip|dlg_DataLabels">Opens the Data Labels dialog, which enables you to set the data labels.</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="FT_TEXT_SEPARATOR"/>
+ <widget name="FT_LABEL_PLACEMENT"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup2">
+ <widgets>
+ <widget name="LB_TEXT_SEPARATOR"/>
+ <widget name="LB_LABEL_PLACEMENT"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/dlg_InsertDataTable.ui b/chart2/uiconfig/ui/dlg_InsertDataTable.ui
new file mode 100644
index 0000000000..446f7a414e
--- /dev/null
+++ b/chart2/uiconfig/ui/dlg_InsertDataTable.ui
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="InsertDataTableDialog">
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="title" translatable="yes" context="dlg_InsertDataTable|dlg_InsertDataTable">Data Table</property>
+ <property name="modal">True</property>
+ <property name="default-width">0</property>
+ <property name="default-height">0</property>
+ <property name="type-hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can-focus">False</property>
+ <property name="layout-style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="can-default">True</property>
+ <property name="has-default">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="margin-end">6</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="dlg_LegendPosition">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkCheckButton" id="showDataTable">
+ <property name="label" translatable="yes" context="dlg_InsertDataTable|horizontalBorderCB">Show data table</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="horizontalBorderCB">
+ <property name="label" translatable="yes" context="dlg_InsertDataTable|horizontalBorderCB">Show horizontal border</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="verticalBorderCB">
+ <property name="label" translatable="yes" context="dlg_InsertDataTable|verticalBorderCB">Show vertical border</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="outlineCB">
+ <property name="label" translatable="yes" context="dlg_InsertDataTable|outlineCB">Show outline</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="keysCB">
+ <property name="label" translatable="yes" context="dlg_InsertDataTable|keysCB">Show keys</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="dataTablePropertiesLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="dlg_InsertDataTable|dataTablePropertiesLabel">Data Table Properties</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/dlg_InsertErrorBars.ui b/chart2/uiconfig/ui/dlg_InsertErrorBars.ui
new file mode 100644
index 0000000000..ea0719132f
--- /dev/null
+++ b/chart2/uiconfig/ui/dlg_InsertErrorBars.ui
@@ -0,0 +1,695 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentNEG">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentPOS">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkImage" id="imageRANGE_SELECT_NEG">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">chart2/res/selectrange.png</property>
+ </object>
+ <object class="GtkImage" id="imageRANGE_SELECT_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">chart2/res/selectrange.png</property>
+ </object>
+ <object class="GtkDialog" id="dlg_InsertErrorBars">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="dlg_InsertErrorBars|dlg_InsertErrorBars">Legend</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="tp_ErrorBars">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkFrame" id="FL_ERROR">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="RB_NONE">
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|RB_NONE">_None</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="active">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_NONE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|RB_NONE">Does not show any error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_CONST">
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|RB_CONST">_Constant Value</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_NONE</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_CONST-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|RB_CONST">Displays constant values that you specify in the Parameters area.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_PERCENT">
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|RB_PERCENT">_Percentage</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_NONE</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_PERCENT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|RB_PERCENT">Displays a percentage. The display refers to the corresponding data point. Set the percentage in the Parameters area.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="RB_FUNCTION">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_NONE</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_FUNCTION-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|RB_FUNCTION">Select a function to calculate the error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_FUNCTION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <items>
+ <item id="0" translatable="yes" context="dlg_InsertErrorBars|liststoreFUNCTION">Standard Error</item>
+ <item id="1" translatable="yes" context="dlg_InsertErrorBars|liststoreFUNCTION">Standard Deviation</item>
+ <item id="2" translatable="yes" context="dlg_InsertErrorBars|liststoreFUNCTION">Variance</item>
+ <item id="3" translatable="yes" context="dlg_InsertErrorBars|liststoreFUNCTION">Error Margin</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_FUNCTION-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|LB_FUNCTION">Select a function to calculate the error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_RANGE">
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|RB_RANGE">Cell _Range</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_NONE</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_RANGE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|RB_RANGE">Click Cell Range and then specify a cell range from which to take the positive and negative error bar values.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|label1">Error Category</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="RB_BOTH">
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|RB_BOTH">Positive _and Negative</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="active">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_BOTH-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|RB_BOTH">Shows positive and negative error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_POSITIVE">
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|RB_POSITIVE">Pos_itive</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_BOTH</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_POSITIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|RB_POSITIVE">Shows only positive error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_NEGATIVE">
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|RB_NEGATIVE">Ne_gative</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_BOTH</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_NEGATIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|RB_NEGATIVE">Shows only negative error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="FI_BOTH">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="FI_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="FI_NEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|label2">Error Indicator</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="framePARAMETERS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkBox" id="boxPOSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|FT_POSITIVE">P_ositive (+)</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">MF_POSITIVE</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MF_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustmentPOS</property>
+ <property name="digits">2</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MF_POSITIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|MF_POSITIVE">Enter the value to add to the displayed value as the positive error value.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="ED_RANGE_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ED_RANGE_POSITIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|ED_RANGE_POSITIVE">Enter the address range from where to get the positive error values. Use the Shrink button to select the range from a sheet.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="IB_RANGE_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="dlg_InsertErrorBars|IB_RANGE_POSITIVE|tooltip_text">Select data range</property>
+ <property name="image">imageRANGE_SELECT_POSITIVE</property>
+ <property name="always-show-image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="IB_RANGE_POSITIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|IB_RANGE_POSITIVE">Click a button to shrink the dialog, then use the mouse to select the cell range in the spreadsheet. Click the button again to restore the dialog to full size.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="boxNEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_NEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|FT_NEGATIVE">_Negative (-)</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">MF_NEGATIVE</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MF_NEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustmentNEG</property>
+ <property name="digits">2</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MF_NEGATIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|MF_NEGATIVE">Enter the value to subtract from the displayed value as the negative error value.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="ED_RANGE_NEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ED_RANGE_NEGATIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|ED_RANGE_NEGATIVE">Enter the address range from where to get the negative error values. Use the Shrink button to select the range from a sheet.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="IB_RANGE_NEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="dlg_InsertErrorBars|IB_RANGE_NEGATIVE|tooltip_text">Select data range</property>
+ <property name="image">imageRANGE_SELECT_NEG</property>
+ <property name="always-show-image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="IB_RANGE_NEGATIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|IB_RANGE_NEGATIVE">Click a button to shrink the dialog, then use the mouse to select the cell range in the spreadsheet. Click the button again to restore the dialog to full size.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_SYN_POS_NEG">
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|CB_SYN_POS_NEG">Same value for both</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_SYN_POS_NEG-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="dlg_InsertErrorBars|extended_tip|CB_SYN_POS_NEG">Enable to use the positive error values also as negative error values. You can only change the value of the "Positive (+)" box. That value gets copied to the "Negative (-)" box automatically.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|label3">Parameters</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="STR_DATA_SELECT_RANGE_FOR_POSITIVE_ERRORBARS">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|STR_DATA_SELECT_RANGE_FOR_POSITIVE_ERRORBARS">Select Range for Positive Error Bars</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="STR_DATA_SELECT_RANGE_FOR_NEGATIVE_ERRORBARS">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|STR_DATA_SELECT_RANGE_FOR_NEGATIVE_ERRORBARS">Select Range for Negative Error Bars</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="STR_CONTROLTEXT_ERROR_BARS_FROM_DATA">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dlg_InsertErrorBars|STR_CONTROLTEXT_ERROR_BARS_FROM_DATA">From Data Table</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="FT_POSITIVE"/>
+ <widget name="FT_NEGATIVE"/>
+ <widget name="FT_NEGATIVE"/>
+ <widget name="FT_POSITIVE"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/dlg_InsertLegend.ui b/chart2/uiconfig/ui/dlg_InsertLegend.ui
new file mode 100644
index 0000000000..978a938c34
--- /dev/null
+++ b/chart2/uiconfig/ui/dlg_InsertLegend.ui
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="dlg_InsertLegend">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="dlg_InsertLegend|dlg_InsertLegend">Legend</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="margin-end">6</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="dlg_LegendPosition">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="framePOSITION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="show">
+ <property name="label" translatable="yes" context="dlg_InsertLegend|show">_Display legend</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="left">
+ <property name="label" translatable="yes" context="dlg_InsertLegend|left">_Left</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="right">
+ <property name="label" translatable="yes" context="dlg_InsertLegend|right">_Right</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">left</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="top">
+ <property name="label" translatable="yes" context="dlg_InsertLegend|top">_Top</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">left</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="bottom">
+ <property name="label" translatable="yes" context="dlg_InsertLegend|bottom">_Bottom</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">left</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="TXT_POSITION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="dlg_InsertLegend|TXT_POSITION">Position</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/imagefragment.ui b/chart2/uiconfig/ui/imagefragment.ui
new file mode 100644
index 0000000000..ab83099fdc
--- /dev/null
+++ b/chart2/uiconfig/ui/imagefragment.ui
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="container">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/insertaxisdlg.ui b/chart2/uiconfig/ui/insertaxisdlg.ui
new file mode 100644
index 0000000000..2853bc594e
--- /dev/null
+++ b/chart2/uiconfig/ui/insertaxisdlg.ui
@@ -0,0 +1,294 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="InsertAxisDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="insertaxisdlg|InsertAxisDialog">Axes</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox3">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area3">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="margin-end">6</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="spacing">12</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="primaryX">
+ <property name="label" translatable="yes" context="insertaxisdlg|primaryX">_X axis</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryX-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertaxisdlg|extended_tip|primaryX">Displays the X axis as a line with subdivisions.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="primaryY">
+ <property name="label" translatable="yes" context="insertaxisdlg|primaryY">_Y axis</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryY-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertaxisdlg|extended_tip|primaryY">Displays the Y axis as a line with subdivisions.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="primaryZ">
+ <property name="label" translatable="yes" context="insertaxisdlg|primaryZ">_Z axis</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryZ-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertaxisdlg|extended_tip|primaryZ">Displays the Z axis as a line with subdivisions.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="insertaxisdlg|label1">Axes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="secondaryX">
+ <property name="label" translatable="yes" context="insertaxisdlg|secondaryX">X _axis</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="secondaryX-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertaxisdlg|extended_tip|secondaryX">Displays a secondary X axis in the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="secondaryY">
+ <property name="label" translatable="yes" context="insertaxisdlg|secondaryY">Y ax_is</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="secondaryY-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertaxisdlg|extended_tip|secondaryY">The major axis and the secondary axis can have different scaling. For example, you can scale one axis to 2 in. and the other to 1.5 in. </property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="secondaryZ">
+ <property name="label" translatable="yes" context="insertaxisdlg|secondaryZ">Z axi_s</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="insertaxisdlg|label2">Secondary Axes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="InsertAxisDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertaxisdlg|extended_tip|InsertAxisDialog">Specifies the axes to be displayed in the chart.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/insertgriddlg.ui b/chart2/uiconfig/ui/insertgriddlg.ui
new file mode 100644
index 0000000000..ed959b2952
--- /dev/null
+++ b/chart2/uiconfig/ui/insertgriddlg.ui
@@ -0,0 +1,299 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="InsertGridDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="insertgriddlg|InsertGridDialog">Grids</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="margin-end">6</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="spacing">12</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="primaryX">
+ <property name="label" translatable="yes" context="insertgriddlg|primaryX">_X axis</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryX-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertgriddlg|extended_tip|primaryX">Adds gridlines to the X axis of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="primaryY">
+ <property name="label" translatable="yes" context="insertgriddlg|primaryY">_Y axis</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryY-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertgriddlg|extended_tip|primaryY">Adds gridlines to the Y axis of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="primaryZ">
+ <property name="label" translatable="yes" context="insertgriddlg|primaryZ">_Z axis</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryZ-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertgriddlg|extended_tip|primaryZ">Adds gridlines to the Z axis of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="insertgriddlg|label1">Major Grids</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="secondaryX">
+ <property name="label" translatable="yes" context="insertgriddlg|secondaryX">X _axis</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="secondaryX-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertgriddlg|extended_tip|secondaryX">Adds gridlines that subdivide the X axis into smaller sections.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="secondaryY">
+ <property name="label" translatable="yes" context="insertgriddlg|secondaryY">Y ax_is</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="secondaryY-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertgriddlg|extended_tip|secondaryY">Adds gridlines that subdivide the Y axis into smaller sections.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="secondaryZ">
+ <property name="label" translatable="yes" context="insertgriddlg|secondaryZ">Z axi_s</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="secondaryZ-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertgriddlg|extended_tip|secondaryZ">Adds gridlines that subdivide the Z axis into smaller sections.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="insertgriddlg|label2">Minor Grids</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="InsertGridDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="insertgriddlg|extended_tip|InsertGridDialog">You can divide the axes into sections by assigning gridlines to them. This allows you to get a better overview of the chart, especially if you are working with large charts.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/inserttitledlg.ui b/chart2/uiconfig/ui/inserttitledlg.ui
new file mode 100644
index 0000000000..1d6664fa09
--- /dev/null
+++ b/chart2/uiconfig/ui/inserttitledlg.ui
@@ -0,0 +1,410 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="InsertTitleDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="inserttitledlg|InsertTitleDialog">Titles</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="labelMainTitle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="inserttitledlg|labelMainTitle">_Title</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">maintitle</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelSubTitle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="inserttitledlg|labelSubTitle">_Subtitle</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">subtitle</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="maintitle">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="maintitle-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="inserttitledlg|extended_tip|maintitle">Enter the desired title for the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="subtitle">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="subtitle-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="inserttitledlg|extended_tip|subtitle">Enter the desired subtitle for the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frameAxes">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="labelPrimaryXaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="inserttitledlg|labelPrimaryXaxis">_X axis</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">primaryXaxis</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelPrimaryYaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="inserttitledlg|labelPrimaryYaxis">_Y axis</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">primaryYaxis</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelPrimaryZaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="inserttitledlg|labelPrimaryZaxis">_Z axis</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">primaryZaxis</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="primaryXaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryXaxis-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="inserttitledlg|extended_tip|primaryXaxis">Enter the desired title for the X axis of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="primaryYaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryYaxis-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="inserttitledlg|extended_tip|primaryYaxis">Enter the desired title for the Y axis of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="primaryZaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryZaxis-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="inserttitledlg|extended_tip|primaryZaxis">Enter the desired title for the Z axis of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="Axe">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="inserttitledlg|Axe">Axes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frameSecondaryAxes">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="labelSecondaryXAxis">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="inserttitledlg|labelSecondaryXAxis">X _axis</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">secondaryXaxis</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelSecondaryYAxis">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="inserttitledlg|labelSecondaryYAxis">Y ax_is</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">secondaryYaxis</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="secondaryXaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="secondaryXaxis-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="inserttitledlg|extended_tip|secondaryXaxis">Enter the desired secondary title for the X axis of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="secondaryYaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="secondaryYaxis-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="inserttitledlg|extended_tip|secondaryYaxis">Enter the desired secondary title for the Y axis of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="inserttitledlg|label2">Secondary Axes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="InsertTitleDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="inserttitledlg|extended_tip|InsertTitleDialog">Opens a dialog to enter or modify the titles in a chart.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/paradialog.ui b/chart2/uiconfig/ui/paradialog.ui
new file mode 100644
index 0000000000..18ceaf4ff3
--- /dev/null
+++ b/chart2/uiconfig/ui/paradialog.ui
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="ParagraphDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="paradialog|ParagraphDialog">Paragraph</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes" context="stock">_Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="labelTP_PARA_STD">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="paradialog|labelTP_PARA_STD">Indents &amp; Spacing</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="labelTP_PARA_ALIGN">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="paradialog|labelTP_PARA_ALIGN">Alignment</property>
+ <property name="xalign">0.5</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="labelTP_PARA_ASIAN">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="paradialog|labelTP_PARA_ASIAN">Asian Typography</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="labelTP_TABULATOR">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="paradialog|labelTP_TABULATOR">Tabs</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="101">reset</action-widget>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/sidebaraxis.ui b/chart2/uiconfig/ui/sidebaraxis.ui
new file mode 100644
index 0000000000..873d6565ce
--- /dev/null
+++ b/chart2/uiconfig/ui/sidebaraxis.ui
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentSpinDegrees">
+ <property name="upper">359</property>
+ <property name="step-increment">5</property>
+ </object>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="ChartAxisPanel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <!-- n-columns=2 n-rows=4 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="row-spacing">3</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_show_label">
+ <property name="label" translatable="yes" context="sidebaraxis|checkbutton_show_label">Show labels</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_reverse">
+ <property name="label" translatable="yes" context="sidebaraxis|checkbutton_reverse">Reverse direction</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="sidebaraxis|label1">_Label position:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">comboboxtext_label_position</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="comboboxtext_label_position">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item translatable="yes" context="sidebaraxis|comboboxtext_label_position">Near Axis</item>
+ <item translatable="yes" context="sidebaraxis|comboboxtext_label_position">Near Axis (other side)</item>
+ <item translatable="yes" context="sidebaraxis|comboboxtext_label_position">Outside start</item>
+ <item translatable="yes" context="sidebaraxis|comboboxtext_label_position">Outside end</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes" context="sidebaraxis|label2">_Text orientation:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">spinbutton1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton1">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentSpinDegrees</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="label_props">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/sidebarelements.ui b/chart2/uiconfig/ui/sidebarelements.ui
new file mode 100644
index 0000000000..f67c3b3990
--- /dev/null
+++ b/chart2/uiconfig/ui/sidebarelements.ui
@@ -0,0 +1,469 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="ChartElementsPanel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <!-- n-columns=2 n-rows=16 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="row-spacing">3</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="l">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">3</property>
+ <property name="label" translatable="yes" context="sidebarelements|l">Titles</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_title">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_title">Title</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <accessibility>
+ <relation type="label-for" target="edit_title"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="edit_title">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="checkbutton_title"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_subtitle">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_subtitle">Subtitle</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <accessibility>
+ <relation type="label-for" target="edit_subtitle"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="edit_subtitle">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="checkbutton_subtitle"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_legen">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">3</property>
+ <property name="label" translatable="yes" context="sidebarelements|label_legen">Legend</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_legend">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_legend">Show legend</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="tooltip-text" translatable="yes" context="sidebarelements|checkbutton_legend|tooltip_text">Show Legend</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="comboboxtext_legend">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item translatable="yes" context="sidebarelements|comboboxtext_legend">Right</item>
+ <item translatable="yes" context="sidebarelements|comboboxtext_legend">Top</item>
+ <item translatable="yes" context="sidebarelements|comboboxtext_legend">Bottom</item>
+ <item translatable="yes" context="sidebarelements|comboboxtext_legend">Left</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_no_overlay">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_no_overlay">Show the legend without overlapping the chart</property>
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_axes">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">3</property>
+ <property name="label" translatable="yes" context="sidebarelements|label_axes">Axes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">6</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_x_axis">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_x_axis">X axis</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_y_axis">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_y_axis">Y axis</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_z_axis">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_z_axis">Z axis</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_2nd_x_axis">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_2nd_x_axis">2nd X axis</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_2nd_y_axis">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_2nd_y_axis">2nd Y axis</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_x_axis_title">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_x_axis_title">X axis title</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_y_axis_title">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_y_axis_title">Y axis title</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_z_axis_title">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_z_axis_title">Z axis title</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_2nd_x_axis_title">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_2nd_x_axis_title">2nd X axis title</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_2nd_y_axis_title">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_2nd_y_axis_title">2nd Y axis title</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_gri">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">3</property>
+ <property name="label" translatable="yes" context="sidebarelements|label_gri">Gridlines</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">12</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_gridline_horizontal_major">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_gridline_horizontal_major">Horizontal major</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">13</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_gridline_vertical_major">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_gridline_vertical_major">Vertical major</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">14</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_gridline_horizontal_minor">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_gridline_horizontal_minor">Horizontal minor</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">13</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_gridline_vertical_minor">
+ <property name="label" translatable="yes" context="sidebarelements|checkbutton_gridline_vertical_minor">Vertical minor</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">14</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box_legend">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkLabel" id="text_title">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="sidebarelements|text_title">Title</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="text_subtitle">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="sidebarelements|text_subtitle">Subtitle</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="placement_label">
+ <property name="can-focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin-start">4</property>
+ <property name="label" translatable="yes" context="sidebarelements|placement_label">_Placement:</property>
+ <property name="use-underline">True</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">15</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/sidebarerrorbar.ui b/chart2/uiconfig/ui/sidebarerrorbar.ui
new file mode 100644
index 0000000000..32c3ef130a
--- /dev/null
+++ b/chart2/uiconfig/ui/sidebarerrorbar.ui
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentNEG">
+ <property name="upper">100</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentPOS">
+ <property name="upper">100</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">chart2/res/errorup_30.png</property>
+ </object>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">chart2/res/errorbothverti_30.png</property>
+ </object>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">chart2/res/errordown_30.png</property>
+ </object>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="ChartErrorBarPanel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <!-- n-columns=2 n-rows=4 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="row-spacing">3</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="sidebarerrorbar|label2">Category:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">comboboxtext_type</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="comboboxtext_type">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item translatable="yes" context="sidebarerrorbar|comboboxtext_type">Constant</item>
+ <item translatable="yes" context="sidebarerrorbar|comboboxtext_type">Percentage</item>
+ <item translatable="yes" context="sidebarerrorbar|comboboxtext_type">Cell Range or Data Table</item>
+ <item translatable="yes" context="sidebarerrorbar|comboboxtext_type">Standard deviation</item>
+ <item translatable="yes" context="sidebarerrorbar|comboboxtext_type">Standard error</item>
+ <item translatable="yes" context="sidebarerrorbar|comboboxtext_type">Variance</item>
+ <item translatable="yes" context="sidebarerrorbar|comboboxtext_type">Error margin</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="sidebarerrorbar|label3">Positive (+):</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="sidebarerrorbar|label4">Negative (-):</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton_pos">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="text" translatable="yes" context="sidebarerrorbar|spinbutton_pos">0.00</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentPOS</property>
+ <property name="digits">2</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinbutton_neg">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="text" translatable="yes" context="sidebarerrorbar|spinbutton_neg">0.00</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentNEG</property>
+ <property name="digits">2</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="radiobutton_positive_negative">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="tooltip-text" translatable="yes" context="sidebarerrorbar|radiobutton_positive_negative|tooltip_text">Positive and Negative</property>
+ <property name="image">image2</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="radiobutton_positive">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="tooltip-text" translatable="yes" context="sidebarerrorbar|radiobutton_positive|tooltip_text">Positive</property>
+ <property name="image">image1</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">radiobutton_positive_negative</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="radiobutton_negative">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="tooltip-text" translatable="yes" context="sidebarerrorbar|radiobutton_negative|tooltip_text">Negative</property>
+ <property name="image">image3</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">radiobutton_positive_negative</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="sidebarerrorbar|label5">Indicator</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/sidebarseries.ui b/chart2/uiconfig/ui/sidebarseries.ui
new file mode 100644
index 0000000000..7996f5c2e3
--- /dev/null
+++ b/chart2/uiconfig/ui/sidebarseries.ui
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="ChartSeriesPanel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <!-- n-columns=2 n-rows=10 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border-width">5</property>
+ <property name="row-spacing">3</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label_series_name">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">3</property>
+ <property name="label" translatable="no">Label</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_label">
+ <property name="label" translatable="yes" context="sidebarseries|checkbutton_label">Show data labels</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="comboboxtext_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item translatable="yes" context="sidebarseries|comboboxtext_label">Above</item>
+ <item translatable="yes" context="sidebarseries|comboboxtext_label">Below</item>
+ <item translatable="yes" context="sidebarseries|comboboxtext_label">Center</item>
+ <item translatable="yes" context="sidebarseries|comboboxtext_label">Outside</item>
+ <item translatable="yes" context="sidebarseries|comboboxtext_label">Inside</item>
+ <item translatable="yes" context="sidebarseries|comboboxtext_label">Near origin</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_trendline">
+ <property name="label" translatable="yes" context="sidebarseries|checkbutton_trendline">Show trendline</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">3</property>
+ <property name="label" translatable="yes" context="sidebarseries|label1">Error Bars</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_y_error">
+ <property name="label" translatable="yes" context="sidebarseries|checkbutton_y_error">Y error bars</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton_x_error">
+ <property name="label" translatable="yes" context="sidebarseries|checkbutton_x_error">X error bars</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="axis_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin-top">12</property>
+ <property name="margin-bottom">3</property>
+ <property name="label" translatable="yes" context="sidebarseries|axis_label">Align Series to Axis</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">6</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_series_tmpl">
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="sidebarseries|label_series_tmpl">Data series '%1'</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">8</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="radiobutton_primary_axis">
+ <property name="label" translatable="yes" context="sidebarseries|radiobutton_primary_axis">Primary Y axis</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="radiobutton_secondary_axis">
+ <property name="label" translatable="yes" context="sidebarseries|radiobutton_secondary_axis">Secondary Y axis</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">radiobutton_primary_axis</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">7</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="datalabel_box">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <child>
+ <object class="GtkLabel" id="label_box">
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="sidebarseries|label_box">P_lacement:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic_widget">comboboxtext_label</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">9</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/sidebartype.ui b/chart2/uiconfig/ui/sidebartype.ui
new file mode 100644
index 0000000000..131a1c5eea
--- /dev/null
+++ b/chart2/uiconfig/ui/sidebartype.ui
@@ -0,0 +1,347 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="lower">1</property>
+ <property name="upper">100</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkListStore" id="liststore2">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ <!-- column-name image -->
+ <column type="GdkPixbuf"/>
+ </columns>
+ </object>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="ChartTypePanel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <!-- n-columns=2 n-rows=9 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="row-spacing">3</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="subtypewin">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="margin-bottom">6</property>
+ <property name="hexpand">True</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">never</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkDrawingArea" id="subtype">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="3dlook">
+ <property name="label" translatable="yes" context="sidebartype|3dlook">_3D Look</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="3dscheme">
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item translatable="yes" context="sidebartype|3dscheme">Simple</item>
+ <item translatable="yes" context="sidebartype|3dscheme">Realistic</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="shapeft">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="label" translatable="yes" context="sidebartype|shapeft">Sh_ape</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">shape</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkTreeView" id="shape">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers-visible">False</property>
+ <property name="headers-clickable">False</property>
+ <property name="search-column">0</property>
+ <property name="show-expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="stack">
+ <property name="label" translatable="yes" context="sidebartype|stack">_Stack series</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="valign">start</property>
+ <property name="vexpand">True</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="linetypeft">
+ <property name="can-focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes" context="sidebartype|linetypeft">_Line type</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">linetype</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="linetype">
+ <property name="can-focus">False</property>
+ <items>
+ <item translatable="yes" context="sidebartype|linetype">Straight</item>
+ <item translatable="yes" context="sidebartype|linetype">Smooth</item>
+ <item translatable="yes" context="sidebartype|linetype">Stepped</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="properties">
+ <property name="label" translatable="yes" context="sidebartype|properties">Properties...</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="sort">
+ <property name="label" translatable="yes" context="sidebartype|sort">_Sort by X values</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="nolinesft">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="sidebartype|nolinesft">_Number of lines</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">nolines</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="nolines">
+ <property name="can-focus">True</property>
+ <property name="no-show-all">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="cmb_chartType">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="valign">center</property>
+ <property name="hexpand">True</property>
+ <property name="model">liststore2</property>
+ <property name="entry-text-column">0</property>
+ <property name="id-column">1</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext9"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext6"/>
+ <attributes>
+ <attribute name="pixbuf">2</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="grid6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkRadioButton" id="ontop">
+ <property name="label" translatable="yes" context="sidebartype|ontop">On top</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="percent">
+ <property name="label" translatable="yes" context="sidebartype|percent">Percent</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">ontop</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="deep">
+ <property name="label" translatable="yes" context="sidebartype|deep">Deep</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">ontop</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/smoothlinesdlg.ui b/chart2/uiconfig/ui/smoothlinesdlg.ui
new file mode 100644
index 0000000000..f68851932f
--- /dev/null
+++ b/chart2/uiconfig/ui/smoothlinesdlg.ui
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="PolynomialsAdjustment">
+ <property name="lower">1</property>
+ <property name="upper">15</property>
+ <property name="value">3</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="ResolutionAdjustment">
+ <property name="lower">1</property>
+ <property name="upper">100</property>
+ <property name="value">20</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkDialog" id="SmoothLinesDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="smoothlinesdlg|SmoothLinesDialog">Smooth Lines</property>
+ <property name="modal">True</property>
+ <property name="default_width">-1</property>
+ <property name="default_height">-1</property>
+ <property name="type_hint">dialog</property>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="homogeneous">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="margin-end">6</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="TypeLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="smoothlinesdlg|TypeLabel">Line _Type:</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="SplineTypeComboBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="active">0</property>
+ <items>
+ <item translatable="yes" context="smoothlinesdlg|SplineTypeComboBox">Cubic spline</item>
+ <item translatable="yes" context="smoothlinesdlg|SplineTypeComboBox">B-spline</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="SplineTypeComboBox-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="smoothlinesdlg|extended_tip|SplineTypeComboBox">Apply a line curve model.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">3</property>
+ <property name="column_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="ResolutionLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="smoothlinesdlg|ResolutionLabel">_Resolution:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ResolutionSpinbutton</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="PolynomialsLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="smoothlinesdlg|PolynomialsLabel">_Degree of polynomials:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">PolynomialsSpinButton</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="ResolutionSpinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">ResolutionAdjustment</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ResolutionSpinbutton-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="smoothlinesdlg|extended_tip|ResolutionSpinbutton">Set the resolution.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="PolynomialsSpinButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">PolynomialsAdjustment</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="PolynomialsSpinButton-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="smoothlinesdlg|extended_tip|PolynomialsSpinButton">Set the degree of the polynomials.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="SmoothLinesDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="smoothlinesdlg|extended_tip|SmoothLinesDialog">Apply a line curve model.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/steppedlinesdlg.ui b/chart2/uiconfig/ui/steppedlinesdlg.ui
new file mode 100644
index 0000000000..f54f3c51cf
--- /dev/null
+++ b/chart2/uiconfig/ui/steppedlinesdlg.ui
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <!-- interface-local-resource-path /home/eric/Documents/computers/libreoffice/core/icon-themes/galaxy/chart2 -->
+ <object class="GtkDialog" id="SteppedLinesDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">3</property>
+ <property name="column_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkImage" id="step_center_x_img">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">chart2/res/step_center_x_30.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="step_end_img">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">chart2/res/step_end_30.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="step_center_y_img">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">chart2/res/step_center_y_30.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="step_start_rb">
+ <property name="label" translatable="yes" context="steppedlinesdlg|step_start_rb">_Start with horizontal line</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="step_start_rb-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="steppedlinesdlg|extended_tip|step_start_rb">Start with horizontal line and step up vertically at the end.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="step_center_x_rb">
+ <property name="label" translatable="yes" context="steppedlinesdlg|step_center_x_rb">Step at the _horizontal mean</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">step_start_rb</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="step_center_x_rb-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="steppedlinesdlg|extended_tip|step_center_x_rb">Start to step up vertically and end with horizontal line.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="step_end_rb">
+ <property name="label" translatable="yes" context="steppedlinesdlg|step_end_rb">_End with horizontal line</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">step_start_rb</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="step_end_rb-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="steppedlinesdlg|extended_tip|step_end_rb">Start with horizontal line, step up vertically in the middle of the X values and end with horizontal line.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="step_center_y_rb">
+ <property name="label" translatable="yes" context="steppedlinesdlg|step_center_y_rb">Step to the _vertical mean</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">step_start_rb</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="step_center_y_rb-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="steppedlinesdlg|extended_tip|step_center_y_rb">Start to step up vertically to the middle of the Y values, draw a horizontal line and finish by stepping vertically to the end.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="step_start_img">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">chart2/res/step_start_30.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="steppedlinesdlg|label2">Type of Stepping</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/titlerotationtabpage.ui b/chart2/uiconfig/ui/titlerotationtabpage.ui
new file mode 100644
index 0000000000..5666ca9c0f
--- /dev/null
+++ b/chart2/uiconfig/ui/titlerotationtabpage.ui
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentSpinDegrees">
+ <property name="upper">359</property>
+ <property name="step_increment">5</property>
+ </object>
+ <object class="GtkFrame" id="TitleRotationTabPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid10">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkSpinButton" id="OrientDegree">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="margin_top">40</property>
+ <property name="adjustment">adjustmentSpinDegrees</property>
+ <property name="wrap">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="OrientDegree-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="titlerotationtabpage|extended_tip|OrientDegree">Allows you to manually enter the orientation angle.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="degreeL">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">40</property>
+ <property name="label" translatable="yes" context="titlerotationtabpage|degreeL">_Degrees</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkCheckButton" id="stackedCB">
+ <property name="label" translatable="yes" context="titlerotationtabpage|stackedCB">Ve_rtically stacked</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="inconsistent">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="stackedCB-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="titlerotationtabpage|extended_tip|stackedCB">Assigns vertical text orientation for cell contents.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelABCD">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="titlerotationtabpage|labelABCD">ABCD</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="textdirL">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="titlerotationtabpage|textdirL">Te_xt direction:</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="textdirLB">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="textdirLB-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="titlerotationtabpage|extended_tip|textdirLB">Specify the text direction for a paragraph that uses complex text layout (CTL). This feature is only available if complex text layout support is enabled.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="dialCtrl">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="dialCtrl-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="titlerotationtabpage|extended_tip|dialCtrl">Clicking anywhere on the wheel defines the variable text orientation.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="labelTextOrient">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="titlerotationtabpage|labelTextOrient">Text Orientation</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_3D_SceneAppearance.ui b/chart2/uiconfig/ui/tp_3D_SceneAppearance.ui
new file mode 100644
index 0000000000..eeced98372
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_3D_SceneAppearance.ui
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="tp_3D_SceneAppearance">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_SCHEME">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_3D_SceneAppearance|FT_SCHEME">Sche_me</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">LB_SCHEME</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_SCHEME">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <items>
+ <item id="0" translatable="yes" context="tp_3D_SceneAppearance|liststoreSCHEME">Simple</item>
+ <item id="1" translatable="yes" context="tp_3D_SceneAppearance|liststoreSCHEME">Realistic</item>
+ <item id="2" translatable="yes" context="tp_3D_SceneAppearance|liststoreSCHEME">Custom</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_SCHEME-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneAppearance|extended_tip|LB_SCHEME">Select a scheme from the list box, or click any of the check boxes below.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkSeparator" id="separator1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_SHADING">
+ <property name="label" translatable="yes" context="tp_3D_SceneAppearance|CB_SHADING">_Shading</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_SHADING-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneAppearance|extended_tip|CB_SHADING">Applies Gouraud shading if marked, or flat shading if unmarked.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_OBJECTLINES">
+ <property name="label" translatable="yes" context="tp_3D_SceneAppearance|CB_OBJECTLINES">_Object borders</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_OBJECTLINES-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneAppearance|extended_tip|CB_OBJECTLINES">Shows borders around the areas by setting the line style to Solid.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_ROUNDEDEDGE">
+ <property name="label" translatable="yes" context="tp_3D_SceneAppearance|CB_ROUNDEDEDGE">_Rounded edges</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_ROUNDEDEDGE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneAppearance|extended_tip|CB_ROUNDEDEDGE">Edges are rounded by 5%.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_3D_SceneGeometry.ui b/chart2/uiconfig/ui/tp_3D_SceneGeometry.ui
new file mode 100644
index 0000000000..ef8e6e0ec0
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_3D_SceneGeometry.ui
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentPERSPECTIVE">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentROTATION1">
+ <property name="lower">-180</property>
+ <property name="upper">180</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentROTATION2">
+ <property name="lower">-180</property>
+ <property name="upper">180</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentROTATION3">
+ <property name="lower">-180</property>
+ <property name="upper">180</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="tp_3DSceneGeometry">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkCheckButton" id="CBX_RIGHT_ANGLED_AXES">
+ <property name="label" translatable="yes" context="tp_3D_SceneGeometry|CBX_RIGHT_ANGLED_AXES">_Right-angled axes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CBX_RIGHT_ANGLED_AXES-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneGeometry|extended_tip|CBX_RIGHT_ANGLED_AXES">If Right-angled axes is enabled, you can rotate the chart contents only in X and Y direction, that is, parallel to the chart borders. Right-angled axes is enabled by default for newly created 3D charts. Pie and Donut charts do not support right-angled axes.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_X_ROTATION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_3D_SceneGeometry|FT_X_ROTATION">_X rotation</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">MTR_FLD_X_ROTATION</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_Y_ROTATION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_3D_SceneGeometry|FT_Y_ROTATION">_Y rotation</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">MTR_FLD_Y_ROTATION</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_Z_ROTATION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_3D_SceneGeometry|FT_Z_ROTATION">_Z rotation</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">MTR_FLD_Z_ROTATION</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CBX_PERSPECTIVE">
+ <property name="label" translatable="yes" context="tp_3D_SceneGeometry|CBX_PERSPECTIVE">_Perspective</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <accessibility>
+ <relation type="label-for" target="MTR_FLD_PERSPECTIVE"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CBX_PERSPECTIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneGeometry|extended_tip|CBX_PERSPECTIVE">Mark the Perspective box to view the chart as through a camera lens. Use the spin button to set the percentage. With a high percentage nearer objects look bigger than more distant objects.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MTR_FLD_PERSPECTIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustmentPERSPECTIVE</property>
+ <accessibility>
+ <relation type="labelled-by" target="CBX_PERSPECTIVE"/>
+ </accessibility>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MTR_FLD_PERSPECTIVE-atkobject">
+ <property name="AtkObject::accessible-name" translatable="yes" context="tp_3D_SceneGeometry|MTR_FLD_PERSPECTIVE-atkobject">Perspective</property>
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneGeometry|extended_tip|MTR_FLD_PERSPECTIVE">Mark the Perspective box to view the chart as through a camera lens. Use the spin button to set the percentage. With a high percentage nearer objects look bigger than more distant objects.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MTR_FLD_Z_ROTATION">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustmentROTATION3</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MTR_FLD_Z_ROTATION-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneGeometry|extended_tip|MTR_FLD_Z_ROTATION">Sets the rotation of the chart on the z axis. The preview responds to the new settings.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MTR_FLD_Y_ROTATION">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustmentROTATION2</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MTR_FLD_Y_ROTATION-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneGeometry|extended_tip|MTR_FLD_Y_ROTATION">Sets the rotation of the chart on the y axis. The preview responds to the new settings.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MTR_FLD_X_ROTATION">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustmentROTATION1</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MTR_FLD_X_ROTATION-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneGeometry|extended_tip|MTR_FLD_X_ROTATION">Sets the rotation of the chart on the x axis. The preview responds to the new settings.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_3D_SceneIllumination.ui b/chart2/uiconfig/ui/tp_3D_SceneIllumination.ui
new file mode 100644
index 0000000000..2187db5ab0
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_3D_SceneIllumination.ui
@@ -0,0 +1,489 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkImage" id="IMG_AMBIENT_COLOR">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">svx/res/colordlg.png</property>
+ </object>
+ <object class="GtkImage" id="IMG_LIGHTSOURCE_COLOR">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">svx/res/colordlg.png</property>
+ </object>
+ <object class="GtkImage" id="IMG_LIGHT_1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">svx/res/lighton.png</property>
+ </object>
+ <object class="GtkImage" id="IMG_LIGHT_2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">svx/res/lighton.png</property>
+ </object>
+ <object class="GtkImage" id="IMG_LIGHT_3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">svx/res/lighton.png</property>
+ </object>
+ <object class="GtkImage" id="IMG_LIGHT_4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">svx/res/lighton.png</property>
+ </object>
+ <object class="GtkImage" id="IMG_LIGHT_5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">svx/res/lighton.png</property>
+ </object>
+ <object class="GtkImage" id="IMG_LIGHT_6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">svx/res/lighton.png</property>
+ </object>
+ <object class="GtkImage" id="IMG_LIGHT_7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">svx/res/lighton.png</property>
+ </object>
+ <object class="GtkImage" id="IMG_LIGHT_8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">svx/res/lighton.png</property>
+ </object>
+ <object class="GtkBox" id="tp_3D_SceneIllumination">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkToggleButton" id="BTN_LIGHT_1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|BTN_LIGHT_1|tooltip_text">Light source 1</property>
+ <property name="image">IMG_LIGHT_1</property>
+ <property name="always_show_image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_LIGHT_1-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|BTN_LIGHT_1">Click to enable or disable the specular light source with highlights.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="BTN_LIGHT_2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|BTN_LIGHT_2|tooltip_text">Light source 2</property>
+ <property name="image">IMG_LIGHT_2</property>
+ <property name="always_show_image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_LIGHT_2-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|BTN_LIGHT_2">Click to enable or disable the uniform light source.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="BTN_LIGHT_3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|BTN_LIGHT_3|tooltip_text">Light source 3</property>
+ <property name="image">IMG_LIGHT_3</property>
+ <property name="always_show_image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_LIGHT_3-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|BTN_LIGHT_3">Click to enable or disable the uniform light source.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="BTN_LIGHT_4">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|BTN_LIGHT_4|tooltip_text">Light source 4</property>
+ <property name="image">IMG_LIGHT_4</property>
+ <property name="always_show_image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_LIGHT_4-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|BTN_LIGHT_4">Click to enable or disable the uniform light source.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="BTN_LIGHT_5">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|BTN_LIGHT_5|tooltip_text">Light source 5</property>
+ <property name="image">IMG_LIGHT_5</property>
+ <property name="always_show_image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_LIGHT_5-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|BTN_LIGHT_5">Click to enable or disable the uniform light source.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="BTN_LIGHT_6">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|BTN_LIGHT_6|tooltip_text">Light source 6</property>
+ <property name="image">IMG_LIGHT_6</property>
+ <property name="always_show_image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_LIGHT_6-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|BTN_LIGHT_6">Click to enable or disable the uniform light source.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="BTN_LIGHT_7">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|BTN_LIGHT_7|tooltip_text">Light source 7</property>
+ <property name="image">IMG_LIGHT_7</property>
+ <property name="always_show_image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_LIGHT_7-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|BTN_LIGHT_7">Click to enable or disable the uniform light source.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="BTN_LIGHT_8">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|BTN_LIGHT_8|tooltip_text">Light source 8</property>
+ <property name="image">IMG_LIGHT_8</property>
+ <property name="always_show_image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_LIGHT_8-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|BTN_LIGHT_8">Click to enable or disable the uniform light source.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkMenuButton" id="LB_LIGHTSOURCE">
+ <property name="label" translatable="no"></property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_LIGHTSOURCE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|LB_LIGHTSOURCE">Select a color for the selected light source.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="BTN_LIGHTSOURCE_COLOR">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|BTN_LIGHTSOURCE_COLOR|tooltip_text">Select a color using the color dialog</property>
+ <property name="image">IMG_LIGHTSOURCE_COLOR</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_LIGHTSOURCE_COLOR-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|BTN_LIGHTSOURCE_COLOR">Select a color using the color dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="FT_LIGHTSOURCE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_3D_SceneIllumination|FT_LIGHTSOURCE">_Light Source</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">BTN_LIGHT_1</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkMenuButton" id="LB_AMBIENTLIGHT">
+ <property name="label" translatable="no"></property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_AMBIENTLIGHT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|LB_AMBIENTLIGHT">Select a color for the ambient light.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="BTN_AMBIENT_COLOR">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|BTN_AMBIENT_COLOR|tooltip_text">Select a color using the color dialog</property>
+ <property name="image">IMG_AMBIENT_COLOR</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_AMBIENT_COLOR-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|BTN_AMBIENT_COLOR">Select a color using the color dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="FT_AMBIENTLIGHT">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_3D_SceneIllumination|FT_AMBIENTLIGHT">_Ambient Light</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">LB_AMBIENTLIGHT</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkDrawingArea" id="CTL_LIGHT_PREVIEW">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <property name="tooltip_text" translatable="yes" context="tp_3D_SceneIllumination|CTL_LIGHT_PREVIEW|tooltip_text">Light Preview</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="corner">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScale" id="hori">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="round_digits">1</property>
+ <property name="draw_value">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScale" id="vert">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="orientation">vertical</property>
+ <property name="round_digits">1</property>
+ <property name="draw_value">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="tp_3D_SceneIllumination-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_3D_SceneIllumination|extended_tip|tp_3D_SceneIllumination">Set the light sources for the 3D view.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_AxisPositions.ui b/chart2/uiconfig/ui/tp_AxisPositions.ui
new file mode 100644
index 0000000000..7cff4022b6
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_AxisPositions.ui
@@ -0,0 +1,681 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="tp_AxisPositions">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkFrame" id="FL_AXIS_LINE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="boxAXIS_LINE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_CROSSES_OTHER_AXIS_AT">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|FT_CROSSES_OTHER_AXIS_AT">_Cross other axis at</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">LB_CROSSES_OTHER_AXIS_AT</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_CROSSES_OTHER_AXIS_AT">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <items>
+ <item translatable="yes" context="tp_AxisPositions|LB_CROSSES_OTHER_AXIS_AT">Start</item>
+ <item translatable="yes" context="tp_AxisPositions|LB_CROSSES_OTHER_AXIS_AT">End</item>
+ <item translatable="yes" context="tp_AxisPositions|LB_CROSSES_OTHER_AXIS_AT">Value</item>
+ <item translatable="yes" context="tp_AxisPositions|LB_CROSSES_OTHER_AXIS_AT">Category</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_CROSSES_OTHER_AXIS_AT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|LB_CROSSES_OTHER_AXIS_AT">Select where to cross the other axis: at start, at end, at a specified value, or at a category.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="EDT_CROSSES_OTHER_AXIS_AT">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="EDT_CROSSES_OTHER_AXIS_AT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|EDT_CROSSES_OTHER_AXIS_AT">Enter the value where the axis line should cross the other axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="EDT_CROSSES_OTHER_AXIS_AT_CATEGORY">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="combobox-entry">
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="EDT_CROSSES_OTHER_AXIS_AT_CATEGORY-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|EDT_CROSSES_OTHER_AXIS_AT_CATEGORY">Select the category where the axis line should cross the other axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_AXIS_BETWEEN_CATEGORIES">
+ <property name="label" translatable="yes" context="tp_AxisPositions|CB_AXIS_BETWEEN_CATEGORIES">Axis _between categories</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="TXT_AXIS_LINE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|TXT_AXIS_LINE">Axis Line</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="FL_POSITION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="RB_ON">
+ <property name="label" translatable="yes" context="tp_AxisPositions|RB_ON">_On tick marks</property>
+ <property name="active">True</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_ON-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|RB_ON">Specifies that the axis is positioned on the first/last tickmarks. This makes the data points visual representation begin/end at the value axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_BETWEEN">
+ <property name="label" translatable="yes" context="tp_AxisPositions|RB_BETWEEN">_Between tick marks</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_ON</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_BETWEEN-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|RB_BETWEEN">Specifies that the axis is positioned between the tickmarks. This makes the data points visual representation begin/end at a distance from the value axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="TXT_POSITION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|TXT_POSITION">Position Axis</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="FL_LABELS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_PLACE_LABELS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|FT_PLACE_LABELS">_Place labels</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">LB_PLACE_LABELS</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_PLACE_LABELS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <items>
+ <item translatable="yes" context="tp_AxisPositions|LB_PLACE_LABELS">Near axis</item>
+ <item translatable="yes" context="tp_AxisPositions|LB_PLACE_LABELS">Near axis (other side)</item>
+ <item translatable="yes" context="tp_AxisPositions|LB_PLACE_LABELS">Outside start</item>
+ <item translatable="yes" context="tp_AxisPositions|LB_PLACE_LABELS">Outside end</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_PLACE_LABELS-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|LB_PLACE_LABELS">Select where to place the labels: near axis, near axis (other side), outside start, or outside end.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_AXIS_LABEL_DISTANCE">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|FT_AXIS_LABEL_DISTANCE">_Distance</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">EDT_AXIS_LABEL_DISTANCE</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="EDT_AXIS_LABEL_DISTANCE">
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment2</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="TXT_FL_LABELS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|TXT_FL_LABELS">Labels</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="FL_TICKS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_MAJOR">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|FT_MAJOR">Major:</property>
+ <property name="xalign">0</property>
+ <accessibility>
+ <relation type="label-for" target="CB_TICKS_INNER"/>
+ <relation type="label-for" target="CB_TICKS_OUTER"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_MINOR">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|FT_MINOR">Minor:</property>
+ <property name="xalign">0</property>
+ <accessibility>
+ <relation type="label-for" target="CB_MINOR_INNER"/>
+ <relation type="label-for" target="CB_MINOR_OUTER"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_TICKS_INNER">
+ <property name="label" translatable="yes" context="tp_AxisPositions|CB_TICKS_INNER">_Inner</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="FT_MAJOR"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_TICKS_INNER-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|CB_TICKS_INNER">Specifies that marks are placed on the inner side of the axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_TICKS_OUTER">
+ <property name="label" translatable="yes" context="tp_AxisPositions|CB_TICKS_OUTER">_Outer</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="FT_MAJOR"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_TICKS_OUTER-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|CB_TICKS_OUTER">Specifies that marks are placed on the outer side of the axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_MINOR_INNER">
+ <property name="label" translatable="yes" context="tp_AxisPositions|CB_MINOR_INNER">I_nner</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="FT_MINOR"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_MINOR_INNER-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|CB_MINOR_INNER">Specifies that minor interval marks are placed on the inner side of the axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_MINOR_OUTER">
+ <property name="label" translatable="yes" context="tp_AxisPositions|CB_MINOR_OUTER">O_uter</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="FT_MINOR"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_MINOR_OUTER-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|CB_MINOR_OUTER">Specifies that minor interval marks are placed on the outer side of the axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="boxPLACE_TICKS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_PLACE_TICKS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|FT_PLACE_TICKS">Place _marks</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">LB_PLACE_TICKS</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_PLACE_TICKS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <items>
+ <item translatable="yes" context="tp_AxisPositions|LB_PLACE_TICKS">At labels</item>
+ <item translatable="yes" context="tp_AxisPositions|LB_PLACE_TICKS">At axis</item>
+ <item translatable="yes" context="tp_AxisPositions|LB_PLACE_TICKS">At axis and labels</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_PLACE_TICKS-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_AxisPositions|extended_tip|LB_PLACE_TICKS">Select where to place the marks: at labels, at axis, or at axis and labels.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="TXT_FL_TICKS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|TXT_FL_TICKS">Interval Marks</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="FL_GRIDS">
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_MAJOR_GRID">
+ <property name="label" translatable="yes" context="tp_AxisPositions|CB_MAJOR_GRID">Show major _grid</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_MINOR_GRID">
+ <property name="label" translatable="yes" context="tp_AxisPositions|CB_MINOR_GRID">_Show minor grid</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="PB_MAJOR_GRID">
+ <property name="label" translatable="yes" context="tp_AxisPositions|PB_MAJOR_GRID">Mo_re...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="PB_MINOR_GRID">
+ <property name="label" translatable="yes" context="tp_AxisPositions|PB_MINOR_GRID">Mor_e...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_AxisPositions|label2">Grids</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroupCOMBOS">
+ <widgets>
+ <widget name="LB_CROSSES_OTHER_AXIS_AT"/>
+ <widget name="LB_PLACE_LABELS"/>
+ <widget name="LB_PLACE_TICKS"/>
+ <widget name="EDT_CROSSES_OTHER_AXIS_AT"/>
+ <widget name="combobox-entry"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroupLABELS">
+ <widgets>
+ <widget name="FT_CROSSES_OTHER_AXIS_AT"/>
+ <widget name="FT_PLACE_LABELS"/>
+ <widget name="FT_AXIS_LABEL_DISTANCE"/>
+ <widget name="FT_MAJOR"/>
+ <widget name="FT_MINOR"/>
+ <widget name="FT_PLACE_TICKS"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_ChartType.ui b/chart2/uiconfig/ui/tp_ChartType.ui
new file mode 100644
index 0000000000..68decb08f0
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_ChartType.ui
@@ -0,0 +1,525 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="lower">1</property>
+ <property name="upper">100</property>
+ <property name="value">1</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkTreeStore" id="liststore2">
+ <columns>
+ <!-- column-name image -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkBox" id="tp_ChartType">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="FT_CAPTION_FOR_WIZARD">
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_ChartType|FT_CAPTION_FOR_WIZARD">Choose a Chart Type</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=2 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="column-spacing">12</property>
+ <child>
+ <!-- n-columns=1 n-rows=3 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row-spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="subtypewin">
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">never</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <child>
+ <object class="GtkDrawingArea" id="subtype">
+ <property name="can-focus">True</property>
+ <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <property name="hexpand">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="subtype-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|subtype">Select a sub type of the basic chart type.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=3 -->
+ <object class="GtkGrid" id="3dblock">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row-spacing">3</property>
+ <child>
+ <!-- n-columns=2 n-rows=1 -->
+ <object class="GtkGrid" id="grid9">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="3dlook">
+ <property name="label" translatable="yes" context="tp_ChartType|3dlook">_3D Look</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <accessibility>
+ <relation type="label-for" target="3dscheme"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="3dlook-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|3dlook">Enables a 3D look for the data values.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="3dscheme">
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item translatable="yes" context="tp_ChartType|3dscheme">Simple</item>
+ <item translatable="yes" context="tp_ChartType|3dscheme">Realistic</item>
+ </items>
+ <accessibility>
+ <relation type="labelled-by" target="3dlook"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="3dscheme-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|3dscheme">Select the type of 3D look.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="shapeft">
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_ChartType|shapeft">Sh_ape</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">shape</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkTreeView" id="shape">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers-visible">False</property>
+ <property name="headers-clickable">False</property>
+ <property name="search-column">0</property>
+ <property name="show-expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="shape-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|shape">Select a shape from the list.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=5 -->
+ <object class="GtkGrid" id="stackblock">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="row-spacing">3</property>
+ <child>
+ <object class="GtkCheckButton" id="stack">
+ <property name="label" translatable="yes" context="tp_ChartType|stack">_Stack series</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="stack-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|stack">Displays stacked series for Line charts.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=3 -->
+ <object class="GtkGrid" id="grid6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="row-spacing">3</property>
+ <child>
+ <object class="GtkRadioButton" id="ontop">
+ <property name="label" translatable="yes" context="tp_ChartType|ontop">On top</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ontop-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|ontop">Stack series display values on top of each other.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="percent">
+ <property name="label" translatable="yes" context="tp_ChartType|percent">Percent</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">ontop</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="percent-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|percent">Stack series display values as percent.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="deep">
+ <property name="label" translatable="yes" context="tp_ChartType|deep">Deep</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">ontop</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=3 n-rows=1 -->
+ <object class="GtkGrid" id="grid7">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="linetypeft">
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_ChartType|linetypeft">_Line type</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">linetype</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="linetype">
+ <property name="can-focus">False</property>
+ <items>
+ <item translatable="yes" context="tp_ChartType|linetype">Straight</item>
+ <item translatable="yes" context="tp_ChartType|linetype">Smooth</item>
+ <item translatable="yes" context="tp_ChartType|linetype">Stepped</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="linetype-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|linetype">Choose the type of line to draw.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="properties">
+ <property name="label" translatable="yes" context="tp_ChartType|properties">Properties...</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="properties-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|properties">Opens a dialog to set the line or curve properties.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">2</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="sort">
+ <property name="label" translatable="yes" context="tp_ChartType|sort">_Sort by X values</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="sort-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|sort">Connects points by ascending X values, even if the order of values is different, in an XY scatter diagram.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=2 n-rows=1 -->
+ <object class="GtkGrid" id="grid8">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="nolinesft">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="label" translatable="yes" context="tp_ChartType|nolinesft">_Number of lines</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">nolines</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="nolines">
+ <property name="can-focus">True</property>
+ <property name="no-show-all">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="nolines-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|nolines">Set the number of lines for the Column and Line chart type.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="can-focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkTreeView" id="charttype">
+ <property name="can-focus">True</property>
+ <property name="has-focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore2</property>
+ <property name="headers-visible">False</property>
+ <property name="headers-clickable">False</property>
+ <property name="search-column">0</property>
+ <property name="show-expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext3"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="charttype-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ChartType|extended_tip|charttype">Select a basic chart type.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_DataLabel.ui b/chart2/uiconfig/ui/tp_DataLabel.ui
new file mode 100644
index 0000000000..0eef45da8f
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_DataLabel.ui
@@ -0,0 +1,579 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentDEGREE">
+ <property name="upper">359</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkBox" id="tp_DataLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="name">box_left</property>
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=2 n-rows=6 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <property name="row-homogeneous">True</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_VALUE_AS_NUMBER">
+ <property name="label" translatable="yes" context="tp_DataLabel|CB_VALUE_AS_NUMBER">Value as _number</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_VALUE_AS_NUMBER-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|CB_VALUE_AS_NUMBER">Displays the absolute values of the data points.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_VALUE_AS_PERCENTAGE">
+ <property name="label" translatable="yes" context="tp_DataLabel|CB_VALUE_AS_PERCENTAGE">Value as _percentage</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_VALUE_AS_PERCENTAGE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|CB_VALUE_AS_PERCENTAGE">Displays the percentage of the data points in each column.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_CATEGORY">
+ <property name="label" translatable="yes" context="tp_DataLabel|CB_CATEGORY">_Category</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_CATEGORY-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|CB_CATEGORY">Shows the data point text labels.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_SYMBOL">
+ <property name="label" translatable="yes" context="tp_DataLabel|CB_SYMBOL">_Legend key</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_SYMBOL-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|CB_SYMBOL">Displays the legend icons next to each data point label.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_WRAP_TEXT">
+ <property name="label" translatable="yes" context="tp_DataLabel|CB_WRAP_TEXT">Auto text _wrap</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="PB_NUMBERFORMAT">
+ <property name="label" translatable="yes" context="tp_DataLabel|PB_NUMBERFORMAT">Number _format...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="valign">center</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="PB_NUMBERFORMAT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|PB_NUMBERFORMAT">Opens a dialog to select the number format.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="PB_PERCENT_NUMBERFORMAT">
+ <property name="label" translatable="yes" context="tp_DataLabel|PB_PERCENT_NUMBERFORMAT">Percentage f_ormat...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="valign">center</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="PB_PERCENT_NUMBERFORMAT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|PB_PERCENT_NUMBERFORMAT">Opens a dialog to select the percentage format.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="CT_LABEL_DIAL">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="label" translatable="yes" context="tp_DataLabel|CT_LABEL_DIAL">ABCD</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="STR_DLG_NUMBERFORMAT_FOR_PERCENTAGE_VALUE">
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataLabel|STR_DLG_NUMBERFORMAT_FOR_PERCENTAGE_VALUE">Number Format for Percentage Value</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_DATA_SERIES_NAME">
+ <property name="label" translatable="yes" context="tp_DataLabel|CB_DATA_SERIES_NAME">_Series name</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_DATA_SERIES_NAME-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|CB_DATA_SERIES_NAME">Shows the data series name in the label.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataLabel|label1">Text Attributes</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=2 n-rows=2 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <property name="row-homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="FT_LABEL_PLACEMENT">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataLabel|FT_LABEL_PLACEMENT">Place_ment</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">LB_LABEL_PLACEMENT</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_LABEL_PLACEMENT">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="valign">center</property>
+ <items>
+ <item id="0" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Best fit</item>
+ <item id="1" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Center</item>
+ <item id="2" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Above</item>
+ <item id="3" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Top left</item>
+ <item id="4" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Left</item>
+ <item id="5" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Bottom left</item>
+ <item id="6" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Below</item>
+ <item id="7" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Bottom right</item>
+ <item id="8" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Right</item>
+ <item id="9" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Top right</item>
+ <item id="10" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Inside</item>
+ <item id="11" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Outside</item>
+ <item id="12" translatable="yes" context="tp_DataLabel|liststorePLACEMENT">Near origin</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_LABEL_PLACEMENT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|LB_LABEL_PLACEMENT">Selects the placement of data labels relative to the objects.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_TEXT_SEPARATOR">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataLabel|FT_TEXT_SEPARATOR">_Separator</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">LB_TEXT_SEPARATOR</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_TEXT_SEPARATOR">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="valign">center</property>
+ <items>
+ <item id="0" translatable="yes" context="tp_DataLabel|liststoreSEPARATOR">Space</item>
+ <item id="1" translatable="yes" context="tp_DataLabel|liststoreSEPARATOR">Comma</item>
+ <item id="2" translatable="yes" context="tp_DataLabel|liststoreSEPARATOR">Semicolon</item>
+ <item id="3" translatable="yes" context="tp_DataLabel|liststoreSEPARATOR">New line</item>
+ <item id="4" translatable="yes" context="tp_DataLabel|liststoreSEPARATOR">Period</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_TEXT_SEPARATOR-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|LB_TEXT_SEPARATOR">Selects the separator between multiple text strings for the same object.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataLabel|label1">Attribute Options</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box_right">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="boxORIENTATION">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkDrawingArea" id="CT_DIAL">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CT_DIAL-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|CT_DIAL">Click in the dial to set the text orientation for the data labels.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="NF_LABEL_DEGREES">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="valign">center</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentDEGREE</property>
+ <property name="wrap">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="NF_LABEL_DEGREES-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|NF_LABEL_DEGREES">Enter the counterclockwise rotation angle for the data labels.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_LABEL_DEGREES">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataLabel|FT_LABEL_DEGREES">_Degrees</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="boxTXT_DIRECTION">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_LABEL_TEXTDIR">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataLabel|FT_LABEL_TEXTDIR">Te_xt direction</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">LB_LABEL_TEXTDIR</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_LABEL_TEXTDIR">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_LABEL_TEXTDIR-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|LB_LABEL_TEXTDIR">Specify the text direction for a paragraph that uses complex text layout (CTL). This feature is only available if complex text layout support is enabled.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataLabel|label2">Rotate Text</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_CUSTOM_LEADER_LINES">
+ <property name="label" translatable="yes" context="tp_DataLabel|CB_CUSTOM_LEADER_LINES">_Connect displaced data labels to data points</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_CUSTOM_LEADER_LINES-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|CB_CUSTOM_LEADER_LINES">Draws a line connecting the data labels to the data points</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataLabel|label3">Leader Lines</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="tp_DataLabel-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataLabel|extended_tip|tp_DataLabel">Opens the Data Labels dialog, which enables you to set the data labels.</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1"/>
+ <object class="GtkSizeGroup" id="sizegroup2"/>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_DataPointOption.ui b/chart2/uiconfig/ui/tp_DataPointOption.ui
new file mode 100644
index 0000000000..f699981785
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_DataPointOption.ui
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentGAP">
+ <property name="upper">600</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentOVERLAP">
+ <property name="lower">-100</property>
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="tp_DataPointOption">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkFrame" id="frameLegend">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_LEGEND_ENTRY_HIDDEN">
+ <property name="label" translatable="yes" context="tp_DataPointOption|CB_LEGEND_ENTRY_HIDDEN">Hide legend entry</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_LEGEND_ENTRY_HIDDEN-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataPointOption|extended_tip|CB_LEGEND_ENTRY_HIDDEN">Do not show legend entry for the selected data series or data point.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataPointOption|label1">Legend Entry</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_DataSource.ui b/chart2/uiconfig/ui/tp_DataSource.ui
new file mode 100644
index 0000000000..c9a3df7cc1
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_DataSource.ui
@@ -0,0 +1,493 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">go-up</property>
+ </object>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">go-down</property>
+ </object>
+ <object class="GtkImage" id="imageIMB_RANGE_CAT">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes" context="tp_DataSource|imageIMB_RANGE_CAT|tooltip_text">Select data range</property>
+ <property name="icon_name">chart2/res/selectrange.png</property>
+ </object>
+ <object class="GtkImage" id="imageIMB_RANGE_MAIN">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes" context="tp_DataSource|imageIMB_RANGE_MAIN|tooltip_text">Select data range</property>
+ <property name="icon_name">chart2/res/selectrange.png</property>
+ </object>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkTreeStore" id="liststore2">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name text2 -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="tp_DataSource">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="FT_SERIES">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataSource|FT_SERIES">Data _series:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">LB_SERIES</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="LB_SERIES">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_SERIES-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataSource|extended_tip|LB_SERIES">Shows a list of all data series in the chart. Click an entry to view and edit that data series. Click Add to insert a new series into the list after the selected entry.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkButton" id="BTN_ADD">
+ <property name="label" translatable="yes" context="tp_DataSource|BTN_ADD">_Add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_ADD-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataSource|extended_tip|BTN_ADD">Adds a new entry below the current entry in the Data Series list. If an entry is selected, the new data series gets the same chart type.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="BTN_UP">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image1</property>
+ <property name="always_show_image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_UP-atkobject">
+ <property name="AtkObject::accessible-name" translatable="yes" context="tp_DataSource|BTN_UP-atkobject">Up</property>
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataSource|extended_tip|BTN_UP">Moves up the selected entry in the Data Series list.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="BTN_REMOVE">
+ <property name="label" translatable="yes" context="tp_DataSource|BTN_REMOVE">_Remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_REMOVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataSource|extended_tip|BTN_REMOVE">Removes the selected entry from the Data Series list.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="BTN_DOWN">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image2</property>
+ <property name="always_show_image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="BTN_DOWN-atkobject">
+ <property name="AtkObject::accessible-name" translatable="yes" context="tp_DataSource|BTN_DOWN-atkobject">Down</property>
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataSource|extended_tip|BTN_DOWN">Moves down the selected entry in the Data Series list.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="FT_ROLE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataSource|FT_ROLE">_Data ranges:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">LB_ROLE</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="LB_ROLE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore2</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext3"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_ROLE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataSource|extended_tip|LB_ROLE">Shows all the data ranges used by the data series that is selected in the Data Series list box. Each data range shows the role name and the source range address.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_RANGE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataSource|FT_RANGE">Ran_ge for %VALUETYPE</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">EDT_RANGE</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="box5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkEntry" id="EDT_RANGE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="EDT_RANGE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataSource|extended_tip|EDT_RANGE">Shows the source range address from the second column of the Data Range list box. You can change the range in the text box or by dragging in the document. To minimize this dialog while you select the data range in Calc, click the Select data range button.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="IMB_RANGE_MAIN">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">imageIMB_RANGE_MAIN</property>
+ <property name="always-show-image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="IMB_RANGE_MAIN-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataSource|extended_tip|IMB_RANGE_MAIN">Shows the source range address from the second column of the Data Range list box. You can change the range in the text box or by dragging in the document. To minimize this dialog while you select the data range in Calc, click the Select data range button.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="FT_CATEGORIES">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataSource|FT_CATEGORIES">_Categories</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">EDT_CATEGORIES</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_DATALABELS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataSource|FT_DATALABELS">Data _labels</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="box6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkEntry" id="EDT_CATEGORIES">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="EDT_CATEGORIES-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataSource|extended_tip|EDT_CATEGORIES">Shows the source range address of the categories (the texts you can see on the x-axis of a category chart). For an XY-chart, the text box contains the source range of the data labels which are displayed for the data points. To minimize this dialog while you select the data range in Calc, click the Select data range button.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="IMB_RANGE_CAT">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">imageIMB_RANGE_CAT</property>
+ <property name="always-show-image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="IMB_RANGE_CAT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_DataSource|extended_tip|IMB_RANGE_CAT">Shows the source range address of the categories (the texts you can see on the x-axis of a category chart). For an XY-chart, the text box contains the source range of the data labels which are displayed for the data points. To minimize this dialog while you select the data range in Calc, click the Select data range button.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_CAPTION_FOR_WIZARD">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_DataSource|FT_CAPTION_FOR_WIZARD">Customize Data Ranges for Individual Data Series</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_DataTable.ui b/chart2/uiconfig/ui/tp_DataTable.ui
new file mode 100644
index 0000000000..ad8bc0fcff
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_DataTable.ui
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="DataTableTabPage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="horizontalBorderCB">
+ <property name="label" translatable="yes" context="tp_DataTable|horizontalBorderCB">Show horizontal border</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="verticalBorderCB">
+ <property name="label" translatable="yes" context="tp_DataTable|verticalBorderCB">Show vertical border</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="outlineCB">
+ <property name="label" translatable="yes" context="tp_DataTable|outlineCB">Show outline</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="keysCB">
+ <property name="label" translatable="yes" context="tp_DataTable|keysCB">Show keys</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="dataTablePropertiesLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_axisLabel|textflowL">Data Table Properties</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_ErrorBars.ui b/chart2/uiconfig/ui/tp_ErrorBars.ui
new file mode 100644
index 0000000000..aa63a36bcf
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_ErrorBars.ui
@@ -0,0 +1,621 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentNEG">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentPOS">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkImage" id="imageRANGE_SELECT_NEG">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">chart2/res/selectrange.png</property>
+ </object>
+ <object class="GtkImage" id="imageRANGE_SELECT_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">chart2/res/selectrange.png</property>
+ </object>
+ <object class="GtkBox" id="tp_ErrorBars">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkFrame" id="FL_ERROR">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="RB_NONE">
+ <property name="label" translatable="yes" context="tp_ErrorBars|RB_NONE">_None</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_NONE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|RB_NONE">Does not show any error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_CONST">
+ <property name="label" translatable="yes" context="tp_ErrorBars|RB_CONST">_Constant Value</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_NONE</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_CONST-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|RB_CONST">Displays constant values that you specify in the Parameters area.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_PERCENT">
+ <property name="label" translatable="yes" context="tp_ErrorBars|RB_PERCENT">_Percentage</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_NONE</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_PERCENT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|RB_PERCENT">Displays a percentage. The display refers to the corresponding data point. Set the percentage in the Parameters area.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="RB_FUNCTION">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_NONE</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_FUNCTION-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|RB_FUNCTION">Select a function to calculate the error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_FUNCTION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <items>
+ <item id="0" translatable="yes" context="tp_ErrorBars|liststoreFUNCTION">Standard Error</item>
+ <item id="1" translatable="yes" context="tp_ErrorBars|liststoreFUNCTION">Standard Deviation</item>
+ <item id="2" translatable="yes" context="tp_ErrorBars|liststoreFUNCTION">Variance</item>
+ <item id="3" translatable="yes" context="tp_ErrorBars|liststoreFUNCTION">Error Margin</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_FUNCTION-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|LB_FUNCTION">Select a function to calculate the error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_RANGE">
+ <property name="label" translatable="yes" context="tp_ErrorBars|RB_RANGE">Cell _Range</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_NONE</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_RANGE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|RB_RANGE">Click Cell Range and then specify a cell range from which to take the positive and negative error bar values.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_ErrorBars|label1">Error Category</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="RB_BOTH">
+ <property name="label" translatable="yes" context="tp_ErrorBars|RB_BOTH">Positive _and Negative</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_BOTH-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|RB_BOTH">Shows positive and negative error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_POSITIVE">
+ <property name="label" translatable="yes" context="tp_ErrorBars|RB_POSITIVE">Pos_itive</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_BOTH</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_POSITIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|RB_POSITIVE">Shows only positive error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_NEGATIVE">
+ <property name="label" translatable="yes" context="tp_ErrorBars|RB_NEGATIVE">Ne_gative</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_BOTH</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_NEGATIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|RB_NEGATIVE">Shows only negative error bars.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="FI_BOTH">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="FI_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="FI_NEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_ErrorBars|label2">Error Indicator</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="framePARAMETERS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkBox" id="boxPOSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_ErrorBars|FT_POSITIVE">P_ositive (+)</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">MF_POSITIVE</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MF_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustmentPOS</property>
+ <property name="digits">2</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MF_POSITIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|MF_POSITIVE">Enter the value to add to the displayed value as the positive error value.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="ED_RANGE_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ED_RANGE_POSITIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|ED_RANGE_POSITIVE">Enter the address range from where to get the positive error values. Use the Shrink button to select the range from a sheet.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="IB_RANGE_POSITIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_ErrorBars|IB_RANGE_POSITIVE|tooltip_text">Select data range</property>
+ <property name="image">imageRANGE_SELECT_POSITIVE</property>
+ <property name="always-show-image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="IB_RANGE_POSITIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|IB_RANGE_POSITIVE">Click a button to shrink the dialog, then use the mouse to select the cell range in the spreadsheet. Click the button again to restore the dialog to full size.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="boxNEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_NEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_ErrorBars|FT_NEGATIVE">_Negative (-)</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">MF_NEGATIVE</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MF_NEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustmentNEG</property>
+ <property name="digits">2</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MF_NEGATIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|MF_NEGATIVE">Enter the value to subtract from the displayed value as the negative error value.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="ED_RANGE_NEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ED_RANGE_NEGATIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|ED_RANGE_NEGATIVE">Enter the address range from where to get the negative error values. Use the Shrink button to select the range from a sheet.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="IB_RANGE_NEGATIVE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_ErrorBars|IB_RANGE_NEGATIVE|tooltip_text">Select data range</property>
+ <property name="image">imageRANGE_SELECT_NEG</property>
+ <property name="always-show-image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="IB_RANGE_NEGATIVE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|IB_RANGE_NEGATIVE">Click a button to shrink the dialog, then use the mouse to select the cell range in the spreadsheet. Click the button again to restore the dialog to full size.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_SYN_POS_NEG">
+ <property name="label" translatable="yes" context="tp_ErrorBars|CB_SYN_POS_NEG">Same value for both</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_SYN_POS_NEG-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_ErrorBars|extended_tip|CB_SYN_POS_NEG">Enable to use the positive error values also as negative error values. You can only change the value of the "Positive (+)" box. That value gets copied to the "Negative (-)" box automatically.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_ErrorBars|label3">Parameters</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="STR_DATA_SELECT_RANGE_FOR_POSITIVE_ERRORBARS">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_ErrorBars|STR_DATA_SELECT_RANGE_FOR_POSITIVE_ERRORBARS">Select Range for Positive Error Bars</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="STR_DATA_SELECT_RANGE_FOR_NEGATIVE_ERRORBARS">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_ErrorBars|STR_DATA_SELECT_RANGE_FOR_NEGATIVE_ERRORBARS">Select Range for Negative Error Bars</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="STR_CONTROLTEXT_ERROR_BARS_FROM_DATA">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_ErrorBars|STR_CONTROLTEXT_ERROR_BARS_FROM_DATA">From Data Table</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="FT_POSITIVE"/>
+ <widget name="FT_NEGATIVE"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_LegendPosition.ui b/chart2/uiconfig/ui/tp_LegendPosition.ui
new file mode 100644
index 0000000000..9584e4ef56
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_LegendPosition.ui
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="tp_LegendPosition">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="framePOSITION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="left">
+ <property name="label" translatable="yes" context="tp_LegendPosition|left">_Left</property>
+ <property name="active">True</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="left-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_LegendPosition|extended_tip|left">Positions the legend at the left of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="right">
+ <property name="label" translatable="yes" context="tp_LegendPosition|right">_Right</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">left</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="right-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_LegendPosition|extended_tip|right">Positions the legend at the right of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="top">
+ <property name="label" translatable="yes" context="tp_LegendPosition|top">_Top</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">left</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="top-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_LegendPosition|extended_tip|top">Positions the legend at the top of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="bottom">
+ <property name="label" translatable="yes" context="tp_LegendPosition|bottom">_Bottom</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">left</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="bottom-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_LegendPosition|extended_tip|bottom">Positions the legend at the bottom of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="TXT_POSITION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_LegendPosition|TXT_POSITION">Position</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frameORIENTATION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="FT_LEGEND_TEXTDIR">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_LegendPosition|FT_LEGEND_TEXTDIR">Te_xt direction</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_LEGEND_TEXTDIR">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_LEGEND_TEXTDIR-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_LegendPosition|extended_tip|LB_LEGEND_TEXTDIR">Specify the text direction for a paragraph that uses complex text layout (CTL). This feature is only available if complex text layout support is enabled.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="TXT_ORIENTATION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_LegendPosition|TXT_ORIENTATION">Text Orientation</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frameOVERLAY">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_NO_OVERLAY">
+ <property name="label" translatable="yes" context="tp_LegendPosition|CB_NO_OVERLAY">Show the legend without overlapping the chart</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_NO_OVERLAY-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_LegendPosition|extended_tip|CB_NO_OVERLAY">Specifies whether the legend should overlap the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="TXT_OVERLAY">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_LegendPosition|TXT_OVERLAY">Overlay</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_PolarOptions.ui b/chart2/uiconfig/ui/tp_PolarOptions.ui
new file mode 100644
index 0000000000..fb6a166ba8
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_PolarOptions.ui
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentDEGREE">
+ <property name="upper">359</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="tp_PolarOptions">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_CLOCKWISE">
+ <property name="label" translatable="yes" context="tp_PolarOptions|CB_CLOCKWISE">_Clockwise direction</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_CLOCKWISE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_PolarOptions|extended_tip|CB_CLOCKWISE">The default direction in which the pieces of a pie chart are ordered is counterclockwise. Enable the Clockwise direction checkbox to draw the pieces in opposite direction.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_PolarOptions|label1">Orientation</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frameANGLE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkDrawingArea" id="CT_ANGLE_DIAL">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CT_ANGLE_DIAL-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_PolarOptions|extended_tip|CT_ANGLE_DIAL">Drag the small dot along the circle or click any position on the circle to set the starting angle of a pie or donut chart. The starting angle is the mathematical angle position where the first piece is drawn. The value of 90 degrees draws the first piece at the 12 o'clock position. A value of 0 degrees starts at the 3 o'clock position.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="NF_STARTING_ANGLE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="adjustment">adjustmentDEGREE</property>
+ <property name="wrap">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="NF_STARTING_ANGLE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_PolarOptions|extended_tip|NF_STARTING_ANGLE">Enter the starting angle between 0 and 359 degrees. You can also click the arrows to change the displayed value.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_ROTATION_DEGREES">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_PolarOptions|FT_ROTATION_DEGREES">_Degrees</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">NF_STARTING_ANGLE</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_PolarOptions|label2">Starting Angle</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="framePLOT_OPTIONS">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_INCLUDE_HIDDEN_CELLS_POLAR">
+ <property name="label" translatable="yes" context="tp_PolarOptions|CB_INCLUDE_HIDDEN_CELLS_POLAR">Include _values from hidden cells</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_PolarOptions|label3">Plot Options</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_RangeChooser.ui b/chart2/uiconfig/ui/tp_RangeChooser.ui
new file mode 100644
index 0000000000..4581db7ddd
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_RangeChooser.ui
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkImage" id="imageIB_RANGE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes" context="tp_RangeChooser|imageIB_RANGE|tooltip_text">Select data range</property>
+ <property name="icon_name">chart2/res/selectrange.png</property>
+ </object>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="tp_RangeChooser">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border_width">6</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="FT_CAPTION_FOR_WIZARD">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_RangeChooser|FT_CAPTION_FOR_WIZARD">Choose a Data Range</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="FT_RANGE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_RangeChooser|FT_RANGE">_Data range:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ED_RANGE</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="ED_RANGE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="ED_RANGE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_RangeChooser|extended_tip|ED_RANGE">Enter the data range that you want to include in your chart. To minimize this dialog while you select the data range in Calc, click the Select data range button.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="IB_RANGE">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes" context="tp_RangeChooser|IB_RANGE|tooltip_text">Select data range</property>
+ <property name="image">imageIB_RANGE</property>
+ <property name="always-show-image">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="IB_RANGE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_RangeChooser|extended_tip|IB_RANGE">Enter the data range that you want to include in your chart. To minimize this dialog while you select the data range in Calc, click the Select data range button.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_DATAROWS">
+ <property name="label" translatable="yes" context="tp_RangeChooser|RB_DATAROWS">Data series in _rows</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_DATAROWS-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_RangeChooser|extended_tip|RB_DATAROWS">Data series get their data from consecutive rows in the selected range. For scatter charts, the first data series will contain x-values for all series. All other data series are used as y-values, one for each series.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_DATACOLS">
+ <property name="label" translatable="yes" context="tp_RangeChooser|RB_DATACOLS">Data series in _columns</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_DATAROWS</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_DATACOLS-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_RangeChooser|extended_tip|RB_DATACOLS">Data series get their data from consecutive columns in the selected range. For scatter charts, the first data column will contain x-values for all series. All other data columns are used as y-values, one for each series.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_FIRST_ROW_ASLABELS">
+ <property name="label" translatable="yes" context="tp_RangeChooser|CB_FIRST_ROW_ASLABELS">_First row as label</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_FIRST_ROW_ASLABELS-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_RangeChooser|extended_tip|CB_FIRST_ROW_ASLABELS">For data series in columns: The first row in the range is used as names for data series. For data series in rows: The first row in the range is used as categories. The remaining rows comprise the data series. If this check box is not selected, all rows are data series.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_FIRST_COLUMN_ASLABELS">
+ <property name="label" translatable="yes" context="tp_RangeChooser|CB_FIRST_COLUMN_ASLABELS">F_irst column as label</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_FIRST_COLUMN_ASLABELS-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_RangeChooser|extended_tip|CB_FIRST_COLUMN_ASLABELS">For data series in columns: The first column in the range is used as names for data series. For data series in rows: The first column in the range is used as categories. The remaining columns comprise the data columns. If this check box is not selected, all columns are data columns.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator" id="separator1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_TIME_BASED">
+ <property name="label" translatable="yes" context="tp_RangeChooser|CB_TIME_BASED">Time based charting</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkEntry" id="ED_TIME_BASED_START">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">5</property>
+ <property name="text">0</property>
+ <property name="truncate-multiline">True</property>
+ <property name="input_purpose">number</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="ED_TIME_BASED_END">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">5</property>
+ <property name="truncate-multiline">True</property>
+ <property name="text">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_RangeChooser|label1">Start Table Index</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ED_TIME_BASED_START</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_RangeChooser|label2">End Table Index</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ED_TIME_BASED_END</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="STR_PAGE_DATA_RANGE">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_RangeChooser|STR_PAGE_DATA_RANGE">Data Range</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">9</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_Scale.ui b/chart2/uiconfig/ui/tp_Scale.ui
new file mode 100644
index 0000000000..f3e272d0d2
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_Scale.ui
@@ -0,0 +1,661 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment3">
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment4">
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentINTERVAL">
+ <property name="lower">1</property>
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentINTERVAL1">
+ <property name="lower">1</property>
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkFrame" id="tp_Scale">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="CBX_REVERSE">
+ <property name="label" translatable="yes" context="tp_Scale|CBX_REVERSE">_Reverse direction</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CBX_REVERSE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|CBX_REVERSE">Defines where the lower and where the higher values are displayed at the axis. The unchecked state is the mathematical direction.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CBX_LOGARITHM">
+ <property name="label" translatable="yes" context="tp_Scale|CBX_LOGARITHM">_Logarithmic scale</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CBX_LOGARITHM-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|CBX_LOGARITHM">Specifies that you want the axis to be subdivided logarithmically.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="boxTYPE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="TXT_AXIS_TYPE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_Scale|TXT_AXIS_TYPE">T_ype</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">LB_AXIS_TYPE</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_AXIS_TYPE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <items>
+ <item translatable="yes" context="tp_Scale|LB_AXIS_TYPE">Automatic</item>
+ <item translatable="yes" context="tp_Scale|LB_AXIS_TYPE">Text</item>
+ <item translatable="yes" context="tp_Scale|LB_AXIS_TYPE">Date</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_AXIS_TYPE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|LB_AXIS_TYPE">For some types of axes, you can select to format an axis as text or date, or to detect the type automatically.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="gridMINMAX">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="TXT_MIN">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_Scale|TXT_MIN">_Minimum</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">EDT_MIN</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="TXT_MAX">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_Scale|TXT_MAX">Ma_ximum</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">EDT_MAX</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CBX_AUTO_MIN">
+ <property name="label" translatable="yes" context="tp_Scale|CBX_AUTO_MIN">_Automatic</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CBX_AUTO_MAX">
+ <property name="label" translatable="yes" context="tp_Scale|CBX_AUTO_MAX">A_utomatic</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="EDT_MIN">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">10</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="EDT_MIN-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|EDT_MIN">Defines the minimum value for the beginning of the axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="EDT_MAX">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">10</property>
+ <property name="adjustment">adjustment2</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="EDT_MAX-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|EDT_MAX">Defines the maximum value for the end of the axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="boxRESOLUTION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="TXT_TIME_RESOLUTION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_Scale|TXT_TIME_RESOLUTION">R_esolution</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">LB_TIME_RESOLUTION</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_TIME_RESOLUTION">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <items>
+ <item id="0" translatable="yes" context="tp_Scale|DATE-RESOLUTION">Days</item>
+ <item id="1" translatable="yes" context="tp_Scale|DATE-RESOLUTION">Months</item>
+ <item id="2" translatable="yes" context="tp_Scale|DATE-RESOLUTION">Years</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_TIME_RESOLUTION-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|LB_TIME_RESOLUTION">Resolution can be set to show days, months, or years as interval steps.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CBX_AUTO_TIME_RESOLUTION">
+ <property name="label" translatable="yes" context="tp_Scale|CBX_AUTO_TIME_RESOLUTION">Automat_ic</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="boxMAIN">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="TXT_STEP_MAIN">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_Scale|TXT_STEP_MAIN">Ma_jor interval</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="box9">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkSpinButton" id="MT_MAIN_DATE_STEP">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">10</property>
+ <property name="adjustment">adjustmentINTERVAL</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MT_MAIN_DATE_STEP-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|MT_MAIN_DATE_STEP">Major interval can be set to show a certain number of days, months, or years.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_MAIN_TIME_UNIT">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <items>
+ <item id="0" translatable="yes" context="tp_Scale|liststoreDATE">Days</item>
+ <item id="1" translatable="yes" context="tp_Scale|liststoreDATE">Months</item>
+ <item id="2" translatable="yes" context="tp_Scale|liststoreDATE">Years</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_MAIN_TIME_UNIT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|LB_MAIN_TIME_UNIT">Major interval can be set to show a certain number of days, months, or years.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="EDT_STEP_MAIN">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">10</property>
+ <property name="adjustment">adjustment4</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="EDT_STEP_MAIN-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|EDT_STEP_MAIN">Defines the interval for the main division of the axes.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CBX_AUTO_STEP_MAIN">
+ <property name="label" translatable="yes" context="tp_Scale|CBX_AUTO_STEP_MAIN">Au_tomatic</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="boxMINOR">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="TXT_STEP_HELP">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_Scale|TXT_STEP_HELP">Minor inter_val</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="TXT_STEP_HELP_COUNT">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_Scale|TXT_STEP_HELP_COUNT">Minor inter_val count</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MT_STEPHELP">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">10</property>
+ <property name="adjustment">adjustmentINTERVAL1</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MT_STEPHELP-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|MT_STEPHELP">Defines the interval for the subdivision of the axes.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="LB_HELP_TIME_UNIT">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <items>
+ <item id="0" translatable="yes" context="tp_Scale|liststoreDATE">Days</item>
+ <item id="1" translatable="yes" context="tp_Scale|liststoreDATE">Months</item>
+ <item id="2" translatable="yes" context="tp_Scale|liststoreDATE">Years</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="LB_HELP_TIME_UNIT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|LB_HELP_TIME_UNIT">Minor interval can be set to show a certain number of days, months, or years.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CBX_AUTO_STEP_HELP">
+ <property name="label" translatable="yes" context="tp_Scale|CBX_AUTO_STEP_HELP">Aut_omatic</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="boxORIGIN">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="TXT_ORIGIN">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_Scale|TXT_ORIGIN">Re_ference value</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="EDT_ORIGIN">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">10</property>
+ <property name="adjustment">adjustment3</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="EDT_ORIGIN-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|EDT_ORIGIN">Specifies at which position to display the values along the axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CBX_AUTO_ORIGIN">
+ <property name="label" translatable="yes" context="tp_Scale|CBX_AUTO_ORIGIN">Automat_ic</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CBX_AUTO_ORIGIN-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Scale|extended_tip|CBX_AUTO_ORIGIN">You must first deselect the Automatic option in order to modify the values.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="FL_SCALE">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_Scale|FL_SCALE">Scale</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroupCOMBO">
+ <widgets>
+ <widget name="LB_AXIS_TYPE"/>
+ <widget name="EDT_MIN"/>
+ <widget name="EDT_MAX"/>
+ <widget name="MT_MAIN_DATE_STEP"/>
+ <widget name="EDT_STEP_MAIN"/>
+ <widget name="MT_STEPHELP"/>
+ <widget name="EDT_ORIGIN"/>
+ <widget name="LB_TIME_RESOLUTION"/>
+ <widget name="LB_MAIN_TIME_UNIT"/>
+ <widget name="LB_HELP_TIME_UNIT"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroupLABELS">
+ <widgets>
+ <widget name="TXT_STEP_HELP_COUNT"/>
+ <widget name="TXT_STEP_HELP"/>
+ <widget name="TXT_STEP_MAIN"/>
+ <widget name="TXT_TIME_RESOLUTION"/>
+ <widget name="TXT_MAX"/>
+ <widget name="TXT_MIN"/>
+ <widget name="TXT_AXIS_TYPE"/>
+ <widget name="CBX_LOGARITHM"/>
+ <widget name="CBX_REVERSE"/>
+ <widget name="TXT_ORIGIN"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_SeriesToAxis.ui b/chart2/uiconfig/ui/tp_SeriesToAxis.ui
new file mode 100644
index 0000000000..d48dd41846
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_SeriesToAxis.ui
@@ -0,0 +1,447 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentGAP">
+ <property name="upper">600</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentOVERLAP">
+ <property name="lower">-100</property>
+ <property name="upper">100</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkBox" id="TP_OPTIONS">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkFrame" id="frameGrpAxis">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="RBT_OPT_AXIS_1">
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|RBT_OPT_AXIS_1">Primary Y axis</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RBT_OPT_AXIS_1-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|RBT_OPT_AXIS_1">This option is active as default. All data series are aligned to the primary Y axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RBT_OPT_AXIS_2">
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|RBT_OPT_AXIS_2">Secondary Y axis</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">RBT_OPT_AXIS_1</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RBT_OPT_AXIS_2-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|RBT_OPT_AXIS_2">Changes the scaling of the Y axis. This axis is only visible when at least one data series is assigned to it and the axis view is active.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|label1">Align Data Series to</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frameSettings">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <!-- n-columns=2 n-rows=2 -->
+ <object class="GtkGrid" id="gridSettings">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_GAP">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|FT_GAP">_Spacing</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">MT_GAP</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="FT_OVERLAP">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|FT_OVERLAP">_Overlap</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">MT_OVERLAP</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MT_GAP">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentGAP</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MT_GAP-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|MT_GAP">Defines the spacing between the columns in percent.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="MT_OVERLAP">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentOVERLAP</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="MT_OVERLAP-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|MT_OVERLAP">Defines the necessary settings for overlapping data series.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_BARS_SIDE_BY_SIDE">
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|CB_BARS_SIDE_BY_SIDE">Show _bars side by side</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_BARS_SIDE_BY_SIDE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|CB_BARS_SIDE_BY_SIDE">The bars from different data series are shown as if they were attached only to one axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_CONNECTOR">
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|CB_CONNECTOR">Connection lines</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_CONNECTOR-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|CB_CONNECTOR">For "stacked" and "percent" column (vertical bar) charts, mark this check box to connect the column layers that belong together with lines.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|label2">Settings</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frameFL_PLOT_OPTIONS">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <!-- n-columns=2 n-rows=3 -->
+ <object class="GtkGrid" id="gridPLOT_OPTIONS">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="FT_MISSING_VALUES">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|FT_MISSING_VALUES">Plot missing values</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_DONT_PAINT">
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|RB_DONT_PAINT">_Leave gap</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_DONT_PAINT-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|RB_DONT_PAINT">For a missing value, no data will be shown. This is the default for chart types Column, Bar, Line, Net.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_ASSUME_ZERO">
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|RB_ASSUME_ZERO">_Assume zero</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">RB_DONT_PAINT</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_ASSUME_ZERO-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|RB_ASSUME_ZERO">For a missing value, the y-value will be shown as zero. This is the default for chart type Area.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_CONTINUE_LINE">
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|RB_CONTINUE_LINE">_Continue line</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">RB_DONT_PAINT</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="RB_CONTINUE_LINE-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|RB_CONTINUE_LINE">For a missing value, the interpolation from the neighbor values will be shown. This is the default for chart type XY.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="CB_INCLUDE_HIDDEN_CELLS">
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|CB_INCLUDE_HIDDEN_CELLS">Include _values from hidden cells</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_INCLUDE_HIDDEN_CELLS-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|CB_INCLUDE_HIDDEN_CELLS">Check to also show values of currently hidden cells within the source cell range.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|label3">Plot Options</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frameLegend">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="CB_LEGEND_ENTRY_HIDDEN">
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|CB_LEGEND_ENTRY_HIDDEN">Hide legend entry</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CB_LEGEND_ENTRY_HIDDEN-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_SeriesToAxis|extended_tip|CB_LEGEND_ENTRY_HIDDEN">Do not show legend entry for the selected data series or data point.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_SeriesToAxis|label4">Legend Entry</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_Trendline.ui b/chart2/uiconfig/ui/tp_Trendline.ui
new file mode 100644
index 0000000000..9a385c7b92
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_Trendline.ui
@@ -0,0 +1,699 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkSizeGroup"/>
+ <object class="GtkAdjustment" id="adjustmentDegree">
+ <property name="lower">2</property>
+ <property name="upper">10</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentForwardBackward">
+ <property name="lower">-10000</property>
+ <property name="upper">10000</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentForwardBackward1">
+ <property name="lower">-10000</property>
+ <property name="upper">10000</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentForwardBackward2">
+ <property name="lower">-10000</property>
+ <property name="upper">10000</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <object class="GtkBox" id="TP_TRENDLINE">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=3 n-rows=9 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">6</property>
+ <property name="row-homogeneous">True</property>
+ <child>
+ <object class="GtkRadioButton" id="linear">
+ <property name="label" translatable="yes" context="tp_Trendline|linear">_Linear</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="linear-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|linear">A linear trend line is shown.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="logarithmic">
+ <property name="label" translatable="yes" context="tp_Trendline|logarithmic">L_ogarithmic</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">linear</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="logarithmic-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|logarithmic">A logarithmic trend line is shown.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="exponential">
+ <property name="label" translatable="yes" context="tp_Trendline|exponential">_Exponential</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">linear</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="exponential-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|exponential">An exponential trend line is shown.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="power">
+ <property name="label" translatable="yes" context="tp_Trendline|power">Po_wer</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">linear</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="power-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|power">A power trend line is shown.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="imageLinear">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="imageLogarithmic">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="imageExponential">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="imagePower">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="imagePolynomial">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="polynomial">
+ <property name="label" translatable="yes" context="tp_Trendline|polynomial">_Polynomial</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">linear</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="polynomial-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|polynomial">A polynomial trend line is shown with a given degree.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_Trendline|label3">Degree</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">degree</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="label3-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|label3">Degree of polynomial trend line.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="degree">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentDegree</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="degree-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|degree">Degree of polynomial trend line.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">2</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="imageMovingAverage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">missing-image</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="movingAverage">
+ <property name="label" translatable="yes" context="tp_Trendline|movingAverage">_Moving Average</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">linear</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="movingAverage-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|movingAverage">A moving average trend line is shown with a given period.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_Trendline|label4">Period</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">period</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="label4-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|label4">Number of points to calculate average of moving average trend line.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="period">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentPeriod</property>
+ <property name="value">2</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="period-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|period">Number of points to calculate average of moving average trend line.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">2</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label10">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_Trendline|label10">_Type</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">combo_moving_type</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="label10-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|label10">How the trend line is calculated.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="combo_moving_type">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <items>
+ <item translatable="yes" context="tp_Trendline|liststore_moving_type">Prior</item>
+ <item translatable="yes" context="tp_Trendline|liststore_moving_type">Central</item>
+ <item translatable="yes" context="tp_Trendline|liststore_moving_type">Averaged Abscissa</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left-attach">2</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_Trendline|label1">Regression Type</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=2 n-rows=9 -->
+ <object class="GtkGrid" id="grid5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <property name="row-homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_Trendline|label7">Extrapolate Forward</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">extrapolateForward</property>
+ <property name="xalign">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="label7-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|label7">Trend line is extrapolated for higher x-values.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_Trendline|label8">Extrapolate Backward</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">extrapolateBackward</property>
+ <property name="xalign">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="label8-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|label8">Trend line is extrapolated for lower x-values.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="extrapolateForward">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentForwardBackward</property>
+ <property name="digits">2</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="extrapolateBackward">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentForwardBackward1</property>
+ <property name="digits">2</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="setIntercept">
+ <property name="label" translatable="yes" context="tp_Trendline|setIntercept">Force _Intercept</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <accessibility>
+ <relation type="label-for" target="interceptValue"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="setIntercept-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|setIntercept">For linear, polynomial and exponential trend lines, intercept value is forced to a given value.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="showEquation">
+ <property name="label" translatable="yes" context="tp_Trendline|showEquation">Show E_quation</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="showEquation-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|showEquation">Shows the trend line equation next to the trend line.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="showCorrelationCoefficient">
+ <property name="label" translatable="yes" context="tp_Trendline|showCorrelationCoefficient">Show _Coefficient of Determination (R²)</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="showCorrelationCoefficient-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|showCorrelationCoefficient">Shows the coefficient of determination next to the trend line.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_Trendline|label5">Trendline _Name</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">entry_name</property>
+ <property name="xalign">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="label5-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|label5">Name of trend line in legend.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_name">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="entry_name-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|entry_name">Name of trend line in legend.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="interceptValue">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="text">0</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustmentForwardBackward2</property>
+ <property name="digits">2</property>
+ <accessibility>
+ <relation type="labelled-by" target="setIntercept"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="interceptValue-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|interceptValue">Value of intercept if it is forced.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_Trendline|label6">_X Variable Name</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">entry_Xname</property>
+ <property name="xalign">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="label6-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|label6">Name of X variable in trend line equation.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_Xname">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="entry_Xname-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|entry_Xname">Name of X variable in trend line equation.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_Trendline|label9">_Y Variable Name</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">entry_Yname</property>
+ <property name="xalign">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="label9-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|label9">Name of Y variable in trend line equation.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_Yname">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="entry_Yname-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_Trendline|extended_tip|entry_Yname">Name of Y variable in trend line equation.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="tp_Trendline|label2">Options</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkAdjustment" id="adjustmentPeriod">
+ <property name="lower">2</property>
+ <property name="upper">100</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/tp_axisLabel.ui b/chart2/uiconfig/ui/tp_axisLabel.ui
new file mode 100644
index 0000000000..93578ff9b4
--- /dev/null
+++ b/chart2/uiconfig/ui/tp_axisLabel.ui
@@ -0,0 +1,430 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustmentSpinDegrees">
+ <property name="upper">359</property>
+ <property name="step_increment">5</property>
+ </object>
+ <object class="GtkBox" id="AxisLabelTabPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkCheckButton" id="showlabelsCB">
+ <property name="label" translatable="yes" context="tp_axisLabel|showlabelsCB">Sho_w labels</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="showlabelsCB-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|showlabelsCB">Specifies whether to show or hide the axis labels.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">18</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="tile">
+ <property name="label" translatable="yes" context="tp_axisLabel|tile">_Tile</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="tile-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|tile">Arranges numbers on the axis side by side.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="odd">
+ <property name="label" translatable="yes" context="tp_axisLabel|odd">St_agger odd</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">tile</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="odd-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|odd">Staggers numbers on the axis, even numbers lower than odd numbers.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="even">
+ <property name="label" translatable="yes" context="tp_axisLabel|even">Stagger _even</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">tile</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="even-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|even">Stagger numbers on the axis, odd numbers lower than even numbers.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="auto">
+ <property name="label" translatable="yes" context="tp_axisLabel|auto">A_utomatic</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">tile</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="auto-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|auto">Automatically arranges numbers on the axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="orderL">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_axisLabel|orderL">Order</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="overlapCB">
+ <property name="label" translatable="yes" context="tp_axisLabel|overlapCB">O_verlap</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="overlapCB-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|overlapCB">Specifies that the text in cells may overlap other cells.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="breakCB">
+ <property name="label" translatable="yes" context="tp_axisLabel|breakCB">_Break</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="breakCB-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|breakCB">Allows a text break.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="textflowL">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_axisLabel|textflowL">Text Flow</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="TitleRotationTabPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid10">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkSpinButton" id="OrientDegree">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="margin_top">40</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustmentSpinDegrees</property>
+ <property name="wrap">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="OrientDegree-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|OrientDegree">Allows you to manually enter the orientation angle.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="degreeL">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">40</property>
+ <property name="label" translatable="yes" context="tp_axisLabel|degreeL">_Degrees</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkCheckButton" id="stackedCB">
+ <property name="label" translatable="yes" context="tp_axisLabel|stackedCB">Ve_rtically stacked</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="inconsistent">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="stackedCB-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|stackedCB">Assigns vertical text orientation for cell contents.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelABCD">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_axisLabel|labelABCD">ABCD</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="textdirL">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_axisLabel|textdirL">Te_xt direction:</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="textdirLB">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="textdirLB-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|textdirLB">Specify the text direction for a paragraph that uses complex text layout (CTL). This feature is only available if complex text layout support is enabled.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="dialCtrl">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="dialCtrl-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="tp_axisLabel|extended_tip|dialCtrl">Clicking anywhere on the wheel defines the variable text orientation.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="labelTextOrient">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="tp_axisLabel|labelTextOrient">Text Orientation</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/uiconfig/ui/wizelementspage.ui b/chart2/uiconfig/ui/wizelementspage.ui
new file mode 100644
index 0000000000..e60e8bb741
--- /dev/null
+++ b/chart2/uiconfig/ui/wizelementspage.ui
@@ -0,0 +1,496 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="chart">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="WizElementsPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frameAxes">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">18</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="labelPrimaryXaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="wizelementspage|labelPrimaryXaxis">_X axis</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">primaryXaxis</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelPrimaryYaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="wizelementspage|labelPrimaryYaxis">_Y axis</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">primaryYaxis</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelPrimaryZaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="wizelementspage|labelPrimaryZaxis">_Z axis</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">primaryZaxis</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="primaryXaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryXaxis-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|primaryXaxis">Enter a label for the x-axis (horizontal).</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="primaryYaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryYaxis-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|primaryYaxis">Enter a label for the y-axis (vertical).</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="primaryZaxis">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primaryZaxis-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|primaryZaxis">Enter a label for the z-axis. This option is only available for three-dimensional charts.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelMainTitle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="wizelementspage|labelMainTitle">_Title</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">maintitle</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelSubTitle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="wizelementspage|labelSubTitle">_Subtitle</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">subtitle</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="maintitle">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="maintitle-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|maintitle">Enter a title for your chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="subtitle">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="subtitle-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|subtitle">Enter a subtitle for your chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelSecondaryXAxis">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="wizelementspage|labelSecondaryXAxis">X _axis</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">secondaryXaxis</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labelSecondaryYAxis">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="wizelementspage|labelSecondaryYAxis">Y ax_is</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">secondaryYaxis</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="secondaryXaxis">
+ <property name="can_focus">True</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="secondaryXaxis-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|secondaryXaxis">Enter a label for the secondary x-axis. This option is only available for charts that support a secondary x-axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="secondaryYaxis">
+ <property name="can_focus">True</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="show">
+ <property name="label" translatable="yes" context="wizelementspage|show">_Display legend</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="show-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|show">Specifies whether to display a legend for the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <child>
+ <object class="GtkRadioButton" id="left">
+ <property name="label" translatable="yes" context="wizelementspage|left">_Left</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="left-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|left">Positions the legend at the left of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="right">
+ <property name="label" translatable="yes" context="wizelementspage|right">_Right</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">left</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="right-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|right">Positions the legend at the right of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="top">
+ <property name="label" translatable="yes" context="wizelementspage|top">_Top</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">left</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="top-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|top">Positions the legend at the top of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="bottom">
+ <property name="label" translatable="yes" context="wizelementspage|bottom">_Bottom</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">left</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="bottom-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|bottom">Positions the legend at the bottom of the chart.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="Axe">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="wizelementspage|Axe">Choose Titles, Legend, and Grid Settings</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frameSecondaryAxes">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="x">
+ <property name="label" translatable="yes" context="wizelementspage|x">X axis</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="x-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|x">Displays grid lines that are perpendicular to the x-axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="y">
+ <property name="label" translatable="yes" context="wizelementspage|y">Y ax_is</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="y-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|y">Displays grid lines that are perpendicular to the y-axis.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="z">
+ <property name="label" translatable="yes" context="wizelementspage|z">Z axi_s</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="z-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="wizelementspage|extended_tip|z">Displays grid lines that are perpendicular to the z-axis. This option is only available for three-dimensional charts.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="wizelementspage|label2">Display Grids</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/chart2/workbench/addin/exports.dxp b/chart2/workbench/addin/exports.dxp
new file mode 100644
index 0000000000..51703a0466
--- /dev/null
+++ b/chart2/workbench/addin/exports.dxp
@@ -0,0 +1,2 @@
+component_writeInfo
+component_getFactory
diff --git a/chart2/workbench/addin/makefile.mk b/chart2/workbench/addin/makefile.mk
new file mode 100644
index 0000000000..a7f8c5f0a2
--- /dev/null
+++ b/chart2/workbench/addin/makefile.mk
@@ -0,0 +1,76 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+PRJ=..$/..
+PRJNAME=chartaddin
+
+TARGET=chartsampleaddin
+
+ENABLE_EXCEPTIONS=TRUE
+USE_DEFFILE=TRUE
+LIBTARGET=NO
+
+# --- Settings ----------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Types -------------------------------------
+
+UNOUCROUT=$(OUT)$/inc$/$(PRJNAME)$/$(TARGET)
+INCPRE+=$(UNOUCROUT)
+
+# --- Types -------------------------------------
+
+# comprehensive type info, so rdb need not to be installed
+# CPPUMAKERFLAGS*=-C
+
+# UNOTYPES=\
+# com.sun.star.lang.XInitialization \
+# com.sun.star.lang.XServiceName \
+# com.sun.star.lang.XServiceInfo \
+# com.sun.star.util.XRefreshable \
+# com.sun.star.lang.XLocalizable \
+# com.sun.star.chart.XDiagram \
+# com.sun.star.chart.XChartDocument \
+# com.sun.star.chart.XAxisXSupplier \
+# com.sun.star.chart.XAxisYSupplier \
+# com.sun.star.chart.XStatisticDisplay \
+# com.sun.star.lang.XMultiServiceFactory
+
+# --- Files -------------------------------------
+
+SLOFILES=\
+ $(SLO)$/sampleaddin.obj
+
+# --- Library -----------------------------------
+
+SHL1TARGET=$(TARGET)$(DLLPOSTFIX)
+SHL1OBJS=$(SLOFILES)
+SHL1STDLIBS= \
+ $(CPPUHELPERLIB) \
+ $(CPPULIB) \
+ $(SALLIB)
+
+SHL1DEPN=makefile.mk
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+DEF1NAME=$(SHL1TARGET)
+DEF1EXPORTFILE=exports.dxp
+
+# --- Targets ----------------------------------
+
+.INCLUDE : target.mk
diff --git a/chart2/workbench/addin/sampleaddin.cxx b/chart2/workbench/addin/sampleaddin.cxx
new file mode 100644
index 0000000000..5e3d23fd5f
--- /dev/null
+++ b/chart2/workbench/addin/sampleaddin.cxx
@@ -0,0 +1,652 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include "sampleaddin.hxx"
+
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/factory.hxx>
+#include <osl/diagnose.h>
+
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/chart/XChartDataArray.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/chart/X3DDisplay.hpp>
+
+using namespace com::sun::star;
+
+// code for creating instances of SampleAddIn
+
+extern "C" {
+
+sal_Bool SAL_CALL component_writeInfo(
+ void * /*pServiceManager*/, registry::XRegistryKey * pRegistryKey )
+{
+ if( pRegistryKey )
+ {
+ try
+ {
+ OUString aImpl = "/" + SampleAddIn::getImplementationName_Static() + "/UNO/SERVICES";
+
+ uno::Reference< registry::XRegistryKey> xNewKey(
+ reinterpret_cast<registry::XRegistryKey*>( pRegistryKey )->createKey( aImpl ) );
+
+ uno::Sequence< OUString > aSequ = SampleAddIn::getSupportedServiceNames_Static();
+ const OUString * pArray = aSequ.getConstArray();
+ for( sal_Int32 i = 0; i < aSequ.(); i++ )
+ xNewKey->createKey( pArray[i] );
+
+ return sal_True;
+ }
+ catch( const registry::InvalidRegistryException& )
+ {
+ TOOLS_WARN_EXCEPTION( "chart2", "" );
+ }
+ }
+ return sal_False;
+}
+
+SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
+ const char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
+{
+ void* pRet = 0;
+
+ if ( pServiceManager &&
+ OUString::createFromAscii( pImplName ) == SampleAddIn::getImplementationName_Static() )
+ {
+ uno::Reference< lang::XSingleServiceFactory> xFactory( cppu::createSingleFactory(
+ reinterpret_cast<lang::XMultiServiceFactory*>( pServiceManager ),
+ SampleAddIn::getImplementationName_Static(),
+ SampleAddIn_CreateInstance,
+ SampleAddIn::getSupportedServiceNames_Static() ) );
+
+ if( xFactory.is())
+ {
+ xFactory->acquire();
+ pRet = xFactory.get();
+ }
+ }
+
+ return pRet;
+}
+
+} // extern C
+
+
+SampleAddIn::SampleAddIn()
+{
+
+}
+
+SampleAddIn::~SampleAddIn()
+{}
+
+// this functionality should be provided by the chart API some day
+sal_Bool SampleAddIn::getLogicalPosition( uno::Reference< drawing::XShape >& xAxis,
+ double fValue,
+ sal_Bool bVertical,
+ awt::Point& aOutPosition )
+{
+ sal_Bool bRet = sal_False;
+
+ if( xAxis.is())
+ {
+ awt::Size aSize = xAxis->getSize();
+ sal_Int32 nLength = bVertical? aSize.Height: aSize.Width;
+
+ uno::Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
+ if( xProp.is())
+ {
+ try
+ {
+ double fMin(0.0), fMax(0.0);
+ uno::Any aAny = xProp->getPropertyValue( "Min" );
+ aAny >>= fMin;
+ aAny = xProp->getPropertyValue( "Max" );
+ aAny >>= fMax;
+
+ double fRange = fMax - fMin;
+ if( fMin <= fValue && fValue <= fMax &&
+ fRange != 0.0 )
+ {
+ double fPercentage = (fValue - fMin) / fRange;
+ awt::Point aPos = xAxis->getPosition();
+
+ if( bVertical )
+ {
+ aOutPosition.X = aPos.X;
+ aOutPosition.Y = static_cast<sal_Int32>(aPos.Y + nLength * (1.0 - fPercentage)); // y scale goes from top to bottom
+ }
+ else
+ {
+ aOutPosition.X = static_cast<sal_Int32>(aPos.X + nLength * fPercentage);
+ aOutPosition.Y = aPos.Y;
+ }
+ bRet = sal_True;
+ }
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ // the shape xAxis was no chart axis
+ }
+ }
+ }
+
+ return bRet;
+}
+
+OUString SampleAddIn::getImplementationName_Static()
+{
+ return "SampleAddIn";
+}
+
+uno::Sequence< OUString > SampleAddIn::getSupportedServiceNames_Static()
+{
+ return {
+ "com.sun.star.chart.ChartAxisXSupplier",
+ "com.sun.star.chart.ChartAxisYSupplier",
+ "com.sun.star.chart.Diagram",
+ "com.sun.star.chart.SampleAddIn"
+ };
+}
+
+uno::Reference< uno::XInterface > SAL_CALL SampleAddIn_CreateInstance(
+ const uno::Reference< lang::XMultiServiceFactory >& )
+{
+ uno::Reference< uno::XInterface > xInst = (cppu::OWeakObject*)new SampleAddIn();
+
+ return xInst;
+}
+
+// implementation of interface methods
+
+// XInitialization
+void SAL_CALL SampleAddIn::initialize( const uno::Sequence< uno::Any >& aArguments )
+ throw( uno::Exception, uno::RuntimeException )
+{
+ // first argument should be the XChartDocument
+ OSL_ENSURE( aArguments.getLength() > 0, "Please initialize Chart AddIn with ChartDocument!" );
+
+ if( aArguments.getLength())
+ {
+ aArguments[ 0 ] >>= mxChartDoc;
+ OSL_ENSURE( mxChartDoc.is(), "First argument in initialization is not an XChartDocument!" );
+
+ // set XY chart as base type to be drawn
+ uno::Reference< beans::XPropertySet > xDocProp( mxChartDoc, uno::UNO_QUERY );
+ if( xDocProp.is())
+ {
+ uno::Any aBaseType;
+ aBaseType <<= "com.sun.star.chart.XYDiagram";
+ try
+ {
+ xDocProp->setPropertyValue( "BaseDiagram" , aBaseType );
+ }
+ catch( ... )
+ {}
+ }
+
+ // change background of plot area to light blue
+ uno::Reference< chart::X3DDisplay > xWallSupplier( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xWallSupplier.is())
+ {
+ uno::Reference< beans::XPropertySet > xDiaProp( xWallSupplier->getWall(), uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySet > xLegendProp( mxChartDoc->getLegend(), uno::UNO_QUERY );
+ if( xDiaProp.is() &&
+ xLegendProp.is())
+ {
+ uno::Any aAny;
+ aAny <<= (sal_Int32)( 0xe0e0f0 );
+ xDiaProp->setPropertyValue( "FillColor" , aAny );
+ xLegendProp->setPropertyValue( "FillColor" , aAny );
+ }
+ }
+ }
+}
+
+// XRefreshable
+/********************************************************************************
+ *
+ * The method refresh is the most important method - here all objects that
+ * are necessary for the chart are created
+ *
+ * in the first implementation you will have to insert everything in this
+ * routine - all old objects are deleted beforehand
+ *
+ ********************************************************************************/
+void SAL_CALL SampleAddIn::refresh() throw( uno::RuntimeException )
+{
+ if( ! mxChartDoc.is())
+ return;
+
+ // first of all get the draw page
+ uno::Reference< drawing::XDrawPageSupplier > xPageSupp( mxChartDoc, uno::UNO_QUERY );
+ uno::Reference< lang::XMultiServiceFactory > xFactory( mxChartDoc, uno::UNO_QUERY );
+ if( xPageSupp.is() &&
+ xFactory.is() )
+ {
+ uno::Reference< drawing::XDrawPage > xPage = xPageSupp->getDrawPage();
+ if( xPage.is())
+ {
+ // now we have the page to insert objects
+
+ // add a horizontal line at the middle value of the first series
+
+ // get the logical position from the coordinate
+ // get x- and y-axis
+ uno::Reference< drawing::XShape > xYAxisShape( getYAxis(), uno::UNO_QUERY );
+ uno::Reference< drawing::XShape > xXAxisShape( getXAxis(), uno::UNO_QUERY );
+
+ if( xXAxisShape.is() &&
+ xYAxisShape.is() )
+ {
+ // create line first time
+ if( ! mxMyRedLine.is())
+ {
+ mxMyRedLine.set(
+ xFactory->createInstance( "com.sun.star.drawing.LineShape" ),
+ uno::UNO_QUERY );
+ xPage->add( mxMyRedLine );
+
+ // make line red and thick
+ uno::Reference< beans::XPropertySet > xShapeProp( mxMyRedLine, uno::UNO_QUERY );
+ if( xShapeProp.is())
+ {
+ uno::Any aColor, aWidth;
+ aColor <<= (sal_Int32)(0xe01010);
+ aWidth <<= (sal_Int32)(50); // 0.5 mm
+ try
+ {
+ xShapeProp->setPropertyValue( "LineColor" , aColor );
+ xShapeProp->setPropertyValue( "LineWidth" , aWidth );
+ }
+ catch( ... )
+ {}
+ }
+ }
+ // create text object first time
+ if( ! mxMyText.is())
+ {
+ mxMyText.set(
+ xFactory->createInstance( "com.sun.star.drawing.TextShape" ),
+ uno::UNO_QUERY );
+ xPage->add( mxMyText );
+
+ // change text
+ OUString aText( "Little Example" );
+ uno::Reference< beans::XPropertySet > xTextProp( mxMyText, uno::UNO_QUERY );
+ if( xTextProp.is())
+ {
+ uno::Any aTrueAny;
+ aTrueAny <<= (sal_Bool)(sal_True);
+ try
+ {
+ xTextProp->setPropertyValue( "TextAutoGrowWidth" , aTrueAny );
+ }
+ catch( ... )
+ {}
+ }
+
+ uno::Reference< text::XTextRange > xTextRange( mxMyText, uno::UNO_QUERY );
+ if( xTextRange.is())
+ {
+ xTextRange->setString( aText );
+ }
+ }
+
+ // position line and text
+
+ // get the array. Note: the first dimension is the length
+ // of each series and the second one is the number of series
+ // this should be changed in the future
+ uno::Sequence< uno::Sequence< double > > aData;
+ uno::Reference< chart::XChartData > xData = mxChartDoc->getData();
+ uno::Reference< chart::XChartDataArray > xDataArray( xData, uno::UNO_QUERY );
+ if( xDataArray.is())
+ aData = xDataArray->getData();
+
+ // get row count == length of each series
+ sal_Int32 nSize = aData.getLength();
+ sal_Int32 nMiddle = nSize / 2;
+ // get value for first series
+ double fMiddleVal = xData->getNotANumber(); // set to NaN
+ if( aData[ nMiddle ].getLength()) // we have at least one series
+ fMiddleVal = aData[ nMiddle ][ 0 ];
+
+ awt::Point aPos;
+ getLogicalPosition( xYAxisShape, fMiddleVal, sal_True, aPos );
+ awt::Size aSize = xXAxisShape->getSize();
+
+ if( mxMyRedLine.is())
+ {
+ awt::Point aEnd = aPos;
+ aEnd.X += aSize.Width;
+
+ uno::Sequence< uno::Sequence< awt::Point > > aPtSeq( 1 );
+ aPtSeq[ 0 ].realloc( 2 );
+ aPtSeq[ 0 ][ 0 ] = aPos;
+ aPtSeq[ 0 ][ 1 ] = aEnd;
+
+ uno::Reference< beans::XPropertySet > xShapeProp( mxMyRedLine, uno::UNO_QUERY );
+ if( xShapeProp.is())
+ {
+ xShapeProp->setPropertyValue( "PolyPolygon" , Any(aPtSeq) );
+ }
+ }
+ if( mxMyText.is())
+ {
+ // put the text centered below the red line
+ aPos.X += ( aSize.Width - mxMyRedLine->getPosition().X ) / 2;
+ aPos.Y += 1000;
+ aPos.Y += static_cast<sal_Int32>(0.1 * xYAxisShape->getSize().Height);
+ mxMyText->setPosition( aPos );
+ }
+ }
+ }
+ }
+}
+
+void SAL_CALL SampleAddIn::addRefreshListener( const uno::Reference< util::XRefreshListener >& )
+ throw( uno::RuntimeException )
+{
+ // not implemented - this is not necessary
+ // (this method exists just because the interface requires it)
+}
+
+void SAL_CALL SampleAddIn::removeRefreshListener( const uno::Reference< util::XRefreshListener >& )
+ throw( uno::RuntimeException )
+{
+ // not implemented - this is not necessary
+ // (this method exists just because the interface requires it)
+}
+
+// XDiagram
+OUString SAL_CALL SampleAddIn::getDiagramType() throw( uno::RuntimeException )
+{
+ return "com.sun.star.chart.SampleDiagram";
+}
+
+// the following methods just delegate to the "parent diagram" (which in the future might no longer exist)
+
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getDataRowProperties( sal_Int32 nRow )
+ throw( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XDiagram > xDia = mxChartDoc->getDiagram();
+ if( xDia.is())
+ return xDia->getDataRowProperties( nRow );
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getDataPointProperties( sal_Int32 nCol, sal_Int32 nRow )
+ throw( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XDiagram > xDia = mxChartDoc->getDiagram();
+ if( xDia.is())
+ return xDia->getDataPointProperties( nCol, nRow );
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+// XShape ( ::XDiagram )
+awt::Size SAL_CALL SampleAddIn::getSize()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< drawing::XShape > xShape( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xShape.is())
+ return xShape->getSize();
+ }
+
+ return awt::Size();
+}
+
+void SAL_CALL SampleAddIn::setSize( const awt::Size& aSize )
+ throw( beans::PropertyVetoException, uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< drawing::XShape > xShape( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xShape.is())
+ xShape->setSize( aSize );
+ }
+}
+
+awt::Point SAL_CALL SampleAddIn::getPosition()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< drawing::XShape > xShape( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xShape.is())
+ return xShape->getPosition();
+ }
+
+ return awt::Point();
+}
+
+void SAL_CALL SampleAddIn::setPosition( const awt::Point& aPos )
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< drawing::XShape > xShape( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xShape.is())
+ xShape->setPosition( aPos );
+ }
+}
+
+// XShapeDescriptor ( ::XShape ::XDiagram )
+OUString SAL_CALL SampleAddIn::getShapeType() throw( css::uno::RuntimeException )
+{
+ return "com.sun.star.chart.SampleAddinShape";
+}
+
+// XAxisXSupplier
+uno::Reference< drawing::XShape > SAL_CALL SampleAddIn::getXAxisTitle()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XAxisXSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xAxisSupp.is())
+ return xAxisSupp->getXAxisTitle();
+ }
+
+ return uno::Reference< drawing::XShape >();
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getXAxis()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XAxisXSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xAxisSupp.is())
+ return xAxisSupp->getXAxis();
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getXMainGrid()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XAxisXSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xAxisSupp.is())
+ return xAxisSupp->getXMainGrid();
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getXHelpGrid()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XAxisXSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xAxisSupp.is())
+ return xAxisSupp->getXHelpGrid();
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+// XAxisYSupplier
+uno::Reference< drawing::XShape > SAL_CALL SampleAddIn::getYAxisTitle()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XAxisYSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xAxisSupp.is())
+ return xAxisSupp->getYAxisTitle();
+ }
+
+ return uno::Reference< drawing::XShape >();
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getYAxis()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XAxisYSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xAxisSupp.is())
+ return xAxisSupp->getYAxis();
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getYMainGrid()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XAxisYSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xAxisSupp.is())
+ return xAxisSupp->getYMainGrid();
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getYHelpGrid()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XAxisYSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xAxisSupp.is())
+ return xAxisSupp->getYHelpGrid();
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+// XStatisticDisplay
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getUpBar()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XStatisticDisplay > xStatDisp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xStatDisp.is())
+ return xStatDisp->getUpBar();
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getDownBar()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XStatisticDisplay > xStatDisp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xStatDisp.is())
+ return xStatDisp->getDownBar();
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getMinMaxLine()
+ throw( uno::RuntimeException )
+{
+ if( mxChartDoc.is())
+ {
+ uno::Reference< chart::XStatisticDisplay > xStatDisp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
+ if( xStatDisp.is())
+ return xStatDisp->getMinMaxLine();
+ }
+
+ return uno::Reference< beans::XPropertySet >();
+}
+
+// XServiceName
+OUString SAL_CALL SampleAddIn::getServiceName() throw( uno::RuntimeException )
+{
+ return "com.sun.star.chart.SampleAddIn";
+}
+
+// XServiceInfo
+OUString SAL_CALL SampleAddIn::getImplementationName() throw( uno::RuntimeException )
+{
+ return getImplementationName_Static();
+}
+
+sal_Bool SAL_CALL SampleAddIn::supportsService( const OUString& ServiceName )
+ throw( uno::RuntimeException )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL SampleAddIn::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ return getSupportedServiceNames_Static();
+}
+
+// XLocalizable
+void SAL_CALL SampleAddIn::setLocale( const lang::Locale& eLocale )
+ throw( uno::RuntimeException )
+{
+ maLocale = eLocale;
+}
+
+lang::Locale SAL_CALL SampleAddIn::getLocale()
+ throw( uno::RuntimeException )
+{
+ return maLocale;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/workbench/addin/sampleaddin.def b/chart2/workbench/addin/sampleaddin.def
new file mode 100644
index 0000000000..b13949b6a2
--- /dev/null
+++ b/chart2/workbench/addin/sampleaddin.def
@@ -0,0 +1,6 @@
+LIBRARY sampleaddin
+DESCRIPTION 'Sample Chart AddIn'
+HEAPSIZE 0
+EXPORTS
+component_writeInfo
+component_getFactory
diff --git a/chart2/workbench/addin/sampleaddin.hxx b/chart2/workbench/addin/sampleaddin.hxx
new file mode 100644
index 0000000000..df45d45894
--- /dev/null
+++ b/chart2/workbench/addin/sampleaddin.hxx
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/chart/XDiagram.hpp>
+#include <com/sun/star/chart/XAxisXSupplier.hpp>
+#include <com/sun/star/chart/XAxisYSupplier.hpp>
+#include <com/sun/star/chart/XStatisticDisplay.hpp>
+
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/lang/XLocalizable.hpp>
+
+#include <com/sun/star/chart/XChartDocument.hpp>
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL
+ SampleAddIn_CreateInstance(
+ const css::uno::Reference< css::lang::XMultiServiceFactory >& );
+
+class SampleAddIn : public cppu::WeakImplHelper<
+ css::lang::XInitialization,
+ css::chart::XDiagram,
+ css::chart::XAxisXSupplier,
+ css::chart::XAxisYSupplier,
+ css::chart::XStatisticDisplay,
+ css::lang::XServiceName,
+ css::lang::XServiceInfo,
+ css::util::XRefreshable,
+ css::lang::XLocalizable >
+{
+private:
+ css::uno::Reference< css::chart::XChartDocument > mxChartDoc;
+ css::lang::Locale maLocale;
+
+ css::uno::Reference< css::drawing::XShape > mxMyRedLine;
+ css::uno::Reference< css::drawing::XShape > mxMyText;
+
+public:
+ SampleAddIn();
+ virtual ~SampleAddIn();
+
+ // class specific code
+ static OUString getImplementationName_Static();
+ static css::uno::Sequence< OUString > getSupportedServiceNames_Static();
+
+ sal_Bool getLogicalPosition( css::uno::Reference< css::drawing::XShape >& xAxis,
+ double fValue,
+ sal_Bool bVertical,
+ css::awt::Point& aOutPosition );
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
+ throw( css::uno::Exception,
+ css::uno::RuntimeException );
+
+ // XDiagram
+ virtual OUString SAL_CALL getDiagramType() throw( css::uno::RuntimeException );
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getDataRowProperties( sal_Int32 nRow )
+ throw( css::lang::IndexOutOfBoundsException,
+ css::uno::RuntimeException );
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getDataPointProperties( sal_Int32 nCol, sal_Int32 nRow )
+ throw( css::lang::IndexOutOfBoundsException,
+ css::uno::RuntimeException );
+
+ // XShape ( ::XDiagram )
+ virtual css::awt::Size SAL_CALL getSize()
+ throw( css::uno::RuntimeException );
+ virtual void SAL_CALL setSize( const css::awt::Size& )
+ throw( css::beans::PropertyVetoException,
+ css::uno::RuntimeException );
+ virtual css::awt::Point SAL_CALL getPosition()
+ throw( css::uno::RuntimeException );
+ virtual void SAL_CALL setPosition( const css::awt::Point& )
+ throw( css::uno::RuntimeException );
+
+ // XShapeDescriptor ( ::XShape ::XDiagram )
+ virtual OUString SAL_CALL getShapeType() throw( css::uno::RuntimeException );
+
+ // XAxisXSupplier
+ virtual css::uno::Reference< css::drawing::XShape > SAL_CALL getXAxisTitle()
+ throw( css::uno::RuntimeException );
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getXAxis()
+ throw( css::uno::RuntimeException );
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getXMainGrid()
+ throw( css::uno::RuntimeException );
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getXHelpGrid()
+ throw( css::uno::RuntimeException );
+
+ // XAxisYSupplier
+ virtual css::uno::Reference< css::drawing::XShape > SAL_CALL getYAxisTitle()
+ throw( css::uno::RuntimeException );
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getYAxis()
+ throw( css::uno::RuntimeException );
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getYHelpGrid()
+ throw( css::uno::RuntimeException );
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getYMainGrid()
+ throw( css::uno::RuntimeException );
+
+ // XStatisticDisplay
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getUpBar()
+ throw( css::uno::RuntimeException );
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getDownBar()
+ throw( css::uno::RuntimeException );
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getMinMaxLine()
+ throw( css::uno::RuntimeException );
+
+ // XServiceName
+ virtual OUString SAL_CALL getServiceName() throw( css::uno::RuntimeException );
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() throw( css::uno::RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName )
+ throw( css::uno::RuntimeException );
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames()
+ throw( css::uno::RuntimeException );
+
+ // XRefreshable
+ virtual void SAL_CALL refresh() throw( css::uno::RuntimeException );
+ virtual void SAL_CALL addRefreshListener( const css::uno::Reference< css::util::XRefreshListener >& l )
+ throw( css::uno::RuntimeException );
+ virtual void SAL_CALL removeRefreshListener( const css::uno::Reference< css::util::XRefreshListener >& l )
+ throw( css::uno::RuntimeException );
+
+ // XLocalizable
+ virtual void SAL_CALL setLocale( const css::lang::Locale& eLocale )
+ throw( css::uno::RuntimeException );
+ virtual css::lang::Locale SAL_CALL getLocale()
+ throw( css::uno::RuntimeException );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */